Skip to content

Commit

Permalink
Implement adding velocity to player from Lua
Browse files Browse the repository at this point in the history
The intended usecase is knockback, but there's potential for more.
  • Loading branch information
sfan5 committed Aug 10, 2019
1 parent b19400a commit cf64054
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 2 deletions.
8 changes: 8 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/client/client.h
Expand Up @@ -227,6 +227,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
void handleCommand_PlayerSpeed(NetworkPacket *pkt);

void ProcessData(NetworkPacket *pkt);

Expand Down
10 changes: 10 additions & 0 deletions src/client/localplayer.cpp
Expand Up @@ -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;
}

Expand All @@ -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
*/
Expand Down Expand Up @@ -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;
}

Expand All @@ -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
*/
Expand Down
6 changes: 6 additions & 0 deletions src/client/localplayer.h
Expand Up @@ -149,6 +149,11 @@ class LocalPlayer : public Player

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);
Expand Down Expand Up @@ -194,6 +199,7 @@ class LocalPlayer : public Player
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;
Expand Down
25 changes: 25 additions & 0 deletions src/content_sao.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -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 ||
Expand All @@ -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

Expand All @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions src/content_sao.h
Expand Up @@ -322,6 +322,7 @@ class PlayerSAO : public UnitSAO
{
return m_dig_pool;
}
void setMaxSpeedOverride(const v3f &vel);
// Returns true if cheated
bool checkMovementCheat();

Expand Down Expand Up @@ -361,6 +362,8 @@ class PlayerSAO : public UnitSAO
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;
Expand Down
2 changes: 1 addition & 1 deletion src/network/clientopcodes.cpp
Expand Up @@ -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,
Expand Down
11 changes: 11 additions & 0 deletions src/network/clientpackethandler.cpp
Expand Up @@ -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
*/
Expand Down
6 changes: 6 additions & 0 deletions src/network/networkprotocol.h
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/network/serveropcodes.cpp
Expand Up @@ -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,
Expand Down
22 changes: 22 additions & 0 deletions src/script/lua_api/l_object.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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),
Expand Down
3 changes: 3 additions & 0 deletions src/script/lua_api/l_object.h
Expand Up @@ -212,6 +212,9 @@ class ObjectRef : public ModApiBase {
// 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);

Expand Down
7 changes: 7 additions & 0 deletions src/server.cpp
Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Expand Up @@ -335,6 +335,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
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);
Expand Down

0 comments on commit cf64054

Please sign in to comment.