+ { // 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);
+
+ // 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);
+
+ // properties for legacy texture field
+ p.texture.serialize(os, protocol_version, true);
+
+ // new properties
+ p.drag.serialize(os);
+ p.jitter.serialize(os);
+ p.bounce.serialize(os);
+ ParticleParamTypes::serializeParameterValue(os, p.attractor_kind);
+ if (p.attractor_kind != ParticleParamTypes::AttractorKind::none) {
+ p.attract.serialize(os);
+ p.attractor_origin.serialize(os);
+ writeU16(os, p.attractor_attachment); /* object ID */
+ writeU8(os, p.attractor_kill);
+ if (p.attractor_kind != ParticleParamTypes::AttractorKind::point) {
+ p.attractor_direction.serialize(os);
+ writeU16(os, p.attractor_direction_attachment);
+ }
+ }
+ p.radius.serialize(os);
+
+ ParticleParamTypes::serializeParameterValue(os, (u16)p.texpool.size());
+ for (const auto& tex : p.texpool) {
+ tex.serialize(os, protocol_version);
+ }
+
+ pkt.putRawString(os.str());
+ }
+