Constructor¶
Vanilla Constructor : Stackable, IConstructionKit at Assets.Scripts.Objects.Constructor. The held-item kit form for placing a single Structure prefab. Used by every "single-item kit" (kit-cable, kit-wall-frame, kit-airlock, ...). The companion MultiConstructor covers multi-prefab kits (rail kit with 8 rail variants, etc.).
Class layout¶
public class Constructor : Stackable, IConstructionKit
{
[Header("Constructor")]
public Structure BuildStructure;
public int QuantityUsed = 1;
public override void OnUsePrimary(Vector3 targetLocation, Quaternion targetRotation, ulong steamId, bool authoringMode)
public virtual void Construct(Grid3 localPosition, Quaternion targetRotation, bool authoringMode, ulong steamId)
public static Structure SpawnConstruct(CreateStructureInstance instance)
public List<Thing> GetConstructedPrefabs()
}
BuildStructure is the prefab the kit places. QuantityUsed is how many of the stack the kit consumes per placed structure (default 1).
OnUsePrimary -> Construct¶
public override void OnUsePrimary(Vector3 targetLocation, Quaternion targetRotation, ulong steamId, bool authoringMode)
{
base.OnUsePrimary(targetLocation, targetRotation, steamId, authoringMode);
Construct(targetLocation.ToGridPosition(), targetRotation, authoringMode, steamId);
}
public virtual void Construct(Grid3 localPosition, Quaternion targetRotation, bool authoringMode, ulong steamId)
{
if (authoringMode || OnUseItem(QuantityUsed, null))
{
CreateStructureInstance createStructureInstance = new CreateStructureInstance(BuildStructure, localPosition, targetRotation, steamId);
if (PaintableMaterial != null && CustomColor.Normal != null)
{
createStructureInstance.CustomColor = CustomColor.Index;
}
SpawnConstruct(createStructureInstance);
}
}
The Quaternion parameter targetRotation flows through unchanged. authoringMode == true bypasses the OnUseItem(...) quantity-consumption check but does NOT bypass any other gate; it is purely a creative-mode item-cost waiver.
SpawnConstruct: simulation vs client routing¶
public static Structure SpawnConstruct(CreateStructureInstance instance)
{
if (GameManager.RunSimulation)
{
Structure structure = Thing.Create<Structure>(instance.Prefab, instance.WorldPosition, instance.WorldRotation, 0L);
structure.SetStructureData(instance.LocalRotation, instance.OwnerClientId, instance.LocalGrid, instance.CustomColor);
return structure;
}
if (NetworkManager.IsClient)
{
new ConstructionCreationMessage(instance).SendToServer();
}
return null;
}
Two execution branches based on simulation role:
GameManager.RunSimulation == true(single-player or multiplayer host): create the structure directly viaThing.Create<Structure>(prefab, worldPos, worldRot)and callSetStructureData(localRot, ...). The full Quaternion lands on the new GameObject's transform AND is mirrored intoStructure.Direction(seeGameSystems/PlacementOrientation.md).RunSimulation == false && NetworkManager.IsClient == true(multiplayer remote client): wrap the placement intent in aConstructionCreationMessageand send to server. The server runs the sameThing.Create + SetStructureDatapath inside the message'sProcess(hostId)handler.
Either branch preserves the Quaternion losslessly; the wire format uses full WriteQuaternion (16 bytes) per Protocols/ConstructionCreationMessage.md.
Authoring mode¶
authoringMode is enabled when the player's active hand holds an AuthoringTool (creative-mode wrench). Source: InventoryManager.cs:422 public static bool IsAuthoringMode => Instance.ActiveHand.Slot.Occupant is AuthoringTool;. The flag travels into Construct(... authoringMode ...) and only affects the OnUseItem quantity-consumption call. It does NOT bypass AllowedRotations, CanConstruct, or any other gate. A player in authoring mode still cannot place a AllowedRotations.Floor device on a wall via vanilla input; the cursor's UpdatePlacement snaps the orientation to floor before OnUsePrimary fires.
Verification history¶
- 2026-04-25: page created from a six-agent decompile pass on the placement pipeline. Source content lifted verbatim from
/tmp/decompile_check/Assets/Scripts/Objects/Constructor.cs. No conflicts.
Open questions¶
None.