using Unity.Mathematics;
namespace ProjectM.Simulation
{
///
/// Deterministic, side-effect-free math for the home-base build grid. Pure (no RNG, no wall-clock)
/// so server and predicting client agree on cell occupancy. Convention:
/// is the min-XZ CORNER of cell (0,0); returns cell CENTERS; cell bounds are
/// half-open so a point on a cell's lower edge belongs to that cell and the far plot edge is out of plot.
/// World->cell uses math.floor (not truncation) so negative coordinates snap correctly. Unit-tested in
/// EditMode (no netcode world required); M6's server placement handler calls these directly.
///
public static class BaseGridMath
{
/// Planar (XZ) world position -> integer grid cell. Uses floor, so values below GridOrigin go negative (out of plot).
public static int2 WorldToCell(in BaseAnchor a, float3 worldPos)
{
float2 local = (worldPos.xz - a.GridOrigin.xz) / a.CellSize;
return (int2)math.floor(local);
}
/// Grid cell -> world position of the cell CENTER, on the base plane (Y = GridOrigin.y).
public static float3 CellToWorld(in BaseAnchor a, int2 cell)
{
float2 centerXZ = a.GridOrigin.xz + ((float2)cell + 0.5f) * a.CellSize;
return new float3(centerXZ.x, a.GridOrigin.y, centerXZ.y);
}
/// True when the cell is inside the plot. Half-open: [0, GridDims), so the far edge is out.
public static bool IsCellInPlot(in BaseAnchor a, int2 cell)
{
return math.all(cell >= 0) && math.all(cell < a.GridDims);
}
/// True when the world point falls inside the plot (its cell is in-plot).
public static bool IsPointInPlot(in BaseAnchor a, float3 worldPos)
{
return IsCellInPlot(a, WorldToCell(a, worldPos));
}
/// Clamp a cell into the valid [0, GridDims-1] range.
public static int2 ClampCell(in BaseAnchor a, int2 cell)
{
return math.clamp(cell, new int2(0, 0), a.GridDims - 1);
}
/// World-space center of the whole plot (== AnchorPos when baked correctly).
public static float3 PlotCenter(in BaseAnchor a)
{
float2 centerXZ = a.GridOrigin.xz + (float2)a.GridDims * a.CellSize * 0.5f;
return new float3(centerXZ.x, a.GridOrigin.y, centerXZ.y);
}
}
}