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 *pkt >> m_access_denied_reason;
154 else if (denyCode < SERVER_ACCESSDENIED_MAX) {
155 m_access_denied_reason = accessDeniedStrings[denyCode];
158 // 13/03/15 Legacy code from 0.4.12 and lesser. must stay 1 year
159 // for compat with old clients
161 if (pkt->getSize() >= 2) {
162 std::wstring wide_reason;
164 m_access_denied_reason = wide_to_narrow(wide_reason);
169 void Client::handleCommand_RemoveNode(NetworkPacket* pkt)
171 if (pkt->getSize() < 6)
179 void Client::handleCommand_AddNode(NetworkPacket* pkt)
181 if (pkt->getSize() < 6 + MapNode::serializedLength(m_server_ser_ver))
188 n.deSerialize(pkt->getU8Ptr(6), m_server_ser_ver);
190 bool remove_metadata = true;
191 u32 index = 6 + MapNode::serializedLength(m_server_ser_ver);
192 if ((pkt->getSize() >= index + 1) && pkt->getU8(index)) {
193 remove_metadata = false;
196 addNode(p, n, remove_metadata);
198 void Client::handleCommand_BlockData(NetworkPacket* pkt)
200 // Ignore too small packet
201 if (pkt->getSize() < 6)
207 std::string datastring(pkt->getString(6), pkt->getSize() - 6);
208 std::istringstream istr(datastring, std::ios_base::binary);
214 sector = m_env.getMap().emergeSector(p2d);
216 assert(sector->getPos() == p2d);
218 block = sector->getBlockNoCreateNoEx(p.Y);
221 Update an existing block
223 block->deSerialize(istr, m_server_ser_ver, false);
224 block->deSerializeNetworkSpecific(istr);
230 block = new MapBlock(&m_env.getMap(), p, this);
231 block->deSerialize(istr, m_server_ser_ver, false);
232 block->deSerializeNetworkSpecific(istr);
233 sector->insertBlock(block);
237 ServerMap::saveBlock(block, m_localdb);
241 Add it to mesh update queue and set it to be acknowledged after update.
243 addUpdateMeshTaskWithEdge(p, true);
246 void Client::handleCommand_Inventory(NetworkPacket* pkt)
248 if (pkt->getSize() < 1)
251 std::string datastring(pkt->getString(0), pkt->getSize());
252 std::istringstream is(datastring, std::ios_base::binary);
254 Player *player = m_env.getLocalPlayer();
255 assert(player != NULL);
257 player->inventory.deSerialize(is);
259 m_inventory_updated = true;
261 delete m_inventory_from_server;
262 m_inventory_from_server = new Inventory(player->inventory);
263 m_inventory_from_server_age = 0.0;
266 void Client::handleCommand_TimeOfDay(NetworkPacket* pkt)
268 if (pkt->getSize() < 2)
275 time_of_day = time_of_day % 24000;
276 float time_speed = 0;
278 if (pkt->getSize() >= 2 + 4) {
282 // Old message; try to approximate speed of time by ourselves
283 float time_of_day_f = (float)time_of_day / 24000.0;
284 float tod_diff_f = 0;
286 if (time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8)
287 tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0;
289 tod_diff_f = time_of_day_f - m_last_time_of_day_f;
291 m_last_time_of_day_f = time_of_day_f;
292 float time_diff = m_time_of_day_update_timer;
293 m_time_of_day_update_timer = 0;
295 if (m_time_of_day_set) {
296 time_speed = (3600.0 * 24.0) * tod_diff_f / time_diff;
297 infostream << "Client: Measured time_of_day speed (old format): "
298 << time_speed << " tod_diff_f=" << tod_diff_f
299 << " time_diff=" << time_diff << std::endl;
303 // Update environment
304 m_env.setTimeOfDay(time_of_day);
305 m_env.setTimeOfDaySpeed(time_speed);
306 m_time_of_day_set = true;
308 u32 dr = m_env.getDayNightRatio();
309 infostream << "Client: time_of_day=" << time_of_day
310 << " time_speed=" << time_speed
311 << " dr=" << dr << std::endl;
314 void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
325 std::wstring message;
326 for (u32 i = 0; i < len; i++) {
328 message += (wchar_t)read_wchar;
331 m_chat_queue.push(message);
334 void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
337 u16 count of removed objects
338 for all removed objects {
341 u16 count of added objects
342 for all added objects {
345 u32 initialization data length
346 string initialization data
352 u16 removed_count, added_count, id;
354 // Read removed objects
355 *pkt >> removed_count;
357 for (u16 i = 0; i < removed_count; i++) {
359 m_env.removeActiveObject(id);
362 // Read added objects
365 for (u16 i = 0; i < added_count; i++) {
367 m_env.addActiveObject(id, type, pkt->readLongString());
369 } catch (PacketError &e) {
370 infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
371 << ". The packet is unreliable, ignoring" << std::endl;
375 void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
386 // Get all data except the command number
387 std::string datastring(pkt->getString(0), pkt->getSize());
388 // Throw them in an istringstream
389 std::istringstream is(datastring, std::ios_base::binary);
392 while(is.eof() == false) {
394 u16 id = readU16((u8*)buf);
398 size_t message_size = readU16((u8*)buf);
400 message.reserve(message_size);
401 for (u32 i = 0; i < message_size; i++) {
403 message.append(buf, 1);
405 // Pass on to the environment
406 m_env.processActiveObjectMessage(id, message);
408 // Packet could be unreliable then ignore it
409 } catch (PacketError &e) {
410 infostream << "handleCommand_ActiveObjectMessages: " << e.what()
411 << ". The packet is unreliable, ignoring" << std::endl;
415 void Client::handleCommand_Movement(NetworkPacket* pkt)
417 Player *player = m_env.getLocalPlayer();
418 assert(player != NULL);
420 float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
422 *pkt >> mad >> maa >> maf >> msw >> mscr >> msf >> mscl >> msj
423 >> lf >> lfs >> ls >> g;
425 player->movement_acceleration_default = mad * BS;
426 player->movement_acceleration_air = maa * BS;
427 player->movement_acceleration_fast = maf * BS;
428 player->movement_speed_walk = msw * BS;
429 player->movement_speed_crouch = mscr * BS;
430 player->movement_speed_fast = msf * BS;
431 player->movement_speed_climb = mscl * BS;
432 player->movement_speed_jump = msj * BS;
433 player->movement_liquid_fluidity = lf * BS;
434 player->movement_liquid_fluidity_smooth = lfs * BS;
435 player->movement_liquid_sink = ls * BS;
436 player->movement_gravity = g * BS;
439 void Client::handleCommand_HP(NetworkPacket* pkt)
442 Player *player = m_env.getLocalPlayer();
443 assert(player != NULL);
445 u8 oldhp = player->hp;
453 // Add to ClientEvent queue
455 event.type = CE_PLAYER_DAMAGE;
456 event.player_damage.amount = oldhp - hp;
457 m_client_event_queue.push(event);
461 void Client::handleCommand_Breath(NetworkPacket* pkt)
463 Player *player = m_env.getLocalPlayer();
464 assert(player != NULL);
470 player->setBreath(breath);
473 void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
475 Player *player = m_env.getLocalPlayer();
476 assert(player != NULL);
481 *pkt >> pos >> pitch >> yaw;
483 player->setPosition(pos);
485 infostream << "Client got TOCLIENT_MOVE_PLAYER"
486 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
487 << " pitch=" << pitch
492 Add to ClientEvent queue.
493 This has to be sent to the main program because otherwise
494 it would just force the pitch and yaw values to whatever
495 the camera points to.
498 event.type = CE_PLAYER_FORCE_MOVE;
499 event.player_force_move.pitch = pitch;
500 event.player_force_move.yaw = yaw;
501 m_client_event_queue.push(event);
503 // Ignore damage for a few seconds, so that the player doesn't
504 // get damage from falling on ground
505 m_ignore_damage_timer = 3.0;
508 void Client::handleCommand_PlayerItem(NetworkPacket* pkt)
510 infostream << "Client: WARNING: Ignoring TOCLIENT_PLAYERITEM" << std::endl;
513 void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
515 bool set_camera_point_target;
516 v3f camera_point_target;
518 *pkt >> set_camera_point_target;
519 *pkt >> camera_point_target;
522 event.type = CE_DEATHSCREEN;
523 event.deathscreen.set_camera_point_target = set_camera_point_target;
524 event.deathscreen.camera_point_target_x = camera_point_target.X;
525 event.deathscreen.camera_point_target_y = camera_point_target.Y;
526 event.deathscreen.camera_point_target_z = camera_point_target.Z;
527 m_client_event_queue.push(event);
530 void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
536 infostream << "Client: Received media announcement: packet size: "
537 << pkt->getSize() << std::endl;
539 if (m_media_downloader == NULL ||
540 m_media_downloader->isStarted()) {
541 const char *problem = m_media_downloader ?
542 "we already saw another announcement" :
543 "all media has been received already";
544 errorstream << "Client: Received media announcement but "
546 << " files=" << num_files
547 << " size=" << pkt->getSize() << std::endl;
551 // Mesh update thread must be stopped while
552 // updating content definitions
553 sanity_check(!m_mesh_update_thread.IsRunning());
555 for (u16 i = 0; i < num_files; i++) {
556 std::string name, sha1_base64;
558 *pkt >> name >> sha1_base64;
560 std::string sha1_raw = base64_decode(sha1_base64);
561 m_media_downloader->addFile(name, sha1_raw);
564 std::vector<std::string> remote_media;
572 std::string baseurl = trim(sf.next(","));
574 m_media_downloader->addRemoteServer(baseurl);
577 catch(SerializationError& e) {
578 // not supported by server or turned off
581 m_media_downloader->step(this);
584 void Client::handleCommand_Media(NetworkPacket* pkt)
588 u16 total number of file bunches
589 u16 index of this bunch
590 u32 number of files in this bunch
602 *pkt >> num_bunches >> bunch_i >> num_files;
604 infostream << "Client: Received files: bunch " << bunch_i << "/"
605 << num_bunches << " files=" << num_files
606 << " size=" << pkt->getSize() << std::endl;
611 if (m_media_downloader == NULL ||
612 !m_media_downloader->isStarted()) {
613 const char *problem = m_media_downloader ?
614 "media has not been requested" :
615 "all media has been received already";
616 errorstream << "Client: Received media but "
618 << " bunch " << bunch_i << "/" << num_bunches
619 << " files=" << num_files
620 << " size=" << pkt->getSize() << std::endl;
624 // Mesh update thread must be stopped while
625 // updating content definitions
626 sanity_check(!m_mesh_update_thread.IsRunning());
628 for (u32 i=0; i < num_files; i++) {
633 std::string data = pkt->readLongString();
635 m_media_downloader->conventionalTransferDone(
640 void Client::handleCommand_ToolDef(NetworkPacket* pkt)
642 infostream << "Client: WARNING: Ignoring TOCLIENT_TOOLDEF" << std::endl;
645 void Client::handleCommand_NodeDef(NetworkPacket* pkt)
647 infostream << "Client: Received node definitions: packet size: "
648 << pkt->getSize() << std::endl;
650 // Mesh update thread must be stopped while
651 // updating content definitions
652 sanity_check(!m_mesh_update_thread.IsRunning());
654 // Decompress node definitions
655 std::string datastring(pkt->getString(0), pkt->getSize());
656 std::istringstream is(datastring, std::ios_base::binary);
657 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
658 std::ostringstream tmp_os;
659 decompressZlib(tmp_is, tmp_os);
661 // Deserialize node definitions
662 std::istringstream tmp_is2(tmp_os.str());
663 m_nodedef->deSerialize(tmp_is2);
664 m_nodedef_received = true;
667 void Client::handleCommand_CraftItemDef(NetworkPacket* pkt)
669 infostream << "Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl;
672 void Client::handleCommand_ItemDef(NetworkPacket* pkt)
674 infostream << "Client: Received item definitions: packet size: "
675 << pkt->getSize() << std::endl;
677 // Mesh update thread must be stopped while
678 // updating content definitions
679 sanity_check(!m_mesh_update_thread.IsRunning());
681 // Decompress item definitions
682 std::string datastring(pkt->getString(0), pkt->getSize());
683 std::istringstream is(datastring, std::ios_base::binary);
684 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
685 std::ostringstream tmp_os;
686 decompressZlib(tmp_is, tmp_os);
688 // Deserialize node definitions
689 std::istringstream tmp_is2(tmp_os.str());
690 m_itemdef->deSerialize(tmp_is2);
691 m_itemdef_received = true;
694 void Client::handleCommand_PlaySound(NetworkPacket* pkt)
699 u8 type; // 0=local, 1=positional, 2=object
704 *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
710 client_id = m_sound->playSound(name, loop, gain);
712 case 1: // positional
713 client_id = m_sound->playSoundAt(name, loop, gain, pos);
717 ClientActiveObject *cao = m_env.getActiveObject(object_id);
719 pos = cao->getPosition();
720 client_id = m_sound->playSoundAt(name, loop, gain, pos);
721 // TODO: Set up sound to move with object
728 if (client_id != -1) {
729 m_sounds_server_to_client[server_id] = client_id;
730 m_sounds_client_to_server[client_id] = server_id;
732 m_sounds_to_objects[client_id] = object_id;
736 void Client::handleCommand_StopSound(NetworkPacket* pkt)
742 std::map<s32, int>::iterator i =
743 m_sounds_server_to_client.find(server_id);
745 if (i != m_sounds_server_to_client.end()) {
746 int client_id = i->second;
747 m_sound->stopSound(client_id);
751 void Client::handleCommand_Privileges(NetworkPacket* pkt)
753 m_privileges.clear();
754 infostream << "Client: Privileges updated: ";
757 *pkt >> num_privileges;
759 for (u16 i = 0; i < num_privileges; i++) {
764 m_privileges.insert(priv);
765 infostream << priv << " ";
767 infostream << std::endl;
770 void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
772 Player *player = m_env.getLocalPlayer();
773 assert(player != NULL);
775 // Store formspec in LocalPlayer
776 player->inventory_formspec = pkt->readLongString();
779 void Client::handleCommand_DetachedInventory(NetworkPacket* pkt)
781 std::string datastring(pkt->getString(0), pkt->getSize());
782 std::istringstream is(datastring, std::ios_base::binary);
784 std::string name = deSerializeString(is);
786 infostream << "Client: Detached inventory update: \"" << name
787 << "\"" << std::endl;
789 Inventory *inv = NULL;
790 if (m_detached_inventories.count(name) > 0)
791 inv = m_detached_inventories[name];
793 inv = new Inventory(m_itemdef);
794 m_detached_inventories[name] = inv;
796 inv->deSerialize(is);
799 void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt)
801 std::string formspec = pkt->readLongString();
802 std::string formname;
807 event.type = CE_SHOW_FORMSPEC;
808 // pointer is required as event is a struct only!
809 // adding a std:string to a struct isn't possible
810 event.show_formspec.formspec = new std::string(formspec);
811 event.show_formspec.formname = new std::string(formname);
812 m_client_event_queue.push(event);
815 void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
817 std::string datastring(pkt->getString(0), pkt->getSize());
818 std::istringstream is(datastring, std::ios_base::binary);
820 v3f pos = readV3F1000(is);
821 v3f vel = readV3F1000(is);
822 v3f acc = readV3F1000(is);
823 float expirationtime = readF1000(is);
824 float size = readF1000(is);
825 bool collisiondetection = readU8(is);
826 std::string texture = deSerializeLongString(is);
827 bool vertical = false;
829 vertical = readU8(is);
833 event.type = CE_SPAWN_PARTICLE;
834 event.spawn_particle.pos = new v3f (pos);
835 event.spawn_particle.vel = new v3f (vel);
836 event.spawn_particle.acc = new v3f (acc);
837 event.spawn_particle.expirationtime = expirationtime;
838 event.spawn_particle.size = size;
839 event.spawn_particle.collisiondetection = collisiondetection;
840 event.spawn_particle.vertical = vertical;
841 event.spawn_particle.texture = new std::string(texture);
843 m_client_event_queue.push(event);
846 void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
860 bool collisiondetection;
863 *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
864 >> minacc >> maxacc >> minexptime >> maxexptime >> minsize
865 >> maxsize >> collisiondetection;
867 std::string texture = pkt->readLongString();
871 bool vertical = false;
877 event.type = CE_ADD_PARTICLESPAWNER;
878 event.add_particlespawner.amount = amount;
879 event.add_particlespawner.spawntime = spawntime;
880 event.add_particlespawner.minpos = new v3f (minpos);
881 event.add_particlespawner.maxpos = new v3f (maxpos);
882 event.add_particlespawner.minvel = new v3f (minvel);
883 event.add_particlespawner.maxvel = new v3f (maxvel);
884 event.add_particlespawner.minacc = new v3f (minacc);
885 event.add_particlespawner.maxacc = new v3f (maxacc);
886 event.add_particlespawner.minexptime = minexptime;
887 event.add_particlespawner.maxexptime = maxexptime;
888 event.add_particlespawner.minsize = minsize;
889 event.add_particlespawner.maxsize = maxsize;
890 event.add_particlespawner.collisiondetection = collisiondetection;
891 event.add_particlespawner.vertical = vertical;
892 event.add_particlespawner.texture = new std::string(texture);
893 event.add_particlespawner.id = id;
895 m_client_event_queue.push(event);
899 void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
904 // Modification set 13/03/15, 1 year of compat for protocol v24
905 if (pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY) {
914 event.type = CE_DELETE_PARTICLESPAWNER;
915 event.delete_particlespawner.id =
916 (pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY ? (u32) legacy_id : id);
918 m_client_event_queue.push(event);
921 void Client::handleCommand_HudAdd(NetworkPacket* pkt)
923 std::string datastring(pkt->getString(0), pkt->getSize());
924 std::istringstream is(datastring, std::ios_base::binary);
940 *pkt >> id >> type >> pos >> name >> scale >> text >> number >> item
941 >> dir >> align >> offset;
945 catch(SerializationError &e) {};
949 } catch(SerializationError &e) {};
952 event.type = CE_HUDADD;
953 event.hudadd.id = id;
954 event.hudadd.type = type;
955 event.hudadd.pos = new v2f(pos);
956 event.hudadd.name = new std::string(name);
957 event.hudadd.scale = new v2f(scale);
958 event.hudadd.text = new std::string(text);
959 event.hudadd.number = number;
960 event.hudadd.item = item;
961 event.hudadd.dir = dir;
962 event.hudadd.align = new v2f(align);
963 event.hudadd.offset = new v2f(offset);
964 event.hudadd.world_pos = new v3f(world_pos);
965 event.hudadd.size = new v2s32(size);
966 m_client_event_queue.push(event);
969 void Client::handleCommand_HudRemove(NetworkPacket* pkt)
976 event.type = CE_HUDRM;
978 m_client_event_queue.push(event);
981 void Client::handleCommand_HudChange(NetworkPacket* pkt)
993 if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
994 stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
996 else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
998 else if (stat == HUD_STAT_WORLD_POS)
1000 else if (stat == HUD_STAT_SIZE )
1006 event.type = CE_HUDCHANGE;
1007 event.hudchange.id = id;
1008 event.hudchange.stat = (HudElementStat)stat;
1009 event.hudchange.v2fdata = new v2f(v2fdata);
1010 event.hudchange.v3fdata = new v3f(v3fdata);
1011 event.hudchange.sdata = new std::string(sdata);
1012 event.hudchange.data = intdata;
1013 event.hudchange.v2s32data = new v2s32(v2s32data);
1014 m_client_event_queue.push(event);
1017 void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
1021 *pkt >> flags >> mask;
1023 Player *player = m_env.getLocalPlayer();
1024 assert(player != NULL);
1026 player->hud_flags &= ~mask;
1027 player->hud_flags |= flags;
1030 void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
1032 u16 param; std::string value;
1034 *pkt >> param >> value;
1036 Player *player = m_env.getLocalPlayer();
1037 assert(player != NULL);
1039 if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
1040 s32 hotbar_itemcount = readS32((u8*) value.c_str());
1041 if (hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX)
1042 player->hud_hotbar_itemcount = hotbar_itemcount;
1044 else if (param == HUD_PARAM_HOTBAR_IMAGE) {
1045 ((LocalPlayer *) player)->hotbar_image = value;
1047 else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
1048 ((LocalPlayer *) player)->hotbar_selected_image = value;
1052 void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
1054 std::string datastring(pkt->getString(0), pkt->getSize());
1055 std::istringstream is(datastring, std::ios_base::binary);
1057 video::SColor *bgcolor = new video::SColor(readARGB8(is));
1058 std::string *type = new std::string(deSerializeString(is));
1059 u16 count = readU16(is);
1060 std::vector<std::string> *params = new std::vector<std::string>;
1062 for (size_t i = 0; i < count; i++)
1063 params->push_back(deSerializeString(is));
1066 event.type = CE_SET_SKY;
1067 event.set_sky.bgcolor = bgcolor;
1068 event.set_sky.type = type;
1069 event.set_sky.params = params;
1070 m_client_event_queue.push(event);
1073 void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt)
1076 u16 day_night_ratio_u;
1078 *pkt >> do_override >> day_night_ratio_u;
1080 float day_night_ratio_f = (float)day_night_ratio_u / 65536;
1083 event.type = CE_OVERRIDE_DAY_NIGHT_RATIO;
1084 event.override_day_night_ratio.do_override = do_override;
1085 event.override_day_night_ratio.ratio_f = day_night_ratio_f;
1086 m_client_event_queue.push(event);
1089 void Client::handleCommand_LocalPlayerAnimations(NetworkPacket* pkt)
1091 LocalPlayer *player = m_env.getLocalPlayer();
1092 assert(player != NULL);
1094 *pkt >> player->local_animations[0];
1095 *pkt >> player->local_animations[1];
1096 *pkt >> player->local_animations[2];
1097 *pkt >> player->local_animations[3];
1098 *pkt >> player->local_animation_speed;
1101 void Client::handleCommand_EyeOffset(NetworkPacket* pkt)
1103 LocalPlayer *player = m_env.getLocalPlayer();
1104 assert(player != NULL);
1106 *pkt >> player->eye_offset_first >> player->eye_offset_third;