mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Implement adding velocity to player from Lua
The intended usecase is knockback, but there's potential for more.
This commit is contained in:
parent
b19400aa74
commit
cf64054390
@ -5465,6 +5465,14 @@ This is basically a reference to a C++ `ServerActiveObject`
|
|||||||
* `get_player_name()`: returns `""` if is not a player
|
* `get_player_name()`: returns `""` if is not a player
|
||||||
* `get_player_velocity()`: returns `nil` if is not a player, otherwise a
|
* `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
|
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_dir()`: get camera direction as a unit vector
|
||||||
* `get_look_vertical()`: pitch in radians
|
* `get_look_vertical()`: pitch in radians
|
||||||
* Angle ranges between -pi/2 and pi/2, which are straight up and down
|
* Angle ranges between -pi/2 and pi/2, which are straight up and down
|
||||||
|
@ -227,6 +227,7 @@ public:
|
|||||||
void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
|
void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
|
||||||
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
|
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
|
||||||
void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
|
void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
|
||||||
|
void handleCommand_PlayerSpeed(NetworkPacket *pkt);
|
||||||
|
|
||||||
void ProcessData(NetworkPacket *pkt);
|
void ProcessData(NetworkPacket *pkt);
|
||||||
|
|
||||||
|
@ -188,6 +188,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
// Copy parent position if local player is attached
|
// Copy parent position if local player is attached
|
||||||
if (isAttached) {
|
if (isAttached) {
|
||||||
setPosition(overridePosition);
|
setPosition(overridePosition);
|
||||||
|
added_velocity = v3f(); // ignored
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,9 +202,13 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
if (noclip && free_move) {
|
if (noclip && free_move) {
|
||||||
position += m_speed * dtime;
|
position += m_speed * dtime;
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
|
added_velocity = v3f(); // ignored
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_speed += added_velocity;
|
||||||
|
added_velocity = v3f();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collision detection
|
Collision detection
|
||||||
*/
|
*/
|
||||||
@ -782,6 +787,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
if (isAttached) {
|
if (isAttached) {
|
||||||
setPosition(overridePosition);
|
setPosition(overridePosition);
|
||||||
m_sneak_node_exists = false;
|
m_sneak_node_exists = false;
|
||||||
|
added_velocity = v3f();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,9 +801,13 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
position += m_speed * dtime;
|
position += m_speed * dtime;
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
m_sneak_node_exists = false;
|
m_sneak_node_exists = false;
|
||||||
|
added_velocity = v3f();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_speed += added_velocity;
|
||||||
|
added_velocity = v3f();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collision detection
|
Collision detection
|
||||||
*/
|
*/
|
||||||
|
@ -149,6 +149,11 @@ public:
|
|||||||
|
|
||||||
bool getAutojump() const { return m_autojump; }
|
bool getAutojump() const { return m_autojump; }
|
||||||
|
|
||||||
|
inline void addVelocity(const v3f &vel)
|
||||||
|
{
|
||||||
|
added_velocity += vel;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void accelerate(const v3f &target_speed, const f32 max_increase_H,
|
void accelerate(const v3f &target_speed, const f32 max_increase_H,
|
||||||
const f32 max_increase_V, const bool use_pitch);
|
const f32 max_increase_V, const bool use_pitch);
|
||||||
@ -194,6 +199,7 @@ private:
|
|||||||
float m_zoom_fov = 0.0f;
|
float m_zoom_fov = 0.0f;
|
||||||
bool m_autojump = false;
|
bool m_autojump = false;
|
||||||
float m_autojump_time = 0.0f;
|
float m_autojump_time = 0.0f;
|
||||||
|
v3f added_velocity = v3f(0.0f, 0.0f, 0.0f); // cleared on each move()
|
||||||
|
|
||||||
GenericCAO *m_cao = nullptr;
|
GenericCAO *m_cao = nullptr;
|
||||||
Client *m_client;
|
Client *m_client;
|
||||||
|
@ -1091,6 +1091,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
|||||||
m_time_from_last_teleport += dtime;
|
m_time_from_last_teleport += dtime;
|
||||||
m_time_from_last_punch += dtime;
|
m_time_from_last_punch += dtime;
|
||||||
m_nocheat_dig_time += 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,
|
// Each frame, parent position is copied if the object is attached,
|
||||||
// otherwise it's calculated normally.
|
// otherwise it's calculated normally.
|
||||||
@ -1412,6 +1413,19 @@ std::string PlayerSAO::getPropertyPacket()
|
|||||||
return gob_cmd_set_properties(m_prop);
|
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()
|
bool PlayerSAO::checkMovementCheat()
|
||||||
{
|
{
|
||||||
if (isAttached() || m_is_singleplayer ||
|
if (isAttached() || m_is_singleplayer ||
|
||||||
@ -1431,6 +1445,14 @@ bool PlayerSAO::checkMovementCheat()
|
|||||||
too, and much more lightweight.
|
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_walk = 0; // horizontal movement
|
||||||
float player_max_jump = 0; // vertical upwards movement
|
float player_max_jump = 0; // vertical upwards movement
|
||||||
|
|
||||||
@ -1439,10 +1461,13 @@ bool PlayerSAO::checkMovementCheat()
|
|||||||
else
|
else
|
||||||
player_max_walk = m_player->movement_speed_walk; // Normal speed
|
player_max_walk = m_player->movement_speed_walk; // Normal speed
|
||||||
player_max_walk *= m_physics_override_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;
|
player_max_jump = m_player->movement_speed_jump * m_physics_override_jump;
|
||||||
// FIXME: Bouncy nodes cause practically unbound increase in Y speed,
|
// FIXME: Bouncy nodes cause practically unbound increase in Y speed,
|
||||||
// until this can be verified correctly, tolerate higher jumping speeds
|
// until this can be verified correctly, tolerate higher jumping speeds
|
||||||
player_max_jump *= 2.0;
|
player_max_jump *= 2.0;
|
||||||
|
player_max_jump = MYMAX(player_max_jump, override_max_V);
|
||||||
|
|
||||||
// Don't divide by zero!
|
// Don't divide by zero!
|
||||||
if (player_max_walk < 0.0001f)
|
if (player_max_walk < 0.0001f)
|
||||||
|
@ -322,6 +322,7 @@ public:
|
|||||||
{
|
{
|
||||||
return m_dig_pool;
|
return m_dig_pool;
|
||||||
}
|
}
|
||||||
|
void setMaxSpeedOverride(const v3f &vel);
|
||||||
// Returns true if cheated
|
// Returns true if cheated
|
||||||
bool checkMovementCheat();
|
bool checkMovementCheat();
|
||||||
|
|
||||||
@ -361,6 +362,8 @@ private:
|
|||||||
float m_time_from_last_punch = 0.0f;
|
float m_time_from_last_punch = 0.0f;
|
||||||
v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
|
v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
|
||||||
float m_nocheat_dig_time = 0.0f;
|
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
|
// Timers
|
||||||
IntervalLimiter m_breathing_interval;
|
IntervalLimiter m_breathing_interval;
|
||||||
|
@ -67,7 +67,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
|
|||||||
null_command_handler,
|
null_command_handler,
|
||||||
{ "TOCLIENT_TIME_OF_DAY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_TimeOfDay }, // 0x29
|
{ "TOCLIENT_TIME_OF_DAY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_TimeOfDay }, // 0x29
|
||||||
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CSMRestrictionFlags }, // 0x2A
|
{ "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,
|
null_command_handler,
|
||||||
null_command_handler,
|
null_command_handler,
|
||||||
|
@ -1383,6 +1383,17 @@ void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt)
|
|||||||
loadMods();
|
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
|
* Mod channels
|
||||||
*/
|
*/
|
||||||
|
@ -194,6 +194,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
New network float format
|
New network float format
|
||||||
ContentFeatures version 13
|
ContentFeatures version 13
|
||||||
Add full Euler rotations instead of just yaw
|
Add full Euler rotations instead of just yaw
|
||||||
|
Add TOCLIENT_PLAYER_SPEED
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LATEST_PROTOCOL_VERSION 37
|
#define LATEST_PROTOCOL_VERSION 37
|
||||||
@ -295,6 +296,11 @@ enum ToClientCommand
|
|||||||
u32 CSMRestrictionFlags byteflag
|
u32 CSMRestrictionFlags byteflag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_PLAYER_SPEED = 0x2B,
|
||||||
|
/*
|
||||||
|
v3f added_vel
|
||||||
|
*/
|
||||||
|
|
||||||
// (oops, there is some gap here)
|
// (oops, there is some gap here)
|
||||||
|
|
||||||
TOCLIENT_CHAT_MESSAGE = 0x2F,
|
TOCLIENT_CHAT_MESSAGE = 0x2F,
|
||||||
|
@ -156,7 +156,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
|
|||||||
null_command_factory,
|
null_command_factory,
|
||||||
{ "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29
|
{ "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29
|
||||||
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", 0, true }, // 0x2A
|
{ "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,
|
null_command_factory,
|
||||||
null_command_factory,
|
null_command_factory,
|
||||||
|
@ -1092,6 +1092,27 @@ int ObjectRef::l_get_player_velocity(lua_State *L)
|
|||||||
return 1;
|
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)
|
// get_look_dir(self)
|
||||||
int ObjectRef::l_get_look_dir(lua_State *L)
|
int ObjectRef::l_get_look_dir(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -1931,6 +1952,7 @@ luaL_Reg ObjectRef::methods[] = {
|
|||||||
luamethod(ObjectRef, is_player_connected),
|
luamethod(ObjectRef, is_player_connected),
|
||||||
luamethod(ObjectRef, get_player_name),
|
luamethod(ObjectRef, get_player_name),
|
||||||
luamethod(ObjectRef, get_player_velocity),
|
luamethod(ObjectRef, get_player_velocity),
|
||||||
|
luamethod(ObjectRef, add_player_velocity),
|
||||||
luamethod(ObjectRef, get_look_dir),
|
luamethod(ObjectRef, get_look_dir),
|
||||||
luamethod(ObjectRef, get_look_pitch),
|
luamethod(ObjectRef, get_look_pitch),
|
||||||
luamethod(ObjectRef, get_look_yaw),
|
luamethod(ObjectRef, get_look_yaw),
|
||||||
|
@ -212,6 +212,9 @@ private:
|
|||||||
// get_player_velocity(self)
|
// get_player_velocity(self)
|
||||||
static int l_get_player_velocity(lua_State *L);
|
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)
|
// get_look_dir(self)
|
||||||
static int l_get_look_dir(lua_State *L);
|
static int l_get_look_dir(lua_State *L);
|
||||||
|
|
||||||
|
@ -1958,6 +1958,13 @@ void Server::SendCSMRestrictionFlags(session_t peer_id)
|
|||||||
Send(&pkt);
|
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,
|
s32 Server::playSound(const SimpleSoundSpec &spec,
|
||||||
const ServerSoundParams ¶ms)
|
const ServerSoundParams ¶ms)
|
||||||
{
|
{
|
||||||
|
@ -335,6 +335,7 @@ public:
|
|||||||
void SendPlayerBreath(PlayerSAO *sao);
|
void SendPlayerBreath(PlayerSAO *sao);
|
||||||
void SendInventory(PlayerSAO* playerSAO);
|
void SendInventory(PlayerSAO* playerSAO);
|
||||||
void SendMovePlayer(session_t peer_id);
|
void SendMovePlayer(session_t peer_id);
|
||||||
|
void SendPlayerSpeed(session_t peer_id, const v3f &added_vel);
|
||||||
|
|
||||||
virtual bool registerModStorage(ModMetadata *storage);
|
virtual bool registerModStorage(ModMetadata *storage);
|
||||||
virtual void unregisterModStorage(const std::string &name);
|
virtual void unregisterModStorage(const std::string &name);
|
||||||
|
Loading…
Reference in New Issue
Block a user