aboutsummaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/clientopcodes.cpp10
-rw-r--r--src/network/clientpackethandler.cpp105
-rw-r--r--src/network/connection.cpp47
-rw-r--r--src/network/connection.h23
-rw-r--r--src/network/networkpacket.cpp13
-rw-r--r--src/network/networkpacket.h2
-rw-r--r--src/network/networkprotocol.h29
-rw-r--r--src/network/serveropcodes.cpp6
-rw-r--r--src/network/serverpackethandler.cpp85
9 files changed, 227 insertions, 93 deletions
diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp
index cee402acd..bdcb1dfce 100644
--- a/src/network/clientopcodes.cpp
+++ b/src/network/clientopcodes.cpp
@@ -78,12 +78,12 @@ 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
- { "TOCLIENT_PLAYERITEM", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_PlayerItem }, // 0x36
+ null_command_handler,
{ "TOCLIENT_DEATHSCREEN", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreen }, // 0x37
{ "TOCLIENT_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Media }, // 0x38
- { "TOCLIENT_TOOLDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ToolDef }, // 0x39
+ null_command_handler,
{ "TOCLIENT_NODEDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_NodeDef }, // 0x3a
- { "TOCLIENT_CRAFTITEMDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CraftItemDef }, // 0x3b
+ null_command_handler,
{ "TOCLIENT_ANNOUNCE_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_AnnounceMedia }, // 0x3c
{ "TOCLIENT_ITEMDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ItemDef }, // 0x3d
null_command_handler,
@@ -108,8 +108,8 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_LOCAL_PLAYER_ANIMATIONS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_LocalPlayerAnimations }, // 0x51
{ "TOCLIENT_EYE_OFFSET", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_EyeOffset }, // 0x52
{ "TOCLIENT_DELETE_PARTICLESPAWNER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeleteParticleSpawner }, // 0x53
- null_command_handler,
- null_command_handler,
+ { "TOCLIENT_CLOUD_PARAMS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CloudParams }, // 0x54
+ { "TOCLIENT_FADE_SOUND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FadeSound }, // 0x55
null_command_handler,
null_command_handler,
null_command_handler,
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 19f8bbf58..0d4b792de 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server.h"
#include "util/strfnd.h"
#include "network/clientopcodes.h"
-#include "script/clientscripting.h"
+#include "script/scripting_client.h"
#include "util/serialize.h"
#include "util/srp.h"
#include "tileanimation.h"
@@ -561,7 +561,6 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
*pkt >> pos >> pitch >> yaw;
- player->got_teleported = true;
player->setPosition(pos);
infostream << "Client got TOCLIENT_MOVE_PLAYER"
@@ -581,15 +580,6 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
event.player_force_move.pitch = pitch;
event.player_force_move.yaw = yaw;
m_client_event_queue.push(event);
-
- // Ignore damage for a few seconds, so that the player doesn't
- // get damage from falling on ground
- m_ignore_damage_timer = 3.0;
-}
-
-void Client::handleCommand_PlayerItem(NetworkPacket* pkt)
-{
- warningstream << "Client: Ignoring TOCLIENT_PLAYERITEM" << std::endl;
}
void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
@@ -718,11 +708,6 @@ void Client::handleCommand_Media(NetworkPacket* pkt)
}
}
-void Client::handleCommand_ToolDef(NetworkPacket* pkt)
-{
- warningstream << "Client: Ignoring TOCLIENT_TOOLDEF" << std::endl;
-}
-
void Client::handleCommand_NodeDef(NetworkPacket* pkt)
{
infostream << "Client: Received node definitions: packet size: "
@@ -743,11 +728,6 @@ void Client::handleCommand_NodeDef(NetworkPacket* pkt)
m_nodedef_received = true;
}
-void Client::handleCommand_CraftItemDef(NetworkPacket* pkt)
-{
- warningstream << "Client: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl;
-}
-
void Client::handleCommand_ItemDef(NetworkPacket* pkt)
{
infostream << "Client: Received item definitions: packet size: "
@@ -770,21 +750,39 @@ void Client::handleCommand_ItemDef(NetworkPacket* pkt)
void Client::handleCommand_PlaySound(NetworkPacket* pkt)
{
+ /*
+ [0] u32 server_id
+ [4] u16 name length
+ [6] char name[len]
+ [ 6 + len] f32 gain
+ [10 + len] u8 type
+ [11 + len] (f32 * 3) pos
+ [23 + len] u16 object_id
+ [25 + len] bool loop
+ [26 + len] f32 fade
+ */
+
s32 server_id;
std::string name;
+
float gain;
u8 type; // 0=local, 1=positional, 2=object
v3f pos;
u16 object_id;
bool loop;
+ float fade = 0;
*pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
+ try {
+ *pkt >> fade;
+ } catch (PacketError &e) {};
+
// Start playing
int client_id = -1;
switch(type) {
case 0: // local
- client_id = m_sound->playSound(name, loop, gain);
+ client_id = m_sound->playSound(name, loop, gain, fade);
break;
case 1: // positional
client_id = m_sound->playSoundAt(name, loop, gain, pos);
@@ -823,6 +821,21 @@ void Client::handleCommand_StopSound(NetworkPacket* pkt)
}
}
+void Client::handleCommand_FadeSound(NetworkPacket *pkt)
+{
+ s32 sound_id;
+ float step;
+ float gain;
+
+ *pkt >> sound_id >> step >> gain;
+
+ UNORDERED_MAP<s32, int>::iterator i =
+ m_sounds_server_to_client.find(sound_id);
+
+ if (i != m_sounds_server_to_client.end())
+ m_sound->fadeSound(i->second, step, gain);
+}
+
void Client::handleCommand_Privileges(NetworkPacket* pkt)
{
m_privileges.clear();
@@ -1133,7 +1146,7 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
// Hide minimap if it has been disabled by the server
- if (m_minimap_disabled_by_server && was_minimap_visible) {
+ if (m_minimap && m_minimap_disabled_by_server && was_minimap_visible) {
// defers a minimap update, therefore only call it if really
// needed, by checking that minimap was visible before
m_minimap->setMinimapMode(MINIMAP_MODE_OFF);
@@ -1155,9 +1168,21 @@ void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
player->hud_hotbar_itemcount = hotbar_itemcount;
}
else if (param == HUD_PARAM_HOTBAR_IMAGE) {
+ // If value not empty verify image exists in texture source
+ if (value != "" && !getTextureSource()->isKnownSourceImage(value)) {
+ errorstream << "Server sent wrong Hud hotbar image (sent value: '"
+ << value << "')" << std::endl;
+ return;
+ }
player->hotbar_image = value;
}
else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
+ // If value not empty verify image exists in texture source
+ if (value != "" && !getTextureSource()->isKnownSourceImage(value)) {
+ errorstream << "Server sent wrong Hud hotbar selected image (sent value: '"
+ << value << "')" << std::endl;
+ return;
+ }
player->hotbar_selected_image = value;
}
}
@@ -1175,11 +1200,45 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
for (size_t i = 0; i < count; i++)
params->push_back(deSerializeString(is));
+ bool clouds = true;
+ try {
+ clouds = readU8(is);
+ } catch (...) {}
+
ClientEvent event;
event.type = CE_SET_SKY;
event.set_sky.bgcolor = bgcolor;
event.set_sky.type = type;
event.set_sky.params = params;
+ event.set_sky.clouds = clouds;
+ m_client_event_queue.push(event);
+}
+
+void Client::handleCommand_CloudParams(NetworkPacket* pkt)
+{
+ f32 density;
+ video::SColor color_bright;
+ video::SColor color_ambient;
+ f32 height;
+ f32 thickness;
+ v2f speed;
+
+ *pkt >> density >> color_bright >> color_ambient
+ >> height >> thickness >> speed;
+
+ ClientEvent event;
+ event.type = CE_CLOUD_PARAMS;
+ event.cloud_params.density = density;
+ // use the underlying u32 representation, because we can't
+ // use struct members with constructors here, and this way
+ // we avoid using new() and delete() for no good reason
+ event.cloud_params.color_bright = color_bright.color;
+ event.cloud_params.color_ambient = color_ambient.color;
+ event.cloud_params.height = height;
+ event.cloud_params.thickness = thickness;
+ // same here: deconstruct to skip constructor
+ event.cloud_params.speed_x = speed.X;
+ event.cloud_params.speed_y = speed.Y;
m_client_event_queue.push(event);
}
diff --git a/src/network/connection.cpp b/src/network/connection.cpp
index e11b4a953..a504bbc08 100644
--- a/src/network/connection.cpp
+++ b/src/network/connection.cpp
@@ -54,7 +54,8 @@ Mutex log_message_mutex;
#endif
-static inline float CALC_DTIME(unsigned int lasttime, unsigned int curtime) {
+static inline float CALC_DTIME(u64 lasttime, u64 curtime)
+{
float value = ( curtime - lasttime) / 1000.0;
return MYMAX(MYMIN(value,0.1),0.0);
}
@@ -930,7 +931,7 @@ void Peer::DecUseCount()
delete this;
}
-void Peer::RTTStatistics(float rtt, std::string profiler_id,
+void Peer::RTTStatistics(float rtt, const std::string &profiler_id,
unsigned int num_samples) {
if (m_last_rtt > 0) {
@@ -969,8 +970,7 @@ void Peer::RTTStatistics(float rtt, std::string profiler_id,
m_rtt.jitter_avg = m_rtt.jitter_avg * (num_samples/(num_samples-1)) +
jitter * (1/num_samples);
- if (profiler_id != "")
- {
+ if (profiler_id != "") {
g_profiler->graphAdd(profiler_id + "_rtt", rtt);
g_profiler->graphAdd(profiler_id + "_jitter", jitter);
}
@@ -982,7 +982,7 @@ void Peer::RTTStatistics(float rtt, std::string profiler_id,
bool Peer::isTimedOut(float timeout)
{
MutexAutoLock lock(m_exclusive_access_mutex);
- u32 current_time = porting::getTimeMs();
+ u64 current_time = porting::getTimeMs();
float dtime = CALC_DTIME(m_last_timeout_check,current_time);
m_last_timeout_check = current_time;
@@ -1277,8 +1277,8 @@ void * ConnectionSendThread::run()
LOG(dout_con<<m_connection->getDesc()
<<"ConnectionSend thread started"<<std::endl);
- u32 curtime = porting::getTimeMs();
- u32 lasttime = curtime;
+ u64 curtime = porting::getTimeMs();
+ u64 lasttime = curtime;
PROFILE(std::stringstream ThreadIdentifier);
PROFILE(ThreadIdentifier << "ConnectionSend: [" << m_connection->getDesc() << "]");
@@ -2047,8 +2047,8 @@ void * ConnectionReceiveThread::run()
PROFILE(ThreadIdentifier << "ConnectionReceive: [" << m_connection->getDesc() << "]");
#ifdef DEBUG_CONNECTION_KBPS
- u32 curtime = porting::getTimeMs();
- u32 lasttime = curtime;
+ u64 curtime = porting::getTimeMs();
+ u64 lasttime = curtime;
float debug_print_timer = 0.0;
#endif
@@ -2391,7 +2391,7 @@ SharedBuffer<u8> ConnectionReceiveThread::processPacket(Channel *channel,
// only calculate rtt from straight sent packets
if (p.resend_count == 0) {
// Get round trip time
- unsigned int current_time = porting::getTimeMs();
+ u64 current_time = porting::getTimeMs();
// a overflow is quite unlikely but as it'd result in major
// rtt miscalculation we handle it here
@@ -2884,16 +2884,21 @@ void Connection::Disconnect()
putCommand(c);
}
-void Connection::Receive(NetworkPacket* pkt)
+bool Connection::Receive(NetworkPacket *pkt, u32 timeout)
{
+ /*
+ Note that this function can potentially wait infinitely if non-data
+ events keep happening before the timeout expires.
+ This is not considered to be a problem (is it?)
+ */
for(;;) {
- ConnectionEvent e = waitEvent(m_bc_receive_timeout);
+ ConnectionEvent e = waitEvent(timeout);
if (e.type != CONNEVENT_NONE)
LOG(dout_con << getDesc() << ": Receive: got event: "
<< e.describe() << std::endl);
switch(e.type) {
case CONNEVENT_NONE:
- throw NoIncomingDataException("No incoming data");
+ return false;
case CONNEVENT_DATA_RECEIVED:
// Data size is lesser than command size, ignoring packet
if (e.data.getSize() < 2) {
@@ -2901,7 +2906,7 @@ void Connection::Receive(NetworkPacket* pkt)
}
pkt->putRawPacket(*e.data, e.data.getSize(), e.peer_id);
- return;
+ return true;
case CONNEVENT_PEER_ADDED: {
UDPPeer tmp(e.peer_id, e.address, this);
if (m_bc_peerhandler)
@@ -2919,7 +2924,19 @@ void Connection::Receive(NetworkPacket* pkt)
"(port already in use?)");
}
}
- throw NoIncomingDataException("No incoming data");
+ return false;
+}
+
+void Connection::Receive(NetworkPacket *pkt)
+{
+ bool any = Receive(pkt, m_bc_receive_timeout);
+ if (!any)
+ throw NoIncomingDataException("No incoming data");
+}
+
+bool Connection::TryReceive(NetworkPacket *pkt)
+{
+ return Receive(pkt, 0);
}
void Connection::Send(u16 peer_id, u8 channelnum,
diff --git a/src/network/connection.h b/src/network/connection.h
index 5ee53b9d4..a202fa2f5 100644
--- a/src/network/connection.h
+++ b/src/network/connection.h
@@ -175,7 +175,7 @@ struct BufferedPacket
Buffer<u8> data; // Data of the packet, including headers
float time; // Seconds from buffering the packet or re-sending
float totaltime; // Seconds from buffering the packet
- unsigned int absolute_send_time;
+ u64 absolute_send_time;
Address address; // Sender or destination
unsigned int resend_count;
};
@@ -383,7 +383,7 @@ struct OutgoingPacket
bool reliable;
bool ack;
- OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_,
+ OutgoingPacket(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_,
bool reliable_,bool ack_=false):
peer_id(peer_id_),
channelnum(channelnum_),
@@ -448,7 +448,7 @@ struct ConnectionCommand
reliable = reliable_;
}
- void ack(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_)
+ void ack(u16 peer_id_, u8 channelnum_, const SharedBuffer<u8> &data_)
{
type = CONCMD_ACK;
peer_id = peer_id_;
@@ -457,7 +457,7 @@ struct ConnectionCommand
reliable = false;
}
- void createPeer(u16 peer_id_, SharedBuffer<u8> data_)
+ void createPeer(u16 peer_id_, const SharedBuffer<u8> &data_)
{
type = CONCMD_CREATE_PEER;
peer_id = peer_id_;
@@ -467,7 +467,7 @@ struct ConnectionCommand
raw = true;
}
- void disableLegacy(u16 peer_id_, SharedBuffer<u8> data_)
+ void disableLegacy(u16 peer_id_, const SharedBuffer<u8> &data_)
{
type = CONCMD_DISABLE_LEGACY;
peer_id = peer_id_;
@@ -732,8 +732,8 @@ class Peer {
virtual void reportRTT(float rtt) {};
void RTTStatistics(float rtt,
- std::string profiler_id="",
- unsigned int num_samples=1000);
+ const std::string &profiler_id = "",
+ unsigned int num_samples = 1000);
bool IncUseCount();
void DecUseCount();
@@ -769,7 +769,7 @@ class Peer {
// Seconds from last receive
float m_timeout_counter;
- u32 m_last_timeout_check;
+ u64 m_last_timeout_check;
};
class UDPPeer : public Peer
@@ -874,7 +874,7 @@ struct ConnectionEvent
return "Invalid ConnectionEvent";
}
- void dataReceived(u16 peer_id_, SharedBuffer<u8> data_)
+ void dataReceived(u16 peer_id_, const SharedBuffer<u8> &data_)
{
type = CONNEVENT_DATA_RECEIVED;
peer_id = peer_id_;
@@ -1016,6 +1016,7 @@ public:
bool Connected();
void Disconnect();
void Receive(NetworkPacket* pkt);
+ bool TryReceive(NetworkPacket* pkt);
void Send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
u16 GetPeerID() { return m_peer_id; }
Address GetPeerAddress(u16 peer_id);
@@ -1050,6 +1051,8 @@ protected:
UDPSocket m_udpSocket;
MutexedQueue<ConnectionCommand> m_command_queue;
+ bool Receive(NetworkPacket *pkt, u32 timeout);
+
void putEvent(ConnectionEvent &e);
void TriggerSend()
@@ -1074,7 +1077,7 @@ private:
// Backwards compatibility
PeerHandler *m_bc_peerhandler;
int m_bc_receive_timeout;
-
+
bool m_shutting_down;
u16 m_next_remote_peer_id;
diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp
index f7a6499dd..7c2c7d0f9 100644
--- a/src/network/networkpacket.cpp
+++ b/src/network/networkpacket.cpp
@@ -58,9 +58,20 @@ void NetworkPacket::putRawPacket(u8 *data, u32 datasize, u16 peer_id)
m_datasize = datasize - 2;
m_peer_id = peer_id;
+ m_data.resize(m_datasize);
+
// split command and datas
m_command = readU16(&data[0]);
- m_data = std::vector<u8>(&data[2], &data[2 + m_datasize]);
+ memcpy(m_data.data(), &data[2], m_datasize);
+}
+
+void NetworkPacket::clear()
+{
+ m_data.clear();
+ m_datasize = 0;
+ m_read_offset = 0;
+ m_command = 0;
+ m_peer_id = 0;
}
const char* NetworkPacket::getString(u32 from_offset)
diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h
index 83dc33f6f..fc14d61d8 100644
--- a/src/network/networkpacket.h
+++ b/src/network/networkpacket.h
@@ -35,7 +35,7 @@ public:
~NetworkPacket();
void putRawPacket(u8 *data, u32 datasize, u16 peer_id);
-
+ void clear();
// Getters
u32 getSize() { return m_datasize; }
u16 getPeerId() { return m_peer_id; }
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index ea532d9e0..7126c237b 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
ContentFeatures and NodeDefManager use a different serialization
format; better for future version cross-compatibility
Many things
+ Obsolete TOCLIENT_PLAYERITEM
PROTOCOL_VERSION 10:
TOCLIENT_PRIVILEGES
Version raised to force 'fly' and 'fast' privileges into effect.
@@ -104,7 +105,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
PROTOCOL_VERSION 22:
add swap_node
PROTOCOL_VERSION 23:
- TOSERVER_CLIENT_READY
+ Obsolete TOSERVER_RECEIVED_MEDIA
+ Server: Stop using TOSERVER_CLIENT_READY
PROTOCOL_VERSION 24:
ContentFeatures version 7
ContentFeatures: change number of special tiles to 6 (CF_SPECIAL_COUNT)
@@ -148,9 +150,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Add node and tile color and palette
Fix plantlike visual_scale being applied squared and add compatibility
with pre-30 clients by sending sqrt(visual_scale)
+ PROTOCOL VERSION 31:
+ Add tile overlay
+ Stop sending TOSERVER_CLIENT_READY
+ PROTOCOL VERSION 32:
+ Add fading sounds
*/
-#define LATEST_PROTOCOL_VERSION 30
+#define LATEST_PROTOCOL_VERSION 32
// Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 24
@@ -577,6 +584,7 @@ enum ToClientCommand
foreach count:
u8 len
u8[len] param
+ u8 clouds (boolean)
*/
TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO = 0x50,
@@ -605,6 +613,23 @@ enum ToClientCommand
u32 id
*/
+ TOCLIENT_CLOUD_PARAMS = 0x54,
+ /*
+ f1000 density
+ u8[4] color_diffuse (ARGB)
+ u8[4] color_ambient (ARGB)
+ f1000 height
+ f1000 thickness
+ v2f1000 speed
+ */
+
+ TOCLIENT_FADE_SOUND = 0x55,
+ /*
+ s32 sound_id
+ float step
+ float gain
+ */
+
TOCLIENT_SRP_BYTES_S_B = 0x60,
/*
Belonging to AUTH_MECHANISM_LEGACY_PASSWORD and AUTH_MECHANISM_SRP.
diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp
index 642dd376a..19978a2b6 100644
--- a/src/network/serveropcodes.cpp
+++ b/src/network/serveropcodes.cpp
@@ -89,7 +89,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
null_command_handler, // 0x3e
null_command_handler, // 0x3f
{ "TOSERVER_REQUEST_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_RequestMedia }, // 0x40
- { "TOSERVER_RECEIVED_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_ReceivedMedia }, // 0x41
+ { "TOSERVER_RECEIVED_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_Deprecated }, // 0x41 not used by the server since protocol version 23
{ "TOSERVER_BREATH", TOSERVER_STATE_INGAME, &Server::handleCommand_Deprecated }, // 0x42 Old breath model which is now deprecated for anticheating
{ "TOSERVER_CLIENT_READY", TOSERVER_STATE_STARTUP, &Server::handleCommand_ClientReady }, // 0x43
null_command_handler, // 0x44
@@ -197,8 +197,8 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_LOCAL_PLAYER_ANIMATIONS", 0, true }, // 0x51
{ "TOCLIENT_EYE_OFFSET", 0, true }, // 0x52
{ "TOCLIENT_DELETE_PARTICLESPAWNER", 0, true }, // 0x53
- null_command_factory,
- null_command_factory,
+ { "TOCLIENT_CLOUD_PARAMS", 0, true }, // 0x54
+ { "TOCLIENT_FADE_SOUND", 0, true }, // 0x55
null_command_factory,
null_command_factory,
null_command_factory,
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index 174b827f0..fc64c142e 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h"
#include "player.h"
#include "rollback_interface.h"
-#include "serverscripting.h"
+#include "scripting_server.h"
#include "settings.h"
#include "tool.h"
#include "version.h"
@@ -211,7 +211,7 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
// Enforce user limit.
// Don't enforce for users that have some admin right
- if (m_clients.getClientIDs(CS_Created).size() >= g_settings->getU16("max_users") &&
+ if (m_clients.isUserLimitReached() &&
!checkPriv(playername, "server") &&
!checkPriv(playername, "ban") &&
!checkPriv(playername, "privs") &&
@@ -520,7 +520,7 @@ void Server::handleCommand_Init_Legacy(NetworkPacket* pkt)
// Enforce user limit.
// Don't enforce for users that have some admin right
- if (m_clients.getClientIDs(CS_Created).size() >= g_settings->getU16("max_users") &&
+ if (m_clients.isUserLimitReached() &&
!checkPriv(playername, "server") &&
!checkPriv(playername, "ban") &&
!checkPriv(playername, "privs") &&
@@ -674,10 +674,6 @@ void Server::handleCommand_RequestMedia(NetworkPacket* pkt)
sendRequestedMedia(pkt->getPeerId(), tosend);
}
-void Server::handleCommand_ReceivedMedia(NetworkPacket* pkt)
-{
-}
-
void Server::handleCommand_ClientReady(NetworkPacket* pkt)
{
u16 peer_id = pkt->getPeerId();
@@ -947,6 +943,18 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
(ma->to_inv.type == InventoryLocation::PLAYER) &&
(ma->to_inv.name == player->getName());
+ InventoryLocation *remote = from_inv_is_current_player ?
+ &ma->to_inv : &ma->from_inv;
+
+ // Check for out-of-range interaction
+ if (remote->type == InventoryLocation::NODEMETA) {
+ v3f node_pos = intToFloat(remote->p, BS);
+ v3f player_pos = player->getPlayerSAO()->getBasePosition();
+ f32 d = player_pos.getDistanceFrom(node_pos);
+ if (!checkInteractDistance(player, d, "inventory"))
+ return;
+ }
+
/*
Disable moving items out of craftpreview
*/
@@ -1261,6 +1269,37 @@ void Server::handleCommand_Respawn(NetworkPacket* pkt)
// the previous addition has been successfully removed
}
+bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string what)
+{
+ PlayerSAO *playersao = player->getPlayerSAO();
+ const InventoryList *hlist = playersao->getInventory()->getList("hand");
+ const ItemDefinition &playeritem_def =
+ playersao->getWieldedItem().getDefinition(m_itemdef);
+ const ItemDefinition &hand_def =
+ hlist ? hlist->getItem(0).getDefinition(m_itemdef) : m_itemdef->get("");
+
+ float max_d = BS * playeritem_def.range;
+ float max_d_hand = BS * hand_def.range;
+
+ if (max_d < 0 && max_d_hand >= 0)
+ max_d = max_d_hand;
+ else if (max_d < 0)
+ max_d = BS * 4.0f;
+
+ // cube diagonal: sqrt(3) = 1.732
+ if (d > max_d * 1.732) {
+ actionstream << "Player " << player->getName()
+ << " tried to access " << what
+ << " from too far: "
+ << "d=" << d <<", max_d=" << max_d
+ << ". ignoring." << std::endl;
+ // Call callbacks
+ m_script->on_cheat(playersao, "interacted_too_far");
+ return false;
+ }
+ return true;
+}
+
void Server::handleCommand_Interact(NetworkPacket* pkt)
{
/*
@@ -1384,33 +1423,13 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
*/
static const bool enable_anticheat = !g_settings->getBool("disable_anticheat");
if ((action == 0 || action == 2 || action == 3 || action == 4) &&
- (enable_anticheat && !isSingleplayer())) {
+ enable_anticheat && !isSingleplayer()) {
float d = player_pos.getDistanceFrom(pointed_pos_under);
- const ItemDefinition &playeritem_def =
- playersao->getWieldedItem().getDefinition(m_itemdef);
- float max_d = BS * playeritem_def.range;
- InventoryList *hlist = playersao->getInventory()->getList("hand");
- const ItemDefinition &hand_def =
- hlist ? (hlist->getItem(0).getDefinition(m_itemdef)) : (m_itemdef->get(""));
- float max_d_hand = BS * hand_def.range;
- if (max_d < 0 && max_d_hand >= 0)
- max_d = max_d_hand;
- else if (max_d < 0)
- max_d = BS * 4.0;
- // cube diagonal: sqrt(3) = 1.73
- if (d > max_d * 1.73) {
- actionstream << "Player " << player->getName()
- << " tried to access " << pointed.dump()
- << " from too far: "
- << "d=" << d <<", max_d=" << max_d
- << ". ignoring." << std::endl;
+ if (!checkInteractDistance(player, d, pointed.dump())) {
// Re-send block to revert change on client-side
RemoteClient *client = getClient(pkt->getPeerId());
v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
client->SetBlockNotSent(blockpos);
- // Call callbacks
- m_script->on_cheat(playersao, "interacted_too_far");
- // Do nothing else
return;
}
}
@@ -1445,8 +1464,8 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
playersao->noCheatDigStart(p_under);
}
else if (pointed.type == POINTEDTHING_OBJECT) {
- // Skip if object has been removed
- if (pointed_object->m_removed)
+ // Skip if object can't be interacted with anymore
+ if (pointed_object->isGone())
return;
actionstream<<player->getName()<<" punches object "
@@ -1604,8 +1623,8 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
if (pointed.type == POINTEDTHING_OBJECT) {
// Right click object
- // Skip if object has been removed
- if (pointed_object->m_removed)
+ // Skip if object can't be interacted with anymore
+ if (pointed_object->isGone())
return;
actionstream << player->getName() << " right-clicks object "