3 Copyright (C) 2015 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
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.
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.
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.
22 #include "util/base64.h"
23 #include "clientmedia.h"
26 #include "mapsector.h"
28 #include "serialization.h"
31 #include "network/clientopcodes.h"
32 #include "util/serialize.h"
34 void Client::handleCommand_Deprecated(NetworkPacket* pkt)
36 infostream << "Got deprecated command "
37 << toClientCommandTable[pkt->getCommand()].name << " from peer "
38 << pkt->getPeerId() << "!" << std::endl;
41 void Client::handleCommand_Hello(NetworkPacket* pkt)
43 if (pkt->getSize() < 1)
49 infostream << "Client: TOCLIENT_HELLO received with "
50 "deployed=" << ((int)deployed & 0xff) << std::endl;
52 if (!ser_ver_supported(deployed)) {
53 infostream << "Client: TOCLIENT_HELLO: Server sent "
54 << "unsupported ser_fmt_ver"<< std::endl;
58 m_server_ser_ver = deployed;
60 // @ TODO auth to server
63 void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
66 *pkt >> playerpos >> m_map_seed >> m_recommended_send_interval;
68 playerpos -= v3f(0, BS / 2, 0);
70 // Set player position
71 Player *player = m_env.getLocalPlayer();
72 assert(player != NULL);
73 player->setPosition(playerpos);
75 infostream << "Client: received map seed: " << m_map_seed << std::endl;
76 infostream << "Client: received recommended send interval "
77 << m_recommended_send_interval<<std::endl;
80 NetworkPacket resp_pkt(TOSERVER_INIT2, 0);
86 void Client::handleCommand_InitLegacy(NetworkPacket* pkt)
88 if (pkt->getSize() < 1)
94 infostream << "Client: TOCLIENT_INIT_LEGACY received with "
95 "deployed=" << ((int)deployed & 0xff) << std::endl;
97 if (!ser_ver_supported(deployed)) {
98 infostream << "Client: TOCLIENT_INIT_LEGACY: Server sent "
99 << "unsupported ser_fmt_ver"<< std::endl;
103 m_server_ser_ver = deployed;
105 // Get player position
106 v3s16 playerpos_s16(0, BS * 2 + BS * 20, 0);
107 if (pkt->getSize() >= 1 + 6) {
108 *pkt >> playerpos_s16;
110 v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS / 2, 0);
113 // Set player position
114 Player *player = m_env.getLocalPlayer();
115 assert(player != NULL);
116 player->setPosition(playerpos_f);
118 if (pkt->getSize() >= 1 + 6 + 8) {
121 infostream << "Client: received map seed: " << m_map_seed << std::endl;
124 if (pkt->getSize() >= 1 + 6 + 8 + 4) {
125 *pkt >> m_recommended_send_interval;
126 infostream << "Client: received recommended send interval "
127 << m_recommended_send_interval<<std::endl;
131 NetworkPacket resp_pkt(TOSERVER_INIT2, 0);
137 void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
139 // The server didn't like our password. Note, this needs
140 // to be processed even if the serialisation format has
141 // not been agreed yet, the same as TOCLIENT_INIT.
142 m_access_denied = true;
143 m_access_denied_reason = "Unknown";
145 if (pkt->getCommand() == TOCLIENT_ACCESS_DENIED) {
146 if (pkt->getSize() < 1)
149 u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA;
151 if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
152 std::wstring wide_reason;
154 m_access_denied_reason = wide_to_narrow(wide_reason);
156 else if (denyCode < SERVER_ACCESSDENIED_MAX) {
157 m_access_denied_reason = accessDeniedStrings[denyCode];
160 // 13/03/15 Legacy code from 0.4.12 and lesser. must stay 1 year
161 // for compat with old clients
163 if (pkt->getSize() >= 2) {
164 std::wstring wide_reason;
166 m_access_denied_reason = wide_to_narrow(wide_reason);
171 void Client::handleCommand_RemoveNode(NetworkPacket* pkt)
173 if (pkt->getSize() < 6)
181 void Client::handleCommand_AddNode(NetworkPacket* pkt)
183 if (pkt->getSize() < 6 + MapNode::serializedLength(m_server_ser_ver))
190 n.deSerialize(pkt->getU8Ptr(6), m_server_ser_ver);
192 bool remove_metadata = true;
193 u32 index = 6 + MapNode::serializedLength(m_server_ser_ver);
194 if ((pkt->getSize() >= index + 1) && pkt->getU8(index)) {
195 remove_metadata = false;
198 addNode(p, n, remove_metadata);
200 void Client::handleCommand_BlockData(NetworkPacket* pkt)
202 // Ignore too small packet
203 if (pkt->getSize() < 6)
209 std::string datastring(pkt->getString(6), pkt->getSize() - 6);
210 std::istringstream istr(datastring, std::ios_base::binary);
216 sector = m_env.getMap().emergeSector(p2d);
218 assert(sector->getPos() == p2d);
220 block = sector->getBlockNoCreateNoEx(p.Y);
223 Update an existing block
225 block->deSerialize(istr, m_server_ser_ver, false);
226 block->deSerializeNetworkSpecific(istr);
232 block = new MapBlock(&m_env.getMap(), p, this);
233 block->deSerialize(istr, m_server_ser_ver, false);
234 block->deSerializeNetworkSpecific(istr);
235 sector->insertBlock(block);
239 ServerMap::saveBlock(block, m_localdb);
243 Add it to mesh update queue and set it to be acknowledged after update.
245 addUpdateMeshTaskWithEdge(p, true);
248 void Client::handleCommand_Inventory(NetworkPacket* pkt)
250 if (pkt->getSize() < 1)
253 std::string datastring(pkt->getString(0), pkt->getSize());
254 std::istringstream is(datastring, std::ios_base::binary);
256 Player *player = m_env.getLocalPlayer();
257 assert(player != NULL);
259 player->inventory.deSerialize(is);
261 m_inventory_updated = true;
263 delete m_inventory_from_server;
264 m_inventory_from_server = new Inventory(player->inventory);
265 m_inventory_from_server_age = 0.0;
268 void Client::handleCommand_TimeOfDay(NetworkPacket* pkt)
270 if (pkt->getSize() < 2)
277 time_of_day = time_of_day % 24000;
278 float time_speed = 0;
280 if (pkt->getSize() >= 2 + 4) {
284 // Old message; try to approximate speed of time by ourselves
285 float time_of_day_f = (float)time_of_day / 24000.0;
286 float tod_diff_f = 0;
288 if (time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8)
289 tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0;
291 tod_diff_f = time_of_day_f - m_last_time_of_day_f;
293 m_last_time_of_day_f = time_of_day_f;
294 float time_diff = m_time_of_day_update_timer;
295 m_time_of_day_update_timer = 0;
297 if (m_time_of_day_set) {
298 time_speed = (3600.0 * 24.0) * tod_diff_f / time_diff;
299 infostream << "Client: Measured time_of_day speed (old format): "
300 << time_speed << " tod_diff_f=" << tod_diff_f
301 << " time_diff=" << time_diff << std::endl;
305 // Update environment
306 m_env.setTimeOfDay(time_of_day);
307 m_env.setTimeOfDaySpeed(time_speed);
308 m_time_of_day_set = true;
310 u32 dr = m_env.getDayNightRatio();
311 infostream << "Client: time_of_day=" << time_of_day
312 << " time_speed=" << time_speed
313 << " dr=" << dr << std::endl;
316 void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
327 std::wstring message;
328 for (u32 i = 0; i < len; i++) {
330 message += (wchar_t)read_wchar;
333 m_chat_queue.push(message);
336 void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
339 u16 count of removed objects
340 for all removed objects {
343 u16 count of added objects
344 for all added objects {
347 u32 initialization data length
348 string initialization data
354 u16 removed_count, added_count, id;
356 // Read removed objects
357 *pkt >> removed_count;
359 for (u16 i = 0; i < removed_count; i++) {
361 m_env.removeActiveObject(id);
364 // Read added objects
367 for (u16 i = 0; i < added_count; i++) {
369 m_env.addActiveObject(id, type, pkt->readLongString());
371 } catch (PacketError &e) {
372 infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
373 << ". The packet is unreliable, ignoring" << std::endl;
377 void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
388 // Get all data except the command number
389 std::string datastring(pkt->getString(0), pkt->getSize());
390 // Throw them in an istringstream
391 std::istringstream is(datastring, std::ios_base::binary);
394 while(is.eof() == false) {
396 u16 id = readU16((u8*)buf);
400 size_t message_size = readU16((u8*)buf);
402 message.reserve(message_size);
403 for (u32 i = 0; i < message_size; i++) {
405 message.append(buf, 1);
407 // Pass on to the environment
408 m_env.processActiveObjectMessage(id, message);
410 // Packet could be unreliable then ignore it
411 } catch (PacketError &e) {
412 infostream << "handleCommand_ActiveObjectMessages: " << e.what()
413 << ". The packet is unreliable, ignoring" << std::endl;
417 void Client::handleCommand_Movement(NetworkPacket* pkt)
419 Player *player = m_env.getLocalPlayer();
420 assert(player != NULL);
422 float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
424 *pkt >> mad >> maa >> maf >> msw >> mscr >> msf >> mscl >> msj
425 >> lf >> lfs >> ls >> g;
427 player->movement_acceleration_default = mad * BS;
428 player->movement_acceleration_air = maa * BS;
429 player->movement_acceleration_fast = maf * BS;
430 player->movement_speed_walk = msw * BS;
431 player->movement_speed_crouch = mscr * BS;
432 player->movement_speed_fast = msf * BS;
433 player->movement_speed_climb = mscl * BS;
434 player->movement_speed_jump = msj * BS;
435 player->movement_liquid_fluidity = lf * BS;
436 player->movement_liquid_fluidity_smooth = lfs * BS;
437 player->movement_liquid_sink = ls * BS;
438 player->movement_gravity = g * BS;
441 void Client::handleCommand_HP(NetworkPacket* pkt)
444 Player *player = m_env.getLocalPlayer();
445 assert(player != NULL);
447 u8 oldhp = player->hp;
455 // Add to ClientEvent queue
457 event.type = CE_PLAYER_DAMAGE;
458 event.player_damage.amount = oldhp - hp;
459 m_client_event_queue.push(event);
463 void Client::handleCommand_Breath(NetworkPacket* pkt)
465 Player *player = m_env.getLocalPlayer();
466 assert(player != NULL);
472 player->setBreath(breath);
475 void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
477 Player *player = m_env.getLocalPlayer();
478 assert(player != NULL);
483 *pkt >> pos >> pitch >> yaw;
485 player->setPosition(pos);
487 infostream << "Client got TOCLIENT_MOVE_PLAYER"
488 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
489 << " pitch=" << pitch
494 Add to ClientEvent queue.
495 This has to be sent to the main program because otherwise
496 it would just force the pitch and yaw values to whatever
497 the camera points to.
500 event.type = CE_PLAYER_FORCE_MOVE;
501 event.player_force_move.pitch = pitch;
502 event.player_force_move.yaw = yaw;
503 m_client_event_queue.push(event);
505 // Ignore damage for a few seconds, so that the player doesn't
506 // get damage from falling on ground
507 m_ignore_damage_timer = 3.0;
510 void Client::handleCommand_PlayerItem(NetworkPacket* pkt)
512 infostream << "Client: WARNING: Ignoring TOCLIENT_PLAYERITEM" << std::endl;
515 void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
517 bool set_camera_point_target;
518 v3f camera_point_target;
520 *pkt >> set_camera_point_target;
521 *pkt >> camera_point_target;
524 event.type = CE_DEATHSCREEN;
525 event.deathscreen.set_camera_point_target = set_camera_point_target;
526 event.deathscreen.camera_point_target_x = camera_point_target.X;
527 event.deathscreen.camera_point_target_y = camera_point_target.Y;
528 event.deathscreen.camera_point_target_z = camera_point_target.Z;
529 m_client_event_queue.push(event);
532 void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
538 infostream << "Client: Received media announcement: packet size: "
539 << pkt->getSize() << std::endl;
541 if (m_media_downloader == NULL ||
542 m_media_downloader->isStarted()) {
543 const char *problem = m_media_downloader ?
544 "we already saw another announcement" :
545 "all media has been received already";
546 errorstream << "Client: Received media announcement but "
548 << " files=" << num_files
549 << " size=" << pkt->getSize() << std::endl;
553 // Mesh update thread must be stopped while
554 // updating content definitions
555 sanity_check(!m_mesh_update_thread.IsRunning());
557 for (u16 i = 0; i < num_files; i++) {
558 std::string name, sha1_base64;
560 *pkt >> name >> sha1_base64;
562 std::string sha1_raw = base64_decode(sha1_base64);
563 m_media_downloader->addFile(name, sha1_raw);
566 std::vector<std::string> remote_media;
574 std::string baseurl = trim(sf.next(","));
576 m_media_downloader->addRemoteServer(baseurl);
579 catch(SerializationError& e) {
580 // not supported by server or turned off
583 m_media_downloader->step(this);
586 void Client::handleCommand_Media(NetworkPacket* pkt)
590 u16 total number of file bunches
591 u16 index of this bunch
592 u32 number of files in this bunch
604 *pkt >> num_bunches >> bunch_i >> num_files;
606 infostream << "Client: Received files: bunch " << bunch_i << "/"
607 << num_bunches << " files=" << num_files
608 << " size=" << pkt->getSize() << std::endl;
613 if (m_media_downloader == NULL ||
614 !m_media_downloader->isStarted()) {
615 const char *problem = m_media_downloader ?
616 "media has not been requested" :
617 "all media has been received already";
618 errorstream << "Client: Received media but "
620 << " bunch " << bunch_i << "/" << num_bunches
621 << " files=" << num_files
622 << " size=" << pkt->getSize() << std::endl;
626 // Mesh update thread must be stopped while
627 // updating content definitions
628 sanity_check(!m_mesh_update_thread.IsRunning());
630 for (u32 i=0; i < num_files; i++) {
635 std::string data = pkt->readLongString();
637 m_media_downloader->conventionalTransferDone(
642 void Client::handleCommand_ToolDef(NetworkPacket* pkt)
644 infostream << "Client: WARNING: Ignoring TOCLIENT_TOOLDEF" << std::endl;
647 void Client::handleCommand_NodeDef(NetworkPacket* pkt)
649 infostream << "Client: Received node definitions: packet size: "
650 << pkt->getSize() << std::endl;
652 // Mesh update thread must be stopped while
653 // updating content definitions
654 sanity_check(!m_mesh_update_thread.IsRunning());
656 // Decompress node definitions
657 std::string datastring(pkt->getString(0), pkt->getSize());
658 std::istringstream is(datastring, std::ios_base::binary);
659 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
660 std::ostringstream tmp_os;
661 decompressZlib(tmp_is, tmp_os);
663 // Deserialize node definitions
664 std::istringstream tmp_is2(tmp_os.str());
665 m_nodedef->deSerialize(tmp_is2);
666 m_nodedef_received = true;
669 void Client::handleCommand_CraftItemDef(NetworkPacket* pkt)
671 infostream << "Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl;
674 void Client::handleCommand_ItemDef(NetworkPacket* pkt)
676 infostream << "Client: Received item definitions: packet size: "
677 << pkt->getSize() << std::endl;
679 // Mesh update thread must be stopped while
680 // updating content definitions
681 sanity_check(!m_mesh_update_thread.IsRunning());
683 // Decompress item definitions
684 std::string datastring(pkt->getString(0), pkt->getSize());
685 std::istringstream is(datastring, std::ios_base::binary);
686 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
687 std::ostringstream tmp_os;
688 decompressZlib(tmp_is, tmp_os);
690 // Deserialize node definitions
691 std::istringstream tmp_is2(tmp_os.str());
692 m_itemdef->deSerialize(tmp_is2);
693 m_itemdef_received = true;
696 void Client::handleCommand_PlaySound(NetworkPacket* pkt)
701 u8 type; // 0=local, 1=positional, 2=object
706 *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
712 client_id = m_sound->playSound(name, loop, gain);
714 case 1: // positional
715 client_id = m_sound->playSoundAt(name, loop, gain, pos);
719 ClientActiveObject *cao = m_env.getActiveObject(object_id);
721 pos = cao->getPosition();
722 client_id = m_sound->playSoundAt(name, loop, gain, pos);
723 // TODO: Set up sound to move with object
730 if (client_id != -1) {
731 m_sounds_server_to_client[server_id] = client_id;
732 m_sounds_client_to_server[client_id] = server_id;
734 m_sounds_to_objects[client_id] = object_id;
738 void Client::handleCommand_StopSound(NetworkPacket* pkt)
744 std::map<s32, int>::iterator i =
745 m_sounds_server_to_client.find(server_id);
747 if (i != m_sounds_server_to_client.end()) {
748 int client_id = i->second;
749 m_sound->stopSound(client_id);
753 void Client::handleCommand_Privileges(NetworkPacket* pkt)
755 m_privileges.clear();
756 infostream << "Client: Privileges updated: ";
759 *pkt >> num_privileges;
761 for (u16 i = 0; i < num_privileges; i++) {
766 m_privileges.insert(priv);
767 infostream << priv << " ";
769 infostream << std::endl;
772 void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
774 Player *player = m_env.getLocalPlayer();
775 assert(player != NULL);
777 // Store formspec in LocalPlayer
778 player->inventory_formspec = pkt->readLongString();
781 void Client::handleCommand_DetachedInventory(NetworkPacket* pkt)
783 std::string datastring(pkt->getString(0), pkt->getSize());
784 std::istringstream is(datastring, std::ios_base::binary);
786 std::string name = deSerializeString(is);
788 infostream << "Client: Detached inventory update: \"" << name
789 << "\"" << std::endl;
791 Inventory *inv = NULL;
792 if (m_detached_inventories.count(name) > 0)
793 inv = m_detached_inventories[name];
795 inv = new Inventory(m_itemdef);
796 m_detached_inventories[name] = inv;
798 inv->deSerialize(is);
801 void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt)
803 std::string formspec = pkt->readLongString();
804 std::string formname;
809 event.type = CE_SHOW_FORMSPEC;
810 // pointer is required as event is a struct only!
811 // adding a std:string to a struct isn't possible
812 event.show_formspec.formspec = new std::string(formspec);
813 event.show_formspec.formname = new std::string(formname);
814 m_client_event_queue.push(event);
817 void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
819 std::string datastring(pkt->getString(0), pkt->getSize());
820 std::istringstream is(datastring, std::ios_base::binary);
822 v3f pos = readV3F1000(is);
823 v3f vel = readV3F1000(is);
824 v3f acc = readV3F1000(is);
825 float expirationtime = readF1000(is);
826 float size = readF1000(is);
827 bool collisiondetection = readU8(is);
828 std::string texture = deSerializeLongString(is);
829 bool vertical = false;
831 vertical = readU8(is);
835 event.type = CE_SPAWN_PARTICLE;
836 event.spawn_particle.pos = new v3f (pos);
837 event.spawn_particle.vel = new v3f (vel);
838 event.spawn_particle.acc = new v3f (acc);
839 event.spawn_particle.expirationtime = expirationtime;
840 event.spawn_particle.size = size;
841 event.spawn_particle.collisiondetection = collisiondetection;
842 event.spawn_particle.vertical = vertical;
843 event.spawn_particle.texture = new std::string(texture);
845 m_client_event_queue.push(event);
848 void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
862 bool collisiondetection;
865 *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
866 >> minacc >> maxacc >> minexptime >> maxexptime >> minsize
867 >> maxsize >> collisiondetection;
869 std::string texture = pkt->readLongString();
873 bool vertical = false;
879 event.type = CE_ADD_PARTICLESPAWNER;
880 event.add_particlespawner.amount = amount;
881 event.add_particlespawner.spawntime = spawntime;
882 event.add_particlespawner.minpos = new v3f (minpos);
883 event.add_particlespawner.maxpos = new v3f (maxpos);
884 event.add_particlespawner.minvel = new v3f (minvel);
885 event.add_particlespawner.maxvel = new v3f (maxvel);
886 event.add_particlespawner.minacc = new v3f (minacc);
887 event.add_particlespawner.maxacc = new v3f (maxacc);
888 event.add_particlespawner.minexptime = minexptime;
889 event.add_particlespawner.maxexptime = maxexptime;
890 event.add_particlespawner.minsize = minsize;
891 event.add_particlespawner.maxsize = maxsize;
892 event.add_particlespawner.collisiondetection = collisiondetection;
893 event.add_particlespawner.vertical = vertical;
894 event.add_particlespawner.texture = new std::string(texture);
895 event.add_particlespawner.id = id;
897 m_client_event_queue.push(event);
901 void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
906 // Modification set 13/03/15, 1 year of compat for protocol v24
907 if (pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY) {
916 event.type = CE_DELETE_PARTICLESPAWNER;
917 event.delete_particlespawner.id =
918 (pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY ? (u32) legacy_id : id);
920 m_client_event_queue.push(event);
923 void Client::handleCommand_HudAdd(NetworkPacket* pkt)
925 std::string datastring(pkt->getString(0), pkt->getSize());
926 std::istringstream is(datastring, std::ios_base::binary);
942 *pkt >> id >> type >> pos >> name >> scale >> text >> number >> item
943 >> dir >> align >> offset;
947 catch(SerializationError &e) {};
951 } catch(SerializationError &e) {};
954 event.type = CE_HUDADD;
955 event.hudadd.id = id;
956 event.hudadd.type = type;
957 event.hudadd.pos = new v2f(pos);
958 event.hudadd.name = new std::string(name);
959 event.hudadd.scale = new v2f(scale);
960 event.hudadd.text = new std::string(text);
961 event.hudadd.number = number;
962 event.hudadd.item = item;
963 event.hudadd.dir = dir;
964 event.hudadd.align = new v2f(align);
965 event.hudadd.offset = new v2f(offset);
966 event.hudadd.world_pos = new v3f(world_pos);
967 event.hudadd.size = new v2s32(size);
968 m_client_event_queue.push(event);
971 void Client::handleCommand_HudRemove(NetworkPacket* pkt)
978 event.type = CE_HUDRM;
980 m_client_event_queue.push(event);
983 void Client::handleCommand_HudChange(NetworkPacket* pkt)
995 if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
996 stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
998 else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
1000 else if (stat == HUD_STAT_WORLD_POS)
1002 else if (stat == HUD_STAT_SIZE )
1008 event.type = CE_HUDCHANGE;
1009 event.hudchange.id = id;
1010 event.hudchange.stat = (HudElementStat)stat;
1011 event.hudchange.v2fdata = new v2f(v2fdata);
1012 event.hudchange.v3fdata = new v3f(v3fdata);
1013 event.hudchange.sdata = new std::string(sdata);
1014 event.hudchange.data = intdata;
1015 event.hudchange.v2s32data = new v2s32(v2s32data);
1016 m_client_event_queue.push(event);
1019 void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
1023 *pkt >> flags >> mask;
1025 Player *player = m_env.getLocalPlayer();
1026 assert(player != NULL);
1028 player->hud_flags &= ~mask;
1029 player->hud_flags |= flags;
1032 void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
1034 u16 param; std::string value;
1036 *pkt >> param >> value;
1038 Player *player = m_env.getLocalPlayer();
1039 assert(player != NULL);
1041 if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
1042 s32 hotbar_itemcount = readS32((u8*) value.c_str());
1043 if (hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX)
1044 player->hud_hotbar_itemcount = hotbar_itemcount;
1046 else if (param == HUD_PARAM_HOTBAR_IMAGE) {
1047 ((LocalPlayer *) player)->hotbar_image = value;
1049 else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
1050 ((LocalPlayer *) player)->hotbar_selected_image = value;
1054 void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
1056 std::string datastring(pkt->getString(0), pkt->getSize());
1057 std::istringstream is(datastring, std::ios_base::binary);
1059 video::SColor *bgcolor = new video::SColor(readARGB8(is));
1060 std::string *type = new std::string(deSerializeString(is));
1061 u16 count = readU16(is);
1062 std::vector<std::string> *params = new std::vector<std::string>;
1064 for (size_t i = 0; i < count; i++)
1065 params->push_back(deSerializeString(is));
1068 event.type = CE_SET_SKY;
1069 event.set_sky.bgcolor = bgcolor;
1070 event.set_sky.type = type;
1071 event.set_sky.params = params;
1072 m_client_event_queue.push(event);
1075 void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt)
1078 u16 day_night_ratio_u;
1080 *pkt >> do_override >> day_night_ratio_u;
1082 float day_night_ratio_f = (float)day_night_ratio_u / 65536;
1085 event.type = CE_OVERRIDE_DAY_NIGHT_RATIO;
1086 event.override_day_night_ratio.do_override = do_override;
1087 event.override_day_night_ratio.ratio_f = day_night_ratio_f;
1088 m_client_event_queue.push(event);
1091 void Client::handleCommand_LocalPlayerAnimations(NetworkPacket* pkt)
1093 LocalPlayer *player = m_env.getLocalPlayer();
1094 assert(player != NULL);
1096 *pkt >> player->local_animations[0];
1097 *pkt >> player->local_animations[1];
1098 *pkt >> player->local_animations[2];
1099 *pkt >> player->local_animations[3];
1100 *pkt >> player->local_animation_speed;
1103 void Client::handleCommand_EyeOffset(NetworkPacket* pkt)
1105 LocalPlayer *player = m_env.getLocalPlayer();
1106 assert(player != NULL);
1108 *pkt >> player->eye_offset_first >> player->eye_offset_third;