Method add_pos for object/player (#14126)

This commit is contained in:
sfence 2024-01-01 22:48:56 +01:00 committed by GitHub
parent c9ab61aa8c
commit d0753dddb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 105 additions and 7 deletions

View File

@ -7465,15 +7465,20 @@ child will follow movement and rotation of that bone.
* Sets the position of the object.
* No-op if object is attached.
* `pos` is a vector `{x=num, y=num, z=num}`
* `add_pos(pos)`:
* Changes position by adding to the current position.
* No-op if object is attached.
* `pos` is a vector `{x=num, y=num, z=num}`.
* In comparison to using `set_pos`, `add_pos` will avoid synchronization problems.
* `get_velocity()`: returns the velocity, a vector.
* `add_velocity(vel)`
* Changes velocity by adding to the current velocity.
* `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
* In comparison to using get_velocity, adding the velocity and then using
set_velocity, add_velocity is supposed to avoid synchronization problems.
Additionally, players also do not support set_velocity.
* In comparison to using `get_velocity`, adding the velocity and then using
`set_velocity`, `add_velocity` is supposed to avoid synchronization problems.
Additionally, players also do not support `set_velocity`.
* If object is a player:
* Does not apply during free_move.
* Does not apply during `free_move`.
* Note that since the player speed is normalized at each move step,
increasing e.g. Y velocity beyond what would usually be achieved
(see: physics overrides) will cause existing X/Z velocity to be reduced.

View File

@ -68,3 +68,19 @@ local function run_player_meta_tests(player)
assert(meta:equals(meta2))
end
unittests.register("test_player_meta", run_player_meta_tests, {player=true})
--
-- Player add pos
--
local function run_player_add_pos_tests(player)
local pos = player:get_pos()
player:add_pos(vector.new(0, 1000, 0))
local newpos = player:get_pos()
player:add_pos(vector.new(0, -1000, 0))
local backpos = player:get_pos()
local newdist = vector.distance(pos, newpos)
assert(math.abs(newdist - 1000) <= 1)
assert(vector.distance(pos, backpos) <= 1)
end
unittests.register("test_player_add_pos", run_player_add_pos_tests, {player=true})

View File

@ -196,6 +196,7 @@ public:
void handleCommand_HP(NetworkPacket* pkt);
void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_MovePlayer(NetworkPacket* pkt);
void handleCommand_MovePlayerRel(NetworkPacket* pkt);
void handleCommand_DeathScreen(NetworkPacket* pkt);
void handleCommand_AnnounceMedia(NetworkPacket* pkt);
void handleCommand_Media(NetworkPacket* pkt);

View File

@ -129,6 +129,11 @@ public:
m_position = position;
m_sneak_node_exists = false;
}
inline void addPosition(const v3f &added_pos)
{
m_position += added_pos;
m_sneak_node_exists = false;
}
v3f getPosition() const { return m_position; }

View File

@ -117,13 +117,13 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_SET_SUN", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetSun }, // 0x5a
{ "TOCLIENT_SET_MOON", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetMoon }, // 0x5b
{ "TOCLIENT_SET_STARS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetStars }, // 0x5c
null_command_handler,
{ "TOCLIENT_MOVE_PLAYER_REL", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayerRel }, // 0x5d,
null_command_handler,
null_command_handler,
{ "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61,
{ "TOCLIENT_MINIMAP_MODES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MinimapModes }, // 0x62,
{ "TOCLIENT_SET_LIGHTING", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SetLighting }, // 0x63,
{ "TOCLIENT_SET_LIGHTING", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SetLighting }, // 0x63,
};
const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false };

View File

@ -635,6 +635,17 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
m_client_event_queue.push(event);
}
void Client::handleCommand_MovePlayerRel(NetworkPacket *pkt)
{
v3f added_pos;
*pkt >> added_pos;
LocalPlayer *player = m_env.getLocalPlayer();
assert(player);
player->addPosition(added_pos);
}
void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
{
bool set_camera_point_target;

View File

@ -221,6 +221,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
[scheduled bump for 5.8.0]
PROTOCOL VERSION 44:
AO_CMD_SET_BONE_POSITION extended
Add TOCLIENT_MOVE_PLAYER_REL
[scheduled bump for 5.9.0]
*/
@ -835,6 +836,11 @@ enum ToClientCommand
f32 day_opacity
*/
TOCLIENT_MOVE_PLAYER_REL = 0x5d,
/*
v3f added_pos
*/
TOCLIENT_SRP_BYTES_S_B = 0x60,
/*
Belonging to AUTH_MECHANISM_SRP.

View File

@ -134,6 +134,21 @@ int ObjectRef::l_set_pos(lua_State *L)
return 0;
}
// add_pos(self, pos)
int ObjectRef::l_add_pos(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
ServerActiveObject *sao = getobject(ref);
if (sao == nullptr)
return 0;
v3f pos = checkFloatPos(L, 2);
sao->addPos(pos);
return 0;
}
// move_to(self, pos, continuous)
int ObjectRef::l_move_to(lua_State *L)
{
@ -2597,6 +2612,7 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, remove),
luamethod_aliased(ObjectRef, get_pos, getpos),
luamethod_aliased(ObjectRef, set_pos, setpos),
luamethod(ObjectRef, add_pos),
luamethod_aliased(ObjectRef, move_to, moveto),
luamethod(ObjectRef, punch),
luamethod(ObjectRef, right_click),

View File

@ -73,6 +73,9 @@ private:
// set_pos(self, pos)
static int l_set_pos(lua_State *L);
// add_pos(self, pos)
static int l_add_pos(lua_State *L);
// move_to(self, pos, continuous)
static int l_move_to(lua_State *L);

View File

@ -1961,6 +1961,13 @@ void Server::SendMovePlayer(session_t peer_id)
Send(&pkt);
}
void Server::SendMovePlayerRel(session_t peer_id, const v3f &added_pos)
{
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER_REL, 0, peer_id);
pkt << added_pos;
Send(&pkt);
}
void Server::SendPlayerFov(session_t peer_id)
{
NetworkPacket pkt(TOCLIENT_FOV, 4 + 1 + 4, peer_id);

View File

@ -364,6 +364,7 @@ public:
void SendPlayerBreath(PlayerSAO *sao);
void SendInventory(PlayerSAO *playerSAO, bool incremental);
void SendMovePlayer(session_t peer_id);
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);

View File

@ -352,7 +352,7 @@ void PlayerSAO::setBasePosition(v3f position)
void PlayerSAO::setPos(const v3f &pos)
{
if(isAttached())
if (isAttached())
return;
// Send mapblock of target location
@ -367,6 +367,30 @@ void PlayerSAO::setPos(const v3f &pos)
m_env->getGameDef()->SendMovePlayer(m_peer_id);
}
void PlayerSAO::addPos(const v3f &added_pos)
{
if (isAttached())
return;
// Backward compatibility for older clients
if (m_player->protocol_version < 44) {
setPos(getBasePosition() + added_pos);
return;
}
// 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);
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);
}
void PlayerSAO::moveTo(v3f pos, bool continuous)
{
if(isAttached())

View File

@ -90,6 +90,7 @@ public:
void step(float dtime, bool send_recommended) override;
void setBasePosition(v3f position);
void setPos(const v3f &pos) override;
void addPos(const v3f &added_pos) override;
void moveTo(v3f pos, bool continuous) override;
void setPlayerYaw(const float yaw);
// Data should not be sent at player initialization

View File

@ -91,6 +91,8 @@ public:
virtual void setPos(const v3f &pos)
{ setBasePosition(pos); }
virtual void addPos(const v3f &added_pos)
{ setBasePosition(m_base_position + added_pos); }
// continuous: if true, object does not stop immediately at pos
virtual void moveTo(v3f pos, bool continuous)
{ setBasePosition(pos); }