Skip to content

Commit

Permalink
Expose analog joystick input to the Lua API
Browse files Browse the repository at this point in the history
  • Loading branch information
grorp committed Feb 4, 2024
1 parent 83f779c commit 286254d
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 40 deletions.
15 changes: 11 additions & 4 deletions doc/lua_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7773,12 +7773,19 @@ child will follow movement and rotation of that bone.
bgcolor[], any non-style elements (eg: label) may result in weird behavior.
* Only affects formspecs shown after this is called.
* `get_formspec_prepend()`: returns a formspec string.
* `get_player_control()`: returns table with player pressed keys
* The table consists of fields with the following boolean values
representing the pressed keys: `up`, `down`, `left`, `right`, `jump`,
`aux1`, `sneak`, `dig`, `place`, `LMB`, `RMB`, and `zoom`.
* `get_player_control()`: returns table with player input
* The table contains the following boolean fields representing the pressed
keys: `up`, `down`, `left`, `right`, `jump`, `aux1`, `sneak`, `dig`,
`place`, `LMB`, `RMB`, and `zoom`.
* The fields `LMB` and `RMB` are equal to `dig` and `place` respectively,
and exist only to preserve backwards compatibility.
* The table also contains the float fields `movement_speed`
and `movement_direction`.
* They take both keyboard and joystick input into account.
* You should ALWAYS use them for movement instead of `up`, `down`,
`left` and `right` to support different input methods correctly.
* `movement_speed` is in the range [0,1].
* `movement_direction` is in radians.
* Returns an empty table `{}` if the object is not a player.
* `get_player_control_bits()`: returns integer with bit packed player pressed
keys.
Expand Down
17 changes: 14 additions & 3 deletions src/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ void Client::Send(NetworkPacket* pkt)
m_con->Send(PEER_ID_SERVER, scf.channel, pkt, scf.reliable);
}

// Will fill up 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 bytes
// Will fill up 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4 bytes
void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt, bool camera_inverted)
{
v3f pf = myplayer->getPosition() * 100;
Expand All @@ -1054,6 +1054,8 @@ void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *
u8 fov = std::fmin(255.0f, clientMap->getCameraFov() * 80.0f);
u8 wanted_range = std::fmin(255.0f,
std::ceil(clientMap->getWantedRange() * (1.0f / MAP_BLOCKSIZE)));
f32 movement_speed = myplayer->control.movement_speed;
f32 movement_dir = myplayer->control.movement_direction;

v3s32 position(pf.X, pf.Y, pf.Z);
v3s32 speed(sf.X, sf.Y, sf.Z);
Expand All @@ -1068,10 +1070,13 @@ void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *
[12+12+4+4+4] u8 fov*80
[12+12+4+4+4+1] u8 ceil(wanted_range / MAP_BLOCKSIZE)
[12+12+4+4+4+1+1] u8 camera_inverted (bool)
[12+12+4+4+4+1+1+1] f32 movement_speed
[12+12+4+4+4+1+1+1+4] f32 movement_direction
*/
*pkt << position << speed << pitch << yaw << keyPressed;
*pkt << fov << wanted_range;
*pkt << camera_inverted;
*pkt << movement_speed << movement_dir;
}

void Client::interact(InteractAction action, const PointedThing& pointed)
Expand Down Expand Up @@ -1408,6 +1413,8 @@ void Client::sendPlayerPos()

u32 keyPressed = player->control.getKeysPressed();
bool camera_inverted = m_camera->getCameraMode() == CAMERA_MODE_THIRD_FRONT;
f32 movement_speed = player->control.movement_speed;
f32 movement_dir = player->control.movement_direction;

if (
player->last_position == player->getPosition() &&
Expand All @@ -1417,7 +1424,9 @@ void Client::sendPlayerPos()
player->last_keyPressed == keyPressed &&
player->last_camera_fov == camera_fov &&
player->last_camera_inverted == camera_inverted &&
player->last_wanted_range == wanted_range)
player->last_wanted_range == wanted_range &&
player->last_movement_speed == movement_speed &&
player->last_movement_dir == movement_dir)
return;

player->last_position = player->getPosition();
Expand All @@ -1428,8 +1437,10 @@ void Client::sendPlayerPos()
player->last_camera_fov = camera_fov;
player->last_camera_inverted = camera_inverted;
player->last_wanted_range = wanted_range;
player->last_movement_speed = movement_speed;
player->last_movement_dir = movement_dir;

NetworkPacket pkt(TOSERVER_PLAYERPOS, 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1);
NetworkPacket pkt(TOSERVER_PLAYERPOS, 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4);

writePlayerPos(player, &map, &pkt, camera_inverted);

Expand Down
1 change: 1 addition & 0 deletions src/client/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2743,6 +2743,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
input->getMovementSpeed(),
input->getMovementDirection()
);
control.setMovementFromKeys();

// autoforward if set: move at maximum speed
if (player->getPlayerSettings().continuous_forward &&
Expand Down
30 changes: 0 additions & 30 deletions src/client/inputhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,21 +317,6 @@ class RealInputHandler : public InputHandler

virtual float getMovementSpeed()
{
bool f = m_receiver->IsKeyDown(keycache.key[KeyType::FORWARD]),
b = m_receiver->IsKeyDown(keycache.key[KeyType::BACKWARD]),
l = m_receiver->IsKeyDown(keycache.key[KeyType::LEFT]),
r = m_receiver->IsKeyDown(keycache.key[KeyType::RIGHT]);
if (f || b || l || r)
{
// if contradictory keys pressed, stay still
if (f && b && l && r)
return 0.0f;
else if (f && b && !l && !r)
return 0.0f;
else if (!f && !b && l && r)
return 0.0f;
return 1.0f; // If there is a keyboard event, assume maximum speed
}
#ifdef HAVE_TOUCHSCREENGUI
return m_receiver->m_touchscreengui->getMovementSpeed();
#else
Expand All @@ -341,21 +326,6 @@ class RealInputHandler : public InputHandler

virtual float getMovementDirection()
{
float x = 0, z = 0;

/* Check keyboard for input */
if (m_receiver->IsKeyDown(keycache.key[KeyType::FORWARD]))
z += 1;
if (m_receiver->IsKeyDown(keycache.key[KeyType::BACKWARD]))
z -= 1;
if (m_receiver->IsKeyDown(keycache.key[KeyType::RIGHT]))
x += 1;
if (m_receiver->IsKeyDown(keycache.key[KeyType::LEFT]))
x -= 1;

if (x != 0 || z != 0) /* If there is a keyboard event, it takes priority */
return atan2(x, z);
else
#ifdef HAVE_TOUCHSCREENGUI
return m_receiver->m_touchscreengui->getMovementDirection();
#else
Expand Down
2 changes: 2 additions & 0 deletions src/client/localplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class LocalPlayer : public Player
u8 last_camera_fov = 0;
u8 last_wanted_range = 0;
bool last_camera_inverted = false;
f32 last_movement_speed = 0.0f;
f32 last_movement_dir = 0.0f;

float camera_impact = 0.0f;

Expand Down
2 changes: 2 additions & 0 deletions src/network/networkprotocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ enum ToServerCommand : u16
[2+12+12+4+4+4] u8 fov*80
[2+12+12+4+4+4+1] u8 ceil(wanted_range / MAP_BLOCKSIZE)
[2+12+12+4+4+4+1+1] u8 camera_inverted (bool)
[2+12+12+4+4+4+1+1+1] f32 movement_speed
[2+12+12+4+4+4+1+1+1+4] f32 movement_direction
*/

Expand Down
11 changes: 9 additions & 2 deletions src/network/serverpackethandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,11 +483,20 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
u8 bits = 0; // bits instead of bool so it is extensible later

*pkt >> keyPressed;
player->control.unpackKeysPressed(keyPressed);
*pkt >> f32fov;
fov = (f32)f32fov / 80.0f;
*pkt >> wanted_range;
if (pkt->getRemainingBytes() >= 1)
*pkt >> bits;
if (pkt->getRemainingBytes() >= 8) {
*pkt >> player->control.movement_speed;
*pkt >> player->control.movement_direction;
} else {
player->control.movement_speed = 0.0f;
player->control.movement_direction = 0.0f;
player->control.setMovementFromKeys();
}

v3f position((f32)ps.X / 100.0f, (f32)ps.Y / 100.0f, (f32)ps.Z / 100.0f);
v3f speed((f32)ss.X / 100.0f, (f32)ss.Y / 100.0f, (f32)ss.Z / 100.0f);
Expand All @@ -507,8 +516,6 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
playersao->setWantedRange(wanted_range);
playersao->setCameraInverted(bits & 0x01);

player->control.unpackKeysPressed(keyPressed);

if (playersao->checkMovementCheat()) {
// Call callbacks
m_script->on_cheat(playersao, "moved_too_fast");
Expand Down
36 changes: 36 additions & 0 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,42 @@ void Player::clearHud()
}
}

void PlayerControl::setMovementFromKeys()
{
bool a_up = direction_keys & (1 << 0),
a_down = direction_keys & (1 << 1),
a_left = direction_keys & (1 << 2),
a_right = direction_keys & (1 << 3);

if (a_up || a_down || a_left || a_right) {
// if contradictory keys pressed, stay still
if (a_up && a_down && a_left && a_right)
movement_speed = 0.0f;
else if (a_up && a_down && !a_left && !a_right)
movement_speed = 0.0f;
else if (!a_up && !a_down && a_left && a_right)
movement_speed = 0.0f;
else
// If there is a keyboard event, assume maximum speed
movement_speed = 1.0f;
}

// Check keyboard for input
float x = 0, z = 0;
if (a_up)
z += 1;
if (a_down)
z -= 1;
if (a_left)
x -= 1;
if (a_right)
x += 1;

if (x != 0 || z != 0)
// If there is a keyboard event, it takes priority
movement_direction = atan2(x, z);
}

#ifndef SERVER

u32 PlayerControl::getKeysPressed() const
Expand Down
6 changes: 5 additions & 1 deletion src/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ struct PlayerControl
movement_direction = a_movement_direction;
}

// Sets movement_speed and movement_direction according to direction_keys
// if direction_keys != 0.
void setMovementFromKeys();

#ifndef SERVER
// For client use
u32 getKeysPressed() const;
Expand All @@ -90,7 +94,7 @@ struct PlayerControl
bool zoom = false;
bool dig = false;
bool place = false;
// Note: These four are NOT available on the server
// Note: These two are NOT available on the server
float pitch = 0.0f;
float yaw = 0.0f;
float movement_speed = 0.0f;
Expand Down
4 changes: 4 additions & 0 deletions src/script/lua_api/l_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1529,6 +1529,10 @@ int ObjectRef::l_get_player_control(lua_State *L)
lua_setfield(L, -2, "dig");
lua_pushboolean(L, control.place);
lua_setfield(L, -2, "place");
lua_pushnumber(L, control.movement_speed);
lua_setfield(L, -2, "movement_speed");
lua_pushnumber(L, control.movement_direction);
lua_setfield(L, -2, "movement_direction");
// Legacy fields to ensure mod compatibility
lua_pushboolean(L, control.dig);
lua_setfield(L, -2, "LMB");
Expand Down

0 comments on commit 286254d

Please sign in to comment.