X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnetwork%2Fclientpackethandler.cpp;h=29e3364db0e2d6ef4a50b365832076702820c0be;hb=21df26984da91143c15587f5a03c98d68c3adc4e;hp=a3f1e668d09bb85dda800e2c63c40ee11579b80a;hpb=fb4d54ee30ee9b8394bac18418b88adb0f9cd953;p=dragonfireclient.git diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index a3f1e668d..29e3364db 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "tileanimation.h" #include "gettext.h" #include "skyparams.h" +#include void Client::handleCommand_Deprecated(NetworkPacket* pkt) { @@ -90,7 +91,7 @@ void Client::handleCommand_Hello(NetworkPacket* pkt) // This is only neccessary though when we actually want to add casing support if (m_chosen_auth_mech != AUTH_MECHANISM_NONE) { - // we recieved a TOCLIENT_HELLO while auth was already going on + // we received a TOCLIENT_HELLO while auth was already going on errorstream << "Client: TOCLIENT_HELLO while auth was already going on" << "(chosen_mech=" << m_chosen_auth_mech << ")." << std::endl; if (m_chosen_auth_mech == AUTH_MECHANISM_SRP || @@ -158,7 +159,7 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt) m_password = m_new_password; - verbosestream << "Client: Recieved TOCLIENT_ACCEPT_SUDO_MODE." << std::endl; + verbosestream << "Client: Received TOCLIENT_ACCEPT_SUDO_MODE." << std::endl; // send packet to actually set the password startAuth(AUTH_MECHANISM_FIRST_SRP); @@ -184,7 +185,7 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt) m_access_denied_reason = "Unknown"; if (pkt->getCommand() != TOCLIENT_ACCESS_DENIED) { - // 13/03/15 Legacy code from 0.4.12 and lesser but is still used + // Legacy code from 0.4.12 and older but is still used // in some places of the server code if (pkt->getSize() >= 2) { std::wstring wide_reason; @@ -197,14 +198,14 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt) if (pkt->getSize() < 1) return; - u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA; + u8 denyCode; *pkt >> denyCode; + if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN || denyCode == SERVER_ACCESSDENIED_CRASH) { *pkt >> m_access_denied_reason; - if (m_access_denied_reason.empty()) { + if (m_access_denied_reason.empty()) m_access_denied_reason = accessDeniedStrings[denyCode]; - } u8 reconnect; *pkt >> reconnect; m_access_denied_reconnect = reconnect & 1; @@ -221,9 +222,8 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt) // Until then (which may be never), this is outside // of the defined protocol. *pkt >> m_access_denied_reason; - if (m_access_denied_reason.empty()) { + if (m_access_denied_reason.empty()) m_access_denied_reason = "Unknown"; - } } } @@ -263,7 +263,7 @@ void Client::handleCommand_NodemetaChanged(NetworkPacket *pkt) return; std::istringstream is(pkt->readLongString(), std::ios::binary); - std::stringstream sstr; + std::stringstream sstr(std::ios::binary | std::ios::in | std::ios::out); decompressZlib(is, sstr); NodeMetadataList meta_updates_list(false); @@ -450,10 +450,10 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt) string initialization data } */ - + LocalPlayer *player = m_env.getLocalPlayer(); - bool try_reattach = player && player->isWaitingForReattach(); - + bool try_reattach = player && player->isWaitingForReattach(); + try { u8 type; u16 removed_count, added_count, id; @@ -504,7 +504,7 @@ void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt) if (!is.good()) break; - std::string message = deSerializeString(is); + std::string message = deSerializeString16(is); // Pass on to the environment m_env.processActiveObjectMessage(id, message); @@ -596,13 +596,13 @@ void Client::handleCommand_Breath(NetworkPacket* pkt) } void Client::handleCommand_MovePlayer(NetworkPacket* pkt) -{ +{ LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); if ((player->getCAO() && player->getCAO()->getParentId()) || player->isWaitingForReattach()) return; - + v3f pos; f32 pitch, yaw; @@ -622,10 +622,10 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt) it would just force the pitch and yaw values to whatever the camera points to. */ - + if (g_settings->getBool("no_force_rotate")) return; - + ClientEvent *event = new ClientEvent(); event->type = CE_PLAYER_FORCE_MOVE; event->player_force_move.pitch = pitch; @@ -684,21 +684,19 @@ void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt) m_media_downloader->addFile(name, sha1_raw); } - try { + { std::string str; - *pkt >> str; Strfnd sf(str); - while(!sf.at_end()) { + while (!sf.at_end()) { std::string baseurl = trim(sf.next(",")); - if (!baseurl.empty()) + if (!baseurl.empty()) { + m_remote_media_servers.emplace_back(baseurl); m_media_downloader->addRemoteServer(baseurl); + } } } - catch(SerializationError& e) { - // not supported by server or turned off - } m_media_downloader->step(this); } @@ -730,31 +728,38 @@ void Client::handleCommand_Media(NetworkPacket* pkt) if (num_files == 0) return; - if (!m_media_downloader || !m_media_downloader->isStarted()) { - const char *problem = m_media_downloader ? - "media has not been requested" : - "all media has been received already"; - errorstream << "Client: Received media but " - << problem << "! " - << " bunch " << bunch_i << "/" << num_bunches - << " files=" << num_files - << " size=" << pkt->getSize() << std::endl; - return; - } + bool init_phase = m_media_downloader && m_media_downloader->isStarted(); - // Mesh update thread must be stopped while - // updating content definitions - sanity_check(!m_mesh_update_thread.isRunning()); + if (init_phase) { + // Mesh update thread must be stopped while + // updating content definitions + sanity_check(!m_mesh_update_thread.isRunning()); + } - for (u32 i=0; i < num_files; i++) { - std::string name; + for (u32 i = 0; i < num_files; i++) { + std::string name, data; *pkt >> name; + data = pkt->readLongString(); - std::string data = pkt->readLongString(); - - m_media_downloader->conventionalTransferDone( - name, data, this); + bool ok = false; + if (init_phase) { + ok = m_media_downloader->conventionalTransferDone(name, data, this); + } else { + // Check pending dynamic transfers, one of them must be it + for (const auto &it : m_pending_media_downloads) { + if (it.second->conventionalTransferDone(name, data, this)) { + ok = true; + break; + } + } + } + if (!ok) { + errorstream << "Client: Received media \"" << name + << "\" but no downloads pending. " << num_bunches << " bunches, " + << num_files << " in this one. (init_phase=" << init_phase + << ")" << std::endl; + } } } @@ -769,12 +774,11 @@ void Client::handleCommand_NodeDef(NetworkPacket* pkt) // Decompress node definitions std::istringstream tmp_is(pkt->readLongString(), std::ios::binary); - std::ostringstream tmp_os; + std::stringstream tmp_os(std::ios::binary | std::ios::in | std::ios::out); decompressZlib(tmp_is, tmp_os); // Deserialize node definitions - std::istringstream tmp_is2(tmp_os.str()); - m_nodedef->deSerialize(tmp_is2); + m_nodedef->deSerialize(tmp_os); m_nodedef_received = true; } @@ -789,12 +793,11 @@ void Client::handleCommand_ItemDef(NetworkPacket* pkt) // Decompress item definitions std::istringstream tmp_is(pkt->readLongString(), std::ios::binary); - std::ostringstream tmp_os; + std::stringstream tmp_os(std::ios::binary | std::ios::in | std::ios::out); decompressZlib(tmp_is, tmp_os); // Deserialize node definitions - std::istringstream tmp_is2(tmp_os.str()); - m_itemdef->deSerialize(tmp_is2); + m_itemdef->deSerialize(tmp_os); m_itemdef_received = true; } @@ -833,12 +836,12 @@ void Client::handleCommand_PlaySound(NetworkPacket* pkt) *pkt >> pitch; *pkt >> ephemeral; } catch (PacketError &e) {}; - + SimpleSoundSpec sound_spec(name, gain, fade, pitch); - + if (m_mods_loaded && m_script->on_play_sound(sound_spec)) return; - + // Start playing int client_id = -1; switch(type) { @@ -987,11 +990,10 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt) ClientEvent *event = new ClientEvent(); event->type = CE_SPAWN_PARTICLE; event->spawn_particle = new ParticleParameters(p); - - if (g_settings->getBool("log_particles")) { - std::cout << p.pos.X << " " << p.pos.Y << " " << p.pos.Z << std::endl; - } - + + if (m_mods_loaded && m_script->on_spawn_particle(*event->spawn_particle)) + return; + m_client_event_queue.push(event); } @@ -1017,7 +1019,7 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) p.minsize = readF32(is); p.maxsize = readF32(is); p.collisiondetection = readU8(is); - p.texture = deSerializeLongString(is); + p.texture = deSerializeString32(is); server_id = readU32(is); @@ -1064,9 +1066,6 @@ void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt) void Client::handleCommand_HudAdd(NetworkPacket* pkt) { - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - u32 server_id; u8 type; v2f pos; @@ -1082,6 +1081,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) v2s32 size; s16 z_index = 0; std::string text2; + u32 style = 0; *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item >> dir >> align >> offset; @@ -1090,25 +1090,28 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) *pkt >> size; *pkt >> z_index; *pkt >> text2; + *pkt >> style; } catch(PacketError &e) {}; ClientEvent *event = new ClientEvent(); - event->type = CE_HUDADD; - event->hudadd.server_id = server_id; - event->hudadd.type = type; - event->hudadd.pos = new v2f(pos); - event->hudadd.name = new std::string(name); - event->hudadd.scale = new v2f(scale); - event->hudadd.text = new std::string(text); - event->hudadd.number = number; - event->hudadd.item = item; - event->hudadd.dir = dir; - event->hudadd.align = new v2f(align); - event->hudadd.offset = new v2f(offset); - event->hudadd.world_pos = new v3f(world_pos); - event->hudadd.size = new v2s32(size); - event->hudadd.z_index = z_index; - event->hudadd.text2 = new std::string(text2); + event->type = CE_HUDADD; + event->hudadd = new ClientEventHudAdd(); + event->hudadd->server_id = server_id; + event->hudadd->type = type; + event->hudadd->pos = pos; + event->hudadd->name = name; + event->hudadd->scale = scale; + event->hudadd->text = text; + event->hudadd->number = number; + event->hudadd->item = item; + event->hudadd->dir = dir; + event->hudadd->align = align; + event->hudadd->offset = offset; + event->hudadd->world_pos = world_pos; + event->hudadd->size = size; + event->hudadd->z_index = z_index; + event->hudadd->text2 = text2; + event->hudadd->style = style; m_client_event_queue.push(event); } @@ -1118,16 +1121,10 @@ void Client::handleCommand_HudRemove(NetworkPacket* pkt) *pkt >> server_id; - auto i = m_hud_server_to_client.find(server_id); - if (i != m_hud_server_to_client.end()) { - int client_id = i->second; - m_hud_server_to_client.erase(i); - - ClientEvent *event = new ClientEvent(); - event->type = CE_HUDRM; - event->hudrm.id = client_id; - m_client_event_queue.push(event); - } + ClientEvent *event = new ClientEvent(); + event->type = CE_HUDRM; + event->hudrm.id = server_id; + m_client_event_queue.push(event); } void Client::handleCommand_HudChange(NetworkPacket* pkt) @@ -1142,31 +1139,41 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt) *pkt >> server_id >> stat; - if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE || - stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET) - *pkt >> v2fdata; - else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2) - *pkt >> sdata; - else if (stat == HUD_STAT_WORLD_POS) - *pkt >> v3fdata; - else if (stat == HUD_STAT_SIZE ) - *pkt >> v2s32data; - else - *pkt >> intdata; - - std::unordered_map::const_iterator i = m_hud_server_to_client.find(server_id); - if (i != m_hud_server_to_client.end()) { - ClientEvent *event = new ClientEvent(); - event->type = CE_HUDCHANGE; - event->hudchange.id = i->second; - event->hudchange.stat = (HudElementStat)stat; - event->hudchange.v2fdata = new v2f(v2fdata); - event->hudchange.v3fdata = new v3f(v3fdata); - event->hudchange.sdata = new std::string(sdata); - event->hudchange.data = intdata; - event->hudchange.v2s32data = new v2s32(v2s32data); - m_client_event_queue.push(event); + // Keep in sync with:server.cpp -> SendHUDChange + switch ((HudElementStat)stat) { + case HUD_STAT_POS: + case HUD_STAT_SCALE: + case HUD_STAT_ALIGN: + case HUD_STAT_OFFSET: + *pkt >> v2fdata; + break; + case HUD_STAT_NAME: + case HUD_STAT_TEXT: + case HUD_STAT_TEXT2: + *pkt >> sdata; + break; + case HUD_STAT_WORLD_POS: + *pkt >> v3fdata; + break; + case HUD_STAT_SIZE: + *pkt >> v2s32data; + break; + default: + *pkt >> intdata; + break; } + + ClientEvent *event = new ClientEvent(); + event->type = CE_HUDCHANGE; + event->hudchange = new ClientEventHudChange(); + event->hudchange->id = server_id; + event->hudchange->stat = static_cast(stat); + event->hudchange->v2fdata = v2fdata; + event->hudchange->v3fdata = v3fdata; + event->hudchange->sdata = sdata; + event->hudchange->data = intdata; + event->hudchange->v2s32data = v2s32data; + m_client_event_queue.push(event); } void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) @@ -1185,26 +1192,32 @@ void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) player->hud_flags |= flags; if (g_settings->getBool("hud_flags_bypass")) - player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | + player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE | HUD_FLAG_MINIMAP_RADAR_VISIBLE; - m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE); bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE); + // Not so satisying code to keep compatibility with old fixed mode system + // --> + // Hide minimap if it has been disabled by the server if (m_minimap && m_minimap_disabled_by_server && was_minimap_visible) // defers a minimap update, therefore only call it if really // needed, by checking that minimap was visible before - m_minimap->setMinimapMode(MINIMAP_MODE_OFF); - - // Switch to surface mode if radar disabled by server - if (m_minimap && m_minimap_radar_disabled_by_server && was_minimap_radar_visible) - m_minimap->setMinimapMode(MINIMAP_MODE_SURFACEx1); - - + m_minimap->setModeIndex(0); + + // If radar has been disabled, try to find a non radar mode or fall back to 0 + if (m_minimap && m_minimap_radar_disabled_by_server + && was_minimap_radar_visible) { + while (m_minimap->getModeIndex() > 0 && + m_minimap->getModeDef().type == MINIMAP_TYPE_RADAR) + m_minimap->nextMode(); + } + // <-- + // End of 'not so satifying code' } void Client::handleCommand_HudSetParam(NetworkPacket* pkt) @@ -1239,11 +1252,11 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; skybox.bgcolor = video::SColor(readARGB8(is)); - skybox.type = std::string(deSerializeString(is)); + skybox.type = std::string(deSerializeString16(is)); u16 count = readU16(is); for (size_t i = 0; i < count; i++) - skybox.textures.emplace_back(deSerializeString(is)); + skybox.textures.emplace_back(deSerializeString16(is)); skybox.clouds = true; try { @@ -1251,19 +1264,17 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) } catch (...) {} // Use default skybox settings: - SkyboxDefaults sky_defaults; - SunParams sun = sky_defaults.getSunDefaults(); - MoonParams moon = sky_defaults.getMoonDefaults(); - StarParams stars = sky_defaults.getStarDefaults(); + SunParams sun = SkyboxDefaults::getSunDefaults(); + MoonParams moon = SkyboxDefaults::getMoonDefaults(); + StarParams stars = SkyboxDefaults::getStarDefaults(); // Fix for "regular" skies, as color isn't kept: if (skybox.type == "regular") { - skybox.sky_color = sky_defaults.getSkyColorDefaults(); + skybox.sky_color = SkyboxDefaults::getSkyColorDefaults(); skybox.fog_tint_type = "default"; skybox.fog_moon_tint = video::SColor(255, 255, 255, 255); skybox.fog_sun_tint = video::SColor(255, 255, 255, 255); - } - else { + } else { sun.visible = false; sun.sunrise_visible = false; moon.visible = false; @@ -1413,6 +1424,8 @@ void Client::handleCommand_LocalPlayerAnimations(NetworkPacket* pkt) *pkt >> player->local_animations[2]; *pkt >> player->local_animations[3]; *pkt >> player->local_animation_speed; + + player->last_animation = -1; } void Client::handleCommand_EyeOffset(NetworkPacket* pkt) @@ -1512,46 +1525,72 @@ void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt) void Client::handleCommand_MediaPush(NetworkPacket *pkt) { std::string raw_hash, filename, filedata; + u32 token; bool cached; *pkt >> raw_hash >> filename >> cached; - filedata = pkt->readLongString(); + if (m_proto_ver >= 40) + *pkt >> token; + else + filedata = pkt->readLongString(); - if (raw_hash.size() != 20 || filedata.empty() || filename.empty() || + if (raw_hash.size() != 20 || filename.empty() || + (m_proto_ver < 40 && filedata.empty()) || !string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) { throw PacketError("Illegal filename, data or hash"); } - verbosestream << "Server pushes media file \"" << filename << "\" with " - << filedata.size() << " bytes of data (cached=" << cached - << ")" << std::endl; + verbosestream << "Server pushes media file \"" << filename << "\" "; + if (filedata.empty()) + verbosestream << "to be fetched "; + else + verbosestream << "with " << filedata.size() << " bytes "; + verbosestream << "(cached=" << cached << ")" << std::endl; if (m_media_pushed_files.count(filename) != 0) { - // Silently ignore for synchronization purposes + // Ignore (but acknowledge). Previously this was for sync purposes, + // but even in new versions media cannot be replaced at runtime. + if (m_proto_ver >= 40) + sendHaveMedia({ token }); return; } - // Compute and check checksum of data - std::string computed_hash; - { - SHA1 ctx; - ctx.addBytes(filedata.c_str(), filedata.size()); - unsigned char *buf = ctx.getDigest(); - computed_hash.assign((char*) buf, 20); - free(buf); - } - if (raw_hash != computed_hash) { - verbosestream << "Hash of file data mismatches, ignoring." << std::endl; + if (!filedata.empty()) { + // LEGACY CODEPATH + // Compute and check checksum of data + std::string computed_hash; + { + SHA1 ctx; + ctx.addBytes(filedata.c_str(), filedata.size()); + unsigned char *buf = ctx.getDigest(); + computed_hash.assign((char*) buf, 20); + free(buf); + } + if (raw_hash != computed_hash) { + verbosestream << "Hash of file data mismatches, ignoring." << std::endl; + return; + } + + // Actually load media + loadMedia(filedata, filename, true); + m_media_pushed_files.insert(filename); + + // Cache file for the next time when this client joins the same server + if (cached) + clientMediaUpdateCache(raw_hash, filedata); return; } - // Actually load media - loadMedia(filedata, filename, true); m_media_pushed_files.insert(filename); - // Cache file for the next time when this client joins the same server - if (cached) - clientMediaUpdateCache(raw_hash, filedata); + // create a downloader for this file + auto downloader(std::make_shared(cached)); + m_pending_media_downloads.emplace_back(token, downloader); + downloader->addFile(filename, raw_hash); + for (const auto &baseurl : m_remote_media_servers) + downloader->addRemoteServer(baseurl); + + downloader->step(this); } /* @@ -1645,3 +1684,38 @@ void Client::handleCommand_ModChannelSignal(NetworkPacket *pkt) if (valid_signal) m_script->on_modchannel_signal(channel, signal); } + +void Client::handleCommand_MinimapModes(NetworkPacket *pkt) +{ + u16 count; // modes + u16 mode; // wanted current mode index after change + + *pkt >> count >> mode; + + if (m_minimap) + m_minimap->clearModes(); + + for (size_t index = 0; index < count; index++) { + u16 type; + std::string label; + u16 size; + std::string texture; + u16 scale; + + *pkt >> type >> label >> size >> texture >> scale; + + if (m_minimap) + m_minimap->addMode(MinimapType(type), size, label, texture, scale); + } + + if (m_minimap) + m_minimap->setModeIndex(mode); +} + +void Client::handleCommand_SetLighting(NetworkPacket *pkt) +{ + Lighting& lighting = m_env.getLocalPlayer()->getLighting(); + + if (pkt->getRemainingBytes() >= 4) + *pkt >> lighting.shadow_intensity; +}