]> git.lizzy.rs Git - minetest.git/blobdiff - src/network/clientpackethandler.cpp
set_fov: Add support for time-based transitions (#9705)
[minetest.git] / src / network / clientpackethandler.cpp
index 1ae47d190edadf00a6d15b636446405e63721ba4..6428ed752541f9a7ab07ffadf211be582b95409b 100644 (file)
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "client/client.h"
 
 #include "util/base64.h"
+#include "client/camera.h"
 #include "chatmessage.h"
 #include "client/clientmedia.h"
 #include "log.h"
@@ -40,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/srp.h"
 #include "tileanimation.h"
 #include "gettext.h"
+#include "skyparams.h"
 
 void Client::handleCommand_Deprecated(NetworkPacket* pkt)
 {
@@ -134,6 +136,9 @@ void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
                                        << m_recommended_send_interval<<std::endl;
 
        // Reply to server
+       /*~ DO NOT TRANSLATE THIS LITERALLY!
+       This is a special string which needs to contain the translation's
+       language code (e.g. "de" for German). */
        std::string lang = gettext("LANG_CODE");
        if (lang == "LANG_CODE")
                lang = "";
@@ -333,7 +338,7 @@ void Client::handleCommand_Inventory(NetworkPacket* pkt)
 
        player->inventory.deSerialize(is);
 
-       m_inventory_updated = true;
+       m_update_wielded_item = true;
 
        delete m_inventory_from_server;
        m_inventory_from_server = new Inventory(player->inventory);
@@ -382,10 +387,10 @@ void Client::handleCommand_TimeOfDay(NetworkPacket* pkt)
        m_env.setTimeOfDaySpeed(time_speed);
        m_time_of_day_set = true;
 
-       u32 dr = m_env.getDayNightRatio();
-       infostream << "Client: time_of_day=" << time_of_day
-                       << " time_speed=" << time_speed
-                       << " dr=" << dr << std::endl;
+       //u32 dr = m_env.getDayNightRatio();
+       //infostream << "Client: time_of_day=" << time_of_day
+       //              << " time_speed=" << time_speed
+       //              << " dr=" << dr << std::endl;
 }
 
 void Client::handleCommand_ChatMessage(NetworkPacket *pkt)
@@ -415,7 +420,7 @@ void Client::handleCommand_ChatMessage(NetworkPacket *pkt)
        chatMessage->type = (ChatMessageType) message_type;
 
        // @TODO send this to CSM using ChatMessage object
-       if (moddingEnabled() && m_script->on_receiving_message(
+       if (modsLoaded() && m_script->on_receiving_message(
                        wide_to_utf8(chatMessage->message))) {
                // Message was consumed by CSM and should not be handled by client
                delete chatMessage;
@@ -463,6 +468,10 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
                infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
                                << ". The packet is unreliable, ignoring" << std::endl;
        }
+
+       // m_activeobjects_received is false before the first
+       // TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD packet is received
+       m_activeobjects_received = true;
 }
 
 void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
@@ -519,22 +528,40 @@ void Client::handleCommand_Movement(NetworkPacket* pkt)
        player->movement_gravity                = g * BS;
 }
 
-void Client::handleCommand_HP(NetworkPacket* pkt)
+void Client::handleCommand_Fov(NetworkPacket *pkt)
 {
+       f32 fov;
+       bool is_multiplier = false;
+       f32 transition_time = 0.0f;
+
+       *pkt >> fov >> is_multiplier;
+
+       // Wrap transition_time extraction within a
+       // try-catch to preserve backwards compat
+       try {
+               *pkt >> transition_time;
+       } catch (PacketError &e) {};
+
+       LocalPlayer *player = m_env.getLocalPlayer();
+       assert(player);
+       player->setFov({ fov, is_multiplier, transition_time });
+       m_camera->notifyFovChange();
+}
 
+void Client::handleCommand_HP(NetworkPacket *pkt)
+{
        LocalPlayer *player = m_env.getLocalPlayer();
        assert(player != NULL);
 
-       u16 oldhp   = player->hp;
+       u16 oldhp = player->hp;
 
        u16 hp;
        *pkt >> hp;
 
        player->hp = hp;
 
-       if (moddingEnabled()) {
+       if (modsLoaded())
                m_script->on_hp_modification(hp);
-       }
 
        if (hp < oldhp) {
                // Add to ClientEvent queue
@@ -766,6 +793,7 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
                [25 + len] bool loop
                [26 + len] f32 fade
                [30 + len] f32 pitch
+               [34 + len] bool ephemeral
        */
 
        s32 server_id;
@@ -778,12 +806,14 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
        bool loop;
        float fade = 0.0f;
        float pitch = 1.0f;
+       bool ephemeral = false;
 
        *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
 
        try {
                *pkt >> fade;
                *pkt >> pitch;
+               *pkt >> ephemeral;
        } catch (PacketError &e) {};
 
        // Start playing
@@ -801,7 +831,6 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
                        if (cao)
                                pos = cao->getPosition();
                        client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
-                       // TODO: Set up sound to move with object
                        break;
                }
                default:
@@ -809,8 +838,11 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt)
        }
 
        if (client_id != -1) {
-               m_sounds_server_to_client[server_id] = client_id;
-               m_sounds_client_to_server[client_id] = server_id;
+               // for ephemeral sounds, server_id is not meaningful
+               if (!ephemeral) {
+                       m_sounds_server_to_client[server_id] = client_id;
+                       m_sounds_client_to_server[client_id] = server_id;
+               }
                if (object_id != 0)
                        m_sounds_to_objects[client_id] = object_id;
        }
@@ -1069,6 +1101,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        v2f offset;
        v3f world_pos;
        v2s32 size;
+       s16 z_index = 0;
 
        *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
                >> dir >> align >> offset;
@@ -1081,6 +1114,11 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
                *pkt >> size;
        } catch(SerializationError &e) {};
 
+       try {
+               *pkt >> z_index;
+       }
+       catch(PacketError &e) {}
+
        ClientEvent *event = new ClientEvent();
        event->type             = CE_HUDADD;
        event->hudadd.server_id = server_id;
@@ -1096,6 +1134,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        event->hudadd.offset    = new v2f(offset);
        event->hudadd.world_pos = new v3f(world_pos);
        event->hudadd.size      = new v2s32(size);
+       event->hudadd.z_index   = z_index;
        m_client_event_queue.push(event);
 }
 
@@ -1200,49 +1239,140 @@ 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.empty() && !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.empty() && !getTextureSource()->isKnownSourceImage(value)) {
-                       errorstream << "Server sent wrong Hud hotbar selected image (sent value: '"
-                                       << value << "')" << std::endl;
-                       return;
-               }
                player->hotbar_selected_image = value;
        }
 }
 
 void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
 {
-       std::string datastring(pkt->getString(0), pkt->getSize());
-       std::istringstream is(datastring, std::ios_base::binary);
+       if (m_proto_ver < 39) {
+               // Handle Protocol 38 and below servers with old set_sky,
+               // ensuring the classic look is kept.
+               std::string datastring(pkt->getString(0), pkt->getSize());
+               std::istringstream is(datastring, std::ios_base::binary);
 
-       video::SColor *bgcolor           = new video::SColor(readARGB8(is));
-       std::string *type                = new std::string(deSerializeString(is));
-       u16 count                        = readU16(is);
-       std::vector<std::string> *params = new std::vector<std::string>;
+               SkyboxParams skybox;
+               skybox.bgcolor = video::SColor(readARGB8(is));
+               skybox.type = std::string(deSerializeString(is));
+               u16 count = readU16(is);
+
+               for (size_t i = 0; i < count; i++)
+                       skybox.textures.emplace_back(deSerializeString(is));
+
+               skybox.clouds = true;
+               try {
+                       skybox.clouds = readU8(is);
+               } catch (...) {}
+
+               // Use default skybox settings:
+               SkyboxDefaults sky_defaults;
+               SunParams sun = sky_defaults.getSunDefaults();
+               MoonParams moon = sky_defaults.getMoonDefaults();
+               StarParams stars = sky_defaults.getStarDefaults();
+
+               // Fix for "regular" skies, as color isn't kept:
+               if (skybox.type == "regular") {
+                       skybox.sky_color = sky_defaults.getSkyColorDefaults();
+                       skybox.tint_type = "default";
+                       skybox.moon_tint = video::SColor(255, 255, 255, 255);
+                       skybox.sun_tint = video::SColor(255, 255, 255, 255);
+               }
+               else {
+                       sun.visible = false;
+                       sun.sunrise_visible = false;
+                       moon.visible = false;
+                       stars.visible = false;
+               }
 
-       for (size_t i = 0; i < count; i++)
-               params->push_back(deSerializeString(is));
+               // Skybox, sun, moon and stars ClientEvents:
+               ClientEvent *sky_event = new ClientEvent();
+               sky_event->type = CE_SET_SKY;
+               sky_event->set_sky = new SkyboxParams(skybox);
+               m_client_event_queue.push(sky_event);
+
+               ClientEvent *sun_event = new ClientEvent();
+               sun_event->type = CE_SET_SUN;
+               sun_event->sun_params = new SunParams(sun);
+               m_client_event_queue.push(sun_event);
+
+               ClientEvent *moon_event = new ClientEvent();
+               moon_event->type = CE_SET_MOON;
+               moon_event->moon_params = new MoonParams(moon);
+               m_client_event_queue.push(moon_event);
+
+               ClientEvent *star_event = new ClientEvent();
+               star_event->type = CE_SET_STARS;
+               star_event->star_params = new StarParams(stars);
+               m_client_event_queue.push(star_event);
+       } else {
+               SkyboxParams skybox;
+               u16 texture_count;
+               std::string texture;
+
+               *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >>
+                       skybox.sun_tint >> skybox.moon_tint >> skybox.tint_type;
+
+               if (skybox.type == "skybox") {
+                       *pkt >> texture_count;
+                       for (int i = 0; i < texture_count; i++) {
+                               *pkt >> texture;
+                               skybox.textures.emplace_back(texture);
+                       }
+               }
+               else if (skybox.type == "regular") {
+                       *pkt >> skybox.sky_color.day_sky >> skybox.sky_color.day_horizon
+                               >> skybox.sky_color.dawn_sky >> skybox.sky_color.dawn_horizon
+                               >> skybox.sky_color.night_sky >> skybox.sky_color.night_horizon
+                               >> skybox.sky_color.indoors;
+               }
 
-       bool clouds = true;
-       try {
-               clouds = readU8(is);
-       } catch (...) {}
+               ClientEvent *event = new ClientEvent();
+               event->type = CE_SET_SKY;
+               event->set_sky = new SkyboxParams(skybox);
+               m_client_event_queue.push(event);
+       }
+}
+
+void Client::handleCommand_HudSetSun(NetworkPacket *pkt)
+{
+       SunParams sun;
+
+       *pkt >> sun.visible >> sun.texture>> sun.tonemap
+               >> sun.sunrise >> sun.sunrise_visible >> sun.scale;
+
+       ClientEvent *event = new ClientEvent();
+       event->type        = CE_SET_SUN;
+       event->sun_params  = new SunParams(sun);
+       m_client_event_queue.push(event);
+}
+
+void Client::handleCommand_HudSetMoon(NetworkPacket *pkt)
+{
+       MoonParams moon;
+
+       *pkt >> moon.visible >> moon.texture
+               >> moon.tonemap >> moon.scale;
+
+       ClientEvent *event = new ClientEvent();
+       event->type        = CE_SET_MOON;
+       event->moon_params = new MoonParams(moon);
+       m_client_event_queue.push(event);
+}
+
+void Client::handleCommand_HudSetStars(NetworkPacket *pkt)
+{
+       StarParams stars;
+
+       *pkt >> stars.visible >> stars.count
+               >> stars.starcolor >> stars.scale;
 
        ClientEvent *event = new ClientEvent();
-       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;
+       event->type        = CE_SET_STARS;
+       event->star_params = new StarParams(stars);
+
        m_client_event_queue.push(event);
 }
 
@@ -1383,6 +1513,17 @@ void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt)
        loadMods();
 }
 
+void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
+{
+       v3f added_vel;
+
+       *pkt >> added_vel;
+
+       LocalPlayer *player = m_env.getLocalPlayer();
+       assert(player != NULL);
+       player->addVelocity(added_vel);
+}
+
 /*
  * Mod channels
  */