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

Add support for per-player FOV overrides and multipliers #7557

Merged
merged 1 commit into from Sep 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions doc/lua_api.txt
Expand Up @@ -5576,12 +5576,21 @@ This is basically a reference to a C++ `ServerActiveObject`
`set_look_vertical`.
* `set_look_yaw(radians)`: sets look yaw - Deprecated. Use
`set_look_horizontal`.
* `get_breath()`: returns players breath
* `set_breath(value)`: sets players breath
* `get_breath()`: returns player's breath
* `set_breath(value)`: sets player's breath
* values:
* `0`: player is drowning
* max: bubbles bar is not shown
* See [Object properties] for more information
* `set_fov(fov, is_multiplier)`: Sets player's FOV
* `fov`: FOV value.
* `is_multiplier`: Set to `true` if the FOV value is a multiplier.
paramat marked this conversation as resolved.
Show resolved Hide resolved
Defaults to `false`.
* Set to 0 to clear FOV override.
* `get_fov()`:
* Returns player's FOV override in degrees, and a boolean depending on whether
the value is a multiplier.
* Returns 0 as first value if player's FOV hasn't been overridden.
* `set_attribute(attribute, value)`: DEPRECATED, use get_meta() instead
* Sets an extra attribute with value on player.
* `value` must be a string, or a number which will be converted to a
Expand Down
20 changes: 17 additions & 3 deletions src/client/camera.cpp
Expand Up @@ -448,12 +448,26 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_r
if (m_camera_mode != CAMERA_MODE_FIRST)
m_camera_position = my_cp;

// Get FOV
/*
* Apply server-sent FOV. If server doesn't enforce FOV,
* check for zoom and set to zoom FOV.
* Otherwise, default to m_cache_fov
*/

f32 fov_degrees;
// Disable zoom with zoom FOV = 0
if (player->getPlayerControl().zoom && player->getZoomFOV() > 0.001f) {
PlayerFovSpec fov_spec = player->getFov();
if (fov_spec.fov > 0.0f) {
// If server-sent FOV is a multiplier, multiply
// it with m_cache_fov instead of overriding
if (fov_spec.is_multiplier)
fov_degrees = m_cache_fov * fov_spec.fov;
else
fov_degrees = fov_spec.fov;
} else if (player->getPlayerControl().zoom && player->getZoomFOV() > 0.001f) {
// Player requests zoom, apply zoom FOV
fov_degrees = player->getZoomFOV();
} else {
// Set to client's selected FOV
fov_degrees = m_cache_fov;
}
fov_degrees = rangelim(fov_degrees, 1.0f, 160.0f);
Expand Down
1 change: 1 addition & 0 deletions src/client/client.h
Expand Up @@ -193,6 +193,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
void handleCommand_Movement(NetworkPacket* pkt);
void handleCommand_Fov(NetworkPacket *pkt);
void handleCommand_HP(NetworkPacket* pkt);
void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_MovePlayer(NetworkPacket* pkt);
Expand Down
4 changes: 2 additions & 2 deletions src/client/game.cpp
Expand Up @@ -1083,7 +1083,7 @@ void Game::run()
// RenderingEngine::run() from this iteration
// + Sleep time until the wanted FPS are reached
limitFps(&draw_times, &dtime);

// Prepare render data for next iteration

updateStats(&stats, draw_times, dtime);
Expand Down Expand Up @@ -2332,7 +2332,7 @@ void Game::toggleFullViewRange()
void Game::checkZoomEnabled()
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
if (player->getZoomFOV() < 0.001f)
if (player->getZoomFOV() < 0.001f || player->getFov().fov > 0.0f)
m_game_ui->showTranslatedStatusText("Zoom currently disabled by game or mod");
}

Expand Down
8 changes: 4 additions & 4 deletions src/network/clientopcodes.cpp
Expand Up @@ -78,7 +78,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_HP", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HP }, // 0x33
{ "TOCLIENT_MOVE_PLAYER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayer }, // 0x34
{ "TOCLIENT_ACCESS_DENIED_LEGACY", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_AccessDenied }, // 0x35
null_command_handler,
{ "TOCLIENT_FOV", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Fov }, // 0x36
{ "TOCLIENT_DEATHSCREEN", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreen }, // 0x37
{ "TOCLIENT_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Media }, // 0x38
null_command_handler,
Expand Down Expand Up @@ -151,9 +151,9 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
null_command_factory, // 0x14
null_command_factory, // 0x15
null_command_factory, // 0x16
{ "TOSERVER_MODCHANNEL_JOIN", 0, true }, // 0x17
{ "TOSERVER_MODCHANNEL_LEAVE", 0, true }, // 0x18
{ "TOSERVER_MODCHANNEL_MSG", 0, true }, // 0x19
{ "TOSERVER_MODCHANNEL_JOIN", 0, true }, // 0x17
{ "TOSERVER_MODCHANNEL_LEAVE", 0, true }, // 0x18
{ "TOSERVER_MODCHANNEL_MSG", 0, true }, // 0x19
null_command_factory, // 0x1a
null_command_factory, // 0x1b
null_command_factory, // 0x1c
Expand Down
13 changes: 11 additions & 2 deletions src/network/clientpackethandler.cpp
Expand Up @@ -519,13 +519,22 @@ void Client::handleCommand_Movement(NetworkPacket* pkt)
player->movement_gravity = g * BS;
}

void Client::handleCommand_HP(NetworkPacket* pkt)
void Client::handleCommand_Fov(NetworkPacket *pkt)
ClobberXD marked this conversation as resolved.
Show resolved Hide resolved
{
f32 fov;
bool is_multiplier;
*pkt >> fov >> is_multiplier;

LocalPlayer *player = m_env.getLocalPlayer();
player->setFov({ fov, is_multiplier });
}

void Client::handleCommand_HP(NetworkPacket *pkt)
{
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);

u16 oldhp = player->hp;
u16 oldhp = player->hp;

u16 hp;
*pkt >> hp;
Expand Down
9 changes: 8 additions & 1 deletion src/network/networkprotocol.h
Expand Up @@ -199,6 +199,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Incremental inventory sending mode
Unknown inventory serialization fields no longer throw an error
Mod-specific formspec version
Player FOV override API
*/

#define LATEST_PROTOCOL_VERSION 38
Expand Down Expand Up @@ -371,7 +372,13 @@ enum ToClientCommand
wstring reason
*/

TOCLIENT_PLAYERITEM = 0x36, // Obsolete
TOCLIENT_FOV = 0x36,
/*
Sends an FOV override/multiplier to client.

float fov
bool is_multiplier
*/

TOCLIENT_DEATHSCREEN = 0x37,
/*
Expand Down
88 changes: 44 additions & 44 deletions src/network/serveropcodes.cpp
Expand Up @@ -104,9 +104,9 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
null_command_handler, // 0x4d
null_command_handler, // 0x4e
null_command_handler, // 0x4f
{ "TOSERVER_FIRST_SRP", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_FirstSrp }, // 0x50
{ "TOSERVER_SRP_BYTES_A", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_SrpBytesA }, // 0x51
{ "TOSERVER_SRP_BYTES_M", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_SrpBytesM }, // 0x52
{ "TOSERVER_FIRST_SRP", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_FirstSrp }, // 0x50
{ "TOSERVER_SRP_BYTES_A", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_SrpBytesA }, // 0x51
{ "TOSERVER_SRP_BYTES_M", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_SrpBytesM }, // 0x52
};

const static ClientCommandFactory null_command_factory = { "TOCLIENT_NULL", 0, false };
Expand All @@ -115,67 +115,67 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{
null_command_factory, // 0x00
null_command_factory, // 0x01
{ "TOCLIENT_HELLO", 0, true }, // 0x02
{ "TOCLIENT_AUTH_ACCEPT", 0, true }, // 0x03
{ "TOCLIENT_ACCEPT_SUDO_MODE", 0, true }, // 0x04
{ "TOCLIENT_DENY_SUDO_MODE", 0, true }, // 0x05
{ "TOCLIENT_HELLO", 0, true }, // 0x02
{ "TOCLIENT_AUTH_ACCEPT", 0, true }, // 0x03
{ "TOCLIENT_ACCEPT_SUDO_MODE", 0, true }, // 0x04
{ "TOCLIENT_DENY_SUDO_MODE", 0, true }, // 0x05
null_command_factory, // 0x06
null_command_factory, // 0x07
null_command_factory, // 0x08
null_command_factory, // 0x09
{ "TOCLIENT_ACCESS_DENIED", 0, true }, // 0x0A
{ "TOCLIENT_ACCESS_DENIED", 0, true }, // 0x0A
null_command_factory, // 0x0B
null_command_factory, // 0x0C
null_command_factory, // 0x0D
null_command_factory, // 0x0E
null_command_factory, // 0x0F
{ "TOCLIENT_INIT", 0, true }, // 0x10
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
{ "TOCLIENT_INIT", 0, true }, // 0x10
null_command_factory, // 0x11
null_command_factory, // 0x12
null_command_factory, // 0x13
null_command_factory, // 0x14
null_command_factory, // 0x15
null_command_factory, // 0x16
null_command_factory, // 0x17
null_command_factory, // 0x18
null_command_factory, // 0x19
null_command_factory, // 0x1A
null_command_factory, // 0x1B
null_command_factory, // 0x1C
null_command_factory, // 0x1D
null_command_factory, // 0x1E
null_command_factory, // 0x1F
{ "TOCLIENT_BLOCKDATA", 2, true }, // 0x20
{ "TOCLIENT_ADDNODE", 0, true }, // 0x21
{ "TOCLIENT_REMOVENODE", 0, true }, // 0x22
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory, // 0x23
null_command_factory, // 0x24
null_command_factory, // 0x25
null_command_factory, // 0x26
{ "TOCLIENT_INVENTORY", 0, true }, // 0x27
null_command_factory,
null_command_factory, // 0x28
{ "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", 0, true }, // 0x2A
{ "TOCLIENT_PLAYER_SPEED", 0, true }, // 0x2B
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory, // 0x2C
null_command_factory, // 0x2D
null_command_factory, // 0x2E
{ "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F
null_command_factory, // 0x30
{ "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", 0, true }, // 0x31
{ "TOCLIENT_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 Special packet, sent by 0 (rel) and 1 (unrel) channel
{ "TOCLIENT_HP", 0, true }, // 0x33
{ "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34
{ "TOCLIENT_ACCESS_DENIED_LEGACY", 0, true }, // 0x35
null_command_factory, // 0x36
{ "TOCLIENT_FOV", 0, true }, // 0x36
{ "TOCLIENT_DEATHSCREEN", 0, true }, // 0x37
{ "TOCLIENT_MEDIA", 2, true }, // 0x38
null_command_factory, // 0x39
{ "TOCLIENT_NODEDEF", 0, true }, // 0x3a
null_command_factory, // 0x3b
{ "TOCLIENT_ANNOUNCE_MEDIA", 0, true }, // 0x3c
{ "TOCLIENT_ITEMDEF", 0, true }, // 0x3d
null_command_factory,
{ "TOCLIENT_NODEDEF", 0, true }, // 0x3A
null_command_factory, // 0x3B
{ "TOCLIENT_ANNOUNCE_MEDIA", 0, true }, // 0x3C
{ "TOCLIENT_ITEMDEF", 0, true }, // 0x3D
null_command_factory, // 0x3E
{ "TOCLIENT_PLAY_SOUND", 0, true }, // 0x3f
{ "TOCLIENT_STOP_SOUND", 0, true }, // 0x40
{ "TOCLIENT_PRIVILEGES", 0, true }, // 0x41
Expand Down Expand Up @@ -203,12 +203,12 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_MODCHANNEL_MSG", 0, true }, // 0x57
{ "TOCLIENT_MODCHANNEL_SIGNAL", 0, true }, // 0x58
{ "TOCLIENT_NODEMETA_CHANGED", 0, true }, // 0x59
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory,
null_command_factory, // 0x5A
null_command_factory, // 0x5B
null_command_factory, // 0x5C
null_command_factory, // 0x5D
null_command_factory, // 0x5E
null_command_factory, // 0x5F
{ "TOSERVER_SRP_BYTES_S_B", 0, true }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61
};
18 changes: 18 additions & 0 deletions src/player.h
Expand Up @@ -32,6 +32,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
#define PLAYERNAME_ALLOWED_CHARS_USER_EXPL "'a' to 'z', 'A' to 'Z', '0' to '9', '-', '_'"

struct PlayerFovSpec
{
f32 fov;
bool is_multiplier;
};

struct PlayerControl
{
PlayerControl() = default;
Expand Down Expand Up @@ -178,6 +184,16 @@ class Player
void setWieldIndex(u16 index);
u16 getWieldIndex() const { return m_wield_index; }

void setFov(const PlayerFovSpec &spec)
{
m_fov_spec = spec;
}

const PlayerFovSpec &getFov() const
{
return m_fov_spec;
}

u32 keyPressed = 0;

HudElement* getHud(u32 id);
Expand All @@ -187,10 +203,12 @@ class Player

u32 hud_flags;
s32 hud_hotbar_itemcount;

protected:
char m_name[PLAYERNAME_SIZE];
v3f m_speed;
u16 m_wield_index = 0;
PlayerFovSpec m_fov_spec = { 0.0f, false };

std::vector<HudElement *> hud;
private:
Expand Down
33 changes: 33 additions & 0 deletions src/script/lua_api/l_object.cpp
Expand Up @@ -1249,6 +1249,37 @@ int ObjectRef::l_set_look_yaw(lua_State *L)
return 1;
}

// set_fov(self, degrees[, is_multiplier])
int ObjectRef::l_set_fov(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (!player)
return 0;

player->setFov({ static_cast<f32>(luaL_checknumber(L, 2)), readParam<bool>(L, 3) });
getServer(L)->SendPlayerFov(player->getPeerId());

return 0;
}

// get_fov(self)
int ObjectRef::l_get_fov(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (!player)
return 0;

PlayerFovSpec fov_spec = player->getFov();
lua_pushnumber(L, fov_spec.fov);
lua_pushboolean(L, fov_spec.is_multiplier);

return 2;
}

// set_breath(self, breath)
int ObjectRef::l_set_breath(lua_State *L)
{
Expand Down Expand Up @@ -1962,6 +1993,8 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_look_vertical),
luamethod(ObjectRef, set_look_yaw),
luamethod(ObjectRef, set_look_pitch),
luamethod(ObjectRef, get_fov),
luamethod(ObjectRef, set_fov),
luamethod(ObjectRef, get_breath),
luamethod(ObjectRef, set_breath),
luamethod(ObjectRef, get_attribute),
Expand Down
6 changes: 6 additions & 0 deletions src/script/lua_api/l_object.h
Expand Up @@ -215,6 +215,9 @@ class ObjectRef : public ModApiBase {
// add_player_velocity(self, {x=num, y=num, z=num})
static int l_add_player_velocity(lua_State *L);

// get_fov(self)
static int l_get_fov(lua_State *L);

// get_look_dir(self)
static int l_get_look_dir(lua_State *L);

Expand All @@ -232,6 +235,9 @@ class ObjectRef : public ModApiBase {
// get_look_yaw2(self)
static int l_get_look_horizontal(lua_State *L);

// set_fov(self, degrees, is_multiplier)
static int l_set_fov(lua_State *L);

// set_look_vertical(self, radians)
static int l_set_look_vertical(lua_State *L);

Expand Down