aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/PlayerList.cpp
diff options
context:
space:
mode:
authordaoge <3523206925@qq.com>2026-03-03 03:04:10 +0800
committerGitHub <noreply@github.com>2026-03-03 03:04:10 +0800
commitb3feddfef372618c8a9d7a0abcaf18cfad866c18 (patch)
tree267761c3bb39241ba5c347bfbe2254d06686e287 /Minecraft.Client/PlayerList.cpp
parent84c31a2331f7a0ec85b9d438992e244f60e5020f (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.cpp851
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