LCOV - code coverage report
Current view: top level - src/network - clientpackethandler.cpp (source / functions) Hit Total Coverage
Test: report Lines: 365 650 56.2 %
Date: 2015-07-11 18:23:49 Functions: 28 48 58.3 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2015 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #include "client.h"
      21             : 
      22             : #include "util/base64.h"
      23             : #include "clientmedia.h"
      24             : #include "log.h"
      25             : #include "map.h"
      26             : #include "mapsector.h"
      27             : #include "nodedef.h"
      28             : #include "serialization.h"
      29             : #include "server.h"
      30             : #include "strfnd.h"
      31             : #include "network/clientopcodes.h"
      32             : #include "util/serialize.h"
      33             : #include "util/srp.h"
      34             : 
      35           0 : void Client::handleCommand_Deprecated(NetworkPacket* pkt)
      36             : {
      37           0 :         infostream << "Got deprecated command "
      38           0 :                         << toClientCommandTable[pkt->getCommand()].name << " from peer "
      39           0 :                         << pkt->getPeerId() << "!" << std::endl;
      40           0 : }
      41             : 
      42           0 : void Client::handleCommand_Hello(NetworkPacket* pkt)
      43             : {
      44           0 :         if (pkt->getSize() < 1)
      45           0 :                 return;
      46             : 
      47             :         u8 serialization_ver;
      48             :         u16 proto_ver;
      49             :         u16 compression_mode;
      50             :         u32 auth_mechs;
      51           0 :         std::string username_legacy; // for case insensitivity
      52           0 :         *pkt >> serialization_ver >> compression_mode >> proto_ver
      53           0 :                 >> auth_mechs >> username_legacy;
      54             : 
      55             :         // Chose an auth method we support
      56           0 :         AuthMechanism chosen_auth_mechanism = choseAuthMech(auth_mechs);
      57             : 
      58           0 :         infostream << "Client: TOCLIENT_HELLO received with "
      59           0 :                         << "serialization_ver=" << (u32)serialization_ver
      60           0 :                         << ", auth_mechs=" << auth_mechs
      61           0 :                         << ", proto_ver=" << proto_ver
      62           0 :                         << ", compression_mode=" << compression_mode
      63           0 :                         << ". Doing auth with mech " << chosen_auth_mechanism << std::endl;
      64             : 
      65           0 :         if (!ser_ver_supported(serialization_ver)) {
      66           0 :                 infostream << "Client: TOCLIENT_HELLO: Server sent "
      67           0 :                                 << "unsupported ser_fmt_ver"<< std::endl;
      68           0 :                 return;
      69             :         }
      70             : 
      71           0 :         m_server_ser_ver = serialization_ver;
      72           0 :         m_proto_ver = proto_ver;
      73             : 
      74             :         //TODO verify that username_legacy matches sent username, only
      75             :         // differs in casing (make both uppercase and compare)
      76             :         // This is only neccessary though when we actually want to add casing support
      77             : 
      78           0 :         if (m_chosen_auth_mech != AUTH_MECHANISM_NONE) {
      79             :                 // we recieved a TOCLIENT_HELLO while auth was already going on
      80           0 :                 errorstream << "Client: TOCLIENT_HELLO while auth was already going on"
      81           0 :                         << "(chosen_mech=" << m_chosen_auth_mech << ")." << std::endl;
      82           0 :                 if ((m_chosen_auth_mech == AUTH_MECHANISM_SRP)
      83           0 :                                 || (m_chosen_auth_mech == AUTH_MECHANISM_LEGACY_PASSWORD)) {
      84           0 :                         srp_user_delete((SRPUser *) m_auth_data);
      85           0 :                         m_auth_data = 0;
      86             :                 }
      87             :         }
      88             : 
      89             :         // Authenticate using that method, or abort if there wasn't any method found
      90           0 :         if (chosen_auth_mechanism != AUTH_MECHANISM_NONE) {
      91           0 :                 startAuth(chosen_auth_mechanism);
      92             :         } else {
      93           0 :                 m_chosen_auth_mech = AUTH_MECHANISM_NONE;
      94           0 :                 m_access_denied = true;
      95           0 :                 m_access_denied_reason = "Unknown";
      96           0 :                 m_con.Disconnect();
      97             :         }
      98             : 
      99             : }
     100             : 
     101           0 : void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
     102             : {
     103           0 :         m_chosen_auth_mech = AUTH_MECHANISM_NONE;
     104           0 :         deleteAuthData();
     105             : 
     106           0 :         v3f playerpos;
     107           0 :         *pkt >> playerpos >> m_map_seed >> m_recommended_send_interval
     108           0 :                 >> m_sudo_auth_methods;
     109             : 
     110           0 :         playerpos -= v3f(0, BS / 2, 0);
     111             : 
     112             :         // Set player position
     113           0 :         Player *player = m_env.getLocalPlayer();
     114             :         assert(player != NULL);
     115           0 :         player->setPosition(playerpos);
     116             : 
     117           0 :         infostream << "Client: received map seed: " << m_map_seed << std::endl;
     118           0 :         infostream << "Client: received recommended send interval "
     119           0 :                                         << m_recommended_send_interval<<std::endl;
     120             : 
     121             :         // Reply to server
     122           0 :         NetworkPacket resp_pkt(TOSERVER_INIT2, 0);
     123           0 :         Send(&resp_pkt);
     124             : 
     125           0 :         m_state = LC_Init;
     126           0 : }
     127           0 : void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
     128             : {
     129           0 :         m_chosen_auth_mech = AUTH_MECHANISM_NONE;
     130           0 :         deleteAuthData();
     131             : 
     132           0 :         m_password = m_new_password;
     133             : 
     134           0 :         verbosestream << "Client: Recieved TOCLIENT_ACCEPT_SUDO_MODE." << std::endl;
     135             : 
     136             :         // send packet to actually set the password
     137           0 :         startAuth(AUTH_MECHANISM_FIRST_SRP);
     138             : 
     139             :         // reset again
     140           0 :         m_chosen_auth_mech = AUTH_MECHANISM_NONE;
     141           0 : }
     142           0 : void Client::handleCommand_DenySudoMode(NetworkPacket* pkt)
     143             : {
     144           0 :         m_chat_queue.push(L"Password change denied. Password NOT changed.");
     145             :         // reset everything and be sad
     146           0 :         deleteAuthData();
     147           0 :         m_chosen_auth_mech = AUTH_MECHANISM_NONE;
     148           0 : }
     149           1 : void Client::handleCommand_InitLegacy(NetworkPacket* pkt)
     150             : {
     151           1 :         if (pkt->getSize() < 1)
     152           0 :                 return;
     153             : 
     154             :         u8 deployed;
     155           1 :         *pkt >> deployed;
     156             : 
     157             :         infostream << "Client: TOCLIENT_INIT_LEGACY received with "
     158           1 :                         "deployed=" << ((int)deployed & 0xff) << std::endl;
     159             : 
     160           1 :         if (!ser_ver_supported(deployed)) {
     161           0 :                 infostream << "Client: TOCLIENT_INIT_LEGACY: Server sent "
     162           0 :                                 << "unsupported ser_fmt_ver"<< std::endl;
     163           0 :                 return;
     164             :         }
     165             : 
     166           1 :         m_server_ser_ver = deployed;
     167           1 :         m_proto_ver = deployed;
     168             : 
     169             :         // Get player position
     170           1 :         v3s16 playerpos_s16(0, BS * 2 + BS * 20, 0);
     171           1 :         if (pkt->getSize() >= 1 + 6) {
     172           1 :                 *pkt >> playerpos_s16;
     173             :         }
     174           1 :         v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS / 2, 0);
     175             : 
     176             : 
     177             :         // Set player position
     178           1 :         Player *player = m_env.getLocalPlayer();
     179             :         assert(player != NULL);
     180           1 :         player->setPosition(playerpos_f);
     181             : 
     182           1 :         if (pkt->getSize() >= 1 + 6 + 8) {
     183             :                 // Get map seed
     184           1 :                 *pkt >> m_map_seed;
     185           1 :                 infostream << "Client: received map seed: " << m_map_seed << std::endl;
     186             :         }
     187             : 
     188           1 :         if (pkt->getSize() >= 1 + 6 + 8 + 4) {
     189           1 :                 *pkt >> m_recommended_send_interval;
     190           1 :                 infostream << "Client: received recommended send interval "
     191           2 :                                 << m_recommended_send_interval<<std::endl;
     192             :         }
     193             : 
     194             :         // Reply to server
     195           2 :         NetworkPacket resp_pkt(TOSERVER_INIT2, 0);
     196           1 :         Send(&resp_pkt);
     197             : 
     198           1 :         m_state = LC_Init;
     199             : }
     200             : 
     201           0 : void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
     202             : {
     203             :         // The server didn't like our password. Note, this needs
     204             :         // to be processed even if the serialisation format has
     205             :         // not been agreed yet, the same as TOCLIENT_INIT.
     206           0 :         m_access_denied = true;
     207           0 :         m_access_denied_reason = "Unknown";
     208             : 
     209           0 :         if (pkt->getCommand() == TOCLIENT_ACCESS_DENIED) {
     210           0 :                 if (pkt->getSize() < 1)
     211           0 :                         return;
     212             : 
     213           0 :                 u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA;
     214           0 :                 *pkt >> denyCode;
     215           0 :                 if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
     216           0 :                         *pkt >> m_access_denied_reason;
     217             :                 }
     218           0 :                 else if (denyCode < SERVER_ACCESSDENIED_MAX) {
     219           0 :                         m_access_denied_reason = accessDeniedStrings[denyCode];
     220             :                 }
     221             :         }
     222             :         // 13/03/15 Legacy code from 0.4.12 and lesser. must stay 1 year
     223             :         // for compat with old clients
     224             :         else {
     225           0 :                 if (pkt->getSize() >= 2) {
     226           0 :                         std::wstring wide_reason;
     227           0 :                         *pkt >> wide_reason;
     228           0 :                         m_access_denied_reason = wide_to_narrow(wide_reason);
     229             :                 }
     230             :         }
     231             : }
     232             : 
     233           6 : void Client::handleCommand_RemoveNode(NetworkPacket* pkt)
     234             : {
     235           6 :         if (pkt->getSize() < 6)
     236           0 :                 return;
     237             : 
     238           6 :         v3s16 p;
     239           6 :         *pkt >> p;
     240           6 :         removeNode(p);
     241             : }
     242             : 
     243          49 : void Client::handleCommand_AddNode(NetworkPacket* pkt)
     244             : {
     245          49 :         if (pkt->getSize() < 6 + MapNode::serializedLength(m_server_ser_ver))
     246           0 :                 return;
     247             : 
     248          49 :         v3s16 p;
     249          49 :         *pkt >> p;
     250             : 
     251          49 :         MapNode n;
     252          49 :         n.deSerialize(pkt->getU8Ptr(6), m_server_ser_ver);
     253             : 
     254          49 :         bool remove_metadata = true;
     255          49 :         u32 index = 6 + MapNode::serializedLength(m_server_ser_ver);
     256          49 :         if ((pkt->getSize() >= index + 1) && pkt->getU8(index)) {
     257          42 :                 remove_metadata = false;
     258             :         }
     259             : 
     260          49 :         addNode(p, n, remove_metadata);
     261             : }
     262         786 : void Client::handleCommand_BlockData(NetworkPacket* pkt)
     263             : {
     264             :         // Ignore too small packet
     265         786 :         if (pkt->getSize() < 6)
     266           0 :                 return;
     267             : 
     268         786 :         v3s16 p;
     269         786 :         *pkt >> p;
     270             : 
     271        1572 :         std::string datastring(pkt->getString(6), pkt->getSize() - 6);
     272        1572 :         std::istringstream istr(datastring, std::ios_base::binary);
     273             : 
     274             :         MapSector *sector;
     275             :         MapBlock *block;
     276             : 
     277         786 :         v2s16 p2d(p.X, p.Z);
     278         786 :         sector = m_env.getMap().emergeSector(p2d);
     279             : 
     280             :         assert(sector->getPos() == p2d);
     281             : 
     282         786 :         block = sector->getBlockNoCreateNoEx(p.Y);
     283         786 :         if (block) {
     284             :                 /*
     285             :                         Update an existing block
     286             :                 */
     287          35 :                 block->deSerialize(istr, m_server_ser_ver, false);
     288          35 :                 block->deSerializeNetworkSpecific(istr);
     289             :         }
     290             :         else {
     291             :                 /*
     292             :                         Create a new block
     293             :                 */
     294         751 :                 block = new MapBlock(&m_env.getMap(), p, this);
     295         751 :                 block->deSerialize(istr, m_server_ser_ver, false);
     296         751 :                 block->deSerializeNetworkSpecific(istr);
     297         751 :                 sector->insertBlock(block);
     298             :         }
     299             : 
     300         786 :         if (m_localdb) {
     301           0 :                 ServerMap::saveBlock(block, m_localdb);
     302             :         }
     303             : 
     304             :         /*
     305             :                 Add it to mesh update queue and set it to be acknowledged after update.
     306             :         */
     307         786 :         addUpdateMeshTaskWithEdge(p, true);
     308             : }
     309             : 
     310           6 : void Client::handleCommand_Inventory(NetworkPacket* pkt)
     311             : {
     312           6 :         if (pkt->getSize() < 1)
     313           0 :                 return;
     314             : 
     315          12 :         std::string datastring(pkt->getString(0), pkt->getSize());
     316          12 :         std::istringstream is(datastring, std::ios_base::binary);
     317             : 
     318           6 :         Player *player = m_env.getLocalPlayer();
     319             :         assert(player != NULL);
     320             : 
     321           6 :         player->inventory.deSerialize(is);
     322             : 
     323           6 :         m_inventory_updated = true;
     324             : 
     325           6 :         delete m_inventory_from_server;
     326           6 :         m_inventory_from_server = new Inventory(player->inventory);
     327           6 :         m_inventory_from_server_age = 0.0;
     328             : }
     329             : 
     330          10 : void Client::handleCommand_TimeOfDay(NetworkPacket* pkt)
     331             : {
     332          10 :         if (pkt->getSize() < 2)
     333           0 :                 return;
     334             : 
     335             :         u16 time_of_day;
     336             : 
     337          10 :         *pkt >> time_of_day;
     338             : 
     339          10 :         time_of_day      = time_of_day % 24000;
     340          10 :         float time_speed = 0;
     341             : 
     342          10 :         if (pkt->getSize() >= 2 + 4) {
     343          10 :                 *pkt >> time_speed;
     344             :         }
     345             :         else {
     346             :                 // Old message; try to approximate speed of time by ourselves
     347           0 :                 float time_of_day_f = (float)time_of_day / 24000.0;
     348           0 :                 float tod_diff_f = 0;
     349             : 
     350           0 :                 if (time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8)
     351           0 :                         tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0;
     352             :                 else
     353           0 :                         tod_diff_f = time_of_day_f - m_last_time_of_day_f;
     354             : 
     355           0 :                 m_last_time_of_day_f       = time_of_day_f;
     356           0 :                 float time_diff            = m_time_of_day_update_timer;
     357           0 :                 m_time_of_day_update_timer = 0;
     358             : 
     359           0 :                 if (m_time_of_day_set) {
     360           0 :                         time_speed = (3600.0 * 24.0) * tod_diff_f / time_diff;
     361           0 :                         infostream << "Client: Measured time_of_day speed (old format): "
     362           0 :                                         << time_speed << " tod_diff_f=" << tod_diff_f
     363           0 :                                         << " time_diff=" << time_diff << std::endl;
     364             :                 }
     365             :         }
     366             : 
     367             :         // Update environment
     368          10 :         m_env.setTimeOfDay(time_of_day);
     369          10 :         m_env.setTimeOfDaySpeed(time_speed);
     370          10 :         m_time_of_day_set = true;
     371             : 
     372          10 :         u32 dr = m_env.getDayNightRatio();
     373          10 :         infostream << "Client: time_of_day=" << time_of_day
     374          10 :                         << " time_speed=" << time_speed
     375          20 :                         << " dr=" << dr << std::endl;
     376             : }
     377             : 
     378           2 : void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
     379             : {
     380             :         /*
     381             :                 u16 command
     382             :                 u16 length
     383             :                 wstring message
     384             :         */
     385             :         u16 len, read_wchar;
     386             : 
     387           2 :         *pkt >> len;
     388             : 
     389           4 :         std::wstring message;
     390         247 :         for (u32 i = 0; i < len; i++) {
     391         245 :                 *pkt >> read_wchar;
     392         245 :                 message += (wchar_t)read_wchar;
     393             :         }
     394             : 
     395           2 :         m_chat_queue.push(message);
     396           2 : }
     397             : 
     398          36 : void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
     399             : {
     400             :         /*
     401             :                 u16 count of removed objects
     402             :                 for all removed objects {
     403             :                         u16 id
     404             :                 }
     405             :                 u16 count of added objects
     406             :                 for all added objects {
     407             :                         u16 id
     408             :                         u8 type
     409             :                         u32 initialization data length
     410             :                         string initialization data
     411             :                 }
     412             :         */
     413             : 
     414             :         try {
     415             :                 u8 type;
     416             :                 u16 removed_count, added_count, id;
     417             : 
     418             :                 // Read removed objects
     419          36 :                 *pkt >> removed_count;
     420             : 
     421          55 :                 for (u16 i = 0; i < removed_count; i++) {
     422          19 :                         *pkt >> id;
     423          19 :                         m_env.removeActiveObject(id);
     424             :                 }
     425             : 
     426             :                 // Read added objects
     427          36 :                 *pkt >> added_count;
     428             : 
     429          80 :                 for (u16 i = 0; i < added_count; i++) {
     430          44 :                         *pkt >> id >> type;
     431          44 :                         m_env.addActiveObject(id, type, pkt->readLongString());
     432             :                 }
     433           0 :         } catch (PacketError &e) {
     434           0 :                 infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
     435           0 :                                 << ". The packet is unreliable, ignoring" << std::endl;
     436             :         }
     437          36 : }
     438             : 
     439         353 : void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
     440             : {
     441             :         /*
     442             :                 for all objects
     443             :                 {
     444             :                         u16 id
     445             :                         u16 message length
     446             :                         string message
     447             :                 }
     448             :         */
     449             :         char buf[6];
     450             :         // Get all data except the command number
     451         706 :         std::string datastring(pkt->getString(0), pkt->getSize());
     452             :         // Throw them in an istringstream
     453         706 :         std::istringstream is(datastring, std::ios_base::binary);
     454             : 
     455             :         try {
     456       57491 :                 while(is.eof() == false) {
     457       28770 :                         is.read(buf, 2);
     458       28770 :                         u16 id = readU16((u8*)buf);
     459       28770 :                         if (is.eof())
     460         201 :                                 break;
     461       28569 :                         is.read(buf, 2);
     462       28569 :                         size_t message_size = readU16((u8*)buf);
     463       57138 :                         std::string message;
     464       28569 :                         message.reserve(message_size);
     465      131031 :                         for (u32 i = 0; i < message_size; i++) {
     466      102462 :                                 is.read(buf, 1);
     467      102462 :                                 message.append(buf, 1);
     468             :                         }
     469             :                         // Pass on to the environment
     470       28569 :                         m_env.processActiveObjectMessage(id, message);
     471             :                 }
     472             :         // Packet could be unreliable then ignore it
     473           0 :         } catch (PacketError &e) {
     474           0 :                 infostream << "handleCommand_ActiveObjectMessages: " << e.what()
     475           0 :                                         << ". The packet is unreliable, ignoring" << std::endl;
     476             :         }
     477         353 : }
     478             : 
     479           1 : void Client::handleCommand_Movement(NetworkPacket* pkt)
     480             : {
     481           1 :         Player *player = m_env.getLocalPlayer();
     482             :         assert(player != NULL);
     483             : 
     484             :         float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
     485             : 
     486           1 :         *pkt >> mad >> maa >> maf >> msw >> mscr >> msf >> mscl >> msj
     487           1 :                 >> lf >> lfs >> ls >> g;
     488             : 
     489           1 :         player->movement_acceleration_default   = mad * BS;
     490           1 :         player->movement_acceleration_air       = maa * BS;
     491           1 :         player->movement_acceleration_fast      = maf * BS;
     492           1 :         player->movement_speed_walk             = msw * BS;
     493           1 :         player->movement_speed_crouch           = mscr * BS;
     494           1 :         player->movement_speed_fast             = msf * BS;
     495           1 :         player->movement_speed_climb            = mscl * BS;
     496           1 :         player->movement_speed_jump             = msj * BS;
     497           1 :         player->movement_liquid_fluidity        = lf * BS;
     498           1 :         player->movement_liquid_fluidity_smooth = lfs * BS;
     499           1 :         player->movement_liquid_sink            = ls * BS;
     500           1 :         player->movement_gravity                = g * BS;
     501           1 : }
     502             : 
     503           1 : void Client::handleCommand_HP(NetworkPacket* pkt)
     504             : {
     505             : 
     506           1 :         Player *player = m_env.getLocalPlayer();
     507             :         assert(player != NULL);
     508             : 
     509           1 :         u8 oldhp   = player->hp;
     510             : 
     511             :         u8 hp;
     512           1 :         *pkt >> hp;
     513             : 
     514           1 :         player->hp = hp;
     515             : 
     516           1 :         if (hp < oldhp) {
     517             :                 // Add to ClientEvent queue
     518             :                 ClientEvent event;
     519           0 :                 event.type = CE_PLAYER_DAMAGE;
     520           0 :                 event.player_damage.amount = oldhp - hp;
     521           0 :                 m_client_event_queue.push(event);
     522             :         }
     523           1 : }
     524             : 
     525           1 : void Client::handleCommand_Breath(NetworkPacket* pkt)
     526             : {
     527           1 :         Player *player = m_env.getLocalPlayer();
     528             :         assert(player != NULL);
     529             : 
     530             :         u16 breath;
     531             : 
     532           1 :         *pkt >> breath;
     533             : 
     534           1 :         player->setBreath(breath);
     535           1 : }
     536             : 
     537           1 : void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
     538             : {
     539           1 :         Player *player = m_env.getLocalPlayer();
     540             :         assert(player != NULL);
     541             : 
     542           1 :         v3f pos;
     543             :         f32 pitch, yaw;
     544             : 
     545           1 :         *pkt >> pos >> pitch >> yaw;
     546             : 
     547           1 :         player->setPosition(pos);
     548             : 
     549           1 :         infostream << "Client got TOCLIENT_MOVE_PLAYER"
     550           2 :                         << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
     551           1 :                         << " pitch=" << pitch
     552           2 :                         << " yaw=" << yaw
     553           2 :                         << std::endl;
     554             : 
     555             :         /*
     556             :                 Add to ClientEvent queue.
     557             :                 This has to be sent to the main program because otherwise
     558             :                 it would just force the pitch and yaw values to whatever
     559             :                 the camera points to.
     560             :         */
     561             :         ClientEvent event;
     562           1 :         event.type = CE_PLAYER_FORCE_MOVE;
     563           1 :         event.player_force_move.pitch = pitch;
     564           1 :         event.player_force_move.yaw = yaw;
     565           1 :         m_client_event_queue.push(event);
     566             : 
     567             :         // Ignore damage for a few seconds, so that the player doesn't
     568             :         // get damage from falling on ground
     569           1 :         m_ignore_damage_timer = 3.0;
     570           1 : }
     571             : 
     572           0 : void Client::handleCommand_PlayerItem(NetworkPacket* pkt)
     573             : {
     574           0 :         infostream << "Client: WARNING: Ignoring TOCLIENT_PLAYERITEM" << std::endl;
     575           0 : }
     576             : 
     577           0 : void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
     578             : {
     579             :         bool set_camera_point_target;
     580           0 :         v3f camera_point_target;
     581             : 
     582           0 :         *pkt >> set_camera_point_target;
     583           0 :         *pkt >> camera_point_target;
     584             : 
     585             :         ClientEvent event;
     586           0 :         event.type                                = CE_DEATHSCREEN;
     587           0 :         event.deathscreen.set_camera_point_target = set_camera_point_target;
     588           0 :         event.deathscreen.camera_point_target_x   = camera_point_target.X;
     589           0 :         event.deathscreen.camera_point_target_y   = camera_point_target.Y;
     590           0 :         event.deathscreen.camera_point_target_z   = camera_point_target.Z;
     591           0 :         m_client_event_queue.push(event);
     592           0 : }
     593             : 
     594           1 : void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
     595             : {
     596             :         u16 num_files;
     597             : 
     598           1 :         *pkt >> num_files;
     599             : 
     600           1 :         infostream << "Client: Received media announcement: packet size: "
     601           2 :                         << pkt->getSize() << std::endl;
     602             : 
     603           2 :         if (m_media_downloader == NULL ||
     604           1 :                         m_media_downloader->isStarted()) {
     605           0 :                 const char *problem = m_media_downloader ?
     606             :                         "we already saw another announcement" :
     607           0 :                         "all media has been received already";
     608           0 :                 errorstream << "Client: Received media announcement but "
     609           0 :                         << problem << "! "
     610           0 :                         << " files=" << num_files
     611           0 :                         << " size=" << pkt->getSize() << std::endl;
     612           0 :                 return;
     613             :         }
     614             : 
     615             :         // Mesh update thread must be stopped while
     616             :         // updating content definitions
     617           1 :         sanity_check(!m_mesh_update_thread.IsRunning());
     618             : 
     619        2636 :         for (u16 i = 0; i < num_files; i++) {
     620        5270 :                 std::string name, sha1_base64;
     621             : 
     622        2635 :                 *pkt >> name >> sha1_base64;
     623             : 
     624        5270 :                 std::string sha1_raw = base64_decode(sha1_base64);
     625        2635 :                 m_media_downloader->addFile(name, sha1_raw);
     626             :         }
     627             : 
     628           2 :         std::vector<std::string> remote_media;
     629             :         try {
     630           2 :                 std::string str;
     631             : 
     632           1 :                 *pkt >> str;
     633             : 
     634           2 :                 Strfnd sf(str);
     635           1 :                 while(!sf.atend()) {
     636           0 :                         std::string baseurl = trim(sf.next(","));
     637           0 :                         if (baseurl != "")
     638           0 :                                 m_media_downloader->addRemoteServer(baseurl);
     639             :                 }
     640             :         }
     641           0 :         catch(SerializationError& e) {
     642             :                 // not supported by server or turned off
     643             :         }
     644             : 
     645           1 :         m_media_downloader->step(this);
     646             : }
     647             : 
     648           0 : void Client::handleCommand_Media(NetworkPacket* pkt)
     649             : {
     650             :         /*
     651             :                 u16 command
     652             :                 u16 total number of file bunches
     653             :                 u16 index of this bunch
     654             :                 u32 number of files in this bunch
     655             :                 for each file {
     656             :                         u16 length of name
     657             :                         string name
     658             :                         u32 length of data
     659             :                         data
     660             :                 }
     661             :         */
     662             :         u16 num_bunches;
     663             :         u16 bunch_i;
     664             :         u32 num_files;
     665             : 
     666           0 :         *pkt >> num_bunches >> bunch_i >> num_files;
     667             : 
     668           0 :         infostream << "Client: Received files: bunch " << bunch_i << "/"
     669           0 :                         << num_bunches << " files=" << num_files
     670           0 :                         << " size=" << pkt->getSize() << std::endl;
     671             : 
     672           0 :         if (num_files == 0)
     673           0 :                 return;
     674             : 
     675           0 :         if (m_media_downloader == NULL ||
     676           0 :                         !m_media_downloader->isStarted()) {
     677           0 :                 const char *problem = m_media_downloader ?
     678             :                         "media has not been requested" :
     679           0 :                         "all media has been received already";
     680           0 :                 errorstream << "Client: Received media but "
     681           0 :                         << problem << "! "
     682           0 :                         << " bunch " << bunch_i << "/" << num_bunches
     683           0 :                         << " files=" << num_files
     684           0 :                         << " size=" << pkt->getSize() << std::endl;
     685           0 :                 return;
     686             :         }
     687             : 
     688             :         // Mesh update thread must be stopped while
     689             :         // updating content definitions
     690           0 :         sanity_check(!m_mesh_update_thread.IsRunning());
     691             : 
     692           0 :         for (u32 i=0; i < num_files; i++) {
     693           0 :                 std::string name;
     694             : 
     695           0 :                 *pkt >> name;
     696             : 
     697           0 :                 std::string data = pkt->readLongString();
     698             : 
     699           0 :                 m_media_downloader->conventionalTransferDone(
     700           0 :                                 name, data, this);
     701             :         }
     702             : }
     703             : 
     704           0 : void Client::handleCommand_ToolDef(NetworkPacket* pkt)
     705             : {
     706           0 :         infostream << "Client: WARNING: Ignoring TOCLIENT_TOOLDEF" << std::endl;
     707           0 : }
     708             : 
     709           1 : void Client::handleCommand_NodeDef(NetworkPacket* pkt)
     710             : {
     711           1 :         infostream << "Client: Received node definitions: packet size: "
     712           2 :                         << pkt->getSize() << std::endl;
     713             : 
     714             :         // Mesh update thread must be stopped while
     715             :         // updating content definitions
     716           1 :         sanity_check(!m_mesh_update_thread.IsRunning());
     717             : 
     718             :         // Decompress node definitions
     719           2 :         std::string datastring(pkt->getString(0), pkt->getSize());
     720           2 :         std::istringstream is(datastring, std::ios_base::binary);
     721           2 :         std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
     722           2 :         std::ostringstream tmp_os;
     723           1 :         decompressZlib(tmp_is, tmp_os);
     724             : 
     725             :         // Deserialize node definitions
     726           2 :         std::istringstream tmp_is2(tmp_os.str());
     727           1 :         m_nodedef->deSerialize(tmp_is2);
     728           1 :         m_nodedef_received = true;
     729           1 : }
     730             : 
     731           0 : void Client::handleCommand_CraftItemDef(NetworkPacket* pkt)
     732             : {
     733           0 :         infostream << "Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl;
     734           0 : }
     735             : 
     736           1 : void Client::handleCommand_ItemDef(NetworkPacket* pkt)
     737             : {
     738           1 :         infostream << "Client: Received item definitions: packet size: "
     739           2 :                         << pkt->getSize() << std::endl;
     740             : 
     741             :         // Mesh update thread must be stopped while
     742             :         // updating content definitions
     743           1 :         sanity_check(!m_mesh_update_thread.IsRunning());
     744             : 
     745             :         // Decompress item definitions
     746           2 :         std::string datastring(pkt->getString(0), pkt->getSize());
     747           2 :         std::istringstream is(datastring, std::ios_base::binary);
     748           2 :         std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
     749           2 :         std::ostringstream tmp_os;
     750           1 :         decompressZlib(tmp_is, tmp_os);
     751             : 
     752             :         // Deserialize node definitions
     753           2 :         std::istringstream tmp_is2(tmp_os.str());
     754           1 :         m_itemdef->deSerialize(tmp_is2);
     755           1 :         m_itemdef_received = true;
     756           1 : }
     757             : 
     758           2 : void Client::handleCommand_PlaySound(NetworkPacket* pkt)
     759             : {
     760             :         s32 server_id;
     761           4 :         std::string name;
     762             :         float gain;
     763             :         u8 type; // 0=local, 1=positional, 2=object
     764           2 :         v3f pos;
     765             :         u16 object_id;
     766             :         bool loop;
     767             : 
     768           2 :         *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
     769             : 
     770             :         // Start playing
     771           2 :         int client_id = -1;
     772           2 :         switch(type) {
     773             :                 case 0: // local
     774           1 :                         client_id = m_sound->playSound(name, loop, gain);
     775           1 :                         break;
     776             :                 case 1: // positional
     777           0 :                         client_id = m_sound->playSoundAt(name, loop, gain, pos);
     778           0 :                         break;
     779             :                 case 2:
     780             :                 { // object
     781           1 :                         ClientActiveObject *cao = m_env.getActiveObject(object_id);
     782           1 :                         if (cao)
     783           1 :                                 pos = cao->getPosition();
     784           1 :                         client_id = m_sound->playSoundAt(name, loop, gain, pos);
     785             :                         // TODO: Set up sound to move with object
     786           1 :                         break;
     787             :                 }
     788             :                 default:
     789           0 :                         break;
     790             :         }
     791             : 
     792           2 :         if (client_id != -1) {
     793           2 :                 m_sounds_server_to_client[server_id] = client_id;
     794           2 :                 m_sounds_client_to_server[client_id] = server_id;
     795           2 :                 if (object_id != 0)
     796           1 :                         m_sounds_to_objects[client_id] = object_id;
     797             :         }
     798           2 : }
     799             : 
     800           0 : void Client::handleCommand_StopSound(NetworkPacket* pkt)
     801             : {
     802             :         s32 server_id;
     803             : 
     804           0 :         *pkt >> server_id;
     805             : 
     806             :         std::map<s32, int>::iterator i =
     807           0 :                 m_sounds_server_to_client.find(server_id);
     808             : 
     809           0 :         if (i != m_sounds_server_to_client.end()) {
     810           0 :                 int client_id = i->second;
     811           0 :                 m_sound->stopSound(client_id);
     812             :         }
     813           0 : }
     814             : 
     815           1 : void Client::handleCommand_Privileges(NetworkPacket* pkt)
     816             : {
     817           1 :         m_privileges.clear();
     818           1 :         infostream << "Client: Privileges updated: ";
     819             :         u16 num_privileges;
     820             : 
     821           1 :         *pkt >> num_privileges;
     822             : 
     823          21 :         for (u16 i = 0; i < num_privileges; i++) {
     824          40 :                 std::string priv;
     825             : 
     826          20 :                 *pkt >> priv;
     827             : 
     828          20 :                 m_privileges.insert(priv);
     829          20 :                 infostream << priv << " ";
     830             :         }
     831           1 :         infostream << std::endl;
     832           1 : }
     833             : 
     834           4 : void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
     835             : {
     836           4 :         Player *player = m_env.getLocalPlayer();
     837             :         assert(player != NULL);
     838             : 
     839             :         // Store formspec in LocalPlayer
     840           4 :         player->inventory_formspec = pkt->readLongString();
     841           4 : }
     842             : 
     843          28 : void Client::handleCommand_DetachedInventory(NetworkPacket* pkt)
     844             : {
     845          56 :         std::string datastring(pkt->getString(0), pkt->getSize());
     846          56 :         std::istringstream is(datastring, std::ios_base::binary);
     847             : 
     848          56 :         std::string name = deSerializeString(is);
     849             : 
     850          28 :         infostream << "Client: Detached inventory update: \"" << name
     851          28 :                         << "\"" << std::endl;
     852             : 
     853          28 :         Inventory *inv = NULL;
     854          28 :         if (m_detached_inventories.count(name) > 0)
     855          19 :                 inv = m_detached_inventories[name];
     856             :         else {
     857           9 :                 inv = new Inventory(m_itemdef);
     858           9 :                 m_detached_inventories[name] = inv;
     859             :         }
     860          28 :         inv->deSerialize(is);
     861          28 : }
     862             : 
     863           0 : void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt)
     864             : {
     865           0 :         std::string formspec = pkt->readLongString();
     866           0 :         std::string formname;
     867             : 
     868           0 :         *pkt >> formname;
     869             : 
     870             :         ClientEvent event;
     871           0 :         event.type = CE_SHOW_FORMSPEC;
     872             :         // pointer is required as event is a struct only!
     873             :         // adding a std:string to a struct isn't possible
     874           0 :         event.show_formspec.formspec = new std::string(formspec);
     875           0 :         event.show_formspec.formname = new std::string(formname);
     876           0 :         m_client_event_queue.push(event);
     877           0 : }
     878             : 
     879           0 : void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
     880             : {
     881           0 :         std::string datastring(pkt->getString(0), pkt->getSize());
     882           0 :         std::istringstream is(datastring, std::ios_base::binary);
     883             : 
     884           0 :         v3f pos                 = readV3F1000(is);
     885           0 :         v3f vel                 = readV3F1000(is);
     886           0 :         v3f acc                 = readV3F1000(is);
     887           0 :         float expirationtime    = readF1000(is);
     888           0 :         float size              = readF1000(is);
     889           0 :         bool collisiondetection = readU8(is);
     890           0 :         std::string texture     = deSerializeLongString(is);
     891           0 :         bool vertical           = false;
     892             :         try {
     893           0 :                 vertical = readU8(is);
     894           0 :         } catch (...) {}
     895             : 
     896             :         ClientEvent event;
     897           0 :         event.type                              = CE_SPAWN_PARTICLE;
     898           0 :         event.spawn_particle.pos                = new v3f (pos);
     899           0 :         event.spawn_particle.vel                = new v3f (vel);
     900           0 :         event.spawn_particle.acc                = new v3f (acc);
     901           0 :         event.spawn_particle.expirationtime     = expirationtime;
     902           0 :         event.spawn_particle.size               = size;
     903           0 :         event.spawn_particle.collisiondetection = collisiondetection;
     904           0 :         event.spawn_particle.vertical           = vertical;
     905           0 :         event.spawn_particle.texture            = new std::string(texture);
     906             : 
     907           0 :         m_client_event_queue.push(event);
     908           0 : }
     909             : 
     910           9 : void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
     911             : {
     912             :         u16 amount;
     913             :         float spawntime;
     914           9 :         v3f minpos;
     915           9 :         v3f maxpos;
     916           9 :         v3f minvel;
     917           9 :         v3f maxvel;
     918           9 :         v3f minacc;
     919           9 :         v3f maxacc;
     920             :         float minexptime;
     921             :         float maxexptime;
     922             :         float minsize;
     923             :         float maxsize;
     924             :         bool collisiondetection;
     925             :         u32 id;
     926             : 
     927           9 :         *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
     928           9 :                 >> minacc >> maxacc >> minexptime >> maxexptime >> minsize
     929           9 :                 >> maxsize >> collisiondetection;
     930             : 
     931          18 :         std::string texture = pkt->readLongString();
     932             : 
     933           9 :         *pkt >> id;
     934             : 
     935           9 :         bool vertical = false;
     936             :         try {
     937           9 :                 *pkt >> vertical;
     938           0 :         } catch (...) {}
     939             : 
     940             :         ClientEvent event;
     941           9 :         event.type                                   = CE_ADD_PARTICLESPAWNER;
     942           9 :         event.add_particlespawner.amount             = amount;
     943           9 :         event.add_particlespawner.spawntime          = spawntime;
     944           9 :         event.add_particlespawner.minpos             = new v3f (minpos);
     945           9 :         event.add_particlespawner.maxpos             = new v3f (maxpos);
     946           9 :         event.add_particlespawner.minvel             = new v3f (minvel);
     947           9 :         event.add_particlespawner.maxvel             = new v3f (maxvel);
     948           9 :         event.add_particlespawner.minacc             = new v3f (minacc);
     949           9 :         event.add_particlespawner.maxacc             = new v3f (maxacc);
     950           9 :         event.add_particlespawner.minexptime         = minexptime;
     951           9 :         event.add_particlespawner.maxexptime         = maxexptime;
     952           9 :         event.add_particlespawner.minsize            = minsize;
     953           9 :         event.add_particlespawner.maxsize            = maxsize;
     954           9 :         event.add_particlespawner.collisiondetection = collisiondetection;
     955           9 :         event.add_particlespawner.vertical           = vertical;
     956           9 :         event.add_particlespawner.texture            = new std::string(texture);
     957           9 :         event.add_particlespawner.id                 = id;
     958             : 
     959           9 :         m_client_event_queue.push(event);
     960           9 : }
     961             : 
     962             : 
     963           0 : void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
     964             : {
     965             :         u16 legacy_id;
     966             :         u32 id;
     967             : 
     968             :         // Modification set 13/03/15, 1 year of compat for protocol v24
     969           0 :         if (pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY) {
     970           0 :                 *pkt >> legacy_id;
     971             :         }
     972             :         else {
     973           0 :                 *pkt >> id;
     974             :         }
     975             : 
     976             : 
     977             :         ClientEvent event;
     978           0 :         event.type                      = CE_DELETE_PARTICLESPAWNER;
     979             :         event.delete_particlespawner.id =
     980           0 :                         (pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY ? (u32) legacy_id : id);
     981             : 
     982           0 :         m_client_event_queue.push(event);
     983           0 : }
     984             : 
     985           2 : void Client::handleCommand_HudAdd(NetworkPacket* pkt)
     986             : {
     987           4 :         std::string datastring(pkt->getString(0), pkt->getSize());
     988           4 :         std::istringstream is(datastring, std::ios_base::binary);
     989             : 
     990             :         u32 id;
     991             :         u8 type;
     992           2 :         v2f pos;
     993           4 :         std::string name;
     994           2 :         v2f scale;
     995           4 :         std::string text;
     996             :         u32 number;
     997             :         u32 item;
     998             :         u32 dir;
     999           2 :         v2f align;
    1000           2 :         v2f offset;
    1001           2 :         v3f world_pos;
    1002           2 :         v2s32 size;
    1003             : 
    1004           2 :         *pkt >> id >> type >> pos >> name >> scale >> text >> number >> item
    1005           2 :                 >> dir >> align >> offset;
    1006             :         try {
    1007           2 :                 *pkt >> world_pos;
    1008             :         }
    1009           0 :         catch(SerializationError &e) {};
    1010             : 
    1011             :         try {
    1012           2 :                 *pkt >> size;
    1013           0 :         } catch(SerializationError &e) {};
    1014             : 
    1015             :         ClientEvent event;
    1016           2 :         event.type             = CE_HUDADD;
    1017           2 :         event.hudadd.id        = id;
    1018           2 :         event.hudadd.type      = type;
    1019           2 :         event.hudadd.pos       = new v2f(pos);
    1020           2 :         event.hudadd.name      = new std::string(name);
    1021           2 :         event.hudadd.scale     = new v2f(scale);
    1022           2 :         event.hudadd.text      = new std::string(text);
    1023           2 :         event.hudadd.number    = number;
    1024           2 :         event.hudadd.item      = item;
    1025           2 :         event.hudadd.dir       = dir;
    1026           2 :         event.hudadd.align     = new v2f(align);
    1027           2 :         event.hudadd.offset    = new v2f(offset);
    1028           2 :         event.hudadd.world_pos = new v3f(world_pos);
    1029           2 :         event.hudadd.size      = new v2s32(size);
    1030           2 :         m_client_event_queue.push(event);
    1031           2 : }
    1032             : 
    1033           0 : void Client::handleCommand_HudRemove(NetworkPacket* pkt)
    1034             : {
    1035             :         u32 id;
    1036             : 
    1037           0 :         *pkt >> id;
    1038             : 
    1039             :         ClientEvent event;
    1040           0 :         event.type     = CE_HUDRM;
    1041           0 :         event.hudrm.id = id;
    1042           0 :         m_client_event_queue.push(event);
    1043           0 : }
    1044             : 
    1045          15 : void Client::handleCommand_HudChange(NetworkPacket* pkt)
    1046             : {
    1047          30 :         std::string sdata;
    1048          15 :         v2f v2fdata;
    1049          15 :         v3f v3fdata;
    1050          15 :         u32 intdata = 0;
    1051          15 :         v2s32 v2s32data;
    1052             :         u32 id;
    1053             :         u8 stat;
    1054             : 
    1055          15 :         *pkt >> id >> stat;
    1056             : 
    1057          30 :         if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
    1058          30 :                 stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
    1059           0 :                 *pkt >> v2fdata;
    1060          15 :         else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
    1061          14 :                 *pkt >> sdata;
    1062           1 :         else if (stat == HUD_STAT_WORLD_POS)
    1063           0 :                 *pkt >> v3fdata;
    1064           1 :         else if (stat == HUD_STAT_SIZE )
    1065           0 :                 *pkt >> v2s32data;
    1066             :         else
    1067           1 :                 *pkt >> intdata;
    1068             : 
    1069             :         ClientEvent event;
    1070          15 :         event.type              = CE_HUDCHANGE;
    1071          15 :         event.hudchange.id      = id;
    1072          15 :         event.hudchange.stat    = (HudElementStat)stat;
    1073          15 :         event.hudchange.v2fdata = new v2f(v2fdata);
    1074          15 :         event.hudchange.v3fdata = new v3f(v3fdata);
    1075          15 :         event.hudchange.sdata   = new std::string(sdata);
    1076          15 :         event.hudchange.data    = intdata;
    1077          15 :         event.hudchange.v2s32data = new v2s32(v2s32data);
    1078          15 :         m_client_event_queue.push(event);
    1079          15 : }
    1080             : 
    1081           1 : void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
    1082             : {
    1083             :         u32 flags, mask;
    1084             : 
    1085           1 :         *pkt >> flags >> mask;
    1086             : 
    1087           1 :         Player *player = m_env.getLocalPlayer();
    1088             :         assert(player != NULL);
    1089             : 
    1090           1 :         player->hud_flags &= ~mask;
    1091           1 :         player->hud_flags |= flags;
    1092           1 : }
    1093             : 
    1094           2 : void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
    1095             : {
    1096           4 :         u16 param; std::string value;
    1097             : 
    1098           2 :         *pkt >> param >> value;
    1099             : 
    1100           2 :         Player *player = m_env.getLocalPlayer();
    1101             :         assert(player != NULL);
    1102             : 
    1103           2 :         if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
    1104           0 :                 s32 hotbar_itemcount = readS32((u8*) value.c_str());
    1105           0 :                 if (hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX)
    1106           0 :                         player->hud_hotbar_itemcount = hotbar_itemcount;
    1107             :         }
    1108           2 :         else if (param == HUD_PARAM_HOTBAR_IMAGE) {
    1109           1 :                 ((LocalPlayer *) player)->hotbar_image = value;
    1110             :         }
    1111           1 :         else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
    1112           1 :                 ((LocalPlayer *) player)->hotbar_selected_image = value;
    1113             :         }
    1114           2 : }
    1115             : 
    1116           0 : void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
    1117             : {
    1118           0 :         std::string datastring(pkt->getString(0), pkt->getSize());
    1119           0 :         std::istringstream is(datastring, std::ios_base::binary);
    1120             : 
    1121           0 :         video::SColor *bgcolor           = new video::SColor(readARGB8(is));
    1122           0 :         std::string *type                = new std::string(deSerializeString(is));
    1123           0 :         u16 count                        = readU16(is);
    1124           0 :         std::vector<std::string> *params = new std::vector<std::string>;
    1125             : 
    1126           0 :         for (size_t i = 0; i < count; i++)
    1127           0 :                 params->push_back(deSerializeString(is));
    1128             : 
    1129             :         ClientEvent event;
    1130           0 :         event.type            = CE_SET_SKY;
    1131           0 :         event.set_sky.bgcolor = bgcolor;
    1132           0 :         event.set_sky.type    = type;
    1133           0 :         event.set_sky.params  = params;
    1134           0 :         m_client_event_queue.push(event);
    1135           0 : }
    1136             : 
    1137           0 : void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt)
    1138             : {
    1139             :         bool do_override;
    1140             :         u16 day_night_ratio_u;
    1141             : 
    1142           0 :         *pkt >> do_override >> day_night_ratio_u;
    1143             : 
    1144           0 :         float day_night_ratio_f = (float)day_night_ratio_u / 65536;
    1145             : 
    1146             :         ClientEvent event;
    1147           0 :         event.type                                 = CE_OVERRIDE_DAY_NIGHT_RATIO;
    1148           0 :         event.override_day_night_ratio.do_override = do_override;
    1149           0 :         event.override_day_night_ratio.ratio_f     = day_night_ratio_f;
    1150           0 :         m_client_event_queue.push(event);
    1151           0 : }
    1152             : 
    1153           1 : void Client::handleCommand_LocalPlayerAnimations(NetworkPacket* pkt)
    1154             : {
    1155           1 :         LocalPlayer *player = m_env.getLocalPlayer();
    1156             :         assert(player != NULL);
    1157             : 
    1158           1 :         *pkt >> player->local_animations[0];
    1159           1 :         *pkt >> player->local_animations[1];
    1160           1 :         *pkt >> player->local_animations[2];
    1161           1 :         *pkt >> player->local_animations[3];
    1162           1 :         *pkt >> player->local_animation_speed;
    1163           1 : }
    1164             : 
    1165           0 : void Client::handleCommand_EyeOffset(NetworkPacket* pkt)
    1166             : {
    1167           0 :         LocalPlayer *player = m_env.getLocalPlayer();
    1168             :         assert(player != NULL);
    1169             : 
    1170           0 :         *pkt >> player->eye_offset_first >> player->eye_offset_third;
    1171           0 : }
    1172             : 
    1173           0 : void Client::handleCommand_SrpBytesSandB(NetworkPacket* pkt)
    1174             : {
    1175           0 :         if ((m_chosen_auth_mech != AUTH_MECHANISM_LEGACY_PASSWORD)
    1176           0 :                         && (m_chosen_auth_mech != AUTH_MECHANISM_SRP)) {
    1177           0 :                 errorstream << "Client: Recieved SRP S_B login message,"
    1178           0 :                         << " but wasn't supposed to (chosen_mech="
    1179           0 :                         << m_chosen_auth_mech << ")." << std::endl;
    1180           0 :                 return;
    1181             :         }
    1182             : 
    1183           0 :         char *bytes_M = 0;
    1184           0 :         size_t len_M = 0;
    1185           0 :         SRPUser *usr = (SRPUser *) m_auth_data;
    1186           0 :         std::string s;
    1187           0 :         std::string B;
    1188           0 :         *pkt >> s >> B;
    1189             : 
    1190           0 :         infostream << "Client: Recieved TOCLIENT_SRP_BYTES_S_B." << std::endl;
    1191             : 
    1192           0 :         srp_user_process_challenge(usr, (const unsigned char *) s.c_str(), s.size(),
    1193           0 :                 (const unsigned char *) B.c_str(), B.size(),
    1194           0 :                 (unsigned char **) &bytes_M, &len_M);
    1195             : 
    1196           0 :         if ( !bytes_M ) {
    1197           0 :                 errorstream << "Client: SRP-6a S_B safety check violation!" << std::endl;
    1198           0 :                 return;
    1199             :         }
    1200             : 
    1201           0 :         NetworkPacket resp_pkt(TOSERVER_SRP_BYTES_M, 0);
    1202           0 :         resp_pkt << std::string(bytes_M, len_M);
    1203           0 :         Send(&resp_pkt);
    1204           3 : }

Generated by: LCOV version 1.11