Building
This page uses Vector3, Quaternion, GameObject, Transform from Unity. The glossary says what each one is.
Building works with furniture the player placed in the world. A building area is one room, shop or other space where furniture can be placed, and the functions that take an areaId use its id. AllAreaIds() gives all of them.
Building furniture the player places
This is the class you start from. It lists the building areas and the furniture placed in them, and Place, Remove and Move change that furniture.
public static class Building
{
public static List<string> AllAreaIds();
public static List<FurnitureItem> GetPlacedFurniture(string areaId);
public static List<FurnitureManagerInfo> Managers(string sceneName);
public static List<BlueprintInfo> AllBlueprints();
public static bool IsBlueprintKnown(string name);
public static bool UnlockBlueprint(string name);
public static bool UnlockBlueprint(string name, bool silent);
public static FurnitureItem Place(string managerGuid, string furnitureId, Vector3 position, Quaternion rotation, Quaternion childRotation, int skin, int altPrefab);
public static FurnitureItem Place(string managerGuid, string furnitureId, Vector3 position, Quaternion rotation, Quaternion childRotation, int skin, int altPrefab, bool requireKnown);
public static bool Remove(string guid);
public static bool Remove(FurnitureItem item);
public static FurnitureItem Find(string guid);
public static bool Move(string guid, Vector3 position, Quaternion rotation);
public static bool Move(FurnitureItem item, Vector3 position, Quaternion rotation);
public static event Action<FurnitureItem> FurniturePlaced;
public static event Action<FurnitureItem> FurnitureRemoved;
public static event Action<FurnitureItem> FurnitureLoaded;
public static bool Applying { get; }
public static bool IsAvailable { get; }
}
| Method | Returns | What it does |
|---|---|---|
AllAreaIds() | List<string> | The id of every building area. |
GetPlacedFurniture(areaId) | List<FurnitureItem> | The furniture the player placed in an area. |
Managers(sceneName) | List<FurnitureManagerInfo> | The building areas in one scene, or in all loaded scenes. |
AllBlueprints() | List<BlueprintInfo> | Every furniture blueprint the game knows, known or not. |
IsBlueprintKnown(name) | bool | true when the player has this blueprint. |
UnlockBlueprint(name) | bool | Gives the blueprint with the game’s “new item” message. |
UnlockBlueprint(name, silent) | bool | Gives the blueprint. silent set to true skips the message. |
Place(managerGuid, furnitureId, position, rotation, childRotation, skin, altPrefab) | FurnitureItem | Places a piece. null when refused. |
Place(managerGuid, furnitureId, position, rotation, childRotation, skin, altPrefab, requireKnown) | FurnitureItem | The same, and refuses unknown furniture when requireKnown is true. |
Remove(guid) | bool | Takes a placed piece out of the world. true when removed. |
Remove(item) | bool | The same for a piece you hold. |
Find(guid) | FurnitureItem | The placed piece with this Guid. null when none. |
Move(guid, position, rotation) | bool | Moves a placed piece. true when moved. |
Move(item, position, rotation) | bool | The same for a piece you hold. |
| Property | Type | What it means |
|---|---|---|
Applying | bool | true while Place, Remove or Move is running. |
IsAvailable | bool | false when a furniture event could not be set up. |
| Event | Gives you | When it fires |
|---|---|---|
FurniturePlaced | FurnitureItem | A piece of furniture has just been placed. |
FurnitureRemoved | FurnitureItem | A piece of furniture has just been taken out. |
FurnitureLoaded | FurnitureItem | One of your mod’s pieces was found after a save loaded. |
FurnitureItem one placed piece of furniture
GetPlacedFurniture, Find, Place and the furniture events give you this, one per placed piece. Its Guid is only good until the next save, so do not keep it as a permanent key.
public sealed class FurnitureItem
{
public string Guid { get; }
public string Id { get; }
public string Title { get; }
public string AreaId { get; }
public Vector3 Position { get; }
public Quaternion Rotation { get; }
public Quaternion ChildRotation { get; }
public int Skin { get; }
public int AltPrefab { get; }
public string ManagerGuid { get; }
public string ParentGuid { get; }
public string AttachedGuid { get; }
public GameObject ParentObject { get; }
public GameObject AttachedObject { get; }
public bool FromApi { get; }
public GameObject Object { get; }
}
| Property | Type | What it means |
|---|---|---|
Guid | string | The piece’s save id. null until the game saves. |
Id | string | The furniture’s id. It starts with obx: for a mod’s furniture, and is the game’s path otherwise. |
Title | string | The name the game shows. |
AreaId | string | The id of the building area it is in. |
Position | Vector3 | Where it is, in world coordinates. |
Rotation | Quaternion | Its turn, relative to the building area, as the game saves it. |
ChildRotation | Quaternion | The turn of its first child object, relative to the piece. Identity when there is no child. |
Skin | int | Which look it has. 0 is the normal look. |
AltPrefab | int | Which alternative shape it has. 0 is the normal shape. |
ManagerGuid | string | The id of the area’s furniture manager. May be null. |
ParentGuid | string | The Guid of the piece it sits on. null when none. |
AttachedGuid | string | The Guid of the piece it is attached to. null when none. |
ParentObject | GameObject | The object of the piece it sits on. null when none. |
AttachedObject | GameObject | The object of the piece it is attached to. null when none. |
FromApi | bool | true when the event was raised inside Place or Remove, so your mod can skip its own echo. |
Object | GameObject | The placed object itself, not a copy. Unity treats it as null once destroyed. |
FurnitureManagerInfo one building area
Managers(sceneName) gives you one of these for each building area. Its Guid is the same value as an id from AllAreaIds.
public sealed class FurnitureManagerInfo
{
public string Guid { get; }
public string SceneName { get; }
}
| Property | Type | What it means |
|---|---|---|
Guid | string | The area’s id, the same value as an id from AllAreaIds. |
SceneName | string | The scene the area is in. |
BlueprintInfo one furniture blueprint
AllBlueprints() gives you one of these for each furniture blueprint the game knows. Pass its Name to UnlockBlueprint to give the player that blueprint.
public sealed class BlueprintInfo
{
public string Name { get; }
public string Title { get; }
public bool Known { get; }
}
| Property | Type | What it means |
|---|---|---|
Name | string | The blueprint’s name, the same name the developer console accepts. |
Title | string | The name the game shows. |
Known | bool | true when the player already has the blueprint. |
Things to know
GetPlacedFurniturelists the furniture the player placed in an area. Furniture that comes with the building is not included. (It readsFurnitureManager.placedFurniture.)Managers(sceneName)lists the building areas in one scene. IfsceneNameisnullor empty, it lists every loaded area. Each entry has the area’s id and the name of its scene. (It readsBuildingSystem.furnitureManagersand matchesgameObject.scene.name.)Managersonly lists areas that have started, so it is empty on the main menu. Several areas in different scenes can share an id, so use the scene name to tell them apart.- There are three places a position can be measured from.
Positionis in the world,Rotationis relative to the building area as the game saves it, andChildRotationis relative to the piece, for its first child object. (Rotationis the root’slocalRotationunder the manager transform (gameObjectMainRotationin the save).ChildRotationis thelocalRotationof child 0 (gameObjectFurnitureRotation).) Placetakes the same three values, so a value you read on one computer can be passed to another. That only works when both computers have the same scene and the same area positions, which is an assumption.Placeputs a piece in an area the way build mode does. It builds the piece from the furniture’s model, turns it, puts it atposition, adds it to the area and appliesskinandaltPrefab.furnitureIdis a mod furniture id (obx:...) or the game’s own path for a normal piece. It returns the new piece, ornullwhen it is refused. (It instantiates the furniture’s prefab under the manager (altPrefab, 0 for the default prefab), sets the root’slocalRotationtorotationand child 0’s tochildRotation, setspositionin world space, adds the piece tomanager.placedFurniturethroughFurniturePlaceable.SetFurnitureInfo, and appliesskinand the alternative prefab throughFurniturePlaceable.UpdateMeta.)PlaceraisesFurniturePlacedonce, after the piece is complete. The event hasFromApiset totrue.- If
Placefails half way, it cleans up. If a step after the object was built fails, the framework destroys the object, removes it from the area’s list and returnsnull. - The first form of
Placedoes not check the furniture id against the list of known furniture. The second form can. If another player decides the id (co-op), always passtrue. - A piece placed in this play session has a
Guidofnulluntil the game saves it. After a save, the game builds the id from the area’s id and the piece’s place in the list. A piece’sGuidchanges when a save runs after another piece in the same area was removed, so do not useGuidas a permanent key. (Build mode does not set it.FurnitureManager.OnSavingGameTertiarysets it to the manager’s GUID plus an index. An empty GUID isnullinFurnitureItem(Guid,ManagerGuid,ParentGuidandAttachedGuid), so a parent or attached piece placed this session has anullParentGuidorAttachedGuiduntil the next save. UseParentObjectorAttachedObjectto link such pieces.) - For co-op, do not send a
Guid, a list position orObjectto another player as the id of a piece. The game renumbers every piece on each save, and the number depends on the order of the list, which a removal or a move can change. - For co-op, the host should make its own id when a piece is placed and keep the list of ids in the co-op code, not in a save entry. Send that id, and call
Findagain after each save to find the newGuid. Remove(guid)takes a placed piece out of the world without giving the item to the player.RemoveraisesFurnitureRemovedbefore the piece is destroyed. The event hasFromApiset totrue. It does not give the item to the player, and it does not run the piece’s own “taken” signal. (It does not run the game’s take step that adds the item to the player’s stock, nor the piece’sonTakenrelay.)Remove(item)does the same for a piece you hold. It works for a piece with noGuid, which theGuidversion can’t reach. (It findsitem.Objectby object identity in a manager’splacedFurniture.)Find(guid)returns the placed piece with thatGuid, ornullwhen no piece matches orguidis empty. It looks in the same list asRemove(guid), so furniture that came with the building is not found.- A
Guidis only good until the next save. Moveputs a placed piece somewhere else. It sets the piece’s worldpositionand its turn relative to the area, the same valuesPlaceuses. The change is saved on the next save. (It sets the root’slocalRotation. The save reads both from the transform.)Movedoes not turn the piece’s first child, and the new spot is not checked, as inPlace. It raises no event. (It does not run the game’s take-and-place: the game’s move starts from the player’s aim (BuildingSystem.Move), thenBuildingSystem.Placeputs the piece down.)ApplyingistruewhilePlace,RemoveorMoveis running. A handler ofFurniturePlacedorFurnitureRemovedcan use it, or theFromApivalue, to tell your mod’s own change from a player’s action. A player’s move does not set it.- There is no “moved” event. When the player moves a piece, you see
FurnitureRemovedand thenFurniturePlaced. (The game has no place where the framework can notice a finished player move.BuildingSystem.Moveonly lifts the piece, and the new spot is known only inBuildingSystem.Place.) AllBlueprints()lists every furniture blueprint the game knows, whether the player has it or not.Knownsays whether the player has it. (It reads the game’s furniture blueprint controller.)UnlockBlueprint(name)gives the player the blueprint and shows the game’s “New item” message.UnlockBlueprint(name, true)gives it without the message, but the Items panel still marks the blueprint as new. (The first form callsTaskItem.GiveItemWithResults. The silent form usesTaskItemsManager.AddTaskItem.)FurniturePlacedfires once for each placed piece. It fires when build mode places a piece, and when a script adds a piece. It does not fire when a save loads, or for furniture that came with the building. (For build mode it is raised from the finalizer onBuildingSystem.Place, after the game has set the rotation and the parent and attached links, soRotation,ChildRotation,ParentGuidandAttachedGuidare final. For a script it is raised fromFurnitureManager.PlacedFurniture(fromPlaceFurniture). Both go throughFurniturePlaceable.SetFurnitureInfo.)FurniturePlacedis not raised whenPlacethrows. The game has no undo, so a piece added before the throw stays placed with no event.- Some items, when put down in build mode, raise a nearly empty
FurniturePlaced. ItsIdisnull, itsTitleis the object’s name, itsGuidisnull, itsSkinandAltPrefabare 0, and itsManagerGuidis the area. Recognise these byId == null. - Only items whose model has a collectible-item part do this. An item without one (for example a coin) raises nothing from that placement. A script that places an item stack gets the same
null-Iditem once. (Build mode places a piece with anitemStackthroughBuildingSystem.Place, which callsItemOperations.SetCollectibleItemValues. That reachesSetFurnitureInfoonly when the prefab has aCollectibleItem, and then the flag is set. The placeable’sfurniturefield is stillnullat that point, so there is noFurnitureto read. A scripted item-stack spawn goes throughPlaceFurnitureandPlacedFurniture.) FurnitureRemovedfires when the game takes a piece out of an area. Moving a piece takes it out, so a move raisesFurnitureRemovedand then, when it is put down,FurniturePlaced. The piece is passed to you before the game destroys it. (It is raised fromFurniturePlaceable.Take.)FurnitureLoadedfires after each save load, for each of your mod’s pieces in the loaded levels. That includes the load after a level change. Use it to re-attach your mod’s behaviour to its pieces.- Write the
FurnitureLoadedhandler so that running it twice on the same piece does no harm, for example checkGetComponentbeforeAddComponent. Only pieces whose id starts withobx:raise it. The game’s own pieces never do. - A piece placed in this session does not raise
FurnitureLoaded, so useFurniturePlacedfor those. Checkitem.Id != null && item.Id.StartsWith("obx:", StringComparison.Ordinal). FurnitureLoadedfires early in the load. It runs afterFurnitureRegistry.Loadedand after your mod’s saved data has loaded, but before theEvents.Loadedhandlers that your mod adds.FurnitureRegistry.Getalready works in it. Writes such asBuilding.Placemay still be refused at that point, so only read and attach. (It runs during the framework’s ownEvents.Loadedhandling.SaveData.Busymay still betrue.)FurnitureLoadedonly looks at levels that are loaded when the load finishes. Pieces in a scene that loads later, or in a level that is not loaded yet, raise nothing until a load includes their level. For those, useEvents.SceneLoadedwithGetPlacedFurniture.- A mod piece whose build failed still raises
FurnitureLoaded. It is a stand-in that keeps itsobx:id.FurnitureRegistry.Get(item.Id)givesnullfor it. - Pieces already in a save do not raise
FurniturePlaced. AfterEvents.Loaded, callGetPlacedFurniture(areaId)for each area inAllAreaIds()to find them. Your mod’s own pieces in a save raiseFurnitureLoadedfor you.
Limits
Placereturnsnullwhile a save is loading or saving, when the area or the furniture is not known, when the model is missing, or whenskinoraltPrefabis out of range.Placealso returnsnullfor an emptymanagerGuidorfurnitureId, or for a position or turn with a number that is not real (not a number, or infinite). In those two cases the problem is written to the log once, and nothing is placed.- With
requireKnownset totrue,Placereturnsnull, logs once and places nothing whenIsKnownFurniture(furnitureId)isfalse. A path that loads something that is not furniture is released and refused, withnull. Remove(guid)returnsfalse, and changes nothing, when the piece is not placed (a piece with noGuidis not found until a save).Remove(guid)also returnsfalse, and changes nothing, when the game does not allow taking the piece, another piece sits on it or is attached to it, it holds things, or a save is loading or saving. An empty ornullguidreturnsfalseand logs once. (The game flag iscantTake. A piece holds things when it has a storage with items, a liquid storage with liquid, a crafting job in progress, or fuel that is burning or in a slot. It also holds things when its trash box has items in it, because the game hands those items to the player when the piece is taken. A collectible item piece and a piece that needs an item to take are refused too. The game keeps such a piece’s contents when it is moved, andRemovewould destroy them, so the piece stays in the world.)Remove(item)returnsfalsewhen the piece was destroyed or is no longer placed.itemmust not benull, or it throwsArgumentNullException.Movereturnsfalse, and changes nothing, when the position or turn has a number that is not real, the game does not allow taking the piece, the piece sits on or is attached to another piece, other pieces sit on it or are attached to it, or a save is loading or saving. (It makes the samecantTakeand parent or attached checks thatRemovemakes.)Movealso returnsfalsefor an emptyguid, and logs once. AnullitemthrowsArgumentNullException.- Both
UnlockBlueprintforms returnfalsewithout doing anything when the player already has the blueprint or the name is not found. An empty ornullname returnsfalseand logs once. Building.IsAvailableisfalsewhen a furniture event could not be set up. A rent problem does not affect it.