diff options
| author | daoge <3523206925@qq.com> | 2026-03-03 03:04:10 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-03 03:04:10 +0800 |
| commit | b3feddfef372618c8a9d7a0abcaf18cfad866c18 (patch) | |
| tree | 267761c3bb39241ba5c347bfbe2254d06686e287 /Minecraft.Client/PlayerList.cpp | |
| parent | 84c31a2331f7a0ec85b9d438992e244f60e5020f (diff) | |
feat: TU19 (Dec 2014) Features & Content (#155)
* try to resolve merge conflict
* feat: TU19 (Dec 2014) Features & Content (#32)
* December 2014 files
* Working release build
* Fix compilation issues
* Add sound to Windows64Media
* Add DLC content and force Tutorial DLC
* Revert "Add DLC content and force Tutorial DLC"
This reverts commit 97a43994725008e35fceb984d5549df9c8cea470.
* Disable broken light packing
* Disable breakpoint during DLC texture map load
Allows DLC loading but the DLC textures are still broken
* Fix post build not working
* ...
* fix vs2022 build
* fix cmake build
---------
Co-authored-by: Loki <lokirautio@gmail.com>
Diffstat (limited to 'Minecraft.Client/PlayerList.cpp')
| -rw-r--r-- | Minecraft.Client/PlayerList.cpp | 851 |
1 files changed, 507 insertions, 344 deletions
diff --git a/Minecraft.Client/PlayerList.cpp b/Minecraft.Client/PlayerList.cpp index 7921cbf8..9fbef2a2 100644 --- a/Minecraft.Client/PlayerList.cpp +++ b/Minecraft.Client/PlayerList.cpp @@ -24,6 +24,7 @@ #include "..\Minecraft.World\net.minecraft.world.level.storage.h" #include "..\Minecraft.World\net.minecraft.world.level.saveddata.h" #include "..\Minecraft.World\JavaMath.h" +#include "..\Minecraft.World\EntityIO.h" #ifdef _XBOX #include "Xbox\Network\NetworkPlayerXbox.h" #elif defined(__PS3__) || defined(__ORBIS__) @@ -36,7 +37,7 @@ PlayerList::PlayerList(MinecraftServer *server) { playerIo = NULL; - this->server = server; + this->server = server; sendAllPlayerInfoIn = 0; overrideGameMode = NULL; @@ -50,11 +51,11 @@ PlayerList::PlayerList(MinecraftServer *server) viewDistance = 10; #endif - //int viewDistance = server->settings->getInt(L"view-distance", 10); + //int viewDistance = server->settings->getInt(L"view-distance", 10); + + maxPlayers = server->settings->getInt(L"max-players", 20); + doWhiteList = false; - maxPlayers = server->settings->getInt(L"max-players", 20); - doWhiteList = false; - InitializeCriticalSection(&m_kickPlayersCS); InitializeCriticalSection(&m_closePlayersCS); } @@ -74,190 +75,236 @@ PlayerList::~PlayerList() void PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer> player, shared_ptr<LoginPacket> packet) { - bool newPlayer = load(player); - player->setLevel(server->getLevel(player->dimension)); - player->gameMode->setLevel((ServerLevel *) player->level); + CompoundTag *playerTag = load(player); - // Make sure these privileges are always turned off for the host player - INetworkPlayer *networkPlayer = connection->getSocket()->getPlayer(); - if(networkPlayer != NULL && networkPlayer->IsHost()) - { - player->enableAllPlayerPrivileges(true); - player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_HOST,1); - } + bool newPlayer = playerTag == NULL; + + player->setLevel(server->getLevel(player->dimension)); + player->gameMode->setLevel((ServerLevel *)player->level); + + // Make sure these privileges are always turned off for the host player + INetworkPlayer *networkPlayer = connection->getSocket()->getPlayer(); + if(networkPlayer != NULL && networkPlayer->IsHost()) + { + player->enableAllPlayerPrivileges(true); + player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_HOST,1); + } #if defined(__PS3__) || defined(__ORBIS__) - // PS3 networking library doesn't automatically assign PlayerUIDs to the network players for anything remote, so need to tell it what to set from the data in this packet now - if( !g_NetworkManager.IsLocalGame() ) + // PS3 networking library doesn't automatically assign PlayerUIDs to the network players for anything remote, so need to tell it what to set from the data in this packet now + if( !g_NetworkManager.IsLocalGame() ) + { + if( networkPlayer != NULL ) { - if( networkPlayer != NULL ) - { - ((NetworkPlayerSony *)networkPlayer)->SetUID( packet->m_onlineXuid ); - } + ((NetworkPlayerSony *)networkPlayer)->SetUID( packet->m_onlineXuid ); } + } #endif - // 4J Stu - TU-1 hotfix - // Fix for #13150 - When a player loads/joins a game after saving/leaving in the nether, sometimes they are spawned on top of the nether and cannot mine down - validatePlayerSpawnPosition(player); + // 4J Stu - TU-1 hotfix + // Fix for #13150 - When a player loads/joins a game after saving/leaving in the nether, sometimes they are spawned on top of the nether and cannot mine down + validatePlayerSpawnPosition(player); -// logger.info(getName() + " logged in with entity id " + playerEntity.entityId + " at (" + playerEntity.x + ", " + playerEntity.y + ", " + playerEntity.z + ")"); + // logger.info(getName() + " logged in with entity id " + playerEntity.entityId + " at (" + playerEntity.x + ", " + playerEntity.y + ", " + playerEntity.z + ")"); - ServerLevel *level = server->getLevel(player->dimension); + ServerLevel *level = server->getLevel(player->dimension); - DWORD playerIndex = 0; + DWORD playerIndex = 0; + { + bool usedIndexes[MINECRAFT_NET_MAX_PLAYERS]; + ZeroMemory( &usedIndexes, MINECRAFT_NET_MAX_PLAYERS * sizeof(bool) ); + for(AUTO_VAR(it, players.begin()); it < players.end(); ++it) { - bool usedIndexes[MINECRAFT_NET_MAX_PLAYERS]; - ZeroMemory( &usedIndexes, MINECRAFT_NET_MAX_PLAYERS * sizeof(bool) ); - for(AUTO_VAR(it, players.begin()); it < players.end(); ++it) - { - usedIndexes[ (int)(*it)->getPlayerIndex() ] = true; - } - for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + usedIndexes[ (int)(*it)->getPlayerIndex() ] = true; + } + for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if(!usedIndexes[i]) { - if(!usedIndexes[i]) - { - playerIndex = i; - break; - } + playerIndex = i; + break; } } - player->setPlayerIndex( playerIndex ); - player->setCustomSkin( packet->m_playerSkinId ); - player->setCustomCape( packet->m_playerCapeId ); + } + player->setPlayerIndex( playerIndex ); + player->setCustomSkin( packet->m_playerSkinId ); + player->setCustomCape( packet->m_playerCapeId ); - // 4J-JEV: Moved this here so we can send player-model texture and geometry data. - shared_ptr<PlayerConnection> playerConnection = shared_ptr<PlayerConnection>(new PlayerConnection(server, connection, player)); - //player->connection = playerConnection; // Used to be assigned in PlayerConnection ctor but moved out so we can use shared_ptr + // 4J-JEV: Moved this here so we can send player-model texture and geometry data. + shared_ptr<PlayerConnection> playerConnection = shared_ptr<PlayerConnection>(new PlayerConnection(server, connection, player)); + //player->connection = playerConnection; // Used to be assigned in PlayerConnection ctor but moved out so we can use shared_ptr - if(newPlayer) - { - int mapScale = 3; + if(newPlayer) + { + int mapScale = 3; #ifdef _LARGE_WORLDS - int scale = MapItemSavedData::MAP_SIZE * 2 * (1 << mapScale); - int centreXC = (int) (Math::round(player->x / scale) * scale); - int centreZC = (int) (Math::round(player->z / scale) * scale); + int scale = MapItemSavedData::MAP_SIZE * 2 * (1 << mapScale); + int centreXC = (int) (Math::round(player->x / scale) * scale); + int centreZC = (int) (Math::round(player->z / scale) * scale); #else - // 4J-PB - for Xbox maps, we'll centre them on the origin of the world, since we can fit the whole world in our map - int centreXC = 0; - int centreZC = 0; + // 4J-PB - for Xbox maps, we'll centre them on the origin of the world, since we can fit the whole world in our map + int centreXC = 0; + int centreZC = 0; #endif - // 4J Added - Give every player a map the first time they join a server - player->inventory->setItem( 9, shared_ptr<ItemInstance>( new ItemInstance(Item::map_Id, 1, level->getAuxValueForMap(player->getXuid(),0,centreXC, centreZC, mapScale ) ) ) ); - if(app.getGameRuleDefinitions() != NULL) - { - app.getGameRuleDefinitions()->postProcessPlayer(player); - } + // 4J Added - Give every player a map the first time they join a server + player->inventory->setItem( 9, shared_ptr<ItemInstance>( new ItemInstance(Item::map_Id, 1, level->getAuxValueForMap(player->getXuid(),0,centreXC, centreZC, mapScale ) ) ) ); + if(app.getGameRuleDefinitions() != NULL) + { + app.getGameRuleDefinitions()->postProcessPlayer(player); } + } - if(!player->customTextureUrl.empty() && player->customTextureUrl.substr(0,3).compare(L"def") != 0 && !app.IsFileInMemoryTextures(player->customTextureUrl)) + if(!player->customTextureUrl.empty() && player->customTextureUrl.substr(0,3).compare(L"def") != 0 && !app.IsFileInMemoryTextures(player->customTextureUrl)) + { + if( server->getConnection()->addPendingTextureRequest(player->customTextureUrl)) { - if( server->getConnection()->addPendingTextureRequest(player->customTextureUrl)) - { #ifndef _CONTENT_PACKAGE - wprintf(L"Sending texture packet to get custom skin %ls from player %ls\n",player->customTextureUrl.c_str(), player->name.c_str()); + wprintf(L"Sending texture packet to get custom skin %ls from player %ls\n",player->customTextureUrl.c_str(), player->name.c_str()); #endif - playerConnection->send(shared_ptr<TextureAndGeometryPacket>( new TextureAndGeometryPacket(player->customTextureUrl,NULL,0) ) ); - } - } - else if(!player->customTextureUrl.empty() && app.IsFileInMemoryTextures(player->customTextureUrl)) - { - // Update the ref count on the memory texture data - app.AddMemoryTextureFile(player->customTextureUrl,NULL,0); + playerConnection->send(shared_ptr<TextureAndGeometryPacket>( new TextureAndGeometryPacket(player->customTextureUrl,NULL,0) ) ); } + } + else if(!player->customTextureUrl.empty() && app.IsFileInMemoryTextures(player->customTextureUrl)) + { + // Update the ref count on the memory texture data + app.AddMemoryTextureFile(player->customTextureUrl,NULL,0); + } - if(!player->customTextureUrl2.empty() && player->customTextureUrl2.substr(0,3).compare(L"def") != 0 && !app.IsFileInMemoryTextures(player->customTextureUrl2)) + if(!player->customTextureUrl2.empty() && player->customTextureUrl2.substr(0,3).compare(L"def") != 0 && !app.IsFileInMemoryTextures(player->customTextureUrl2)) + { + if( server->getConnection()->addPendingTextureRequest(player->customTextureUrl2)) { - if( server->getConnection()->addPendingTextureRequest(player->customTextureUrl2)) - { #ifndef _CONTENT_PACKAGE - wprintf(L"Sending texture packet to get custom skin %ls from player %ls\n",player->customTextureUrl2.c_str(), player->name.c_str()); + wprintf(L"Sending texture packet to get custom skin %ls from player %ls\n",player->customTextureUrl2.c_str(), player->name.c_str()); #endif - playerConnection->send(shared_ptr<TexturePacket>( new TexturePacket(player->customTextureUrl2,NULL,0) ) ); - } - } - else if(!player->customTextureUrl2.empty() && app.IsFileInMemoryTextures(player->customTextureUrl2)) - { - // Update the ref count on the memory texture data - app.AddMemoryTextureFile(player->customTextureUrl2,NULL,0); + playerConnection->send(shared_ptr<TexturePacket>( new TexturePacket(player->customTextureUrl2,NULL,0) ) ); } + } + else if(!player->customTextureUrl2.empty() && app.IsFileInMemoryTextures(player->customTextureUrl2)) + { + // Update the ref count on the memory texture data + app.AddMemoryTextureFile(player->customTextureUrl2,NULL,0); + } - player->setIsGuest( packet->m_isGuest ); + player->setIsGuest( packet->m_isGuest ); - Pos *spawnPos = level->getSharedSpawnPos(); + Pos *spawnPos = level->getSharedSpawnPos(); - updatePlayerGameMode(player, nullptr, level); + updatePlayerGameMode(player, nullptr, level); - // Update the privileges with the correct game mode - GameType *gameType = Player::getPlayerGamePrivilege(player->getAllPlayerGamePrivileges(),Player::ePlayerGamePrivilege_CreativeMode) ? GameType::CREATIVE : GameType::SURVIVAL; - gameType = LevelSettings::validateGameType(gameType->getId()); - if (player->gameMode->getGameModeForPlayer() != gameType) - { - player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_CreativeMode,player->gameMode->getGameModeForPlayer()->getId() ); - } + // Update the privileges with the correct game mode + GameType *gameType = Player::getPlayerGamePrivilege(player->getAllPlayerGamePrivileges(),Player::ePlayerGamePrivilege_CreativeMode) ? GameType::CREATIVE : GameType::SURVIVAL; + gameType = LevelSettings::validateGameType(gameType->getId()); + if (player->gameMode->getGameModeForPlayer() != gameType) + { + player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_CreativeMode,player->gameMode->getGameModeForPlayer()->getId() ); + } - //shared_ptr<PlayerConnection> playerConnection = shared_ptr<PlayerConnection>(new PlayerConnection(server, connection, player)); - player->connection = playerConnection; // Used to be assigned in PlayerConnection ctor but moved out so we can use shared_ptr + //shared_ptr<PlayerConnection> playerConnection = shared_ptr<PlayerConnection>(new PlayerConnection(server, connection, player)); + player->connection = playerConnection; // Used to be assigned in PlayerConnection ctor but moved out so we can use shared_ptr - // 4J Added to store UGC settings - playerConnection->m_friendsOnlyUGC = packet->m_friendsOnlyUGC; - playerConnection->m_offlineXUID = packet->m_offlineXuid; - playerConnection->m_onlineXUID = packet->m_onlineXuid; + // 4J Added to store UGC settings + playerConnection->m_friendsOnlyUGC = packet->m_friendsOnlyUGC; + playerConnection->m_offlineXUID = packet->m_offlineXuid; + playerConnection->m_onlineXUID = packet->m_onlineXuid; - // This player is now added to the list, so incrementing this value invalidates all previous PreLogin packets - if(packet->m_friendsOnlyUGC) ++server->m_ugcPlayersVersion; + // This player is now added to the list, so incrementing this value invalidates all previous PreLogin packets + if(packet->m_friendsOnlyUGC) ++server->m_ugcPlayersVersion; - addPlayerToReceiving( player ); + addPlayerToReceiving( player ); - playerConnection->send( shared_ptr<LoginPacket>( new LoginPacket(L"", player->entityId, level->getLevelData()->getGenerator(), level->getSeed(), player->gameMode->getGameModeForPlayer()->getId(), - (byte) level->dimension->id, (byte) level->getMaxBuildHeight(), (byte) getMaxPlayers(), - level->difficulty, TelemetryManager->GetMultiplayerInstanceID(), (BYTE)playerIndex, level->useNewSeaLevel(), player->getAllPlayerGamePrivileges(), - level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale() ) ) ); - playerConnection->send( shared_ptr<SetSpawnPositionPacket>( new SetSpawnPositionPacket(spawnPos->x, spawnPos->y, spawnPos->z) ) ); - playerConnection->send( shared_ptr<PlayerAbilitiesPacket>( new PlayerAbilitiesPacket(&player->abilities)) ); - delete spawnPos; + playerConnection->send( shared_ptr<LoginPacket>( new LoginPacket(L"", player->entityId, level->getLevelData()->getGenerator(), level->getSeed(), player->gameMode->getGameModeForPlayer()->getId(), + (byte) level->dimension->id, (byte) level->getMaxBuildHeight(), (byte) getMaxPlayers(), + level->difficulty, TelemetryManager->GetMultiplayerInstanceID(), (BYTE)playerIndex, level->useNewSeaLevel(), player->getAllPlayerGamePrivileges(), + level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale() ) ) ); + playerConnection->send( shared_ptr<SetSpawnPositionPacket>( new SetSpawnPositionPacket(spawnPos->x, spawnPos->y, spawnPos->z) ) ); + playerConnection->send( shared_ptr<PlayerAbilitiesPacket>( new PlayerAbilitiesPacket(&player->abilities)) ); + playerConnection->send( shared_ptr<SetCarriedItemPacket>( new SetCarriedItemPacket(player->inventory->selected))); + delete spawnPos; - sendLevelInfo(player, level); + updateEntireScoreboard((ServerScoreboard *) level->getScoreboard(), player); - // 4J-PB - removed, since it needs to be localised in the language the client is in - //server->players->broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(L"§e" + playerEntity->name + L" joined the game.") ) ); - broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(player->name, ChatPacket::e_ChatPlayerJoinedGame) ) ); + sendLevelInfo(player, level); - MemSect(14); - add(player); - MemSect(0); + // 4J-PB - removed, since it needs to be localised in the language the client is in + //server->players->broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(L"§e" + playerEntity->name + L" joined the game.") ) ); + broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(player->name, ChatPacket::e_ChatPlayerJoinedGame) ) ); - player->doTick(true, true, false); // 4J - added - force sending of the nearest chunk before the player is teleported, so we have somewhere to arrive on... - playerConnection->teleport(player->x, player->y, player->z, player->yRot, player->xRot); + MemSect(14); + add(player); + MemSect(0); - server->getConnection()->addPlayerConnection(playerConnection); - playerConnection->send( shared_ptr<SetTimePacket>( new SetTimePacket(level->getTime()) ) ); + player->doTick(true, true, false); // 4J - added - force sending of the nearest chunk before the player is teleported, so we have somewhere to arrive on... + playerConnection->teleport(player->x, player->y, player->z, player->yRot, player->xRot); - AUTO_VAR(activeEffects, player->getActiveEffects()); - for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) + server->getConnection()->addPlayerConnection(playerConnection); + playerConnection->send( shared_ptr<SetTimePacket>( new SetTimePacket(level->getGameTime(), level->getDayTime(), level->getGameRules()->getBoolean(GameRules::RULE_DAYLIGHT)) ) ); + + AUTO_VAR(activeEffects, player->getActiveEffects()); + for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) + { + MobEffectInstance *effect = *it; + playerConnection->send(shared_ptr<UpdateMobEffectPacket>( new UpdateMobEffectPacket(player->entityId, effect) ) ); + } + + player->initMenu(); + + if (playerTag != NULL && playerTag->contains(Entity::RIDING_TAG)) + { + // this player has been saved with a mount tag + shared_ptr<Entity> mount = EntityIO::loadStatic(playerTag->getCompound(Entity::RIDING_TAG), level); + if (mount != NULL) { - MobEffectInstance *effect = *it; - playerConnection->send(shared_ptr<UpdateMobEffectPacket>( new UpdateMobEffectPacket(player->entityId, effect) ) ); + mount->forcedLoading = true; + level->addEntity(mount); + player->ride(mount); + mount->forcedLoading = false; } + } - player->initMenu(); - - // If we are joining at the same time as someone in the end on this system is travelling through the win portal, - // then we should set our wonGame flag to true so that respawning works when the EndPoem is closed - INetworkPlayer *thisPlayer = player->connection->getNetworkPlayer(); - if( thisPlayer != NULL ) + // If we are joining at the same time as someone in the end on this system is travelling through the win portal, + // then we should set our wonGame flag to true so that respawning works when the EndPoem is closed + INetworkPlayer *thisPlayer = player->connection->getNetworkPlayer(); + if( thisPlayer != NULL ) + { + for(AUTO_VAR(it, players.begin()); it != players.end(); ++it) { - for(AUTO_VAR(it, players.begin()); it != players.end(); ++it) + shared_ptr<ServerPlayer> servPlayer = *it; + INetworkPlayer *checkPlayer = servPlayer->connection->getNetworkPlayer(); + if(thisPlayer != checkPlayer && checkPlayer != NULL && thisPlayer->IsSameSystem( checkPlayer ) && servPlayer->wonGame ) { - shared_ptr<ServerPlayer> servPlayer = *it; - INetworkPlayer *checkPlayer = servPlayer->connection->getNetworkPlayer(); - if(thisPlayer != checkPlayer && checkPlayer != NULL && thisPlayer->IsSameSystem( checkPlayer ) && servPlayer->wonGame ) - { - player->wonGame = true; - break; - } + player->wonGame = true; + break; } } + } +} + +void PlayerList::updateEntireScoreboard(ServerScoreboard *scoreboard, shared_ptr<ServerPlayer> player) +{ + //unordered_set<Objective *> objectives; + + //for (PlayerTeam team : scoreboard->getPlayerTeams()) + //{ + // player->connection->send( shared_ptr<SetPlayerTeamPacket>(new SetPlayerTeamPacket(team, SetPlayerTeamPacket::METHOD_ADD))); + //} + + //for (int slot = 0; slot < Scoreboard::DISPLAY_SLOTS; slot++) + //{ + // Objective objective = scoreboard->getDisplayObjective(slot); + + // if (objective != NULL && !objectives->contains(objective)) + // { + // vector<shared_ptr<Packet> > *packets = scoreboard->getStartTrackingPackets(objective); + + // for (Packet packet : packets) + // { + // player->connection->send(packet); + // } + + // objectives->add(objective); + // } + //} } void PlayerList::setLevel(ServerLevelArray levels) @@ -280,8 +327,7 @@ int PlayerList::getMaxRange() return PlayerChunkMap::convertChunkRangeToBlock(getViewDistance()); } - // 4J Changed return val to bool to check if new player or loaded player -bool PlayerList::load(shared_ptr<ServerPlayer> player) +CompoundTag *PlayerList::load(shared_ptr<ServerPlayer> player) { return playerIo->load(player); } @@ -301,6 +347,8 @@ void PlayerList::validatePlayerSpawnPosition(shared_ptr<ServerPlayer> player) // Make sure that the player is on the ground, and in the centre x/z of the current column app.DebugPrintf("Original pos is %f, %f, %f in dimension %d\n", player->x, player->y, player->z, player->dimension); + bool spawnForced = player->isRespawnForced(); + double targetX = 0; if(player->x < 0) targetX = Mth::ceil(player->x) - 0.5; else targetX = Mth::floor(player->x) + 0.5; @@ -316,10 +364,10 @@ void PlayerList::validatePlayerSpawnPosition(shared_ptr<ServerPlayer> player) app.DebugPrintf("New pos is %f, %f, %f in dimension %d\n", player->x, player->y, player->z, player->dimension); ServerLevel *level = server->getLevel(player->dimension); - while (level->getCubes(player, player->bb)->size() != 0) + while (level->getCubes(player, player->bb)->size() != 0) { - player->setPos(player->x, player->y + 1, player->z); - } + player->setPos(player->x, player->y + 1, player->z); + } app.DebugPrintf("Final pos is %f, %f, %f in dimension %d\n", player->x, player->y, player->z, player->dimension); // 4J Stu - If we are in the nether and the above while loop has put us above the nether then we have a problem @@ -342,11 +390,11 @@ void PlayerList::validatePlayerSpawnPosition(shared_ptr<ServerPlayer> player) Pos *bedPosition = player->getRespawnPosition(); if (bedPosition != NULL) { - Pos *respawnPosition = Player::checkBedValidRespawnPosition(server->getLevel(player->dimension), bedPosition); + Pos *respawnPosition = Player::checkBedValidRespawnPosition(server->getLevel(player->dimension), bedPosition, spawnForced); if (respawnPosition != NULL) { player->moveTo(respawnPosition->x + 0.5f, respawnPosition->y + 0.1f, respawnPosition->z + 0.5f, 0, 0); - player->setRespawnPosition(bedPosition); + player->setRespawnPosition(bedPosition, spawnForced); } delete bedPosition; } @@ -354,7 +402,7 @@ void PlayerList::validatePlayerSpawnPosition(shared_ptr<ServerPlayer> player) { player->setPos(player->x, player->y + 1, player->z); } - + app.DebugPrintf("Updated pos is %f, %f, %f in dimension %d\n", player->x, player->y, player->z, player->dimension); } } @@ -367,12 +415,12 @@ void PlayerList::add(shared_ptr<ServerPlayer> player) broadcastAll(shared_ptr<PlayerInfoPacket>( new PlayerInfoPacket( player ) ) ); } - players.push_back(player); + players.push_back(player); // 4J Added addPlayerToReceiving(player); - // Ensure the area the player is spawning in is loaded! + // Ensure the area the player is spawning in is loaded! ServerLevel *level = server->getLevel(player->dimension); // 4J Stu - TU-1 hotfix @@ -381,8 +429,8 @@ void PlayerList::add(shared_ptr<ServerPlayer> player) // 4J Stu - Swapped these lines about so that we get the chunk visiblity packet way ahead of all the add tracked entity packets // Fix for #9169 - ART : Sign text is replaced with the words “Awaiting approval”. - changeDimension(player, NULL); - level->addEntity(player); + changeDimension(player, NULL); + level->addEntity(player); for (int i = 0; i < players.size(); i++) { @@ -417,12 +465,20 @@ void PlayerList::move(shared_ptr<ServerPlayer> player) void PlayerList::remove(shared_ptr<ServerPlayer> player) { - save(player); + save(player); //4J Stu - We don't want to save the map data for guests, so when we are sure that the player is gone delete the map if(player->isGuest()) playerIo->deleteMapFilesForPlayer(player); ServerLevel *level = player->getLevel(); - level->removeEntity(player); - level->getChunkMap()->remove(player); + if (player->riding != NULL) + { + // remove mount first because the player unmounts when being + // removed, also remove mount because it's saved in the player's + // save tag + level->removeEntityImmediately(player->riding); + app.DebugPrintf("removing player mount"); + } + level->removeEntity(player); + level->getChunkMap()->remove(player); AUTO_VAR(it, find(players.begin(),players.end(),player)); if( it != players.end() ) { @@ -441,12 +497,12 @@ void PlayerList::remove(shared_ptr<ServerPlayer> player) shared_ptr<ServerPlayer> PlayerList::getPlayerForLogin(PendingConnection *pendingConnection, const wstring& userName, PlayerUID xuid, PlayerUID onlineXuid) { - if (players.size() >= maxPlayers) + if (players.size() >= maxPlayers) { - pendingConnection->disconnect(DisconnectPacket::eDisconnect_ServerFull); - return shared_ptr<ServerPlayer>(); - } - + pendingConnection->disconnect(DisconnectPacket::eDisconnect_ServerFull); + return shared_ptr<ServerPlayer>(); + } + shared_ptr<ServerPlayer> player = shared_ptr<ServerPlayer>(new ServerPlayer(server, server->getLevel(0), userName, new ServerPlayerGameMode(server->getLevel(0)) )); player->gameMode->player = player; // 4J added as had to remove this assignment from ServerPlayer ctor player->setXuid( xuid ); // 4J Added @@ -466,7 +522,7 @@ shared_ptr<ServerPlayer> PlayerList::getPlayerForLogin(PendingConnection *pendin player->gameMode->setGameRules( GameRuleDefinition::generateNewGameRulesInstance(GameRulesInstance::eGameRulesInstanceType_ServerPlayer, serverRuleDefs, pendingConnection->connection) ); } - return player; + return player; } shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlayer, int targetDimension, bool keepAllPlayerData) @@ -525,22 +581,24 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay AUTO_VAR(it, find(players.begin(),players.end(),serverPlayer)); if( it != players.end() ) { - players.erase(it); + players.erase(it); } - server->getLevel(serverPlayer->dimension)->removeEntityImmediately(serverPlayer); + server->getLevel(serverPlayer->dimension)->removeEntityImmediately(serverPlayer); - Pos *bedPosition = serverPlayer->getRespawnPosition(); + Pos *bedPosition = serverPlayer->getRespawnPosition(); + bool spawnForced = serverPlayer->isRespawnForced(); removePlayerFromReceiving(serverPlayer); - serverPlayer->dimension = targetDimension; + serverPlayer->dimension = targetDimension; EDefaultSkins skin = serverPlayer->getPlayerDefaultSkin(); DWORD playerIndex = serverPlayer->getPlayerIndex(); PlayerUID playerXuid = serverPlayer->getXuid(); PlayerUID playerOnlineXuid = serverPlayer->getOnlineXuid(); - - shared_ptr<ServerPlayer> player = shared_ptr<ServerPlayer>(new ServerPlayer(server, server->getLevel(serverPlayer->dimension), serverPlayer->name, new ServerPlayerGameMode(server->getLevel(serverPlayer->dimension)))); + + shared_ptr<ServerPlayer> player = shared_ptr<ServerPlayer>(new ServerPlayer(server, server->getLevel(serverPlayer->dimension), serverPlayer->getName(), new ServerPlayerGameMode(server->getLevel(serverPlayer->dimension)))); + player->connection = serverPlayer->connection; player->restoreFrom(serverPlayer, keepAllPlayerData); if (keepAllPlayerData) { @@ -552,9 +610,8 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay player->setOnlineXuid( playerOnlineXuid ); // 4J Added // 4J Stu - Don't reuse the id. If we do, then the player can be re-added after being removed, but the add packet gets sent before the remove packet - //player->entityId = serverPlayer->entityId; + //player->entityId = serverPlayer->entityId; - player->connection = serverPlayer->connection; player->setPlayerDefaultSkin( skin ); player->setIsGuest( serverPlayer->isGuest() ); player->setPlayerIndex( playerIndex ); @@ -570,7 +627,7 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay addPlayerToReceiving(player); - ServerLevel *level = server->getLevel(serverPlayer->dimension); + ServerLevel *level = server->getLevel(serverPlayer->dimension); // reset the player's game mode (first pick from old, then copy level if // necessary) @@ -582,39 +639,40 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay player->moveTo(serverPlayer->x, serverPlayer->y, serverPlayer->z, serverPlayer->yRot, serverPlayer->xRot); if(bedPosition != NULL) { - player->setRespawnPosition(bedPosition); + player->setRespawnPosition(bedPosition, spawnForced); delete bedPosition; } // Fix for #81759 - TU9: Content: Gameplay: Entering The End Exit Portal replaces the Player's currently held item with the first one from the Quickbar player->inventory->selected = serverPlayer->inventory->selected; } - else if (bedPosition != NULL) + else if (bedPosition != NULL) { - Pos *respawnPosition = Player::checkBedValidRespawnPosition(server->getLevel(serverPlayer->dimension), bedPosition); - if (respawnPosition != NULL) + Pos *respawnPosition = Player::checkBedValidRespawnPosition(server->getLevel(serverPlayer->dimension), bedPosition, spawnForced); + if (respawnPosition != NULL) { - player->moveTo(respawnPosition->x + 0.5f, respawnPosition->y + 0.1f, respawnPosition->z + 0.5f, 0, 0); - player->setRespawnPosition(bedPosition); - } + player->moveTo(respawnPosition->x + 0.5f, respawnPosition->y + 0.1f, respawnPosition->z + 0.5f, 0, 0); + player->setRespawnPosition(bedPosition, spawnForced); + } else { - player->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::NO_RESPAWN_BED_AVAILABLE, 0) ) ); - } + player->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::NO_RESPAWN_BED_AVAILABLE, 0) ) ); + } delete bedPosition; - } + } - // Ensure the area the player is spawning in is loaded! - level->cache->create(((int) player->x) >> 4, ((int) player->z) >> 4); + // Ensure the area the player is spawning in is loaded! + level->cache->create(((int) player->x) >> 4, ((int) player->z) >> 4); - while (!level->getCubes(player, player->bb)->empty()) + while (!level->getCubes(player, player->bb)->empty()) { - player->setPos(player->x, player->y + 1, player->z); - } + player->setPos(player->x, player->y + 1, player->z); + } player->connection->send( shared_ptr<RespawnPacket>( new RespawnPacket((char) player->dimension, player->level->getSeed(), player->level->getMaxBuildHeight(), - player->gameMode->getGameModeForPlayer(), level->difficulty, level->getLevelData()->getGenerator(), - player->level->useNewSeaLevel(), player->entityId, level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale()) ) ); - player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot); + player->gameMode->getGameModeForPlayer(), level->difficulty, level->getLevelData()->getGenerator(), + player->level->useNewSeaLevel(), player->entityId, level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale()) ) ); + player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot); + player->connection->send( shared_ptr<SetExperiencePacket>( new SetExperiencePacket(player->experienceProgress, player->totalExperience, player->experienceLevel)) ); if(keepAllPlayerData) { @@ -629,13 +687,14 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay player->getEntityData()->markDirty(Mob::DATA_EFFECT_COLOR_ID); } - sendLevelInfo(player, level); + sendLevelInfo(player, level); - level->getChunkMap()->add(player); - level->addEntity(player); - players.push_back(player); + level->getChunkMap()->add(player); + level->addEntity(player); + players.push_back(player); - player->initMenu(); + player->initMenu(); + player->setHealth(player->getHealth()); // 4J-JEV - Dying before this point in the tutorial is pretty annoying, // making sure to remove health/hunger and give you back your meat. @@ -650,7 +709,7 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay player->displayClientMessage(IDS_PLAYER_LEFT_END); } - return player; + return player; } @@ -704,7 +763,7 @@ void PlayerList::toggleDimension(shared_ptr<ServerPlayer> player, int targetDime player->getLevel()->getTracker()->removeEntity(player); } - ServerLevel *oldLevel = server->getLevel(player->dimension); + ServerLevel *oldLevel = server->getLevel(player->dimension); // 4J Stu - Do this much earlier so we don't end up unloading chunks in the wrong dimension player->getLevel()->getChunkMap()->remove(player); @@ -718,9 +777,9 @@ void PlayerList::toggleDimension(shared_ptr<ServerPlayer> player, int targetDime player->displayClientMessage(IDS_PLAYER_LEFT_END); } - player->dimension = targetDimension; + player->dimension = targetDimension; - ServerLevel *newLevel = server->getLevel(player->dimension); + ServerLevel *newLevel = server->getLevel(player->dimension); // 4J Stu - Fix for #46423 - TU5: Art: Code: No burning animation visible after entering The Nether while burning player->clearFire(); // Stop burning if travelling through a portal @@ -729,109 +788,129 @@ void PlayerList::toggleDimension(shared_ptr<ServerPlayer> player, int targetDime player->flushEntitiesToRemove(); player->connection->send( shared_ptr<RespawnPacket>( new RespawnPacket((char) player->dimension, newLevel->getSeed(), newLevel->getMaxBuildHeight(), - player->gameMode->getGameModeForPlayer(), newLevel->difficulty, newLevel->getLevelData()->getGenerator(), - newLevel->useNewSeaLevel(), player->entityId, newLevel->getLevelData()->getXZSize(), newLevel->getLevelData()->getHellScale()) ) ); + player->gameMode->getGameModeForPlayer(), newLevel->difficulty, newLevel->getLevelData()->getGenerator(), + newLevel->useNewSeaLevel(), player->entityId, newLevel->getLevelData()->getXZSize(), newLevel->getLevelData()->getHellScale()) ) ); + + oldLevel->removeEntityImmediately(player); + player->removed = false; + + repositionAcrossDimension(player, lastDimension, oldLevel, newLevel); + changeDimension(player, oldLevel); + + player->gameMode->setLevel(newLevel); + + // Resend the teleport if we haven't yet sent the chunk they will land on + if( !g_NetworkManager.SystemFlagGet(player->connection->getNetworkPlayer(),ServerPlayer::getFlagIndexForChunk( ChunkPos(player->xChunk,player->zChunk), player->level->dimension->id ) ) ) + { + player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot, false); + // Force sending of the current chunk + player->doTick(true, true, true); + } - oldLevel->removeEntityImmediately(player); - player->removed = false; + player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot); - double xt = player->x; - double zt = player->z; - double scale = newLevel->getLevelData()->getHellScale(); // 4J Scale was 8 but this is all we can fit in - if (player->dimension == -1) + // 4J Stu - Fix for #64683 - Customer Encountered: TU7: Content: Gameplay: Potion effects are removed after using the Nether Portal + vector<MobEffectInstance *> *activeEffects = player->getActiveEffects(); + for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) { - xt /= scale; - zt /= scale; - player->moveTo(xt, player->y, zt, player->yRot, player->xRot); - if (player->isAlive()) + MobEffectInstance *effect = *it; + + player->connection->send(shared_ptr<UpdateMobEffectPacket>( new UpdateMobEffectPacket(player->entityId, effect) ) ); + } + delete activeEffects; + player->getEntityData()->markDirty(Mob::DATA_EFFECT_COLOR_ID); + + sendLevelInfo(player, newLevel); + sendAllPlayerInfo(player); +} + +void PlayerList::repositionAcrossDimension(shared_ptr<Entity> entity, int lastDimension, ServerLevel *oldLevel, ServerLevel *newLevel) +{ + double xt = entity->x; + double zt = entity->z; + double xOriginal = entity->x; + double yOriginal = entity->y; + double zOriginal = entity->z; + float yRotOriginal = entity->yRot; + double scale = newLevel->getLevelData()->getHellScale(); // 4J Scale was 8 but this is all we can fit in + if (entity->dimension == -1) + { + xt /= scale; + zt /= scale; + entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot); + if (entity->isAlive()) { - oldLevel->tick(player, false); - } - } - else if (player->dimension == 0) - { - xt *= scale; - zt *= scale; - player->moveTo(xt, player->y, zt, player->yRot, player->xRot); - if (player->isAlive()) + oldLevel->tick(entity, false); + } + } + else if (entity->dimension == 0) + { + xt *= scale; + zt *= scale; + entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot); + if (entity->isAlive()) { - oldLevel->tick(player, false); - } - } + oldLevel->tick(entity, false); + } + } else { - Pos *p = newLevel->getDimensionSpecificSpawn(); + Pos *p; + + if (lastDimension == 1) + { + // Coming from the end + p = newLevel->getSharedSpawnPos(); + } + else + { + // Going to the end + p = newLevel->getDimensionSpecificSpawn(); + } xt = p->x; - player->y = p->y; + entity->y = p->y; zt = p->z; delete p; - player->moveTo(xt, player->y, zt, 90, 0); - if (player->isAlive()) + entity->moveTo(xt, entity->y, zt, 90, 0); + if (entity->isAlive()) { - oldLevel->tick(player, false); + oldLevel->tick(entity, false); } } - - removePlayerFromReceiving(player, false, lastDimension); - addPlayerToReceiving(player); - if (lastDimension == 1) + if(entity->GetType() == eTYPE_SERVERPLAYER) { + shared_ptr<ServerPlayer> player = dynamic_pointer_cast<ServerPlayer>(entity); + removePlayerFromReceiving(player, false, lastDimension); + addPlayerToReceiving(player); } - else + + if (lastDimension != 1) { xt = (double) Mth::clamp((int) xt, -Level::MAX_LEVEL_SIZE + 128, Level::MAX_LEVEL_SIZE - 128); zt = (double) Mth::clamp((int) zt, -Level::MAX_LEVEL_SIZE + 128, Level::MAX_LEVEL_SIZE - 128); - if (player->isAlive()) + if (entity->isAlive()) { - newLevel->addEntity(player); - player->moveTo(xt, player->y, zt, player->yRot, player->xRot); - newLevel->tick(player, false); + newLevel->addEntity(entity); + entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot); + newLevel->tick(entity, false); newLevel->cache->autoCreate = true; - (new PortalForcer())->force(newLevel, player); + newLevel->getPortalForcer()->force(entity, xOriginal, yOriginal, zOriginal, yRotOriginal); newLevel->cache->autoCreate = false; } } - - player->setLevel(newLevel); - changeDimension(player, oldLevel); - - player->gameMode->setLevel(newLevel); - - // Resend the teleport if we haven't yet sent the chunk they will land on - if( !g_NetworkManager.SystemFlagGet(player->connection->getNetworkPlayer(),ServerPlayer::getFlagIndexForChunk( ChunkPos(player->xChunk,player->zChunk), player->level->dimension->id ) ) ) - { - player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot, false); - // Force sending of the current chunk - player->doTick(true, true, true); - } - - player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot); - - // 4J Stu - Fix for #64683 - Customer Encountered: TU7: Content: Gameplay: Potion effects are removed after using the Nether Portal - vector<MobEffectInstance *> *activeEffects = player->getActiveEffects(); - for(AUTO_VAR(it, activeEffects->begin()); it != activeEffects->end(); ++it) - { - MobEffectInstance *effect = *it; - - player->connection->send(shared_ptr<UpdateMobEffectPacket>( new UpdateMobEffectPacket(player->entityId, effect) ) ); - } - delete activeEffects; - player->getEntityData()->markDirty(Mob::DATA_EFFECT_COLOR_ID); - - sendLevelInfo(player, newLevel); - sendAllPlayerInfo(player); + entity->setLevel(newLevel); } void PlayerList::tick() { // 4J - brought changes to how often this is sent forward from 1.2.3 - if (++sendAllPlayerInfoIn > SEND_PLAYER_INFO_INTERVAL) + if (++sendAllPlayerInfoIn > SEND_PLAYER_INFO_INTERVAL) { - sendAllPlayerInfoIn = 0; - } + sendAllPlayerInfoIn = 0; + } if (sendAllPlayerInfoIn < players.size()) { @@ -879,7 +958,7 @@ void PlayerList::tick() { if( selectedPlayer->IsLocal() != TRUE ) { -//#ifdef _XBOX + //#ifdef _XBOX PlayerUID xuid = selectedPlayer->GetUID(); // Kick this player from the game shared_ptr<ServerPlayer> player = nullptr; @@ -903,7 +982,7 @@ void PlayerList::tick() player->connection->setWasKicked(); player->connection->send( shared_ptr<DisconnectPacket>( new DisconnectPacket(DisconnectPacket::eDisconnect_Kicked) )); } -//#endif + //#endif } } } @@ -941,31 +1020,31 @@ void PlayerList::prioritiseTileChanges(int x, int y, int z, int dimension) void PlayerList::broadcastAll(shared_ptr<Packet> packet) { - for (unsigned int i = 0; i < players.size(); i++) + for (unsigned int i = 0; i < players.size(); i++) { - shared_ptr<ServerPlayer> player = players[i]; - player->connection->send(packet); - } + shared_ptr<ServerPlayer> player = players[i]; + player->connection->send(packet); + } } void PlayerList::broadcastAll(shared_ptr<Packet> packet, int dimension) { - for (unsigned int i = 0; i < players.size(); i++) + for (unsigned int i = 0; i < players.size(); i++) { - shared_ptr<ServerPlayer> player = players[i]; - if (player->dimension == dimension) player->connection->send(packet); - } + shared_ptr<ServerPlayer> player = players[i]; + if (player->dimension == dimension) player->connection->send(packet); + } } wstring PlayerList::getPlayerNames() { - wstring msg; - for (unsigned int i = 0; i < players.size(); i++) + wstring msg; + for (unsigned int i = 0; i < players.size(); i++) { - if (i > 0) msg += L", "; - msg += players[i]->name; - } - return msg; + if (i > 0) msg += L", "; + msg += players[i]->name; + } + return msg; } bool PlayerList::isWhiteListed(const wstring& name) @@ -991,38 +1070,145 @@ bool PlayerList::isOp(shared_ptr<ServerPlayer> player) shared_ptr<ServerPlayer> PlayerList::getPlayer(const wstring& name) { - for (unsigned int i = 0; i < players.size(); i++) + for (unsigned int i = 0; i < players.size(); i++) { - shared_ptr<ServerPlayer> p = players[i]; - if (p->name == name) // 4J - used to be case insensitive (using equalsIgnoreCase) - imagine we'll be shifting to XUIDs anyway + shared_ptr<ServerPlayer> p = players[i]; + if (p->name == name) // 4J - used to be case insensitive (using equalsIgnoreCase) - imagine we'll be shifting to XUIDs anyway { - return p; - } - } - return nullptr; + return p; + } + } + return nullptr; } // 4J Added shared_ptr<ServerPlayer> PlayerList::getPlayer(PlayerUID uid) { - for (unsigned int i = 0; i < players.size(); i++) + for (unsigned int i = 0; i < players.size(); i++) { - shared_ptr<ServerPlayer> p = players[i]; - if (p->getXuid() == uid || p->getOnlineXuid() == uid) // 4J - used to be case insensitive (using equalsIgnoreCase) - imagine we'll be shifting to XUIDs anyway + shared_ptr<ServerPlayer> p = players[i]; + if (p->getXuid() == uid || p->getOnlineXuid() == uid) // 4J - used to be case insensitive (using equalsIgnoreCase) - imagine we'll be shifting to XUIDs anyway { - return p; - } - } - return nullptr; + return p; + } + } + return nullptr; +} + +shared_ptr<ServerPlayer> PlayerList::getNearestPlayer(Pos *position, int range) +{ + if (players.empty()) return nullptr; + if (position == NULL) return players.at(0); + shared_ptr<ServerPlayer> current = nullptr; + double dist = -1; + int rangeSqr = range * range; + + for (int i = 0; i < players.size(); i++) + { + shared_ptr<ServerPlayer> next = players.at(i); + double newDist = position->distSqr(next->getCommandSenderWorldPosition()); + + if ((dist == -1 || newDist < dist) && (range <= 0 || newDist <= rangeSqr)) + { + dist = newDist; + current = next; + } + } + + return current; +} + +vector<ServerPlayer> *PlayerList::getPlayers(Pos *position, int rangeMin, int rangeMax, int count, int mode, int levelMin, int levelMax, unordered_map<wstring, int> *scoreRequirements, const wstring &playerName, const wstring &teamName, Level *level) +{ + app.DebugPrintf("getPlayers NOT IMPLEMENTED!"); + return NULL; + + /*if (players.empty()) return NULL; + vector<shared_ptr<ServerPlayer> > result = new vector<shared_ptr<ServerPlayer> >(); + bool reverse = count < 0; + bool playerNameNot = !playerName.empty() && playerName.startsWith("!"); + bool teamNameNot = !teamName.empty() && teamName.startsWith("!"); + int rangeMinSqr = rangeMin * rangeMin; + int rangeMaxSqr = rangeMax * rangeMax; + count = Mth.abs(count); + + if (playerNameNot) playerName = playerName.substring(1); + if (teamNameNot) teamName = teamName.substring(1); + + for (int i = 0; i < players.size(); i++) { + ServerPlayer player = players.get(i); + + if (level != null && player.level != level) continue; + if (playerName != null) { + if (playerNameNot == playerName.equalsIgnoreCase(player.getAName())) continue; + } + if (teamName != null) { + Team team = player.getTeam(); + String actualName = team == null ? "" : team.getName(); + if (teamNameNot == teamName.equalsIgnoreCase(actualName)) continue; + } + + if (position != null && (rangeMin > 0 || rangeMax > 0)) { + float distance = position.distSqr(player.getCommandSenderWorldPosition()); + if (rangeMin > 0 && distance < rangeMinSqr) continue; + if (rangeMax > 0 && distance > rangeMaxSqr) continue; + } + + if (!meetsScoreRequirements(player, scoreRequirements)) continue; + + if (mode != GameType.NOT_SET.getId() && mode != player.gameMode.getGameModeForPlayer().getId()) continue; + if (levelMin > 0 && player.experienceLevel < levelMin) continue; + if (player.experienceLevel > levelMax) continue; + + result.add(player); + } + + if (position != null) Collections.sort(result, new PlayerDistanceComparator(position)); + if (reverse) Collections.reverse(result); + if (count > 0) result = result.subList(0, Math.min(count, result.size())); + + return result;*/ +} + +bool PlayerList::meetsScoreRequirements(shared_ptr<Player> player, unordered_map<wstring, int> scoreRequirements) +{ + app.DebugPrintf("meetsScoreRequirements NOT IMPLEMENTED!"); + return false; + + //if (scoreRequirements == null || scoreRequirements.size() == 0) return true; + + //for (Map.Entry<String, Integer> requirement : scoreRequirements.entrySet()) { + // String name = requirement.getKey(); + // boolean min = false; + + // if (name.endsWith("_min") && name.length() > 4) { + // min = true; + // name = name.substring(0, name.length() - 4); + // } + + // Scoreboard scoreboard = player.getScoreboard(); + // Objective objective = scoreboard.getObjective(name); + // if (objective == null) return false; + // Score score = player.getScoreboard().getPlayerScore(player.getAName(), objective); + // int value = score.getScore(); + + // if (value < requirement.getValue() && min) { + // return false; + // } else if (value > requirement.getValue() && !min) { + // return false; + // } + //} + + //return true; } void PlayerList::sendMessage(const wstring& name, const wstring& message) { - shared_ptr<ServerPlayer> player = getPlayer(name); - if (player != NULL) + shared_ptr<ServerPlayer> player = getPlayer(name); + if (player != NULL) { - player->connection->send( shared_ptr<ChatPacket>( new ChatPacket(message) ) ); - } + player->connection->send( shared_ptr<ChatPacket>( new ChatPacket(message) ) ); + } } void PlayerList::broadcast(double x, double y, double z, double range, int dimension, shared_ptr<Packet> packet) @@ -1040,11 +1226,11 @@ void PlayerList::broadcast(shared_ptr<Player> except, double x, double y, double sentTo.push_back(dynamic_pointer_cast<ServerPlayer>(except)); } - for (unsigned int i = 0; i < players.size(); i++) + for (unsigned int i = 0; i < players.size(); i++) { - shared_ptr<ServerPlayer> p = players[i]; - if (p == except) continue; - if (p->dimension != dimension) continue; + shared_ptr<ServerPlayer> p = players[i]; + if (p == except) continue; + if (p->dimension != dimension) continue; // 4J - don't send to the same machine more than once bool dontSend = false; @@ -1074,10 +1260,10 @@ void PlayerList::broadcast(shared_ptr<Player> except, double x, double y, double } - double xd = x - p->x; - double yd = y - p->y; - double zd = z - p->z; - if (xd * xd + yd * yd + zd * zd < range * range) + double xd = x - p->x; + double yd = y - p->y; + double zd = z - p->z; + if (xd * xd + yd * yd + zd * zd < range * range) { #if 0 // _DEBUG shared_ptr<LevelSoundPacket> SoundPacket= dynamic_pointer_cast<LevelSoundPacket>(packet); @@ -1090,35 +1276,11 @@ void PlayerList::broadcast(shared_ptr<Player> except, double x, double y, double app.DebugPrintf("\n"); } #endif - p->connection->send(packet); + p->connection->send(packet); sentTo.push_back( p ); - } - } - -} - -void PlayerList::broadcastToAllOps(const wstring& message) -{ - shared_ptr<Packet> chatPacket = shared_ptr<ChatPacket>( new ChatPacket(message) ); - for (unsigned int i = 0; i < players.size(); i++) - { - shared_ptr<ServerPlayer> p = players[i]; - if (isOp(p->name)) - { - p->connection->send(chatPacket); - } - } -} + } + } -bool PlayerList::sendTo(const wstring& name, shared_ptr<Packet> packet) -{ - shared_ptr<ServerPlayer> player = getPlayer(name); - if (player != NULL) - { - player->connection->send(packet); - return true; - } - return false; } void PlayerList::saveAll(ProgressListener *progressListener, bool bDeleteGuestMaps /*= false*/) @@ -1131,7 +1293,7 @@ void PlayerList::saveAll(ProgressListener *progressListener, bool bDeleteGuestMa for (unsigned int i = 0; i < players.size(); i++) { playerIo->save(players[i]); - + //4J Stu - We don't want to save the map data for guests, so when we are sure that the player is gone delete the map if(bDeleteGuestMaps && players[i]->isGuest()) playerIo->deleteMapFilesForPlayer(players[i]); @@ -1156,16 +1318,16 @@ void PlayerList::reloadWhitelist() void PlayerList::sendLevelInfo(shared_ptr<ServerPlayer> player, ServerLevel *level) { - player->connection->send( shared_ptr<SetTimePacket>( new SetTimePacket(level->getTime()) ) ); - if (level->isRaining()) + player->connection->send( shared_ptr<SetTimePacket>( new SetTimePacket(level->getGameTime(), level->getDayTime(), level->getGameRules()->getBoolean(GameRules::RULE_DAYLIGHT)) ) ); + if (level->isRaining()) { - player->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::START_RAINING, 0) ) ); - } + player->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::START_RAINING, 0) ) ); + } else { // 4J Stu - Fix for #44836 - Customer Encountered: Out of Sync Weather [A-10] // If it was raining when the player left the level, and is now not raining we need to make sure that state is updated - player->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::STOP_RAINING, 0) ) ); + player->connection->send( shared_ptr<GameEventPacket>( new GameEventPacket(GameEventPacket::STOP_RAINING, 0) ) ); } // send the stronghold position if there is one @@ -1177,8 +1339,9 @@ void PlayerList::sendLevelInfo(shared_ptr<ServerPlayer> player, ServerLevel *lev void PlayerList::sendAllPlayerInfo(shared_ptr<ServerPlayer> player) { - player->refreshContainer(player->inventoryMenu); - player->resetSentInfo(); + player->refreshContainer(player->inventoryMenu); + player->resetSentInfo(); + player->connection->send( shared_ptr<SetCarriedItemPacket>( new SetCarriedItemPacket(player->inventory->selected)) ); } int PlayerList::getPlayerCount() @@ -1215,7 +1378,7 @@ int PlayerList::getViewDistance() void PlayerList::setOverrideGameMode(GameType *gameMode) { - this->overrideGameMode = gameMode; + overrideGameMode = gameMode; } void PlayerList::updatePlayerGameMode(shared_ptr<ServerPlayer> newPlayer, shared_ptr<ServerPlayer> oldPlayer, Level *level) @@ -1389,7 +1552,7 @@ void PlayerList::addPlayerToReceiving(shared_ptr<ServerPlayer> player) } } } - + if( shouldAddPlayer ) { #ifndef _CONTENT_PACKAGE |
