Skip to content

Wall

Vanilla game class for wall structures. Inherits from LargeStructure. Wall-painting flow must honor inheritance ordering when dispatching.

Wall extends LargeStructure inheritance ordering

Source: F0029f.

Wall extends LargeStructure. The wall branch in PaintNetwork must come first. If walls-painting is disabled for a wall target, the method returns early rather than falling through to the large-structure grid flood.

Visual wall variants share the Wall C# class

Source: Assembly-CSharp.dll decompile, full : Wall subclass scan.

The visual wall variants the player sees in Stationpedia ("Wall", "Wall Flat", "Wall Arched", "Wall Iron", "Wall Padded", "Wall Composite", "Wall Glass", and so on) are not separate C# classes. They are Unity prefab variants of the same Wall class, distinguished by:

  • A different prefab PrefabHash and PrefabName (e.g. StructureWall, StructureWallFlat, StructureWallArched).
  • A different Wall.WallMaterialType enum value (Default, Metal, Composite, Glass) for the four material families.
  • A different mesh assigned to _wallMesh.

The complete set of C# classes that derive from Wall is exactly four:

Class Inheritance Notes
RocketCrewUmbilicalDoor : Wall Crew umbilical door for rockets.
ShutteredWindowConnector : Wall, IWindowShutter Shutter connector.
WallTransparent : Wall Glass / window walls. ShutteredWindow : WallTransparent extends this further.
Floor : Wall Floor tiles. LadderPlatform : Floor extends this further.

There is no FlatWall, ArchedWall, WallShort, WallTall, or per-visual-style subclass anywhere in Assembly-CSharp.dll.

Implication for type-keyed flood-fill code. Code that filters by Thing.GetType() (exact type, not is) treats every visual wall variant as the same target. originalWall.GetType() == typeof(Wall) holds for a Wall, a Flat Wall, an Arched Wall, an Iron Wall, etc., all at once. A flood-fill keyed on s.GetType() != targetType does not separate them; it paints every Wall instance bounding the same Room, regardless of visual variant. Distinguishing visual variants requires comparing PrefabHash (or PrefabName), not GetType().

GridPosition puts a face-mounted wall inside the room it faces

A wall's WorldPosition sits on a cell FACE, not in a cell: cell centres are at odd world metres and a wall reads one even coordinate (a ceiling panel at y 206, a partition at z -692). The value that decides which Room it belongs to is not that position but Thing.GridPosition, which is CenterPosition.ToGrid() where CenterPosition is Position + Rotation * Bounds.center. The rotated bounds centre pushes the wall off the face and into the cell it faces, so the lookup lands inside the room.

Structure.GetRoom() is a one-line dictionary lookup on that value, and there is no public member that answers it:

protected Room GetRoom()
{
    return base.GridController?.RoomController?.GetRoom(GridPosition);
}

public Room GetRoom(Grid3 grid)
{
    Room value = null;
    RoomLookup?.TryGetValue(grid, out value);
    return value;
}

RoomLookup is keyed by the room's own Grids, written in RoomController.Register, so a grid key that is not one of a room's own cells resolves to null. That is why GetRoom is a test for "inside the room volume" and never for "on its boundary": a wall answers it only because its bounds centre is inside.

Measured live on 2026-09-23 through the TestRig control plane (GET /thing, fields GridPosition, PrefabHash) against the Spray Paint Plus fixture world, whose save records room 35 as a 5 x 5 single-level room, x -12970..-12890 by z -6910..-6830 at y 2050:

  • Twenty-five StructureWallIron ceiling panels at y 206, every one facing (0, -1, 0). Each reported a GridPosition one metre BELOW itself, and the twenty-five values are exactly room 35's twenty-five Grids, one panel per cell. PrefabHash 1287324802 on all of them.
  • Nineteen StructureCompositeWindowIron on the room's four sides at y 205, each facing inward. Every one reported a GridPosition that is also one of those twenty-five cells, so windows and panels share cells: 2950 at (-1298, 205, -691) and 2963 at (-1297, 206, -691) both report Grid3(-12970, 2050, -6910). PrefabHash -688284639.
  • Two more StructureWallIron, 2706 at (-1294, 205, -693) facing +x and 3123 at (-1292, 205, -693) facing -x, plus StructureWallIron02 3272 above them. All three reported Grid3(-12930, 2050, -6930), one cell beyond the room boundary in z and therefore a different room, while carrying the same PrefabHash as the twenty-five.

Runtime types, read off the same rows: StructureWallIron, StructureWallIron02 and StructureWallFlat are all Wall; StructureCompositeWindowIron is WallTransparent. StructureFrame is Frame, which is a sibling under LargeStructure rather than a Wall.

Two consequences for room-keyed flood code. A scan over room.Grids alone already reaches every wall of that room, because each one's own GridPosition is a room cell; the extra layer such code usually adds for "walls sit on the boundary" buys nothing on the wall side and does reach into the neighbouring room, where the GetRoom comparison is what excludes it. And a cell holds walls of several variants at once, so PrefabHash rather than GetType() is the only filter that separates them (see the section above).

Verification history

  • 2026-04-20: page created from the Research migration; verbatim content lifted from F0029f. No conflicts.
  • 2026-04-28: added "Visual wall variants share the Wall C# class" section after a SprayPaintPlus bug report ("wall painting is spilling over to different types of walls"). Confirmed via decompile scan that the visual variants are prefabs of one C# class, not distinct types. Additive content; no conflict.
  • 2026-09-23: added "GridPosition puts a face-mounted wall inside the room it faces" from Structure.GetRoom, RoomController.GetRoom and Register, plus a live GET /thing read of forty-seven walls around one room on game 0.2.6428.27798. Additive; nothing on the page is contradicted. The playtest that rests on it is a wall stroke floods its own room and its own variant in Mods/SprayPaintPlus/playtests/.

Open questions

None at creation.