using System.Numerics; namespace AcDream.App.World; /// /// Session-scoped owner of the landblock origin used to translate retail /// full-cell coordinates into the current streamed world coordinate system. /// A placeholder can exist before the first authoritative player position; /// distinguishes it from a server-confirmed origin. /// /// /// This owner is update/render-thread confined with the rest of live world /// mutation. It intentionally exposes no cross-thread snapshot contract. /// internal sealed class LiveWorldOriginState { public int CenterX { get; private set; } public int CenterY { get; private set; } public bool IsKnown { get; private set; } public void SetPlaceholder(int centerX, int centerY) { CenterX = centerX; CenterY = centerY; IsKnown = false; } public bool TryInitialize(int centerX, int centerY) { if (IsKnown) return false; CenterX = centerX; CenterY = centerY; IsKnown = true; return true; } public void Recenter(int centerX, int centerY) { CenterX = centerX; CenterY = centerY; } public (int X, int Y) GetCenter() => (CenterX, CenterY); /// /// Converts the streamed render frame back into retail's landblock-local /// physics frame at the one placement seed boundary. /// public Vector3 CellLocalForSeed(Vector3 worldPosition, uint cellId) { int landblockX = (int)((cellId >> 24) & 0xFFu); int landblockY = (int)((cellId >> 16) & 0xFFu); var origin = new Vector3( (landblockX - CenterX) * 192f, (landblockY - CenterY) * 192f, 0f); return worldPosition - origin; } /// /// Ends the accepted-origin lifetime while retaining the last coordinates /// as the next placeholder. Consumers must gate them on /// until the next accepted player position. /// public void Reset() => IsKnown = false; }