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;
}