Skip to content

Cell

Vanilla game class representing a single voxel cell in the world grid. Used by Room.Grids and the room-neighbor scan.

Fully qualified type: Assets.Scripts.GridSystem.Cell (decompile line 272151). Namespace differs from most game-object types under Assets.Scripts.Objects; mods referencing Cell in a Harmony patch signature must using Assets.Scripts.GridSystem;.

NeighborCells 26-cell and filter to 6

Source: F0028.

Cell.NeighborCells returns all 26 surrounding cells (corners and diagonals included). The mod filters to 6 orthogonal neighbors by checking that exactly one axis of the Grid3 difference is nonzero.

6-neighbor filter comment (F0353)

Source comment from NetworkPainterPatch.cs:298-303:

Cell.NeighborCells contains all 26 surrounding cells (includeCorners:true in the Cell ctor). We want 6-orthogonal only: exactly one grid axis differs between the two cells.

Cell fields

Field cluster on Cell:

public static readonly ConcurrentDictionary<Cell, byte> AllCells = new ConcurrentDictionary<Cell, byte>();

public GridController GridController;

public readonly WorldGrid WorldGrid;

public Vector3 Position;

public Dictionary<Grid3, Structure> Structural = new Dictionary<Grid3, Structure>();

public List<Structure> AllStructures = new List<Structure>();

public List<Cell> NeighborCells = new List<Cell>();

public Stairs Stairs;

public bool HasLight;

Structural is the face-keyed structure map (one Grid3 key per occupied face, up to six faces plus a body per cell). AllStructures is the flat list of everything touching the cell, which the SprayPaintPlus wall and large-structure floods iterate. NeighborCells is the precomputed all-26 neighbor list (see the section above). AllCells is the global set of every cell.

AllStructures and Structural hold large-grid structures. SmallGrid-derived occupants (pipes, cables, chutes, small devices, robotic-arm rails, ladders) register in the parallel 0.5 m small grid, one occupant per typed slot on a SmallCell, not here. See SmallCell.md. This is why the mod floods pipes and cables through their dedicated network objects and reserves the large-cell BFS (AllStructures + NeighborCells) for walls and large structures.

IsBlocked / IsBlockedLight

public bool IsBlocked
{
    get
    {
        Structure structural = GetStructural(Position);
        ...
    }
}

public bool IsBlockedLight
{
    get
    {
        Structure structural = GetStructural(Position);
        ...
    }
}

Both resolve the structure at the cell's own Position via GetStructural and test its collision / pass flags.

A structure appears in AllStructures of every cell of its footprint

Cell.Add takes the cell-relative position of the occupied slot, so it is called once per cell a structure covers and each of those cells lists it. For CollisionType.BlockCustom, the branch that also fills the dedicated Cell.Stairs slot, the append is unconditional:

public bool Add(Structure structure, Grid3 relativePosition)
{
    switch (structure.StructureCollisionType)
    {
    case CollisionType.BlockCustom:
    {
        Stairs stairs = structure as Stairs;
        if ((bool)stairs)
        {
            Stairs = stairs;
        }
        AllStructures.Add(structure);
        break;
    }
    case CollisionType.BlockGrid:
    case CollisionType.BlockFace:
        if (!AddStructural(structure, relativePosition))
        {
            return false;
        }
        break;
    default:
        AllStructures.Add(structure);
        break;
    }
    return true;
}

AddStructural reaches the same list by the other two routes: it appends when Lookup.IsValid(relativePosition - Grid) is false, and it appends after Lookup.Set when the face slot is free.

Two consequences for a flood that iterates AllStructures. One object can be reported by several cells, so a walk over a cell set has to de-duplicate or accept repeats; and Thing.Cell is only one of those cells, the one the structure registered against, which is not necessarily the one Thing.GridPosition names. Measured 2026-09-23 on four Stairs-class stairwell pieces: GridPosition put all four in one cell column while Thing.Cell reported alternating landing cells two apart, and a cell flood keyed on GridPosition reached all four. See Stairs.md, "GridPosition is the bounds centre".

NeighborCells is built once in the constructor and is the full 26-cell set, never wider:

Span<Grid3> span = stackalloc Grid3[32];
int count = 0;
GridController.GetNeighborCells(Grid, span, ref count, includeCorners: true);

Verification history

  • 2026-04-20: page created from the Research migration; verbatim content lifted from F0028, F0353. No conflicts.
  • 2026-05-15: verified namespace Assets.Scripts.GridSystem.Cell (decompile line 272151); added pre-page note for mod authors patching method signatures that take Cell.
  • 2026-05-22: added "Cell fields" section (with "IsBlocked / IsBlockedLight" subsection) from a room/grid/atmospherics decompile pass. Additive; existing sections unchanged. Source: Assets.Scripts.GridSystem.Cell in Assembly-CSharp, game version 0.2.6228.27061. Added related links to GridController, Structure.
  • 2026-06-19: noted in "Cell fields" that SmallGrid occupants (pipes, cables, ladders, etc.) register in the parallel SmallCell small grid, not AllStructures; added related link to the new SmallCell.md. Game version 0.2.6228.27061.
  • 2026-09-23: added "A structure appears in AllStructures of every cell of its footprint" from Cell.Add, AddStructural and the Cell constructor, with a live measurement of four stairwells whose Thing.Cell and GridPosition disagree. Additive; nothing on the page is contradicted, and it extends rather than replaces the existing "Cell fields" description of AllStructures. Game version 0.2.6428.27798.

Open questions

None at creation.