Browse Source

Allow looped animation to be used safely with old clients

fixes #12657
sfan5 1 year ago
parent
commit
c607bee19e
4 changed files with 15 additions and 8 deletions
  1. 1 0
      src/client/particles.cpp
  2. 2 2
      src/particles.cpp
  3. 10 4
      src/tileanimation.cpp
  4. 2 2
      src/tileanimation.h

+ 1 - 0
src/client/particles.cpp

@@ -555,6 +555,7 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
 
 	// synchronize animation length with particle life if desired
 	if (pp.animation.type != TAT_NONE) {
+		// FIXME: this should be moved into a TileAnimationParams class method
 		if (pp.animation.type == TAT_VERTICAL_FRAMES &&
 			pp.animation.vertical_frames.length < 0) {
 			auto& a = pp.animation.vertical_frames;

+ 2 - 2
src/particles.cpp

@@ -127,7 +127,7 @@ void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const
 	os << serializeString32(texture.string);
 	writeU8(os, vertical);
 	writeU8(os, collision_removal);
-	animation.serialize(os, 6); /* NOT the protocol ver */
+	animation.serialize(os, protocol_ver);
 	writeU8(os, glow);
 	writeU8(os, object_collision);
 	writeU16(os, node.param0);
@@ -160,7 +160,7 @@ void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
 	texture.string     = deSerializeString32(is);
 	vertical           = readU8(is);
 	collision_removal  = readU8(is);
-	animation.deSerialize(is, 6); /* NOT the protocol ver */
+	animation.deSerialize(is, protocol_ver);
 	glow               = readU8(is);
 	object_collision   = readU8(is);
 

+ 10 - 4
src/tileanimation.cpp

@@ -19,21 +19,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "tileanimation.h"
 #include "util/serialize.h"
 
-void TileAnimationParams::serialize(std::ostream &os, u16 protocol_version) const
+void TileAnimationParams::serialize(std::ostream &os, u16 protocol_ver) const
 {
+	// The particle code overloads the length parameter so that negative numbers
+	// indicate an extra feature which old clients don't understand (crash).
+	// In hindsight it would have been better to use an extra parameter for this
+	// but we're stuck with this now.
+	const bool need_abs = protocol_ver < 40;
+
 	writeU8(os, type);
 	if (type == TAT_VERTICAL_FRAMES) {
 		writeU16(os, vertical_frames.aspect_w);
 		writeU16(os, vertical_frames.aspect_h);
-		writeF32(os, vertical_frames.length);
+		writeF32(os, need_abs ? fabs(vertical_frames.length) : vertical_frames.length);
 	} else if (type == TAT_SHEET_2D) {
 		writeU8(os, sheet_2d.frames_w);
 		writeU8(os, sheet_2d.frames_h);
-		writeF32(os, sheet_2d.frame_length);
+		writeF32(os, need_abs ? fabs(sheet_2d.frame_length) : sheet_2d.frame_length);
 	}
 }
 
-void TileAnimationParams::deSerialize(std::istream &is, u16 protocol_version)
+void TileAnimationParams::deSerialize(std::istream &is, u16 protocol_ver)
 {
 	type = (TileAnimationType) readU8(is);
 

+ 2 - 2
src/tileanimation.h

@@ -50,8 +50,8 @@ struct TileAnimationParams
 		} sheet_2d;
 	};
 
-	void serialize(std::ostream &os, u16 protocol_version) const;
-	void deSerialize(std::istream &is, u16 protocol_version);
+	void serialize(std::ostream &os, u16 protocol_ver) const;
+	void deSerialize(std::istream &is, u16 protocol_ver);
 	void determineParams(v2u32 texture_size, int *frame_count, int *frame_length_ms,
 			v2u32 *frame_size) const;
 	void getTextureModifer(std::ostream &os, v2u32 texture_size, int frame) const;