aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt8
-rw-r--r--src/client/client.h1
-rw-r--r--src/client/localplayer.cpp10
-rw-r--r--src/client/localplayer.h6
-rw-r--r--src/content_sao.cpp25
-rw-r--r--src/content_sao.h3
-rw-r--r--src/network/clientopcodes.cpp2
-rw-r--r--src/network/clientpackethandler.cpp11
-rw-r--r--src/network/networkprotocol.h6
-rw-r--r--src/network/serveropcodes.cpp2
-rw-r--r--src/script/lua_api/l_object.cpp22
-rw-r--r--src/script/lua_api/l_object.h3
-rw-r--r--src/server.cpp7
-rw-r--r--src/server.h1
14 files changed, 105 insertions, 2 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 840841e6b..9fd2ba3f5 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -5465,6 +5465,14 @@ This is basically a reference to a C++ `ServerActiveObject`
* `get_player_name()`: returns `""` if is not a player
* `get_player_velocity()`: returns `nil` if is not a player, otherwise a
table {x, y, z} representing the player's instantaneous velocity in nodes/s
+* `add_player_velocity(vel)`
+ * Adds to player velocity, this happens client-side and only once.
+ * 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.
+ * Example: `add_player_velocity({x=0, y=6.5, z=0})` is equivalent to
+ pressing the jump key (assuming default settings)
* `get_look_dir()`: get camera direction as a unit vector
* `get_look_vertical()`: pitch in radians
* Angle ranges between -pi/2 and pi/2, which are straight up and down
diff --git a/src/client/client.h b/src/client/client.h
index 15a4689c1..3bfb1631e 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -227,6 +227,7 @@ public:
void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
+ void handleCommand_PlayerSpeed(NetworkPacket *pkt);
void ProcessData(NetworkPacket *pkt);
diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp
index 0e273a16a..c356f7c24 100644
--- a/src/client/localplayer.cpp
+++ b/src/client/localplayer.cpp
@@ -188,6 +188,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
// Copy parent position if local player is attached
if (isAttached) {
setPosition(overridePosition);
+ added_velocity = v3f(); // ignored
return;
}
@@ -201,9 +202,13 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
if (noclip && free_move) {
position += m_speed * dtime;
setPosition(position);
+ added_velocity = v3f(); // ignored
return;
}
+ m_speed += added_velocity;
+ added_velocity = v3f();
+
/*
Collision detection
*/
@@ -782,6 +787,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
if (isAttached) {
setPosition(overridePosition);
m_sneak_node_exists = false;
+ added_velocity = v3f();
return;
}
@@ -795,9 +801,13 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
position += m_speed * dtime;
setPosition(position);
m_sneak_node_exists = false;
+ added_velocity = v3f();
return;
}
+ m_speed += added_velocity;
+ added_velocity = v3f();
+
/*
Collision detection
*/
diff --git a/src/client/localplayer.h b/src/client/localplayer.h
index 84cfa583a..16e7996ae 100644
--- a/src/client/localplayer.h
+++ b/src/client/localplayer.h
@@ -149,6 +149,11 @@ public:
bool getAutojump() const { return m_autojump; }
+ inline void addVelocity(const v3f &vel)
+ {
+ added_velocity += vel;
+ }
+
private:
void accelerate(const v3f &target_speed, const f32 max_increase_H,
const f32 max_increase_V, const bool use_pitch);
@@ -194,6 +199,7 @@ private:
float m_zoom_fov = 0.0f;
bool m_autojump = false;
float m_autojump_time = 0.0f;
+ v3f added_velocity = v3f(0.0f, 0.0f, 0.0f); // cleared on each move()
GenericCAO *m_cao = nullptr;
Client *m_client;
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 0f1e2f435..de300481f 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -1091,6 +1091,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_time_from_last_teleport += dtime;
m_time_from_last_punch += dtime;
m_nocheat_dig_time += dtime;
+ m_max_speed_override_time = MYMAX(m_max_speed_override_time - dtime, 0.0f);
// Each frame, parent position is copied if the object is attached,
// otherwise it's calculated normally.
@@ -1412,6 +1413,19 @@ std::string PlayerSAO::getPropertyPacket()
return gob_cmd_set_properties(m_prop);
}
+void PlayerSAO::setMaxSpeedOverride(const v3f &vel)
+{
+ if (m_max_speed_override_time == 0.0f)
+ m_max_speed_override = vel;
+ else
+ m_max_speed_override += vel;
+ if (m_player) {
+ float accel = MYMIN(m_player->movement_acceleration_default,
+ m_player->movement_acceleration_air);
+ m_max_speed_override_time = m_max_speed_override.getLength() / accel / BS;
+ }
+}
+
bool PlayerSAO::checkMovementCheat()
{
if (isAttached() || m_is_singleplayer ||
@@ -1431,6 +1445,14 @@ bool PlayerSAO::checkMovementCheat()
too, and much more lightweight.
*/
+ float override_max_H, override_max_V;
+ if (m_max_speed_override_time > 0.0f) {
+ override_max_H = MYMAX(fabs(m_max_speed_override.X), fabs(m_max_speed_override.Z));
+ override_max_V = fabs(m_max_speed_override.Y);
+ } else {
+ override_max_H = override_max_V = 0.0f;
+ }
+
float player_max_walk = 0; // horizontal movement
float player_max_jump = 0; // vertical upwards movement
@@ -1439,10 +1461,13 @@ bool PlayerSAO::checkMovementCheat()
else
player_max_walk = m_player->movement_speed_walk; // Normal speed
player_max_walk *= m_physics_override_speed;
+ player_max_walk = MYMAX(player_max_walk, override_max_H);
+
player_max_jump = m_player->movement_speed_jump * m_physics_override_jump;
// FIXME: Bouncy nodes cause practically unbound increase in Y speed,
// until this can be verified correctly, tolerate higher jumping speeds
player_max_jump *= 2.0;
+ player_max_jump = MYMAX(player_max_jump, override_max_V);
// Don't divide by zero!
if (player_max_walk < 0.0001f)
diff --git a/src/content_sao.h b/src/content_sao.h
index beaf697e6..2dd839e11 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -322,6 +322,7 @@ public:
{
return m_dig_pool;
}
+ void setMaxSpeedOverride(const v3f &vel);
// Returns true if cheated
bool checkMovementCheat();
@@ -361,6 +362,8 @@ private:
float m_time_from_last_punch = 0.0f;
v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
float m_nocheat_dig_time = 0.0f;
+ float m_max_speed_override_time = 0.0f;
+ v3f m_max_speed_override = v3f(0.0f, 0.0f, 0.0f);
// Timers
IntervalLimiter m_breathing_interval;
diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp
index 7f3ab50ed..8641cadec 100644
--- a/src/network/clientopcodes.cpp
+++ b/src/network/clientopcodes.cpp
@@ -67,7 +67,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
null_command_handler,
{ "TOCLIENT_TIME_OF_DAY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_TimeOfDay }, // 0x29
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CSMRestrictionFlags }, // 0x2A
- null_command_handler,
+ { "TOCLIENT_PLAYER_SPEED", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_PlayerSpeed }, // 0x2B
null_command_handler,
null_command_handler,
null_command_handler,
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 1ae47d190..520fcfa81 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -1383,6 +1383,17 @@ void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt)
loadMods();
}
+void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
+{
+ v3f added_vel;
+
+ *pkt >> added_vel;
+
+ LocalPlayer *player = m_env.getLocalPlayer();
+ assert(player != NULL);
+ player->addVelocity(added_vel);
+}
+
/*
* Mod channels
*/
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 0ab11ee7e..451518bbf 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -194,6 +194,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
New network float format
ContentFeatures version 13
Add full Euler rotations instead of just yaw
+ Add TOCLIENT_PLAYER_SPEED
*/
#define LATEST_PROTOCOL_VERSION 37
@@ -295,6 +296,11 @@ enum ToClientCommand
u32 CSMRestrictionFlags byteflag
*/
+ TOCLIENT_PLAYER_SPEED = 0x2B,
+ /*
+ v3f added_vel
+ */
+
// (oops, there is some gap here)
TOCLIENT_CHAT_MESSAGE = 0x2F,
diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp
index 013b549c6..8c5579a36 100644
--- a/src/network/serveropcodes.cpp
+++ b/src/network/serveropcodes.cpp
@@ -156,7 +156,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
null_command_factory,
{ "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", 0, true }, // 0x2A
- null_command_factory,
+ { "TOCLIENT_PLAYER_SPEED", 0, true }, // 0x2B
null_command_factory,
null_command_factory,
null_command_factory,
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 5dba63159..be2172f1b 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -1092,6 +1092,27 @@ int ObjectRef::l_get_player_velocity(lua_State *L)
return 1;
}
+// add_player_velocity(self, {x=num, y=num, z=num})
+int ObjectRef::l_add_player_velocity(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ v3f vel = checkFloatPos(L, 2);
+
+ RemotePlayer *player = getplayer(ref);
+ PlayerSAO *co = getplayersao(ref);
+ if (!player || !co)
+ return 0;
+
+ session_t peer_id = player->getPeerId();
+ if (peer_id == PEER_ID_INEXISTENT)
+ return 0;
+ // Do it
+ co->setMaxSpeedOverride(vel);
+ getServer(L)->SendPlayerSpeed(peer_id, vel);
+ return 0;
+}
+
// get_look_dir(self)
int ObjectRef::l_get_look_dir(lua_State *L)
{
@@ -1931,6 +1952,7 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, is_player_connected),
luamethod(ObjectRef, get_player_name),
luamethod(ObjectRef, get_player_velocity),
+ luamethod(ObjectRef, add_player_velocity),
luamethod(ObjectRef, get_look_dir),
luamethod(ObjectRef, get_look_pitch),
luamethod(ObjectRef, get_look_yaw),
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index 653d833f6..2390c5195 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -212,6 +212,9 @@ private:
// get_player_velocity(self)
static int l_get_player_velocity(lua_State *L);
+ // add_player_velocity(self, {x=num, y=num, z=num})
+ static int l_add_player_velocity(lua_State *L);
+
// get_look_dir(self)
static int l_get_look_dir(lua_State *L);
diff --git a/src/server.cpp b/src/server.cpp
index 27388e666..5dd3d0061 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1958,6 +1958,13 @@ void Server::SendCSMRestrictionFlags(session_t peer_id)
Send(&pkt);
}
+void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
+{
+ NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
+ pkt << added_vel;
+ Send(&pkt);
+}
+
s32 Server::playSound(const SimpleSoundSpec &spec,
const ServerSoundParams &params)
{
diff --git a/src/server.h b/src/server.h
index 4232653eb..06adbad68 100644
--- a/src/server.h
+++ b/src/server.h
@@ -335,6 +335,7 @@ public:
void SendPlayerBreath(PlayerSAO *sao);
void SendInventory(PlayerSAO* playerSAO);
void SendMovePlayer(session_t peer_id);
+ void SendPlayerSpeed(session_t peer_id, const v3f &added_vel);
virtual bool registerModStorage(ModMetadata *storage);
virtual void unregisterModStorage(const std::string &name);