]> git.lizzy.rs Git - minetest.git/blobdiff - src/network/clientpackethandler.cpp
Replace std::list<session_t> in networking code (#10215)
[minetest.git] / src / network / clientpackethandler.cpp
index 8d0225a3dce73c50ec8fe8e4e923187217ce9505..8d87ff8f215e7ebb98031df8fc7dc80b248d4e2b 100644 (file)
@@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "script/scripting_client.h"
 #include "util/serialize.h"
 #include "util/srp.h"
+#include "util/sha1.h"
 #include "tileanimation.h"
 #include "gettext.h"
 #include "skyparams.h"
@@ -207,6 +208,9 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
                m_access_denied_reconnect = reconnect & 1;
        } else if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
                *pkt >> m_access_denied_reason;
+       } else if (denyCode == SERVER_ACCESSDENIED_TOO_MANY_USERS) {
+               m_access_denied_reason = accessDeniedStrings[denyCode];
+               m_access_denied_reconnect = true;
        } else if (denyCode < SERVER_ACCESSDENIED_MAX) {
                m_access_denied_reason = accessDeniedStrings[denyCode];
        } else {
@@ -958,114 +962,66 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
        std::string datastring(pkt->getString(0), pkt->getSize());
        std::istringstream is(datastring, std::ios_base::binary);
 
-       v3f pos                 = readV3F32(is);
-       v3f vel                 = readV3F32(is);
-       v3f acc                 = readV3F32(is);
-       float expirationtime    = readF32(is);
-       float size              = readF32(is);
-       bool collisiondetection = readU8(is);
-       std::string texture     = deSerializeLongString(is);
-
-       bool vertical          = false;
-       bool collision_removal = false;
-       TileAnimationParams animation;
-       animation.type         = TAT_NONE;
-       u8 glow                = 0;
-       bool object_collision  = false;
-       try {
-               vertical = readU8(is);
-               collision_removal = readU8(is);
-               animation.deSerialize(is, m_proto_ver);
-               glow = readU8(is);
-               object_collision = readU8(is);
-       } catch (...) {}
+       ParticleParameters p;
+       p.deSerialize(is, m_proto_ver);
 
        ClientEvent *event = new ClientEvent();
-       event->type                              = CE_SPAWN_PARTICLE;
-       event->spawn_particle.pos                = new v3f (pos);
-       event->spawn_particle.vel                = new v3f (vel);
-       event->spawn_particle.acc                = new v3f (acc);
-       event->spawn_particle.expirationtime     = expirationtime;
-       event->spawn_particle.size               = size;
-       event->spawn_particle.collisiondetection = collisiondetection;
-       event->spawn_particle.collision_removal  = collision_removal;
-       event->spawn_particle.object_collision   = object_collision;
-       event->spawn_particle.vertical           = vertical;
-       event->spawn_particle.texture            = new std::string(texture);
-       event->spawn_particle.animation          = animation;
-       event->spawn_particle.glow               = glow;
+       event->type           = CE_SPAWN_PARTICLE;
+       event->spawn_particle = new ParticleParameters(p);
 
        m_client_event_queue.push(event);
 }
 
 void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
 {
-       u16 amount;
-       float spawntime;
-       v3f minpos;
-       v3f maxpos;
-       v3f minvel;
-       v3f maxvel;
-       v3f minacc;
-       v3f maxacc;
-       float minexptime;
-       float maxexptime;
-       float minsize;
-       float maxsize;
-       bool collisiondetection;
-       u32 server_id;
-
-       *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
-               >> minacc >> maxacc >> minexptime >> maxexptime >> minsize
-               >> maxsize >> collisiondetection;
-
-       std::string texture = pkt->readLongString();
-
-       *pkt >> server_id;
-
-       bool vertical          = false;
-       bool collision_removal = false;
-       u16 attached_id        = 0;
-       TileAnimationParams animation;
-       animation.type         = TAT_NONE;
-       u8 glow                = 0;
-       bool object_collision  = false;
-       try {
-               *pkt >> vertical;
-               *pkt >> collision_removal;
-               *pkt >> attached_id;
+       std::string datastring(pkt->getString(0), pkt->getSize());
+       std::istringstream is(datastring, std::ios_base::binary);
 
-               // 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);
-               object_collision = readU8(is);
-       } catch (...) {}
+       ParticleSpawnerParameters p;
+       u32 server_id;
+       u16 attached_id = 0;
+
+       p.amount             = readU16(is);
+       p.time               = readF32(is);
+       p.minpos             = readV3F32(is);
+       p.maxpos             = readV3F32(is);
+       p.minvel             = readV3F32(is);
+       p.maxvel             = readV3F32(is);
+       p.minacc             = readV3F32(is);
+       p.maxacc             = readV3F32(is);
+       p.minexptime         = readF32(is);
+       p.maxexptime         = readF32(is);
+       p.minsize            = readF32(is);
+       p.maxsize            = readF32(is);
+       p.collisiondetection = readU8(is);
+       p.texture            = deSerializeLongString(is);
+
+       server_id = readU32(is);
+
+       p.vertical = readU8(is);
+       p.collision_removal = readU8(is);
+
+       attached_id = readU16(is);
+
+       p.animation.deSerialize(is, m_proto_ver);
+       p.glow = readU8(is);
+       p.object_collision = readU8(is);
+
+       // This is kinda awful
+       do {
+               u16 tmp_param0 = readU16(is);
+               if (is.eof())
+                       break;
+               p.node.param0 = tmp_param0;
+               p.node.param2 = readU8(is);
+               p.node_tile   = readU8(is);
+       } while (0);
 
        auto event = new ClientEvent();
-       event->type                                   = CE_ADD_PARTICLESPAWNER;
-       event->add_particlespawner.amount             = amount;
-       event->add_particlespawner.spawntime          = spawntime;
-       event->add_particlespawner.minpos             = new v3f (minpos);
-       event->add_particlespawner.maxpos             = new v3f (maxpos);
-       event->add_particlespawner.minvel             = new v3f (minvel);
-       event->add_particlespawner.maxvel             = new v3f (maxvel);
-       event->add_particlespawner.minacc             = new v3f (minacc);
-       event->add_particlespawner.maxacc             = new v3f (maxacc);
-       event->add_particlespawner.minexptime         = minexptime;
-       event->add_particlespawner.maxexptime         = maxexptime;
-       event->add_particlespawner.minsize            = minsize;
-       event->add_particlespawner.maxsize            = maxsize;
-       event->add_particlespawner.collisiondetection = collisiondetection;
-       event->add_particlespawner.collision_removal  = collision_removal;
-       event->add_particlespawner.object_collision   = object_collision;
-       event->add_particlespawner.attached_id        = attached_id;
-       event->add_particlespawner.vertical           = vertical;
-       event->add_particlespawner.texture            = new std::string(texture);
-       event->add_particlespawner.id                 = server_id;
-       event->add_particlespawner.animation          = animation;
-       event->add_particlespawner.glow               = glow;
+       event->type                            = CE_ADD_PARTICLESPAWNER;
+       event->add_particlespawner.p           = new ParticleSpawnerParameters(p);
+       event->add_particlespawner.attached_id = attached_id;
+       event->add_particlespawner.id          = server_id;
 
        m_client_event_queue.push(event);
 }
@@ -1102,22 +1058,16 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        v3f world_pos;
        v2s32 size;
        s16 z_index = 0;
+       std::string text2;
 
        *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
                >> dir >> align >> offset;
        try {
                *pkt >> world_pos;
-       }
-       catch(SerializationError &e) {};
-
-       try {
                *pkt >> size;
-       } catch(SerializationError &e) {};
-
-       try {
                *pkt >> z_index;
-       }
-       catch(PacketError &e) {}
+               *pkt >> text2;
+       } catch(PacketError &e) {};
 
        ClientEvent *event = new ClientEvent();
        event->type             = CE_HUDADD;
@@ -1135,6 +1085,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        event->hudadd.world_pos = new v3f(world_pos);
        event->hudadd.size      = new v2s32(size);
        event->hudadd.z_index   = z_index;
+       event->hudadd.text2     = new std::string(text2);
        m_client_event_queue.push(event);
 }
 
@@ -1171,7 +1122,7 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
        if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
                stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
                *pkt >> v2fdata;
-       else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
+       else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2)
                *pkt >> sdata;
        else if (stat == HUD_STAT_WORLD_POS)
                *pkt >> v3fdata;
@@ -1524,6 +1475,51 @@ void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
        player->addVelocity(added_vel);
 }
 
+void Client::handleCommand_MediaPush(NetworkPacket *pkt)
+{
+       std::string raw_hash, filename, filedata;
+       bool cached;
+
+       *pkt >> raw_hash >> filename >> cached;
+       filedata = pkt->readLongString();
+
+       if (raw_hash.size() != 20 || filedata.empty() || filename.empty() ||
+                       !string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
+               throw PacketError("Illegal filename, data or hash");
+       }
+
+       verbosestream << "Server pushes media file \"" << filename << "\" with "
+               << filedata.size() << " bytes of data (cached=" << cached
+               << ")" << std::endl;
+
+       if (m_media_pushed_files.count(filename) != 0) {
+               // Silently ignore for synchronization purposes
+               return;
+       }
+
+       // Compute and check checksum of data
+       std::string computed_hash;
+       {
+               SHA1 ctx;
+               ctx.addBytes(filedata.c_str(), filedata.size());
+               unsigned char *buf = ctx.getDigest();
+               computed_hash.assign((char*) buf, 20);
+               free(buf);
+       }
+       if (raw_hash != computed_hash) {
+               verbosestream << "Hash of file data mismatches, ignoring." << std::endl;
+               return;
+       }
+
+       // Actually load media
+       loadMedia(filedata, filename, true);
+       m_media_pushed_files.insert(filename);
+
+       // Cache file for the next time when this client joins the same server
+       if (cached)
+               clientMediaUpdateCache(raw_hash, filedata);
+}
+
 /*
  * Mod channels
  */