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