summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/clientopcodes.cpp12
-rw-r--r--src/network/clientopcodes.h2
-rw-r--r--src/network/clientpackethandler.cpp127
-rw-r--r--src/network/connection.cpp22
-rw-r--r--src/network/connection.h18
-rw-r--r--src/network/networkpacket.cpp8
-rw-r--r--src/network/networkpacket.h11
-rw-r--r--src/network/networkprotocol.h45
-rw-r--r--src/network/serveropcodes.cpp8
-rw-r--r--src/network/serveropcodes.h2
-rw-r--r--src/network/serverpackethandler.cpp180
11 files changed, 261 insertions, 174 deletions
diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp
index 3364de8c5..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,
@@ -193,7 +193,7 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
null_command_factory, // 0x3f
{ "TOSERVER_REQUEST_MEDIA", 1, true }, // 0x40
{ "TOSERVER_RECEIVED_MEDIA", 1, true }, // 0x41
- { "TOSERVER_BREATH", 0, true }, // 0x42
+ { "TOSERVER_BREATH", 0, true }, // 0x42 old TOSERVER_BREATH. Ignored by servers
{ "TOSERVER_CLIENT_READY", 0, true }, // 0x43
null_command_factory, // 0x44
null_command_factory, // 0x45
diff --git a/src/network/clientopcodes.h b/src/network/clientopcodes.h
index 9143865b8..43a93bb4f 100644
--- a/src/network/clientopcodes.h
+++ b/src/network/clientopcodes.h
@@ -41,7 +41,7 @@ struct ToClientCommandHandler
struct ServerCommandFactory
{
const char* name;
- u16 channel;
+ u8 channel;
bool reliable;
};
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 411982f69..59669fe6d 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -30,8 +30,10 @@ 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/scripting_client.h"
#include "util/serialize.h"
#include "util/srp.h"
+#include "tileanimation.h"
void Client::handleCommand_Deprecated(NetworkPacket* pkt)
{
@@ -140,7 +142,7 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
}
void Client::handleCommand_DenySudoMode(NetworkPacket* pkt)
{
- m_chat_queue.push(L"Password change denied. Password NOT changed.");
+ pushToChatQueue(L"Password change denied. Password NOT changed.");
// reset everything and be sad
deleteAuthData();
}
@@ -410,7 +412,10 @@ void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
message += (wchar_t)read_wchar;
}
- m_chat_queue.push(message);
+ // If chat message not consummed by client lua API
+ if (!moddingEnabled() || !m_script->on_receiving_message(wide_to_utf8(message))) {
+ pushToChatQueue(message);
+ }
}
void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
@@ -521,6 +526,10 @@ void Client::handleCommand_HP(NetworkPacket* pkt)
player->hp = hp;
+ if (moddingEnabled()) {
+ m_script->on_hp_modification(hp);
+ }
+
if (hp < oldhp) {
// Add to ClientEvent queue
ClientEvent event;
@@ -552,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"
@@ -578,11 +586,6 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
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)
{
bool set_camera_point_target;
@@ -709,11 +712,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: "
@@ -724,9 +722,7 @@ void Client::handleCommand_NodeDef(NetworkPacket* pkt)
sanity_check(!m_mesh_update_thread.isRunning());
// Decompress node definitions
- std::string datastring(pkt->getString(0), pkt->getSize());
- std::istringstream is(datastring, std::ios_base::binary);
- std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
+ std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
std::ostringstream tmp_os;
decompressZlib(tmp_is, tmp_os);
@@ -736,11 +732,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: "
@@ -751,9 +742,7 @@ void Client::handleCommand_ItemDef(NetworkPacket* pkt)
sanity_check(!m_mesh_update_thread.isRunning());
// Decompress item definitions
- std::string datastring(pkt->getString(0), pkt->getSize());
- std::istringstream is(datastring, std::ios_base::binary);
- std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
+ std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
std::ostringstream tmp_os;
decompressZlib(tmp_is, tmp_os);
@@ -765,21 +754,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);
@@ -818,6 +825,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();
@@ -896,9 +918,14 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
std::string texture = deSerializeLongString(is);
bool vertical = false;
bool collision_removal = false;
+ struct TileAnimationParams animation;
+ animation.type = TAT_NONE;
+ u8 glow = 0;
try {
vertical = readU8(is);
collision_removal = readU8(is);
+ animation.deSerialize(is, m_proto_ver);
+ glow = readU8(is);
} catch (...) {}
ClientEvent event;
@@ -912,6 +939,8 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
event.spawn_particle.collision_removal = collision_removal;
event.spawn_particle.vertical = vertical;
event.spawn_particle.texture = new std::string(texture);
+ event.spawn_particle.animation = animation;
+ event.spawn_particle.glow = glow;
m_client_event_queue.push(event);
}
@@ -943,12 +972,20 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
bool vertical = false;
bool collision_removal = false;
+ struct TileAnimationParams animation;
+ animation.type = TAT_NONE;
+ u8 glow = 0;
u16 attached_id = 0;
try {
*pkt >> vertical;
*pkt >> collision_removal;
*pkt >> attached_id;
+ // This is horrible but required (why are there two ways to deserialize pkts?)
+ std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes());
+ std::istringstream is(datastring, std::ios_base::binary);
+ animation.deSerialize(is, m_proto_ver);
+ glow = readU8(is);
} catch (...) {}
ClientEvent event;
@@ -971,6 +1008,8 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
event.add_particlespawner.vertical = vertical;
event.add_particlespawner.texture = new std::string(texture);
event.add_particlespawner.id = id;
+ event.add_particlespawner.animation = animation;
+ event.add_particlespawner.glow = glow;
m_client_event_queue.push(event);
}
@@ -1111,10 +1150,10 @@ 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_mapper->setMinimapMode(MINIMAP_MODE_OFF);
+ m_minimap->setMinimapMode(MINIMAP_MODE_OFF);
}
}
@@ -1153,11 +1192,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 b711cae11..fb3ba92ae 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;
@@ -1237,7 +1237,7 @@ void UDPPeer::RunCommandQueues(
u16 UDPPeer::getNextSplitSequenceNumber(u8 channel)
{
assert(channel < CHANNEL_COUNT); // Pre-condition
- return channels[channel].readNextIncomingSeqNum();
+ return channels[channel].readNextSplitSeqNum();
}
void UDPPeer::setNextSplitSequenceNumber(u8 channel, u16 seqnum)
@@ -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
diff --git a/src/network/connection.h b/src/network/connection.h
index 5ee53b9d4..8b7ed9773 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_;
diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp
index 388afc18e..f7a6499dd 100644
--- a/src/network/networkpacket.cpp
+++ b/src/network/networkpacket.cpp
@@ -63,7 +63,7 @@ void NetworkPacket::putRawPacket(u8 *data, u32 datasize, u16 peer_id)
m_data = std::vector<u8>(&data[2], &data[2 + m_datasize]);
}
-char* NetworkPacket::getString(u32 from_offset)
+const char* NetworkPacket::getString(u32 from_offset)
{
checkReadOffset(from_offset, 0);
@@ -105,7 +105,7 @@ NetworkPacket& NetworkPacket::operator>>(std::string& dst)
return *this;
}
-NetworkPacket& NetworkPacket::operator<<(std::string src)
+NetworkPacket& NetworkPacket::operator<<(const std::string &src)
{
u16 msgsize = src.size();
if (msgsize > STRING_MAX_LEN) {
@@ -119,7 +119,7 @@ NetworkPacket& NetworkPacket::operator<<(std::string src)
return *this;
}
-void NetworkPacket::putLongString(std::string src)
+void NetworkPacket::putLongString(const std::string &src)
{
u32 msgsize = src.size();
if (msgsize > LONG_STRING_MAX_LEN) {
@@ -155,7 +155,7 @@ NetworkPacket& NetworkPacket::operator>>(std::wstring& dst)
return *this;
}
-NetworkPacket& NetworkPacket::operator<<(std::wstring src)
+NetworkPacket& NetworkPacket::operator<<(const std::wstring &src)
{
u16 msgsize = src.size();
if (msgsize > WIDE_STRING_MAX_LEN) {
diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h
index 524470999..83dc33f6f 100644
--- a/src/network/networkpacket.h
+++ b/src/network/networkpacket.h
@@ -41,20 +41,23 @@ public:
u16 getPeerId() { return m_peer_id; }
u16 getCommand() { return m_command; }
const u32 getRemainingBytes() const { return m_datasize - m_read_offset; }
+ const char* getRemainingString() { return getString(m_read_offset); }
// Returns a c-string without copying.
// A better name for this would be getRawString()
- char* getString(u32 from_offset);
+ const char* getString(u32 from_offset);
// major difference to putCString(): doesn't write len into the buffer
void putRawString(const char* src, u32 len);
+ void putRawString(const std::string &src)
+ { putRawString(src.c_str(), src.size()); }
NetworkPacket& operator>>(std::string& dst);
- NetworkPacket& operator<<(std::string src);
+ NetworkPacket& operator<<(const std::string &src);
- void putLongString(std::string src);
+ void putLongString(const std::string &src);
NetworkPacket& operator>>(std::wstring& dst);
- NetworkPacket& operator<<(std::wstring src);
+ NetworkPacket& operator<<(const std::wstring &src);
std::string readLongString();
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 018b392b6..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)
@@ -138,19 +140,34 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Add nodedef v3 - connected nodeboxes
PROTOCOL_VERSION 28:
CPT2_MESHOPTIONS
+ PROTOCOL_VERSION 29:
+ Server doesn't accept TOSERVER_BREATH anymore
+ serialization of TileAnimation params changed
+ TAT_SHEET_2D
+ Removed client-sided chat perdiction
+ PROTOCOL VERSION 30:
+ New ContentFeatures serialization version
+ 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 28
+#define LATEST_PROTOCOL_VERSION 32
// Server's supported network protocol range
-#define SERVER_PROTOCOL_VERSION_MIN 13
+#define SERVER_PROTOCOL_VERSION_MIN 24
#define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
// Client's supported network protocol range
// The minimal version depends on whether
// send_pre_v25_init is enabled or not
#define CLIENT_PROTOCOL_VERSION_MIN 25
-#define CLIENT_PROTOCOL_VERSION_MIN_LEGACY 13
+#define CLIENT_PROTOCOL_VERSION_MIN_LEGACY 24
#define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
// Constant that differentiates the protocol from random data and other protocols
@@ -567,6 +584,7 @@ enum ToClientCommand
foreach count:
u8 len
u8[len] param
+ u8 clouds (boolean)
*/
TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO = 0x50,
@@ -595,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.
@@ -833,7 +868,7 @@ enum ToServerCommand
<no payload data>
*/
- TOSERVER_BREATH = 0x42,
+ TOSERVER_BREATH = 0x42, // Obsolete
/*
u16 breath
*/
diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp
index 9b14a1be3..19978a2b6 100644
--- a/src/network/serveropcodes.cpp
+++ b/src/network/serveropcodes.cpp
@@ -89,8 +89,8 @@ 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_BREATH", TOSERVER_STATE_INGAME, &Server::handleCommand_Breath }, // 0x42
+ { "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
null_command_handler, // 0x45
@@ -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/serveropcodes.h b/src/network/serveropcodes.h
index aa3301069..72323ae24 100644
--- a/src/network/serveropcodes.h
+++ b/src/network/serveropcodes.h
@@ -41,7 +41,7 @@ struct ToServerCommandHandler
struct ClientCommandFactory
{
const char* name;
- u16 channel;
+ u8 channel;
bool reliable;
};
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index dca9aabc4..5b026bbdb 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -23,10 +23,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_abm.h"
#include "content_sao.h"
#include "emerge.h"
+#include "mapblock.h"
#include "nodedef.h"
#include "player.h"
#include "rollback_interface.h"
-#include "scripting_game.h"
+#include "scripting_server.h"
#include "settings.h"
#include "tool.h"
#include "version.h"
@@ -613,20 +614,6 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
u16 protocol_version = m_clients.getProtocolVersion(pkt->getPeerId());
- ///// begin compatibility code
- PlayerSAO* playersao = NULL;
- if (protocol_version <= 22) {
- playersao = StageTwoClientInit(pkt->getPeerId());
-
- if (playersao == NULL) {
- actionstream
- << "TOSERVER_INIT2 stage 2 client init failed for peer "
- << pkt->getPeerId() << std::endl;
- return;
- }
- }
- ///// end compatibility code
-
/*
Send some initialization data
*/
@@ -656,13 +643,6 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
float time_speed = g_settings->getFloat("time_speed");
SendTimeOfDay(pkt->getPeerId(), time, time_speed);
- ///// begin compatibility code
- if (protocol_version <= 22) {
- m_clients.event(pkt->getPeerId(), CSE_SetClientReady);
- m_script->on_joinplayer(playersao);
- }
- ///// end compatibility code
-
// Warnings about protocol version can be issued here
if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) {
SendChatMessage(pkt->getPeerId(), L"# Server: WARNING: YOUR CLIENT'S "
@@ -694,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();
@@ -742,6 +718,13 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
m_clients.event(peer_id, CSE_SetClientReady);
m_script->on_joinplayer(playersao);
+ // Send shutdown timer if shutdown has been scheduled
+ if (m_shutdown_timer > 0.0f) {
+ std::wstringstream ws;
+ ws << L"*** Server shutting down in "
+ << duration_to_string(myround(m_shutdown_timer)).c_str() << ".";
+ SendChatMessage(pkt->getPeerId(), ws.str());
+ }
}
void Server::handleCommand_GotBlocks(NetworkPacket* pkt)
@@ -810,7 +793,7 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
v3f speed((f32)ss.X / 100.0, (f32)ss.Y / 100.0, (f32)ss.Z / 100.0);
pitch = modulo360f(pitch);
- yaw = modulo360f(yaw);
+ yaw = wrapDegrees_0_360(yaw);
playersao->setBasePosition(position);
player->setSpeed(speed);
@@ -1021,6 +1004,15 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
delete a;
return;
}
+
+ // Disallow dropping items if dead
+ if (playersao->isDead()) {
+ infostream << "Ignoring IDropAction from "
+ << (da->from_inv.dump()) << ":" << da->from_list
+ << " because player is dead." << std::endl;
+ delete a;
+ return;
+ }
}
/*
Handle restrictions and special cases of the craft action
@@ -1118,6 +1110,13 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
}
if (g_settings->getBool("enable_damage")) {
+ if (playersao->isDead()) {
+ verbosestream << "Server::ProcessData(): Info: "
+ "Ignoring damage as player " << player->getName()
+ << " is already dead." << std::endl;
+ return;
+ }
+
actionstream << player->getName() << " damaged by "
<< (int)damage << " hp at " << PP(playersao->getBasePosition() / BS)
<< std::endl;
@@ -1127,46 +1126,6 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
}
}
-void Server::handleCommand_Breath(NetworkPacket* pkt)
-{
- u16 breath;
-
- *pkt >> breath;
-
- RemotePlayer *player = m_env->getPlayer(pkt->getPeerId());
-
- if (player == NULL) {
- errorstream << "Server::ProcessData(): Canceling: "
- "No player for peer_id=" << pkt->getPeerId()
- << " disconnecting peer!" << std::endl;
- m_con.DisconnectPeer(pkt->getPeerId());
- return;
- }
-
-
- PlayerSAO *playersao = player->getPlayerSAO();
- if (playersao == NULL) {
- errorstream << "Server::ProcessData(): Canceling: "
- "No player object for peer_id=" << pkt->getPeerId()
- << " disconnecting peer!" << std::endl;
- m_con.DisconnectPeer(pkt->getPeerId());
- return;
- }
-
- /*
- * If player is dead, we don't need to update the breath
- * He is dead !
- */
- if (playersao->isDead()) {
- verbosestream << "TOSERVER_BREATH: " << player->getName()
- << " is dead. Ignoring packet";
- return;
- }
-
- playersao->setBreath(breath);
- SendPlayerBreath(pkt->getPeerId());
-}
-
void Server::handleCommand_Password(NetworkPacket* pkt)
{
if (pkt->getSize() != PASSWORD_SIZE * 2)
@@ -1313,6 +1272,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
2: digging completed
3: place block or item (to abovesurface)
4: use item
+ 5: rightclick air ("activate")
*/
u8 action;
u16 item_i;
@@ -1345,8 +1305,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
}
if (playersao->isDead()) {
- verbosestream << "TOSERVER_INTERACT: " << player->getName()
- << " is dead. Ignoring packet";
+ actionstream << "Server: NoCheat: " << player->getName()
+ << " tried to interact while dead; ignoring." << std::endl;
+ if (pointed.type == POINTEDTHING_NODE) {
+ // Re-send block to revert change on client-side
+ RemoteClient *client = getClient(pkt->getPeerId());
+ v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface);
+ client->SetBlockNotSent(blockpos);
+ }
+ // Call callbacks
+ m_script->on_cheat(playersao, "interacted_while_dead");
return;
}
@@ -1385,15 +1353,48 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
}
/*
+ Make sure the player is allowed to do it
+ */
+ if (!checkPriv(player->getName(), "interact")) {
+ actionstream<<player->getName()<<" attempted to interact with "
+ <<pointed.dump()<<" without 'interact' privilege"
+ <<std::endl;
+ // Re-send block to revert change on client-side
+ RemoteClient *client = getClient(pkt->getPeerId());
+ // Digging completed -> under
+ if (action == 2) {
+ v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
+ client->SetBlockNotSent(blockpos);
+ }
+ // Placement -> above
+ if (action == 3) {
+ v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
+ client->SetBlockNotSent(blockpos);
+ }
+ return;
+ }
+
+ /*
Check that target is reasonably close
(only when digging or placing things)
*/
static const bool enable_anticheat = !g_settings->getBool("disable_anticheat");
- if ((action == 0 || action == 2 || action == 3) &&
+ if ((action == 0 || action == 2 || action == 3 || action == 4) &&
(enable_anticheat && !isSingleplayer())) {
float d = player_pos.getDistanceFrom(pointed_pos_under);
- float max_d = BS * 14; // Just some large enough value
- if (d > max_d) {
+ 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: "
@@ -1411,28 +1412,6 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
}
/*
- Make sure the player is allowed to do it
- */
- if (!checkPriv(player->getName(), "interact")) {
- actionstream<<player->getName()<<" attempted to interact with "
- <<pointed.dump()<<" without 'interact' privilege"
- <<std::endl;
- // Re-send block to revert change on client-side
- RemoteClient *client = getClient(pkt->getPeerId());
- // Digging completed -> under
- if (action == 2) {
- v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
- client->SetBlockNotSent(blockpos);
- }
- // Placement -> above
- if (action == 3) {
- v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
- client->SetBlockNotSent(blockpos);
- }
- return;
- }
-
- /*
If something goes wrong, this player is to blame
*/
RollbackScopeActor rollback_scope(m_rollback,
@@ -1443,11 +1422,6 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
*/
if (action == 0) {
if (pointed.type == POINTEDTHING_NODE) {
- /*
- NOTE: This can be used in the future to check if
- somebody is cheating, by checking the timing.
- */
-
MapNode n(CONTENT_IGNORE);
bool pos_ok;
@@ -1475,7 +1449,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
<<pointed.object_id<<": "
<<pointed_object->getDescription()<<std::endl;
- ItemStack punchitem = playersao->getWieldedItem();
+ ItemStack punchitem = playersao->getWieldedItemOrHand();
ToolCapabilities toolcap =
punchitem.getToolCapabilities(m_itemdef);
v3f dir = (pointed_object->getBasePosition() -
@@ -1542,7 +1516,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
m_script->on_cheat(playersao, "finished_unknown_dig");
}
// Get player's wielded item
- ItemStack playeritem = playersao->getWieldedItem();
+ ItemStack playeritem = playersao->getWieldedItemOrHand();
ToolCapabilities playeritem_toolcap =
playeritem.getToolCapabilities(m_itemdef);
// Get diggability and expected digging time
@@ -1550,7 +1524,9 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
&playeritem_toolcap);
// If can't dig, try hand
if (!params.diggable) {
- const ItemDefinition &hand = m_itemdef->get("");
+ InventoryList *hlist = playersao->getInventory()->getList("hand");
+ const ItemDefinition &hand =
+ hlist ? hlist->getItem(0).getDefinition(m_itemdef) : m_itemdef->get("");
const ToolCapabilities *tp = hand.tool_capabilities;
if (tp)
params = getDigParams(m_nodedef->get(n).groups, tp);