Class AbilityObjectObserverBroadcastSerializers
Hand written wire formats for the three per-object ability broadcasts: AbilityObjectDestroyedBroadcast, AbilityObjectHitBroadcast and AbilityObjectRedirectBroadcast.
public static class AbilityObjectObserverBroadcastSerializers
- Inheritance
-
AbilityObjectObserverBroadcastSerializers
- Inherited Members
Remarks
These are per-hit and per-object messages paid once per observer, and the generated serializer wrote every field of every one of them packed and unconditionally. Two things were wrong with that.
-
Packing a full-entropy word costs a byte rather than saving four. FishNet's packed
32-bit form is a seven-bit-per-byte varint, so a value that uses the whole range takes FIVE
bytes where the unpacked form takes four.
ContainerIDisseed ^ (tick * 1000003)(AbilityContainerAllocator.ComputeContainerId) and PackedHeading is an AimDirectionCompression word; both are unpacked here. Object ids, the ability id and the absolute tick stay packed, because those genuinely are small. -
A hit message has two shapes and was written as one. A deflected hit is answered by
AbilityController.OnAbilityObjectHitBroadcastreading the heading and returning, so the point, the normal, the victim and the direct-impact flag were written and never read — twenty-five bytes per deflected hit per observer. A header byte now names the shape, in the style of WriteAbilityActivatedBroadcast(Writer, AbilityActivatedBroadcast).
Discovered by FishNet's codegen through the Write*/Read* naming convention and
applied across assemblies because each struct carries [UseGlobalCustomSerializer].
Methods
ReadAbilityObjectDestroyedBroadcast(Reader)
Reads an AbilityObjectDestroyedBroadcast written by the method above.
public static AbilityObjectDestroyedBroadcast ReadAbilityObjectDestroyedBroadcast(this Reader reader)
Parameters
readerReader
Returns
ReadAbilityObjectHitBroadcast(Reader)
Reads an AbilityObjectHitBroadcast written by the method above.
public static AbilityObjectHitBroadcast ReadAbilityObjectHitBroadcast(this Reader reader)
Parameters
readerReader
Returns
Remarks
Fields a shape does not carry come back at their defaults — Vector3.zero for the
point and the normal, 0 for the deflect heading, false for the impact flags,
and 0 for the victim, which is this message's "hit scenery" value rather than
the -1 an activation uses for an absent target. That is exactly what the receiving
side expects: AbilityController.OnAbilityObjectHitBroadcast branches on
Deflected first and only reads the fields the
remaining shape carries.
ReadAbilityObjectRedirectBroadcast(Reader)
Reads an AbilityObjectRedirectBroadcast written by the method above.
public static AbilityObjectRedirectBroadcast ReadAbilityObjectRedirectBroadcast(this Reader reader)
Parameters
readerReader
Returns
WriteAbilityObjectDestroyedBroadcast(Writer, AbilityObjectDestroyedBroadcast)
Writes an AbilityObjectDestroyedBroadcast.
public static void WriteAbilityObjectDestroyedBroadcast(this Writer writer, AbilityObjectDestroyedBroadcast value)
Parameters
writerWritervalueAbilityObjectDestroyedBroadcast
WriteAbilityObjectHitBroadcast(Writer, AbilityObjectHitBroadcast)
Writes an AbilityObjectHitBroadcast in its shape-dependent form.
public static void WriteAbilityObjectHitBroadcast(this Writer writer, AbilityObjectHitBroadcast value)
Parameters
writerWritervalueAbilityObjectHitBroadcast
Remarks
Two shapes, named by the header byte. A deflection carries the heading and nothing else: the receiver applies it and returns before it looks at the point, the normal, the victim or any of the impact flags, so writing them was pure waste on the one hit shape that occurs in bursts. An ordinary impact carries the point, the normal and — only when it is not a scenery hit — the victim id, and carries no heading at all. The block and the end are bits in the header rather than fields, so neither costs the impact shape anything at all.
PackedDeflectHeading is unpacked, like the
container id above it, and the shaping is what makes that the right call. The field used
to be written on every hit and was 0 on almost all of them, which is the one case
the packed form is good at — a single byte. Now it is written only when a deflection
actually happened, so every value that reaches the wire is a full-entropy
AimDirectionCompression word, which the packed form spends five bytes on.
WriteAbilityObjectRedirectBroadcast(Writer, AbilityObjectRedirectBroadcast)
Writes an AbilityObjectRedirectBroadcast.
public static void WriteAbilityObjectRedirectBroadcast(this Writer writer, AbilityObjectRedirectBroadcast value)
Parameters
writerWritervalueAbilityObjectRedirectBroadcast