]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/network/clientpackethandler.cpp
Lua API: Particle callbacks; Add NoWeather
[dragonfireclient.git] / src / network / clientpackethandler.cpp
index e000acc928d767a56d6c27386a5bf522a14e30a2..55f85571d3bbe0972e48373f2df370d463730e68 100644 (file)
@@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include <iostream>
 #include "client/client.h"
 
 #include "util/base64.h"
@@ -33,12 +34,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "server.h"
 #include "util/strfnd.h"
 #include "client/clientevent.h"
+#include "client/content_cao.h"
 #include "client/sound.h"
 #include "network/clientopcodes.h"
 #include "network/connection.h"
 #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 +210,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 {
@@ -444,7 +450,10 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
                        string initialization data
                }
        */
-
+       
+       LocalPlayer *player = m_env.getLocalPlayer();
+       bool try_reattach = player && player->isWaitingForReattach();   
+       
        try {
                u8 type;
                u16 removed_count, added_count, id;
@@ -463,6 +472,8 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
                for (u16 i = 0; i < added_count; i++) {
                        *pkt >> id >> type;
                        m_env.addActiveObject(id, type, pkt->readLongString());
+                       if (try_reattach)
+                               player->tryReattach(id);
                }
        } catch (PacketError &e) {
                infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
@@ -493,7 +504,7 @@ void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
                        if (!is.good())
                                break;
 
-                       std::string message = deSerializeString(is);
+                       std::string message = deSerializeString16(is);
 
                        // Pass on to the environment
                        m_env.processActiveObjectMessage(id, message);
@@ -585,16 +596,19 @@ void Client::handleCommand_Breath(NetworkPacket* pkt)
 }
 
 void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
-{
+{              
        LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
+       if ((player->getCAO() && player->getCAO()->getParentId()) || player->isWaitingForReattach())
+               return;
+       
        v3f pos;
        f32 pitch, yaw;
 
        *pkt >> pos >> pitch >> yaw;
 
-       player->setPosition(pos);
+       player->setLegitPosition(pos);
 
        infostream << "Client got TOCLIENT_MOVE_PLAYER"
                        << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
@@ -608,6 +622,10 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
                it would just force the pitch and yaw values to whatever
                the camera points to.
        */
+       
+       if (g_settings->getBool("no_force_rotate"))
+               return;
+       
        ClientEvent *event = new ClientEvent();
        event->type = CE_PLAYER_FORCE_MOVE;
        event->player_force_move.pitch = pitch;
@@ -815,7 +833,12 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
                *pkt >> pitch;
                *pkt >> ephemeral;
        } catch (PacketError &e) {};
-
+       
+       SimpleSoundSpec sound_spec(name, gain, fade, pitch);
+       
+       if (m_mods_loaded && m_script->on_play_sound(sound_spec))
+               return;
+       
        // Start playing
        int client_id = -1;
        switch(type) {
@@ -964,7 +987,10 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
        ClientEvent *event = new ClientEvent();
        event->type           = CE_SPAWN_PARTICLE;
        event->spawn_particle = new ParticleParameters(p);
-
+       
+       if (m_mods_loaded && m_script->on_spawn_particle(*event->spawn_particle))
+               return;
+       
        m_client_event_queue.push(event);
 }
 
@@ -990,7 +1016,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
        p.minsize            = readF32(is);
        p.maxsize            = readF32(is);
        p.collisiondetection = readU8(is);
-       p.texture            = deSerializeLongString(is);
+       p.texture            = deSerializeString32(is);
 
        server_id = readU32(is);
 
@@ -1157,18 +1183,33 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
        player->hud_flags &= ~mask;
        player->hud_flags |= flags;
 
+       if (g_settings->getBool("hud_flags_bypass"))
+               player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE     | HUD_FLAG_HEALTHBAR_VISIBLE |
+                       HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
+                       HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE   |
+                       HUD_FLAG_MINIMAP_RADAR_VISIBLE;
+
        m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
        bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
 
+       // Not so satisying code to keep compatibility with old fixed mode system
+       // -->
+
        // Hide minimap if it has been disabled by the server
        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);
-
-       // Switch to surface mode if radar disabled by server
-       if (m_minimap && m_minimap_radar_disabled_by_server && was_minimap_radar_visible)
-               m_minimap->setMinimapMode(MINIMAP_MODE_SURFACEx1);
+               m_minimap->setModeIndex(0);
+
+       // If radar has been disabled, try to find a non radar mode or fall back to 0
+       if (m_minimap && m_minimap_radar_disabled_by_server
+                       && was_minimap_radar_visible) {
+               while (m_minimap->getModeIndex() > 0 &&
+                               m_minimap->getModeDef().type == MINIMAP_TYPE_RADAR)
+                       m_minimap->nextMode();
+       }
+       // <--
+       // End of 'not so satifying code'
 }
 
 void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
@@ -1203,11 +1244,11 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
 
                SkyboxParams skybox;
                skybox.bgcolor = video::SColor(readARGB8(is));
-               skybox.type = std::string(deSerializeString(is));
+               skybox.type = std::string(deSerializeString16(is));
                u16 count = readU16(is);
 
                for (size_t i = 0; i < count; i++)
-                       skybox.textures.emplace_back(deSerializeString(is));
+                       skybox.textures.emplace_back(deSerializeString16(is));
 
                skybox.clouds = true;
                try {
@@ -1462,6 +1503,8 @@ void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt)
 
 void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
 {
+       if (g_settings->getBool("antiknockback"))
+               return;
        v3f added_vel;
 
        *pkt >> added_vel;
@@ -1471,6 +1514,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
  */
@@ -1562,3 +1650,30 @@ void Client::handleCommand_ModChannelSignal(NetworkPacket *pkt)
        if (valid_signal)
                m_script->on_modchannel_signal(channel, signal);
 }
+
+void Client::handleCommand_MinimapModes(NetworkPacket *pkt)
+{
+       u16 count; // modes
+       u16 mode;  // wanted current mode index after change
+
+       *pkt >> count >> mode;
+
+       if (m_minimap)
+               m_minimap->clearModes();
+
+       for (size_t index = 0; index < count; index++) {
+               u16 type;
+               std::string label;
+               u16 size;
+               std::string texture;
+               u16 scale;
+
+               *pkt >> type >> label >> size >> texture >> scale;
+
+               if (m_minimap)
+                       m_minimap->addMode(MinimapType(type), size, label, texture, scale);
+       }
+
+       if (m_minimap)
+               m_minimap->setModeIndex(mode);
+}