Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RemotePlayer: make peer ID always reflect the validity of PlayerSAO #14317

Merged
merged 4 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/network/serverpackethandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
if (playersao->checkMovementCheat()) {
// Call callbacks
m_script->on_cheat(playersao, "moved_too_fast");
SendMovePlayer(pkt->getPeerId());
SendMovePlayer(playersao);
}
}

Expand Down Expand Up @@ -993,7 +993,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
return;
}

playersao->getPlayer()->setWieldIndex(item_i);
player->setWieldIndex(item_i);

// Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
ServerActiveObject *pointed_object = NULL;
Expand Down Expand Up @@ -1161,7 +1161,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
// Get player's wielded item
// See also: Game::handleDigging
ItemStack selected_item, hand_item;
playersao->getPlayer()->getWieldedItem(&selected_item, &hand_item);
player->getWieldedItem(&selected_item, &hand_item);

// Get diggability and expected digging time
DigParams params = getDigParams(m_nodedef->get(n).groups,
Expand Down Expand Up @@ -1253,7 +1253,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
// Do stuff
if (m_script->item_OnSecondaryUse(selected_item, playersao, pointed)) {
if (selected_item.has_value() && playersao->setWieldedItem(*selected_item))
SendInventory(playersao, true);
SendInventory(player, true);
}

pointed_object->rightClick(playersao);
Expand All @@ -1262,7 +1262,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)

// Apply returned ItemStack
if (selected_item.has_value() && playersao->setWieldedItem(*selected_item))
SendInventory(playersao, true);
SendInventory(player, true);
}

if (pointed.type != POINTEDTHING_NODE)
Expand Down Expand Up @@ -1296,7 +1296,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
if (m_script->item_OnUse(selected_item, playersao, pointed)) {
// Apply returned ItemStack
if (selected_item.has_value() && playersao->setWieldedItem(*selected_item))
SendInventory(playersao, true);
SendInventory(player, true);
}

return;
Expand All @@ -1315,7 +1315,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
if (m_script->item_OnSecondaryUse(selected_item, playersao, pointed)) {
// Apply returned ItemStack
if (selected_item.has_value() && playersao->setWieldedItem(*selected_item))
SendInventory(playersao, true);
SendInventory(player, true);
}

return;
Expand Down
5 changes: 5 additions & 0 deletions src/remoteplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef):
m_star_params = SkyboxDefaults::getStarDefaults();
}

RemotePlayer::~RemotePlayer()
{
if (m_sao)
m_sao->setPlayer(nullptr);
}

RemotePlayerChatResult RemotePlayer::canSendChatMessage()
{
Expand Down
3 changes: 2 additions & 1 deletion src/remoteplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class RemotePlayer : public Player

public:
RemotePlayer(const char *name, IItemDefManager *idef);
virtual ~RemotePlayer() = default;
virtual ~RemotePlayer();

PlayerSAO *getPlayerSAO() { return m_sao; }
void setPlayerSAO(PlayerSAO *sao) { m_sao = sao; }
Expand Down Expand Up @@ -135,6 +135,7 @@ class RemotePlayer : public Player
u16 protocol_version = 0;
u16 formspec_version = 0;

/// returns PEER_ID_INEXISTENT when PlayerSAO is not ready
session_t getPeerId() const { return m_peer_id; }

void setPeerId(session_t peer_id) { m_peer_id = peer_id; }
Expand Down
2 changes: 1 addition & 1 deletion src/script/lua_api/l_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ int ObjectRef::l_set_wielded_item(lua_State *L)

bool success = sao->setWieldedItem(item);
if (success && sao->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
getServer(L)->SendInventory((PlayerSAO *)sao, true);
getServer(L)->SendInventory(((PlayerSAO *)sao)->getPlayer(), true);
}
lua_pushboolean(L, success);
return 1;
Expand Down
53 changes: 36 additions & 17 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ Server::~Server()
kick_msg = g_settings->get("kick_msg_shutdown");
}
m_env->saveLoadedPlayers(true);
m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
kick_msg, reconnect);
}

Expand Down Expand Up @@ -590,7 +590,7 @@ void Server::step()
std::string async_err = m_async_fatal_error.get();
if (!async_err.empty()) {
if (!m_simple_singleplayer_mode) {
m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
g_settings->get("kick_msg_crash"),
g_settings->getBool("ask_reconnect_on_crash"));
}
Expand Down Expand Up @@ -1105,7 +1105,7 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
/*
Send complete position information
*/
SendMovePlayer(peer_id);
SendMovePlayer(playersao);

// Send privileges
SendPlayerPrivileges(peer_id);
Expand All @@ -1114,7 +1114,7 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
SendPlayerInventoryFormspec(peer_id);

// Send inventory
SendInventory(playersao, false);
SendInventory(player, false);

// Send HP
SendPlayerHP(playersao, false);
Expand Down Expand Up @@ -1458,10 +1458,8 @@ void Server::SendNodeDef(session_t peer_id,
Non-static send methods
*/

void Server::SendInventory(PlayerSAO *sao, bool incremental)
void Server::SendInventory(RemotePlayer *player, bool incremental)
{
RemotePlayer *player = sao->getPlayer();

// Do not send new format to old clients
incremental &= player->protocol_version >= 38;

Expand All @@ -1471,11 +1469,11 @@ void Server::SendInventory(PlayerSAO *sao, bool incremental)
Serialize it
*/

NetworkPacket pkt(TOCLIENT_INVENTORY, 0, sao->getPeerID());
NetworkPacket pkt(TOCLIENT_INVENTORY, 0, player->getPeerId());

std::ostringstream os(std::ios::binary);
sao->getInventory()->serialize(os, incremental);
sao->getInventory()->setModified(false);
player->inventory.serialize(os, incremental);
player->inventory.setModified(false);
player->setModified(true);

const std::string &s = os.str();
Expand Down Expand Up @@ -1900,17 +1898,12 @@ void Server::SendPlayerBreath(PlayerSAO *sao)
SendBreath(sao->getPeerID(), sao->getBreath());
}

void Server::SendMovePlayer(session_t peer_id)
void Server::SendMovePlayer(PlayerSAO *sao)
{
RemotePlayer *player = m_env->getPlayer(peer_id);
assert(player);
PlayerSAO *sao = player->getPlayerSAO();
assert(sao);

// Send attachment updates instantly to the client prior updating position
sao->sendOutdatedData();

NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, sao->getPeerID());
pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;

{
Expand Down Expand Up @@ -2877,6 +2870,15 @@ void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
DisconnectPeer(peer_id);
}

void Server::kickAllPlayers(AccessDeniedCode reason,
const std::string &str_reason, bool reconnect)
{
std::vector<session_t> clients = m_clients.getClientIDs();
for (const session_t client_id : clients) {
DenyAccess(client_id, reason, str_reason, reconnect);
}
}

void Server::DisconnectPeer(session_t peer_id)
{
m_modchannel_mgr->leaveAllChannels(peer_id);
Expand Down Expand Up @@ -3929,6 +3931,23 @@ PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_v
return NULL;
}

/*
Object construction sequence/hierarchy
--------------------------------------
1. RemoteClient (tightly connection-bound)
2. RemotePlayer (controls, in-game appearance)
3. PlayerSAO (movable object in-game)
PlayerSAO controls the peer_id assignment of RemotePlayer,
indicating whether the player is ready

Destruction sequence
--------------------
1. PlayerSAO pending removal flag
2. PlayerSAO save data before free
3. RemotePlayer, then PlayerSAO freed
4. RemoteClient freed
*/

if (!player) {
player = new RemotePlayer(name, idef());
}
Expand Down
6 changes: 4 additions & 2 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
void DenySudoAccess(session_t peer_id);
void DenyAccess(session_t peer_id, AccessDeniedCode reason,
const std::string &custom_reason = "", bool reconnect = false);
void kickAllPlayers(AccessDeniedCode reason,
const std::string &str_reason, bool reconnect);
void acceptAuth(session_t peer_id, bool forSudoMode);
void DisconnectPeer(session_t peer_id);
bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval);
Expand All @@ -363,8 +365,8 @@ class Server : public con::PeerHandler, public MapEventReceiver,
void HandlePlayerHPChange(PlayerSAO *sao, const PlayerHPChangeReason &reason);
void SendPlayerHP(PlayerSAO *sao, bool effect);
void SendPlayerBreath(PlayerSAO *sao);
void SendInventory(PlayerSAO *playerSAO, bool incremental);
void SendMovePlayer(session_t peer_id);
void SendInventory(RemotePlayer *player, bool incremental);
void SendMovePlayer(PlayerSAO *sao);
void SendMovePlayerRel(session_t peer_id, const v3f &added_pos);
void SendPlayerSpeed(session_t peer_id, const v3f &added_vel);
void SendPlayerFov(session_t peer_id);
Expand Down
45 changes: 26 additions & 19 deletions src/server/player_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p
bool is_singleplayer):
UnitSAO(env_, v3f(0,0,0)),
m_player(player_),
m_peer_id(peer_id_),
m_peer_id_initial(peer_id_),
m_is_singleplayer(is_singleplayer)
{
SANITY_CHECK(m_peer_id != PEER_ID_INEXISTENT);
SANITY_CHECK(m_peer_id_initial != PEER_ID_INEXISTENT);

m_prop.hp_max = PLAYER_MAX_HP_DEFAULT;
m_prop.breath_max = PLAYER_MAX_BREATH_DEFAULT;
Expand Down Expand Up @@ -88,19 +88,22 @@ void PlayerSAO::addedToEnvironment(u32 dtime_s)
ServerActiveObject::addedToEnvironment(dtime_s);
ServerActiveObject::setBasePosition(m_base_position);
m_player->setPlayerSAO(this);
m_player->setPeerId(m_peer_id);
m_player->setPeerId(m_peer_id_initial);
SmallJoker marked this conversation as resolved.
Show resolved Hide resolved
m_peer_id_initial = PEER_ID_INEXISTENT; // don't try to use it again.
m_last_good_position = m_base_position;
}

// Called before removing from environment
void PlayerSAO::removingFromEnvironment()
{
ServerActiveObject::removingFromEnvironment();
if (m_player->getPlayerSAO() == this) {
unlinkPlayerSessionAndSave();
for (u32 attached_particle_spawner : m_attached_particle_spawners) {
m_env->deleteParticleSpawner(attached_particle_spawner, false);
}

// If this fails, fix the ActiveObjectMgr code in ServerEnvironment
SANITY_CHECK(m_player->getPlayerSAO() == this);

unlinkPlayerSessionAndSave();
for (u32 attached_particle_spawner : m_attached_particle_spawners) {
m_env->deleteParticleSpawner(attached_particle_spawner, false);
}
}

Expand Down Expand Up @@ -236,7 +239,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
" is attached to nonexistent parent. This is a bug." << std::endl;
clearParentAttachment();
setBasePosition(m_last_good_position);
m_env->getGameDef()->SendMovePlayer(m_peer_id);
m_env->getGameDef()->SendMovePlayer(this);
}

//dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl;
Expand Down Expand Up @@ -357,14 +360,14 @@ void PlayerSAO::setPos(const v3f &pos)

// Send mapblock of target location
v3s16 blockpos = v3s16(pos.X / MAP_BLOCKSIZE, pos.Y / MAP_BLOCKSIZE, pos.Z / MAP_BLOCKSIZE);
m_env->getGameDef()->SendBlock(m_peer_id, blockpos);
m_env->getGameDef()->SendBlock(getPeerID(), blockpos);

setBasePosition(pos);
// Movement caused by this command is always valid
m_last_good_position = getBasePosition();
m_move_pool.empty();
m_time_from_last_teleport = 0.0;
m_env->getGameDef()->SendMovePlayer(m_peer_id);
m_env->getGameDef()->SendMovePlayer(this);
}

void PlayerSAO::addPos(const v3f &added_pos)
Expand All @@ -381,14 +384,14 @@ void PlayerSAO::addPos(const v3f &added_pos)
// Send mapblock of target location
v3f pos = getBasePosition() + added_pos;
v3s16 blockpos = v3s16(pos.X / MAP_BLOCKSIZE, pos.Y / MAP_BLOCKSIZE, pos.Z / MAP_BLOCKSIZE);
m_env->getGameDef()->SendBlock(m_peer_id, blockpos);
m_env->getGameDef()->SendBlock(getPeerID(), blockpos);

setBasePosition(pos);
// Movement caused by this command is always valid
m_last_good_position = getBasePosition();
m_move_pool.empty();
m_time_from_last_teleport = 0.0;
m_env->getGameDef()->SendMovePlayerRel(m_peer_id, added_pos);
m_env->getGameDef()->SendMovePlayerRel(getPeerID(), added_pos);
}

void PlayerSAO::moveTo(v3f pos, bool continuous)
Expand All @@ -401,7 +404,7 @@ void PlayerSAO::moveTo(v3f pos, bool continuous)
m_last_good_position = getBasePosition();
m_move_pool.empty();
m_time_from_last_teleport = 0.0;
m_env->getGameDef()->SendMovePlayer(m_peer_id);
m_env->getGameDef()->SendMovePlayer(this);
}

void PlayerSAO::setPlayerYaw(const float yaw)
Expand Down Expand Up @@ -433,7 +436,7 @@ void PlayerSAO::setWantedRange(const s16 range)
void PlayerSAO::setPlayerYawAndSend(const float yaw)
{
setPlayerYaw(yaw);
m_env->getGameDef()->SendMovePlayer(m_peer_id);
m_env->getGameDef()->SendMovePlayer(this);
}

void PlayerSAO::setLookPitch(const float pitch)
Expand All @@ -447,7 +450,7 @@ void PlayerSAO::setLookPitch(const float pitch)
void PlayerSAO::setLookPitchAndSend(const float pitch)
{
setLookPitch(pitch);
m_env->getGameDef()->SendMovePlayer(m_peer_id);
m_env->getGameDef()->SendMovePlayer(this);
}

u32 PlayerSAO::punch(v3f dir,
Expand Down Expand Up @@ -578,16 +581,20 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item)

void PlayerSAO::disconnected()
{
m_peer_id = PEER_ID_INEXISTENT;
markForRemoval();
m_player->setPeerId(PEER_ID_INEXISTENT);
}

session_t PlayerSAO::getPeerID() const
{
// Before adding `this` to the server env, m_player is still nullptr.
return m_player ? m_player->getPeerId() : PEER_ID_INEXISTENT;
}

void PlayerSAO::unlinkPlayerSessionAndSave()
{
assert(m_player->getPlayerSAO() == this);
m_player->setPeerId(PEER_ID_INEXISTENT);
m_env->savePlayer(m_player);
m_player->setPlayerSAO(NULL);
m_env->removePlayer(m_player);
}

Expand Down
5 changes: 3 additions & 2 deletions src/server/player_sao.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ class PlayerSAO : public UnitSAO

void disconnected();

void setPlayer(RemotePlayer *player) { m_player = player; }
RemotePlayer *getPlayer() { return m_player; }
session_t getPeerID() const { return m_peer_id; }
session_t getPeerID() const;

// Cheat prevention

Expand Down Expand Up @@ -193,7 +194,7 @@ class PlayerSAO : public UnitSAO
std::string generateUpdatePhysicsOverrideCommand() const;

RemotePlayer *m_player = nullptr;
session_t m_peer_id = 0;
session_t m_peer_id_initial = 0; ///< only used to initialize RemotePlayer

// Cheat prevention
LagPool m_dig_pool;
Expand Down