namespace AcDream.Core.World;
///
/// Allocates stable, collision-free local ids for dat-authored
/// LandBlockInfo.Objects and building shells.
///
///
/// The top nibble is fixed at 0xC. The remaining 28 bits encode the
/// complete landblock X byte, Y byte, and a 12-bit per-landblock counter:
/// 0xCXXYYIII. The former 0xC0XXYYII packing had only eight
/// counter bits, so a legitimate dense retail landblock aborted after 255
/// entries and was retried every time it streamed into view.
///
public static class LandblockStaticEntityIdAllocator
{
public const uint MaxCounter = 0xFFFu;
public static uint Base(uint landblockX, uint landblockY) =>
0xC0000000u
| ((landblockX & 0xFFu) << 20)
| ((landblockY & 0xFFu) << 12);
public static uint Allocate(uint landblockX, uint landblockY, ref uint counter)
{
if (counter > MaxCounter)
{
throw new InvalidDataException(
$"Landblock ({landblockX & 0xFFu:X2},{landblockY & 0xFFu:X2}) exceeds the 4096-entry static entity id namespace.");
}
return Base(landblockX, landblockY) + counter++;
}
public static bool IsInNamespace(uint entityId) =>
(entityId & 0xF0000000u) == 0xC0000000u;
}