From ba2fee07518d9c6154799b61ba1b14a2cb43ace7 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Wed, 5 Apr 2023 20:23:16 +0200 Subject: [PATCH] Particle spawner: Fix missing parameters The changes done to clientpackethandler.cpp and server.cpp move the compatibility code into a protocol version check so that older code parts can easily be removed in the future (e.g. bump of minimal version). --- src/network/clientpackethandler.cpp | 69 ++++++++++++++++------------- src/network/networkprotocol.h | 62 ++++++++++++++++---------- src/server.cpp | 41 +++++++++++------ 3 files changed, 105 insertions(+), 67 deletions(-) diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index c64541d77..942f101fc 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -994,14 +994,22 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) p.amount = readU16(is); p.time = readF32(is); - // older protocols do not support tweening, and send only - // static ranges, so we can't just use the normal serialization - // functions for the older values. - p.pos.start.legacyDeSerialize(is); - p.vel.start.legacyDeSerialize(is); - p.acc.start.legacyDeSerialize(is); - p.exptime.start.legacyDeSerialize(is); - p.size.start.legacyDeSerialize(is); + bool missing_end_values = false; + if (m_proto_ver >= 42) { + // All tweenable parameters + p.pos.deSerialize(is); + p.vel.deSerialize(is); + p.acc.deSerialize(is); + p.exptime.deSerialize(is); + p.size.deSerialize(is); + } else { + p.pos.start.legacyDeSerialize(is); + p.vel.start.legacyDeSerialize(is); + p.acc.start.legacyDeSerialize(is); + p.exptime.start.legacyDeSerialize(is); + p.size.start.legacyDeSerialize(is); + missing_end_values = true; + } p.collisiondetection = readU8(is); p.texture.string = deSerializeString32(is); @@ -1017,8 +1025,6 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) p.glow = readU8(is); p.object_collision = readU8(is); - bool legacy_format = true; - // This is kinda awful do { u16 tmp_param0 = readU16(is); @@ -1028,25 +1034,30 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) p.node.param2 = readU8(is); p.node_tile = readU8(is); - // v >= 5.6.0 - f32 tmp_sbias = readF32(is); - if (is.eof()) - break; + if (m_proto_ver < 42) { + // v >= 5.6.0 + f32 tmp_sbias = readF32(is); + if (is.eof()) + break; - // initial bias must be stored separately in the stream to preserve - // backwards compatibility with older clients, which do not support - // a bias field in their range "format" - p.pos.start.bias = tmp_sbias; - p.vel.start.bias = readF32(is); - p.acc.start.bias = readF32(is); - p.exptime.start.bias = readF32(is); - p.size.start.bias = readF32(is); + // initial bias must be stored separately in the stream to preserve + // backwards compatibility with older clients, which do not support + // a bias field in their range "format" + p.pos.start.bias = tmp_sbias; + p.vel.start.bias = readF32(is); + p.acc.start.bias = readF32(is); + p.exptime.start.bias = readF32(is); + p.size.start.bias = readF32(is); - p.pos.end.deSerialize(is); - p.vel.end.deSerialize(is); - p.acc.end.deSerialize(is); - p.exptime.end.deSerialize(is); - p.size.end.deSerialize(is); + p.pos.end.deSerialize(is); + p.vel.end.deSerialize(is); + p.acc.end.deSerialize(is); + p.exptime.end.deSerialize(is); + p.size.end.deSerialize(is); + + missing_end_values = false; + } + // else: fields are already read by deSerialize() very early // properties for legacy texture field p.texture.deSerialize(is, m_proto_ver, true); @@ -1077,11 +1088,9 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt) newtex.deSerialize(is, m_proto_ver); p.texpool.push_back(newtex); } - - legacy_format = false; } while(0); - if (legacy_format) { + if (missing_end_values) { // there's no tweening data to be had, so we need to set the // legacy params to constant values, otherwise everything old // will tween to zero diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 8f70e378e..7275d8130 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -213,6 +213,7 @@ with this program; if not, write to the Free Software Foundation, Inc., PROTOCOL VERSION 42: TOSERVER_UPDATE_CLIENT_INFO added new fields for TOCLIENT_SET_LIGHTING and TOCLIENT_SET_SKY + Send forgotten TweenedParameter properties [scheduled bump for 5.7.0] */ @@ -538,20 +539,33 @@ enum ToClientCommand TOCLIENT_ADD_PARTICLESPAWNER = 0x47, /* - -- struct range { T min, T max, f32 bias }; - -- struct tween { T start, T end }; + using range = RangedParameter { + T min, max + f32 bias + } + using tween = TweenedParameter { + u8 style + u16 reps + f32 beginning + T start, end + } + u16 amount f32 spawntime - v3f minpos - v3f maxpos - v3f minvel - v3f maxvel - v3f minacc - v3f maxacc - f32 minexptime - f32 maxexptime - f32 minsize - f32 maxsize + if PROTOCOL_VERSION >= 42 { + tween pos, vel, acc, exptime, size + } else { + v3f minpos + v3f maxpos + v3f minvel + v3f maxvel + v3f minacc + v3f maxacc + f32 minexptime + f32 maxexptime + f32 minsize + f32 maxsize + } u8 bool collisiondetection u32 len u8[len] texture @@ -562,18 +576,20 @@ enum ToClientCommand u8 glow u8 object_collision - f32 pos_start_bias - f32 vel_start_bias - f32 acc_start_bias - f32 exptime_start_bias - f32 size_start_bias + if PROTOCOL_VERSION < 42 { + f32 pos_start_bias + f32 vel_start_bias + f32 acc_start_bias + f32 exptime_start_bias + f32 size_start_bias - range pos_end - -- i.e v3f pos_end_min - -- v3f pos_end_max - -- f32 pos_end_bias - range vel_end - range acc_end + range pos_end + -- i.e v3f pos_end_min + -- v3f pos_end_max + -- f32 pos_end_bias + range vel_end + range acc_end + } tween> drag -- i.e. v3f drag_start_min diff --git a/src/server.cpp b/src/server.cpp index 197e76e16..89629a15d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1649,7 +1649,18 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version, NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 100, peer_id); pkt << p.amount << p.time; - { // serialize legacy fields + + if (protocol_version >= 42) { + // Serialize entire thing + std::ostringstream os(std::ios_base::binary); + p.pos.serialize(os); + p.vel.serialize(os); + p.acc.serialize(os); + p.exptime.serialize(os); + p.size.serialize(os); + pkt.putRawString(os.str()); + } else { + // serialize legacy fields only (compatibility) std::ostringstream os(std::ios_base::binary); p.pos.start.legacySerialize(os); p.vel.start.legacySerialize(os); @@ -1672,21 +1683,23 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version, pkt << p.node.param0 << p.node.param2 << p.node_tile; { // serialize new fields - // initial bias for older properties - pkt << p.pos.start.bias - << p.vel.start.bias - << p.acc.start.bias - << p.exptime.start.bias - << p.size.start.bias; - std::ostringstream os(std::ios_base::binary); + if (protocol_version < 42) { + // initial bias for older properties + pkt << p.pos.start.bias + << p.vel.start.bias + << p.acc.start.bias + << p.exptime.start.bias + << p.size.start.bias; - // final tween frames of older properties - p.pos.end.serialize(os); - p.vel.end.serialize(os); - p.acc.end.serialize(os); - p.exptime.end.serialize(os); - p.size.end.serialize(os); + // final tween frames of older properties + p.pos.end.serialize(os); + p.vel.end.serialize(os); + p.acc.end.serialize(os); + p.exptime.end.serialize(os); + p.size.end.serialize(os); + } + // else: fields are already written by serialize() very early // properties for legacy texture field p.texture.serialize(os, protocol_version, true);