mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Add support for per-player FOV overrides and multipliers
This commit is contained in:
parent
5c9983400f
commit
47da640d77
@ -5580,12 +5580,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.
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -193,6 +193,7 @@ public:
|
||||
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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
@ -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
|
||||
|
@ -523,13 +523,22 @@ void Client::handleCommand_Movement(NetworkPacket* pkt)
|
||||
player->movement_gravity = g * BS;
|
||||
}
|
||||
|
||||
void Client::handleCommand_HP(NetworkPacket* pkt)
|
||||
void Client::handleCommand_Fov(NetworkPacket *pkt)
|
||||
{
|
||||
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;
|
||||
|
@ -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
|
||||
@ -370,7 +371,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,
|
||||
/*
|
||||
|
@ -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 };
|
||||
@ -115,51 +115,51 @@ 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
|
||||
@ -167,15 +167,15 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
|
||||
{ "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
|
||||
@ -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
src/player.h
18
src/player.h
@ -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;
|
||||
@ -178,6 +184,16 @@ public:
|
||||
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);
|
||||
@ -187,10 +203,12 @@ public:
|
||||
|
||||
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:
|
||||
|
@ -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)
|
||||
{
|
||||
@ -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),
|
||||
|
@ -215,6 +215,9 @@ private:
|
||||
// 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);
|
||||
|
||||
@ -232,6 +235,9 @@ private:
|
||||
// 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);
|
||||
|
||||
|
@ -1765,6 +1765,16 @@ void Server::SendMovePlayer(session_t peer_id)
|
||||
Send(&pkt);
|
||||
}
|
||||
|
||||
void Server::SendPlayerFov(session_t peer_id)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_FOV, 4 + 1, peer_id);
|
||||
|
||||
PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov();
|
||||
pkt << fov_spec.fov << fov_spec.is_multiplier;
|
||||
|
||||
Send(&pkt);
|
||||
}
|
||||
|
||||
void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
|
||||
f32 animation_speed)
|
||||
{
|
||||
|
@ -336,6 +336,7 @@ public:
|
||||
void SendInventory(PlayerSAO *playerSAO, bool incremental);
|
||||
void SendMovePlayer(session_t peer_id);
|
||||
void SendPlayerSpeed(session_t peer_id, const v3f &added_vel);
|
||||
void SendPlayerFov(session_t peer_id);
|
||||
|
||||
void sendDetachedInventories(session_t peer_id, bool incremental);
|
||||
|
||||
@ -515,7 +516,6 @@ private:
|
||||
/*
|
||||
Variables
|
||||
*/
|
||||
|
||||
// World directory
|
||||
std::string m_path_world;
|
||||
// Subgame specification
|
||||
@ -575,7 +575,6 @@ private:
|
||||
/*
|
||||
Threads
|
||||
*/
|
||||
|
||||
// A buffer for time steps
|
||||
// step() increments and AsyncRunStep() run by m_thread reads it.
|
||||
float m_step_dtime = 0.0f;
|
||||
@ -590,14 +589,14 @@ private:
|
||||
/*
|
||||
Time related stuff
|
||||
*/
|
||||
|
||||
// Timer for sending time of day over network
|
||||
float m_time_of_day_send_timer = 0.0f;
|
||||
// Uptime of server in seconds
|
||||
MutexedVariable<double> m_uptime;
|
||||
|
||||
/*
|
||||
Client interface
|
||||
*/
|
||||
Client interface
|
||||
*/
|
||||
ClientInterface m_clients;
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user