C++11 cleanup inventorymanager (#6077)
[oweals/minetest.git] / src / network / clientpackethandler.cpp
index 6d42edd7d8055f276c0fbee12c06a3f446f2a76a..e6f0d7092fbfacf5d4df6f9a626082c99843f794 100644 (file)
@@ -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)
 {
@@ -110,7 +112,7 @@ void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
        playerpos -= v3f(0, BS / 2, 0);
 
        // Set player position
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
        player->setPosition(playerpos);
 
@@ -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();
 }
@@ -176,7 +178,7 @@ void Client::handleCommand_InitLegacy(NetworkPacket* pkt)
 
 
        // Set player position
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
        player->setPosition(playerpos_f);
 
@@ -333,7 +335,7 @@ void Client::handleCommand_Inventory(NetworkPacket* pkt)
        std::string datastring(pkt->getString(0), pkt->getSize());
        std::istringstream is(datastring, std::ios_base::binary);
 
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        player->inventory.deSerialize(is);
@@ -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)
@@ -486,7 +491,7 @@ void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
 
 void Client::handleCommand_Movement(NetworkPacket* pkt)
 {
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
@@ -511,7 +516,7 @@ void Client::handleCommand_Movement(NetworkPacket* pkt)
 void Client::handleCommand_HP(NetworkPacket* pkt)
 {
 
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        u8 oldhp   = player->hp;
@@ -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;
@@ -532,7 +541,7 @@ void Client::handleCommand_HP(NetworkPacket* pkt)
 
 void Client::handleCommand_Breath(NetworkPacket* pkt)
 {
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        u16 breath;
@@ -544,7 +553,7 @@ void Client::handleCommand_Breath(NetworkPacket* pkt)
 
 void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
 {
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        v3f pos;
@@ -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;
@@ -634,7 +637,6 @@ void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
                m_media_downloader->addFile(name, sha1_raw);
        }
 
-       std::vector<std::string> remote_media;
        try {
                std::string str;
 
@@ -681,8 +683,7 @@ void Client::handleCommand_Media(NetworkPacket* pkt)
        if (num_files == 0)
                return;
 
-       if (m_media_downloader == NULL ||
-                       !m_media_downloader->isStarted()) {
+       if (!m_media_downloader || !m_media_downloader->isStarted()) {
                const char *problem = m_media_downloader ?
                        "media has not been requested" :
                        "all media has been received already";
@@ -710,11 +711,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: "
@@ -725,9 +721,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);
 
@@ -737,11 +731,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: "
@@ -752,9 +741,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);
 
@@ -766,31 +753,52 @@ 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
+               [30 + len] f32 pitch
+       */
+
        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.0f;
+       float pitch = 1.0f;
 
        *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
 
+       try {
+               *pkt >> fade;
+               *pkt >> pitch;
+       } 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, pitch);
                        break;
                case 1: // positional
-                       client_id = m_sound->playSoundAt(name, loop, gain, pos);
+                       client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
                        break;
                case 2:
                { // object
                        ClientActiveObject *cao = m_env.getActiveObject(object_id);
                        if (cao)
                                pos = cao->getPosition();
-                       client_id = m_sound->playSoundAt(name, loop, gain, pos);
+                       client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
                        // TODO: Set up sound to move with object
                        break;
                }
@@ -812,13 +820,28 @@ void Client::handleCommand_StopSound(NetworkPacket* pkt)
 
        *pkt >> server_id;
 
-       UNORDERED_MAP<s32, int>::iterator i = m_sounds_server_to_client.find(server_id);
+       std::unordered_map<s32, int>::iterator i = m_sounds_server_to_client.find(server_id);
        if (i != m_sounds_server_to_client.end()) {
                int client_id = i->second;
                m_sound->stopSound(client_id);
        }
 }
 
+void Client::handleCommand_FadeSound(NetworkPacket *pkt)
+{
+       s32 sound_id;
+       float step;
+       float gain;
+
+       *pkt >> sound_id >> step >> gain;
+
+       std::unordered_map<s32, int>::const_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();
@@ -840,7 +863,7 @@ void Client::handleCommand_Privileges(NetworkPacket* pkt)
 
 void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
 {
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        // Store formspec in LocalPlayer
@@ -897,9 +920,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;
@@ -913,6 +941,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);
 }
@@ -944,10 +974,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;
@@ -966,9 +1006,12 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
        event.add_particlespawner.maxsize            = maxsize;
        event.add_particlespawner.collisiondetection = collisiondetection;
        event.add_particlespawner.collision_removal  = collision_removal;
+       event.add_particlespawner.attached_id        = attached_id;
        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);
 }
@@ -1098,7 +1141,7 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
 
        *pkt >> flags >> mask;
 
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        bool was_minimap_visible = player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE;
@@ -1109,10 +1152,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);
        }
 }
 
@@ -1122,7 +1165,7 @@ void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
 
        *pkt >> param >> value;
 
-       Player *player = m_env.getLocalPlayer();
+       LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
        if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
@@ -1131,10 +1174,22 @@ void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
                        player->hud_hotbar_itemcount = hotbar_itemcount;
        }
        else if (param == HUD_PARAM_HOTBAR_IMAGE) {
-               ((LocalPlayer *) player)->hotbar_image = value;
+               // 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) {
-               ((LocalPlayer *) player)->hotbar_selected_image = value;
+               // 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;
        }
 }
 
@@ -1151,11 +1206,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);
 }
 
@@ -1195,6 +1284,28 @@ void Client::handleCommand_EyeOffset(NetworkPacket* pkt)
        *pkt >> player->eye_offset_first >> player->eye_offset_third;
 }
 
+void Client::handleCommand_UpdatePlayerList(NetworkPacket* pkt)
+{
+       u8 type;
+       u16 num_players;
+       *pkt >> type >> num_players;
+       PlayerListModifer notice_type = (PlayerListModifer) type;
+
+       for (u16 i = 0; i < num_players; i++) {
+               std::string name;
+               *pkt >> name;
+               switch (notice_type) {
+               case PLAYER_LIST_INIT:
+               case PLAYER_LIST_ADD:
+                       m_env.addPlayerName(name);
+                       continue;
+               case PLAYER_LIST_REMOVE:
+                       m_env.removePlayerName(name);
+                       continue;
+               }
+       }
+}
+
 void Client::handleCommand_SrpBytesSandB(NetworkPacket* pkt)
 {
        if ((m_chosen_auth_mech != AUTH_MECHANISM_LEGACY_PASSWORD)