mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Previously, secondary (non-host) split-screen connections used isPrimaryConnection() to gate nearly all world update packets, meaning the second local player would never receive tile updates, entity movement, sounds, particles, explosions, etc. The fix introduces per-connection tracking of which entities and chunks each ClientConnection has loaded, and uses that information to decide whether a secondary connection needs to process a given packet or if the primary connection already handled it. New members in ClientConnection: - m_trackedEntityIds: set of entity IDs this connection has received AddEntity/AddMob/AddPlayer etc. for - m_visibleChunks: set of chunk coordinates (packed into int64) this connection has marked visible - Both sets are cleared on close(), respawn (dimension change), and destructor New helpers: - findPrimaryConnection(): walks the MultiPlayerLevel connection list to find the connection on the primary pad - shouldProcessForEntity(id): secondary connection skips the packet only if the primary is already tracking that entity - shouldProcessForPosition(x, z): secondary connection skips the packet only if the primary already has that chunk visible - anyOtherConnectionHasChunk(x, z): used when a chunk becomes invisible to avoid hiding it from the level if another connection still needs it - isTrackingEntity(id): public accessor used by shouldProcessForEntity on the primary connection Packet handler changes: - handleMoveEntity, handleMoveEntitySmall, handleSetEntityMotion, handleTakeItemEntity: replaced isPrimaryConnection() with shouldProcessForEntity() so secondary connections still process movement for entities they know about - handleExplosion, handleLevelEvent: replaced isPrimaryConnection() with shouldProcessForPosition() so block destruction and level events fire for the correct connection based on chunks - handleChunkTilesUpdate, handleBlockRegionUpdate, handleTileUpdate, handleSignUpdate, handleTileEntityData, handleTileEvent, handleTileDestruction, handleComplexItemData, handleSoundEvent, handleParticleEvent: removed the isPrimaryConnection() guard entirely -- these are world-state updates that all connections must process regardless of which pad is primary - handleChunkVisibilityArea / handleChunkVisibility: now populate m_visibleChunks; on visibility=false, setChunkVisible(false) is only called on the level if no other connection still has that chunk loaded - handleAddEntity, handleAddExperienceOrb, handleAddPainting, handleAddPlayer, handleAddMob: now insert into m_trackedEntityIds on arrival - handleRemoveEntity: now erases from m_trackedEntityIds on removal - handleLevelEvent: removed a duplicate levelEvent() call that was always firing regardless of the isPrimaryConnection() check above it (latent bug) MultiPlayerLevel: added friend class ClientConnection to allow access to the connections list without exposing it publicly.
109 lines
3.8 KiB
C++
109 lines
3.8 KiB
C++
#pragma once
|
|
using namespace std;
|
|
#include "..\Minecraft.World\HashExtension.h"
|
|
#include "..\Minecraft.World\net.minecraft.world.level.h"
|
|
#include "..\Minecraft.World\net.minecraft.world.entity.h"
|
|
#include "..\Minecraft.World\JavaIntHash.h"
|
|
|
|
class ClientConnection;
|
|
class MultiPlayerChunkCache;
|
|
|
|
using namespace std;
|
|
|
|
class MultiPlayerLevel : public Level
|
|
{
|
|
friend class ClientConnection;
|
|
private:
|
|
static const int TICKS_BEFORE_RESET = 20 * 4;
|
|
|
|
class ResetInfo
|
|
{
|
|
public:
|
|
int x, y, z, ticks, tile, data;
|
|
ResetInfo(int x, int y, int z, int tile, int data);
|
|
};
|
|
|
|
vector<ResetInfo> updatesToReset; // 4J - was linked list but vector seems more appropriate
|
|
bool m_bEnableResetChanges; // 4J Added
|
|
public:
|
|
void unshareChunkAt(int x, int z); // 4J - added
|
|
void shareChunkAt(int x, int z); // 4J - added
|
|
|
|
void enableResetChanges(bool enable) { m_bEnableResetChanges = enable; } // 4J Added
|
|
private:
|
|
int unshareCheckX; // 4J - added
|
|
int unshareCheckZ; // 4J - added
|
|
int compressCheckX; // 4J - added
|
|
int compressCheckZ; // 4J - added
|
|
vector<ClientConnection *> connections; // 4J Stu - Made this a vector as we can have more than one local connection
|
|
MultiPlayerChunkCache *chunkCache;
|
|
Minecraft *minecraft;
|
|
Scoreboard *scoreboard;
|
|
|
|
public:
|
|
MultiPlayerLevel(ClientConnection *connection, LevelSettings *levelSettings, int dimension, int difficulty);
|
|
virtual ~MultiPlayerLevel();
|
|
virtual void tick() ;
|
|
|
|
void clearResetRegion(int x0, int y0, int z0, int x1, int y1, int z1);
|
|
protected:
|
|
ChunkSource *createChunkSource(); // 4J - was virtual, but was called from parent ctor
|
|
public:
|
|
virtual void validateSpawn();
|
|
protected:
|
|
virtual void tickTiles();
|
|
public:
|
|
void setChunkVisible(int x, int z, bool visible);
|
|
|
|
private:
|
|
unordered_map<int, shared_ptr<Entity>, IntKeyHash2, IntKeyEq> entitiesById; // 4J - was IntHashMap
|
|
unordered_set<shared_ptr<Entity> > forced;
|
|
unordered_set<shared_ptr<Entity> > reEntries;
|
|
|
|
public:
|
|
virtual bool addEntity(shared_ptr<Entity> e);
|
|
virtual void removeEntity(shared_ptr<Entity> e);
|
|
protected:
|
|
virtual void entityAdded(shared_ptr<Entity> e);
|
|
virtual void entityRemoved(shared_ptr<Entity> e);
|
|
public:
|
|
void putEntity(int id, shared_ptr<Entity> e);
|
|
shared_ptr<Entity> getEntity(int id);
|
|
shared_ptr<Entity> removeEntity(int id);
|
|
virtual void removeEntities(vector<shared_ptr<Entity> > *list); // 4J Added override
|
|
virtual bool setData(int x, int y, int z, int data, int updateFlags, bool forceUpdate =false );
|
|
virtual bool setTileAndData(int x, int y, int z, int tile, int data, int updateFlags);
|
|
bool doSetTileAndData(int x, int y, int z, int tile, int data);
|
|
virtual void disconnect(bool sendDisconnect = true);
|
|
void animateTick(int xt, int yt, int zt);
|
|
protected:
|
|
virtual Tickable *makeSoundUpdater(shared_ptr<Minecart> minecart);
|
|
virtual void tickWeather();
|
|
|
|
static const int ANIMATE_TICK_MAX_PARTICLES = 500;
|
|
|
|
public:
|
|
void animateTickDoWork(); // 4J added
|
|
unordered_set<int> chunksToAnimate; // 4J added
|
|
|
|
public:
|
|
void removeAllPendingEntityRemovals();
|
|
|
|
virtual void playSound(shared_ptr<Entity> entity, int iSound, float volume, float pitch);
|
|
|
|
virtual void playLocalSound(double x, double y, double z, int iSound, float volume, float pitch, bool distanceDelay = false, float fClipSoundDist = 16.0f);
|
|
|
|
virtual void createFireworks(double x, double y, double z, double xd, double yd, double zd, CompoundTag *infoTag);
|
|
virtual void setScoreboard(Scoreboard *scoreboard);
|
|
virtual void setDayTime(int64_t newTime);
|
|
|
|
// 4J Stu - Added so we can have multiple local connections
|
|
void addClientConnection(ClientConnection *c) { connections.push_back( c ); }
|
|
void removeClientConnection(ClientConnection *c, bool sendDisconnect);
|
|
|
|
void tickAllConnections();
|
|
|
|
void dataReceivedForChunk(int x, int z); // 4J added
|
|
void removeUnusedTileEntitiesInRegion(int x0, int y0, int z0, int x1, int y1, int z1); // 4J added
|
|
};
|