PacketDiagnostics
One-shot, version-agnostic per-tick packet sampler for modeled entities.
The bundler (PacketBundle.send() in EasyMinecraftGoals) collapses a tick's packets into one ClientboundBundlePacket per player, so the wire packet count looks fine — but the bundle payload is the sum of every bone's move + metadata packet, every tick, for every visible model. That payload (and the client-side deserialization cost) is what saturates connections in dense NPC areas. This class makes that payload measurable.
How it works: when armed, com.magmaguy.freeminecraftmodels.customentity.ModeledEntitiesClock wraps the real packet bundle in a CountingPacketBundle that tallies every addPacket(packet, viewers) call — total packets, packets delivered (summed across viewers), a breakdown by packet type, and a per-player count. After the configured number of ticks the aggregate is frozen into Sample for the command to print.
Counts are exact (they tally the real addPacket calls). Byte figures are rough estimates from estimateBytes — getting the true wire size would require re-serializing each NMS packet through the player's connection codec, which is fragile across versions. The packet count per player per tick is the number that actually explains client saturation, so that's what to watch.
Threading: arming happens from the command thread; counting happens on the async model clock thread. Arming/result handoff uses volatile fields and a synchronized block; the per-tick wrapper is a fresh object each tick so there is no shared mutable counting state between ticks.
Types
Functions
ticks model-clock ticks.