Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement player:get_point_dir() and player:get_point_screen_pos() #15567

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doc/lua_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8401,6 +8401,22 @@ child will follow movement and rotation of that bone.
table {x, y, z} representing the player's instantaneous velocity in nodes/s
* `add_player_velocity(vel)`: **DEPRECATED**, use add_velocity(vel) instead.
* `get_look_dir()`: get camera direction as a unit vector
* `get_point_dir()`: get pointing direction as a unit vector
* If the player uses a crosshair, this returns the same value as `get_look_dir`.
* If the player uses the touchscreen controls without a crosshair, ...
* ...the look direction and the pointing direction may differ.
* ...the player doesn't have a well-defined pointing direction when not
touching the screen. In this case, `get_point_dir` returns the last
valid pointing direction.
* `get_point_screen_pos()`: get pointer position in screen-space
* Returns a 2D vector in coordinates relative to the screen size:
`{x = 0..1, y = 0..1}`
* If the player uses a crosshair, this always returns `{x = 0.5, y = 0.5}`
* If the player uses the touchscreen controls without a crosshair, ...
* ...other values may be returned.
* ...the player doesn't have a well-defined pointer position when not
touching the screen. In this case, `get_point_screen_pos` returns the
last valid pointer position.
* `get_look_vertical()`: pitch in radians
* Angle ranges between -pi/2 and pi/2, which are straight up and down
respectively.
Expand Down
20 changes: 17 additions & 3 deletions src/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,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 + 4 + 4 bytes
// Will fill up 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 + 4 + 4 + 8 + 4 + 4 bytes
void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt, bool camera_inverted)
{
v3f pf = myplayer->getPosition() * 100;
Expand All @@ -1027,6 +1027,9 @@ void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *
std::ceil(clientMap->getWantedRange() * (1.0f / MAP_BLOCKSIZE)));
f32 movement_speed = myplayer->control.movement_speed;
f32 movement_dir = myplayer->control.movement_direction;
v2f pointer_pos = myplayer->pointer_pos;
f32 point_pitch = myplayer->point_pitch;
f32 point_yaw = myplayer->point_yaw;

v3s32 position(pf.X, pf.Y, pf.Z);
v3s32 speed(sf.X, sf.Y, sf.Z);
Expand All @@ -1043,11 +1046,16 @@ void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *
[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
[12+12+4+4+4+1+1+1+4+4] v2f pointer_pos
[12+12+4+4+4+1+1+1+4+4+8] f32 point_pitch
[12+12+4+4+4+1+1+1+4+4+8+4] f32 point_yaw
*/
*pkt << position << speed << pitch << yaw << keyPressed;
*pkt << fov << wanted_range;
*pkt << camera_inverted;
*pkt << movement_speed << movement_dir;
*pkt << pointer_pos;
*pkt << point_pitch << point_yaw;
}

void Client::interact(InteractAction action, const PointedThing& pointed)
Expand Down Expand Up @@ -1394,7 +1402,10 @@ void Client::sendPlayerPos()
player->last_camera_inverted == camera_inverted &&
player->last_wanted_range == wanted_range &&
player->last_movement_speed == movement_speed &&
player->last_movement_dir == movement_dir)
player->last_movement_dir == movement_dir &&
player->last_pointer_pos == player->pointer_pos &&
player->last_point_pitch == player->point_pitch &&
player->last_point_yaw == player->point_yaw)
return;

player->last_position = player->getPosition();
Expand All @@ -1407,8 +1418,11 @@ void Client::sendPlayerPos()
player->last_wanted_range = wanted_range;
player->last_movement_speed = movement_speed;
player->last_movement_dir = movement_dir;
player->last_pointer_pos = player->pointer_pos;
player->last_point_pitch = player->point_pitch;
player->last_point_yaw = player->point_yaw;

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

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

Expand Down
28 changes: 28 additions & 0 deletions src/client/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ class Game {

void updateCameraDirection(CameraOrientation *cam, float dtime);
void updateCameraOrientation(CameraOrientation *cam, float dtime);
void updatePointDir(const CameraOrientation &cam);
void updatePlayerControl(const CameraOrientation &cam);
void updatePauseState();
void step(f32 dtime);
Expand Down Expand Up @@ -996,6 +997,7 @@ void Game::run()
cam_view.camera_yaw) * m_cache_cam_smoothing;
cam_view.camera_pitch += (cam_view_target.camera_pitch -
cam_view.camera_pitch) * m_cache_cam_smoothing;
updatePointDir(cam_view);
updatePlayerControl(cam_view);

updatePauseState();
Expand Down Expand Up @@ -2427,6 +2429,32 @@ void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
cam->camera_pitch = rangelim(cam->camera_pitch, -89.5, 89.5);
}

void Game::updatePointDir(const CameraOrientation &cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();

if (g_touchcontrols && isTouchCrosshairDisabled()) {
v2s32 pointer_pos = g_touchcontrols->getPointerPos();
v2u32 screensize = driver->getScreenSize();

player->pointer_pos.X = (f32)pointer_pos.X / (f32)screensize.X;
player->pointer_pos.Y = (f32)pointer_pos.Y / (f32)screensize.Y;

const v3f point_dir = g_touchcontrols->getShootline().getVector().normalize();
// getHorizontalAngle is Irrlicht's "direction to rotation" function
// Roll (Z) is always 0
const v3f point_rot = point_dir.getHorizontalAngle();

player->point_pitch = point_rot.X;
player->point_yaw = point_rot.Y;
} else {
player->pointer_pos.X = 0.5f;
player->pointer_pos.Y = 0.5f;
player->point_pitch = 0.0f;
player->point_yaw = 0.0f;
}
}


void Game::updatePlayerControl(const CameraOrientation &cam)
{
Expand Down
3 changes: 3 additions & 0 deletions src/client/localplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ class LocalPlayer : public Player
bool last_camera_inverted = false;
f32 last_movement_speed = 0.0f;
f32 last_movement_dir = 0.0f;
v2f last_pointer_pos = v2f(0.5f, 0.5f);
float last_point_pitch = 0.0f;
float last_point_yaw = 0.0f;

float camera_impact = 0.0f;

Expand Down
23 changes: 9 additions & 14 deletions src/gui/touchcontrols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,10 +531,11 @@ void TouchControls::translateEvent(const SEvent &event)
m_move_has_really_moved = false;
m_move_downtime = porting::getTimeMs();
m_move_pos = touch_pos;
// DON'T reset m_tap_state here, otherwise many short taps
// will be ignored if you tap very fast.
m_had_move_id = true;
m_move_prevent_short_tap = prevent_short_tap;

// DON'T reset m_tap_state here, otherwise many short taps
// will be ignored if you tap very fast.
}
}
}
Expand Down Expand Up @@ -662,11 +663,10 @@ void TouchControls::step(float dtime)
// Only updating when m_has_move_id means that the shootline will stay at
// it's last in-world position when the player doesn't need it.
if (!m_draw_crosshair && (m_has_move_id || m_had_move_id)) {
v2s32 pointer_pos = getPointerPos();
m_shootline = m_device
->getSceneManager()
->getSceneCollisionManager()
->getRayFromScreenCoordinates(pointer_pos);
->getRayFromScreenCoordinates(m_move_pos);
}
m_had_move_id = false;
}
Expand Down Expand Up @@ -748,18 +748,13 @@ void TouchControls::show()
setVisible(true);
}

v2s32 TouchControls::getPointerPos()
{
if (m_draw_crosshair)
return v2s32(m_screensize.X / 2, m_screensize.Y / 2);
// We can't just use m_pointer_pos[m_move_id] because applyContextControls
// may emit release events after m_pointer_pos[m_move_id] is erased.
return m_move_pos;
}

void TouchControls::emitMouseEvent(EMOUSE_INPUT_EVENT type)
{
v2s32 pointer_pos = getPointerPos();
v2s32 pointer_pos = m_draw_crosshair
? v2s32(m_screensize.X / 2, m_screensize.Y / 2)
// applyContextControls may emit mouse release events after
// m_pointer_pos[m_move_id] is erased.
: m_move_pos;

SEvent event{};
event.EventType = EET_MOUSE_INPUT_EVENT;
Expand Down
14 changes: 12 additions & 2 deletions src/gui/touchcontrols.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,22 @@ class TouchControls
return res;
}

/**
* Returns the pointer position in pixels.
*
* May only be used if crosshair is disabled (see setUseCrosshair)
*/
v2s32 getPointerPos() { return m_move_pos; }

/**
* Returns a line which describes what the player is pointing at.
* The starting point and looking direction are significant,
* the line should be scaled to match its length to the actual distance
* the player can reach.
* The line starts at the camera and ends on the camera's far plane.
* The coordinates do not contain the camera offset.
*
* May only be used if crosshair is disabled (see setUseCrosshair)
*/
line3d<f32> getShootline() { return m_shootline; }

Expand Down Expand Up @@ -155,7 +164,9 @@ class TouchControls
size_t m_move_id;
bool m_move_has_really_moved = false;
u64 m_move_downtime = 0;
// m_move_pos stays valid even after m_move_id has been released.
// m_move_pos is equivalent to m_pointer_pos[m_move_id] while m_has_move_id
// is true. However, m_move_pos stays valid even after the m_move_id pointer
// has been released and m_pointer_pos[m_move_id] has been erased.
v2s32 m_move_pos;
// This is needed so that we don't miss if m_has_move_id is true for less
// than one client step, i.e. press and release happen in the same step.
Expand Down Expand Up @@ -217,7 +228,6 @@ class TouchControls
// map to store the IDs and positions of currently pressed pointers
std::unordered_map<size_t, v2s32> m_pointer_pos;

v2s32 getPointerPos();
void emitMouseEvent(EMOUSE_INPUT_EVENT type);
TouchInteractionMode m_last_mode = TouchInteractionMode_END;
TapState m_tap_state = TapState::None;
Expand Down
3 changes: 3 additions & 0 deletions src/network/networkprotocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,9 @@ enum ToServerCommand : u16
[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
[2+12+12+4+4+4+1+1+1+4+4] v2f pointer_pos
[2+12+12+4+4+4+1+1+1+4+4+8] f32 point_pitch
[2+12+12+4+4+4+1+1+1+4+4+8+4] f32 point_yaw

*/

Expand Down
10 changes: 10 additions & 0 deletions src/network/serverpackethandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,16 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
player->control.setMovementFromKeys();
}

if (pkt->getRemainingBytes() >= 16) {
*pkt >> player->pointer_pos;
*pkt >> player->point_pitch >> player->point_yaw;
} else {
player->pointer_pos.X = 0.5f;
player->pointer_pos.Y = 0.5f;
player->point_pitch = 0.0f;
player->point_yaw = 0.0f;
}

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 Down
12 changes: 12 additions & 0 deletions src/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ class Player
PlayerControl control;
const PlayerControl& getPlayerControl() { return control; }

// Pointer position, as screen coordinates in the range 0..1
// When using a crosshair, this is always (0.5, 0.5)
v2f pointer_pos = v2f(0.5f, 0.5f);
// Pointing direction, represented as pitch/yaw in degrees
// When using a crosshair, it's unspecified what values these will have.
f32 point_pitch = 0.0f;
f32 point_yaw = 0.0f;

// Note: If there is no crosshair and the player is not touching the screen,
// pointer position and pointing direction are not well-defined. In this
// case, the last valid values are kept.

PlayerPhysicsOverride physics_override;

// Returns non-empty `selected` ItemStack. `hand` is a fallback, if specified
Expand Down
42 changes: 37 additions & 5 deletions src/script/lua_api/l_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1246,12 +1246,42 @@ int ObjectRef::l_get_look_dir(lua_State *L)
if (playersao == nullptr)
return 0;

float pitch = playersao->getRadLookPitchDep();
float yaw = playersao->getRadYawDep();
v3f v(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) *
std::sin(yaw));
push_v3f(L, playersao->getLookDir());
return 1;
}

// get_point_screen_pos(self)
int ObjectRef::l_get_point_screen_pos(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == nullptr)
return 0;

push_v2f(L, player->pointer_pos);
return 1;
}

// get_point_dir(self)
int ObjectRef::l_get_point_dir(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
PlayerSAO* playersao = getplayersao(ref);
if (playersao == nullptr)
return 0;

RemotePlayer *player = playersao->getPlayer();

if (player->pointer_pos.X == 0.5f && player->pointer_pos.Y == 0.5f) {
appgurueu marked this conversation as resolved.
Show resolved Hide resolved
push_v3f(L, playersao->getLookDir());
return 1;
}

push_v3f(L, v);
const v3f point_rot = v3f(player->point_pitch, player->point_yaw, 0.0f);
const v3f point_dir = point_rot.rotationToDirection();
push_v3f(L, point_dir);
return 1;
}

Expand Down Expand Up @@ -2840,6 +2870,8 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, is_player),
luamethod(ObjectRef, get_player_name),
luamethod(ObjectRef, get_look_dir),
luamethod(ObjectRef, get_point_screen_pos),
luamethod(ObjectRef, get_point_dir),
luamethod(ObjectRef, get_look_pitch),
luamethod(ObjectRef, get_look_yaw),
luamethod(ObjectRef, get_look_vertical),
Expand Down
6 changes: 6 additions & 0 deletions src/script/lua_api/l_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ class ObjectRef : public ModApiBase {
// get_look_dir(self)
static int l_get_look_dir(lua_State *L);

// get_point_screen_pos(self)
static int l_get_point_screen_pos(lua_State *L);

// get_point_dir(self)
static int l_get_point_dir(lua_State *L);

// DEPRECATED
// get_look_pitch(self)
static int l_get_look_pitch(lua_State *L);
Expand Down
9 changes: 9 additions & 0 deletions src/server/player_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,15 @@ void PlayerSAO::setPlayerYaw(const float yaw)
UnitSAO::setRotation(rotation);
}

v3f PlayerSAO::getLookDir() const
{
// FIXME: get rid of deprecated method usage
float pitch = getRadLookPitchDep();
float yaw = getRadYawDep();
return v3f(std::cos(pitch) * std::cos(yaw), std::sin(pitch), std::cos(pitch) *
std::sin(yaw));
}

void PlayerSAO::setFov(const float fov)
{
if (m_player && fov != m_fov)
Expand Down
1 change: 1 addition & 0 deletions src/server/player_sao.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class PlayerSAO : public UnitSAO
f32 getRadLookPitch() const { return m_pitch * core::DEGTORAD; }
// Deprecated
f32 getRadLookPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; }
v3f getLookDir() const;
void setFov(const float pitch);
f32 getFov() const { return m_fov; }
void setWantedRange(const s16 range);
Expand Down
Loading