X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fnetwork%2Fclientpackethandler.cpp;h=8d87ff8f215e7ebb98031df8fc7dc80b248d4e2b;hb=8ca602150d4fdce6dcc63fa13e22aeaac5b927cc;hp=b887c02825a73a8b14e818ad1a510759e8d82552;hpb=244121b9643f91e1b8ffb4c37a255d7603da2116;p=minetest.git diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index b887c0282..8d87ff8f2 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/client.h" #include "util/base64.h" +#include "client/camera.h" #include "chatmessage.h" #include "client/clientmedia.h" #include "log.h" @@ -38,8 +39,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "script/scripting_client.h" #include "util/serialize.h" #include "util/srp.h" +#include "util/sha1.h" #include "tileanimation.h" #include "gettext.h" +#include "skyparams.h" void Client::handleCommand_Deprecated(NetworkPacket* pkt) { @@ -134,6 +137,9 @@ void Client::handleCommand_AuthAccept(NetworkPacket* pkt) << m_recommended_send_interval<> m_access_denied_reason; + } else if (denyCode == SERVER_ACCESSDENIED_TOO_MANY_USERS) { + m_access_denied_reason = accessDeniedStrings[denyCode]; + m_access_denied_reconnect = true; } else if (denyCode < SERVER_ACCESSDENIED_MAX) { m_access_denied_reason = accessDeniedStrings[denyCode]; } else { @@ -382,10 +391,10 @@ void Client::handleCommand_TimeOfDay(NetworkPacket* pkt) m_env.setTimeOfDaySpeed(time_speed); m_time_of_day_set = true; - u32 dr = m_env.getDayNightRatio(); - infostream << "Client: time_of_day=" << time_of_day - << " time_speed=" << time_speed - << " dr=" << dr << std::endl; + //u32 dr = m_env.getDayNightRatio(); + //infostream << "Client: time_of_day=" << time_of_day + // << " time_speed=" << time_speed + // << " dr=" << dr << std::endl; } void Client::handleCommand_ChatMessage(NetworkPacket *pkt) @@ -526,11 +535,21 @@ void Client::handleCommand_Movement(NetworkPacket* pkt) void Client::handleCommand_Fov(NetworkPacket *pkt) { f32 fov; - bool is_multiplier; + bool is_multiplier = false; + f32 transition_time = 0.0f; + *pkt >> fov >> is_multiplier; + // Wrap transition_time extraction within a + // try-catch to preserve backwards compat + try { + *pkt >> transition_time; + } catch (PacketError &e) {}; + LocalPlayer *player = m_env.getLocalPlayer(); - player->setFov({ fov, is_multiplier }); + assert(player); + player->setFov({ fov, is_multiplier, transition_time }); + m_camera->notifyFovChange(); } void Client::handleCommand_HP(NetworkPacket *pkt) @@ -943,114 +962,66 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt) std::string datastring(pkt->getString(0), pkt->getSize()); std::istringstream is(datastring, std::ios_base::binary); - v3f pos = readV3F32(is); - v3f vel = readV3F32(is); - v3f acc = readV3F32(is); - float expirationtime = readF32(is); - float size = readF32(is); - bool collisiondetection = readU8(is); - std::string texture = deSerializeLongString(is); - - bool vertical = false; - bool collision_removal = false; - TileAnimationParams animation; - animation.type = TAT_NONE; - u8 glow = 0; - bool object_collision = false; - try { - vertical = readU8(is); - collision_removal = readU8(is); - animation.deSerialize(is, m_proto_ver); - glow = readU8(is); - object_collision = readU8(is); - } catch (...) {} + ParticleParameters p; + p.deSerialize(is, m_proto_ver); ClientEvent *event = new ClientEvent(); - event->type = CE_SPAWN_PARTICLE; - event->spawn_particle.pos = new v3f (pos); - event->spawn_particle.vel = new v3f (vel); - event->spawn_particle.acc = new v3f (acc); - event->spawn_particle.expirationtime = expirationtime; - event->spawn_particle.size = size; - event->spawn_particle.collisiondetection = collisiondetection; - event->spawn_particle.collision_removal = collision_removal; - event->spawn_particle.object_collision = object_collision; - event->spawn_particle.vertical = vertical; - event->spawn_particle.texture = new std::string(texture); - event->spawn_particle.animation = animation; - event->spawn_particle.glow = glow; + event->type = CE_SPAWN_PARTICLE; + event->spawn_particle = new ParticleParameters(p); m_client_event_queue.push(event); } void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) { - u16 amount; - float spawntime; - v3f minpos; - v3f maxpos; - v3f minvel; - v3f maxvel; - v3f minacc; - v3f maxacc; - float minexptime; - float maxexptime; - float minsize; - float maxsize; - bool collisiondetection; - u32 server_id; - - *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel - >> minacc >> maxacc >> minexptime >> maxexptime >> minsize - >> maxsize >> collisiondetection; - - std::string texture = pkt->readLongString(); - - *pkt >> server_id; - - bool vertical = false; - bool collision_removal = false; - u16 attached_id = 0; - TileAnimationParams animation; - animation.type = TAT_NONE; - u8 glow = 0; - bool object_collision = false; - try { - *pkt >> vertical; - *pkt >> collision_removal; - *pkt >> attached_id; + std::string datastring(pkt->getString(0), pkt->getSize()); + std::istringstream is(datastring, std::ios_base::binary); - // This is horrible but required (why are there two ways to deserialize pkts?) - std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes()); - std::istringstream is(datastring, std::ios_base::binary); - animation.deSerialize(is, m_proto_ver); - glow = readU8(is); - object_collision = readU8(is); - } catch (...) {} + ParticleSpawnerParameters p; + u32 server_id; + u16 attached_id = 0; + + p.amount = readU16(is); + p.time = readF32(is); + p.minpos = readV3F32(is); + p.maxpos = readV3F32(is); + p.minvel = readV3F32(is); + p.maxvel = readV3F32(is); + p.minacc = readV3F32(is); + p.maxacc = readV3F32(is); + p.minexptime = readF32(is); + p.maxexptime = readF32(is); + p.minsize = readF32(is); + p.maxsize = readF32(is); + p.collisiondetection = readU8(is); + p.texture = deSerializeLongString(is); + + server_id = readU32(is); + + p.vertical = readU8(is); + p.collision_removal = readU8(is); + + attached_id = readU16(is); + + p.animation.deSerialize(is, m_proto_ver); + p.glow = readU8(is); + p.object_collision = readU8(is); + + // This is kinda awful + do { + u16 tmp_param0 = readU16(is); + if (is.eof()) + break; + p.node.param0 = tmp_param0; + p.node.param2 = readU8(is); + p.node_tile = readU8(is); + } while (0); auto event = new ClientEvent(); - event->type = CE_ADD_PARTICLESPAWNER; - event->add_particlespawner.amount = amount; - event->add_particlespawner.spawntime = spawntime; - event->add_particlespawner.minpos = new v3f (minpos); - event->add_particlespawner.maxpos = new v3f (maxpos); - event->add_particlespawner.minvel = new v3f (minvel); - event->add_particlespawner.maxvel = new v3f (maxvel); - event->add_particlespawner.minacc = new v3f (minacc); - event->add_particlespawner.maxacc = new v3f (maxacc); - event->add_particlespawner.minexptime = minexptime; - event->add_particlespawner.maxexptime = maxexptime; - event->add_particlespawner.minsize = minsize; - event->add_particlespawner.maxsize = maxsize; - event->add_particlespawner.collisiondetection = collisiondetection; - event->add_particlespawner.collision_removal = collision_removal; - event->add_particlespawner.object_collision = object_collision; - event->add_particlespawner.attached_id = attached_id; - event->add_particlespawner.vertical = vertical; - event->add_particlespawner.texture = new std::string(texture); - event->add_particlespawner.id = server_id; - event->add_particlespawner.animation = animation; - event->add_particlespawner.glow = glow; + event->type = CE_ADD_PARTICLESPAWNER; + event->add_particlespawner.p = new ParticleSpawnerParameters(p); + event->add_particlespawner.attached_id = attached_id; + event->add_particlespawner.id = server_id; m_client_event_queue.push(event); } @@ -1087,22 +1058,16 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) v3f world_pos; v2s32 size; s16 z_index = 0; + std::string text2; *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item >> dir >> align >> offset; try { *pkt >> world_pos; - } - catch(SerializationError &e) {}; - - try { *pkt >> size; - } catch(SerializationError &e) {}; - - try { *pkt >> z_index; - } - catch(PacketError &e) {} + *pkt >> text2; + } catch(PacketError &e) {}; ClientEvent *event = new ClientEvent(); event->type = CE_HUDADD; @@ -1120,6 +1085,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) 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); m_client_event_queue.push(event); } @@ -1156,7 +1122,7 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt) 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) + 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; @@ -1233,28 +1199,131 @@ void Client::handleCommand_HudSetParam(NetworkPacket* pkt) void Client::handleCommand_HudSetSky(NetworkPacket* pkt) { - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); + if (m_proto_ver < 39) { + // Handle Protocol 38 and below servers with old set_sky, + // ensuring the classic look is kept. + std::string datastring(pkt->getString(0), pkt->getSize()); + std::istringstream is(datastring, std::ios_base::binary); - video::SColor *bgcolor = new video::SColor(readARGB8(is)); - std::string *type = new std::string(deSerializeString(is)); - u16 count = readU16(is); - std::vector *params = new std::vector; + SkyboxParams skybox; + skybox.bgcolor = video::SColor(readARGB8(is)); + skybox.type = std::string(deSerializeString(is)); + u16 count = readU16(is); + + for (size_t i = 0; i < count; i++) + skybox.textures.emplace_back(deSerializeString(is)); + + skybox.clouds = true; + try { + skybox.clouds = readU8(is); + } catch (...) {} + + // Use default skybox settings: + SkyboxDefaults sky_defaults; + SunParams sun = sky_defaults.getSunDefaults(); + MoonParams moon = sky_defaults.getMoonDefaults(); + StarParams stars = sky_defaults.getStarDefaults(); + + // Fix for "regular" skies, as color isn't kept: + if (skybox.type == "regular") { + skybox.sky_color = sky_defaults.getSkyColorDefaults(); + skybox.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 { + sun.visible = false; + sun.sunrise_visible = false; + moon.visible = false; + stars.visible = false; + } - for (size_t i = 0; i < count; i++) - params->push_back(deSerializeString(is)); + // Skybox, sun, moon and stars ClientEvents: + ClientEvent *sky_event = new ClientEvent(); + sky_event->type = CE_SET_SKY; + sky_event->set_sky = new SkyboxParams(skybox); + m_client_event_queue.push(sky_event); + + ClientEvent *sun_event = new ClientEvent(); + sun_event->type = CE_SET_SUN; + sun_event->sun_params = new SunParams(sun); + m_client_event_queue.push(sun_event); + + ClientEvent *moon_event = new ClientEvent(); + moon_event->type = CE_SET_MOON; + moon_event->moon_params = new MoonParams(moon); + m_client_event_queue.push(moon_event); + + ClientEvent *star_event = new ClientEvent(); + star_event->type = CE_SET_STARS; + star_event->star_params = new StarParams(stars); + m_client_event_queue.push(star_event); + } else { + SkyboxParams skybox; + u16 texture_count; + std::string texture; + + *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >> + skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; + + if (skybox.type == "skybox") { + *pkt >> texture_count; + for (int i = 0; i < texture_count; i++) { + *pkt >> texture; + skybox.textures.emplace_back(texture); + } + } + else if (skybox.type == "regular") { + *pkt >> skybox.sky_color.day_sky >> skybox.sky_color.day_horizon + >> skybox.sky_color.dawn_sky >> skybox.sky_color.dawn_horizon + >> skybox.sky_color.night_sky >> skybox.sky_color.night_horizon + >> skybox.sky_color.indoors; + } - bool clouds = true; - try { - clouds = readU8(is); - } catch (...) {} + ClientEvent *event = new ClientEvent(); + event->type = CE_SET_SKY; + event->set_sky = new SkyboxParams(skybox); + m_client_event_queue.push(event); + } +} + +void Client::handleCommand_HudSetSun(NetworkPacket *pkt) +{ + SunParams sun; + + *pkt >> sun.visible >> sun.texture>> sun.tonemap + >> sun.sunrise >> sun.sunrise_visible >> sun.scale; + + ClientEvent *event = new ClientEvent(); + event->type = CE_SET_SUN; + event->sun_params = new SunParams(sun); + m_client_event_queue.push(event); +} + +void Client::handleCommand_HudSetMoon(NetworkPacket *pkt) +{ + MoonParams moon; + + *pkt >> moon.visible >> moon.texture + >> moon.tonemap >> moon.scale; + + ClientEvent *event = new ClientEvent(); + event->type = CE_SET_MOON; + event->moon_params = new MoonParams(moon); + m_client_event_queue.push(event); +} + +void Client::handleCommand_HudSetStars(NetworkPacket *pkt) +{ + StarParams stars; + + *pkt >> stars.visible >> stars.count + >> stars.starcolor >> stars.scale; ClientEvent *event = new ClientEvent(); - event->type = CE_SET_SKY; - event->set_sky.bgcolor = bgcolor; - event->set_sky.type = type; - event->set_sky.params = params; - event->set_sky.clouds = clouds; + event->type = CE_SET_STARS; + event->star_params = new StarParams(stars); + m_client_event_queue.push(event); } @@ -1406,6 +1475,51 @@ void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt) player->addVelocity(added_vel); } +void Client::handleCommand_MediaPush(NetworkPacket *pkt) +{ + std::string raw_hash, filename, filedata; + bool cached; + + *pkt >> raw_hash >> filename >> cached; + filedata = pkt->readLongString(); + + if (raw_hash.size() != 20 || filedata.empty() || filename.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; + + if (m_media_pushed_files.count(filename) != 0) { + // Silently ignore for synchronization purposes + 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; + 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); +} + /* * Mod channels */