diff --git a/Minecraft.Client/PlayerList.cpp b/Minecraft.Client/PlayerList.cpp index ba82ec6ac..8a6b531a5 100644 --- a/Minecraft.Client/PlayerList.cpp +++ b/Minecraft.Client/PlayerList.cpp @@ -496,6 +496,50 @@ void PlayerList::add(shared_ptr player) } } + // Send AddPlayerPackets so all players appear in each other's Tab list + // regardless of render distance. The entity tracking system will send + // another AddPlayerPacket when they enter range, which is handled + // gracefully by putEntity replacing the old entity. + { + PlayerUID xuid = INVALID_XUID; + PlayerUID onlineXuid = INVALID_XUID; +#ifndef MINECRAFT_SERVER_BUILD + xuid = player->getXuid(); + onlineXuid = player->getOnlineXuid(); +#endif + int xp = Mth::floor(player->x * 32.0); + int yp = Mth::floor(player->y * 32.0); + int zp = Mth::floor(player->z * 32.0); + int yRotp = Mth::floor(player->yRot * 256.0f / 360.0f); + int xRotp = Mth::floor(player->xRot * 256.0f / 360.0f); + int yHeadRotp = Mth::floor(player->yHeadRot * 256.0f / 360.0f); + + // Broadcast the new player to all existing players + broadcastAll(std::make_shared(player, xuid, onlineXuid, xp, yp, zp, yRotp, xRotp, yHeadRotp)); + + // Send all existing players to the new player + for (size_t i = 0; i < players.size(); i++) + { + shared_ptr op = players.at(i); + if (op != player && op->connection->getNetworkPlayer()) + { + PlayerUID opXuid = INVALID_XUID; + PlayerUID opOnlineXuid = INVALID_XUID; +#ifndef MINECRAFT_SERVER_BUILD + opXuid = op->getXuid(); + opOnlineXuid = op->getOnlineXuid(); +#endif + int oxp = Mth::floor(op->x * 32.0); + int oyp = Mth::floor(op->y * 32.0); + int ozp = Mth::floor(op->z * 32.0); + int oyRotp = Mth::floor(op->yRot * 256.0f / 360.0f); + int oxRotp = Mth::floor(op->xRot * 256.0f / 360.0f); + int oyHeadRotp = Mth::floor(op->yHeadRot * 256.0f / 360.0f); + player->connection->send(std::make_shared(op, opXuid, opOnlineXuid, oxp, oyp, ozp, oyRotp, oxRotp, oyHeadRotp)); + } + } + } + if(level->isAtLeastOnePlayerSleeping()) { shared_ptr firstSleepingPlayer = nullptr; @@ -528,6 +572,14 @@ if (player->riding != nullptr) level->removeEntityImmediately(player->riding); app.DebugPrintf("removing player mount"); } + // Notify all clients to remove this player entity, not just those who + // had the player in tracking range. This ensures players added to the + // Tab list via the AddPlayerPacket broadcast are properly cleaned up. + { + intArray ids(1); + ids[0] = player->entityId; + broadcastAll(std::make_shared(ids)); + } level->getTracker()->removeEntity(player); level->removeEntity(player); level->getChunkMap()->remove(player);