namespace ProjectM.Simulation
{
///
/// Pure, Burst-safe packing of the predicted-projectile classification key
/// (). Layout: owner(14) | socket(2) | fireCount(12) | fork(4) = 32
/// bits exact. Reserving 2 socket bits is the review's NP-1/RS-1/DB-3 fix: under the LANTERN 4-socket kit,
/// two sockets firing the same-prefab projectile on ONE tick carry independent per-socket fire counts that
/// are near-guaranteed equal early (both 0->1); without a socket discriminator their SpawnIds collide and
/// ProjectileClassificationSystem cross-adopts one predicted entity and orphans the other. Fork keeps
/// all 4 low bits (Phase-4 Fork mutation fans up to 8 shots). Extracted so the collision-free property is
/// unit-tested independently of the netcode prediction context.
///
public static class ProjectileSpawnId
{
public const int OwnerBits = 14;
public const int SocketBits = 2;
public const int FireCountBits = 12;
public const int ForkBits = 4;
/// Pack the classification key. Inputs are masked to their bit widths (wrap, not overflow).
public static uint Pack(int netId, int socket, uint fireCount, int fork)
{
return ((((uint)netId) & 0x3FFFu) << (SocketBits + FireCountBits + ForkBits)) // owner -> bits 18..31
| (((uint)socket & 0x3u) << (FireCountBits + ForkBits)) // socket -> bits 16..17
| ((fireCount & 0x0FFFu) << ForkBits) // fireCount -> bits 4..15
| ((uint)fork & 0xFu); // fork -> bits 0..3
}
}
}