diff --git a/.gitignore b/.gitignore index 226e4105..2b8f6159 100644 --- a/.gitignore +++ b/.gitignore @@ -420,3 +420,4 @@ server-data/ tools/*.class tools/*.swf tools/staging/ +tools/server-monitor/ diff --git a/Minecraft.Client/EntityTracker.cpp b/Minecraft.Client/EntityTracker.cpp index 087227e7..736c27a2 100644 --- a/Minecraft.Client/EntityTracker.cpp +++ b/Minecraft.Client/EntityTracker.cpp @@ -21,6 +21,10 @@ #include "..\Minecraft.World\net.minecraft.world.level.chunk.h" #include "PlayerConnection.h" +#ifdef _WINDOWS64 +extern bool g_Win64DedicatedServer; +#endif + EntityTracker::EntityTracker(ServerLevel *level) { this->level = level; @@ -139,32 +143,40 @@ void EntityTracker::tick() // 4J Stu - If one player on a system is updated, then make sure they all are as they all have their // range extended to include entities visible by any other player on the system // Fix for #11194 - Gameplay: Host player and their split-screen avatars can become invisible and invulnerable to client. - MinecraftServer *server = MinecraftServer::getInstance(); - for( unsigned int i = 0; i < server->getPlayers()->players.size(); i++ ) + // NOTE: On dedicated servers, IsSameSystem() always returns false for remote + // players (no split-screen), so this loop does nothing. Skip it entirely to + // avoid the O(players * movedPlayers) overhead. +#ifdef _WINDOWS64 + if (!g_Win64DedicatedServer) +#endif { - shared_ptr ep = server->getPlayers()->players[i]; - if( ep->dimension != level->dimension->id ) continue; - - if( ep->connection == nullptr ) continue; - INetworkPlayer *thisPlayer = ep->connection->getNetworkPlayer(); - if( thisPlayer == nullptr ) continue; - - bool addPlayer = false; - for (unsigned int j = 0; j < movedPlayers.size(); j++) + MinecraftServer *server = MinecraftServer::getInstance(); + for( unsigned int i = 0; i < server->getPlayers()->players.size(); i++ ) { - shared_ptr sp = movedPlayers[j]; + shared_ptr ep = server->getPlayers()->players[i]; + if( ep->dimension != level->dimension->id ) continue; - if( sp == ep ) break; + if( ep->connection == nullptr ) continue; + INetworkPlayer *thisPlayer = ep->connection->getNetworkPlayer(); + if( thisPlayer == nullptr ) continue; - if(sp->connection == nullptr) continue; - INetworkPlayer *otherPlayer = sp->connection->getNetworkPlayer(); - if( otherPlayer != nullptr && thisPlayer->IsSameSystem(otherPlayer) ) + bool addPlayer = false; + for (unsigned int j = 0; j < movedPlayers.size(); j++) { - addPlayer = true; - break; + shared_ptr sp = movedPlayers[j]; + + if( sp == ep ) break; + + if(sp->connection == nullptr) continue; + INetworkPlayer *otherPlayer = sp->connection->getNetworkPlayer(); + if( otherPlayer != nullptr && thisPlayer->IsSameSystem(otherPlayer) ) + { + addPlayer = true; + break; + } } - } - if( addPlayer ) movedPlayers.push_back( ep ); + if( addPlayer ) movedPlayers.push_back( ep ); + } } for (unsigned int i = 0; i < movedPlayers.size(); i++) diff --git a/Minecraft.Client/TrackedEntity.cpp b/Minecraft.Client/TrackedEntity.cpp index 3ecd6678..44536b62 100644 --- a/Minecraft.Client/TrackedEntity.cpp +++ b/Minecraft.Client/TrackedEntity.cpp @@ -23,6 +23,10 @@ #include +#ifdef _WINDOWS64 +extern bool g_Win64DedicatedServer; +#endif + TrackedEntity::TrackedEntity(shared_ptr e, int range, int updateInterval, bool trackDelta) { // 4J added initialisers @@ -351,6 +355,19 @@ void TrackedEntity::sendDirtyEntityData() void TrackedEntity::broadcast(shared_ptr packet) { +#ifdef _WINDOWS64 + // On dedicated servers, IsSameSystem() always returns false for remote players + // (no split-screen), so the dedup loop never filters anything. Skip straight + // to sending to all players in seenBy to avoid O(seenBy^2) overhead. + if (g_Win64DedicatedServer) + { + for (auto& player : seenBy) + { + player->connection->send(packet); + } + return; + } +#endif if( Packet::canSendToAnyClient( packet ) ) { // 4J-PB - due to the knockback on a player being hit, we need to send to all players, but limit the network traffic here to players that have not already had it sent to their system @@ -462,7 +479,13 @@ TrackedEntity::eVisibility TrackedEntity::isVisible(EntityTracker *tracker, shar // 4J - added. Try and find other players who are in the same dimension as this one and on the same machine, and extend our visibility // so things are consider visible to this player if they are near the other one. This is because we only send entity tracking info to // players who canReceiveAllPackets(). - if(!bVisible) + // NOTE: On dedicated servers, all real players are remote so IsSameSystem() + // always returns false. Skip this O(players) loop entirely. +#ifdef _WINDOWS64 + if (!bVisible && !g_Win64DedicatedServer) +#else + if (!bVisible) +#endif { MinecraftServer *server = MinecraftServer::getInstance(); INetworkPlayer *thisPlayer = sp->connection->getNetworkPlayer();