Skip to content

Generated reference. This page mirrors Code/Housing/README.md, this module's source-of-truth documentation (Standards/02_DOCUMENTATION_STANDARDS.md §1). Edit it there, not here -- this file is regenerated on every docs build and any local edit is silently overwritten.

Housing

Purpose. Property groups: buying a fixed set of World ownables (Door, WorldContainer) as one unit, at one price, with one Ownership record for the whole group. The "master/slave door linking → property groups" follow-on ROADMAP.md Milestone 7 already named and deferred, finally scoped by ADR-0013. See 29_HOUSING.md.

Responsibilities. - HousingListingDefinition — content, not code (ADR-0004's precedent): a display name, the group's own fixed GroupOwnableId, the fixed set of member OwnableIds (MemberOwnableIds), and GroupPrice. See that file's header comment for why GroupOwnableId is author-assigned data, not runtime-generated. - IHousingListingRegistry / HousingListingRegistry — every loaded, validated listing, mirroring IItemRegistry/IJobRegistry minus inheritance resolution. - IHousingService / HousingStorePurchaseGroupAsync: the atomic (by ordering, not by a real transaction, same as PropertyStore.PurchaseAsync) validate, assign-ownership, link-members, debit-money, publish-event sequence. Holds no persisted state of its own — see HousingStore.cs's header comment. - HousingConfiguration — the operator-tunable kiosk interaction range, following Code/World/DoorConfiguration.cs's precedent. - HousingListingComponent — the placed-in-map kiosk: [Property] ListingAssetId, [Sync(FromHost)] IsOwned/OwnerName, and [Rpc.Host] RequestPurchaseGroup(), following DoorComponent's exact shape (one component instance per entity, acting on itself).

Not responsible for. - Who owns a group, or access resolution — Ownership's job, entirely untouched by this module (ADR-0013 point 3: IOwnershipService gains zero new surface). - A door's or container's own lock/seal stateWorld's job; this module only ever calls IPropertyService.SetGroupAsync/IWorldContainerService.SetGroupAsync to link a member in, never touches IsLocked/IsSealed itself. - Moving moneyEconomy's job, same as PropertyStore. - Reselling a group, or changing its membership after purchase. ADR-0013's own deliberately deferred open question — membership is fixed at purchase time from the listing; there is no "add/remove a member" API anywhere in this module. - A member id that resolves to neither a registered Door nor a registered WorldContainer. Logged as an operator-visible anomaly during PurchaseGroupAsync, never a reason to fail an otherwise-legitimate purchase — see HousingStore.LinkMembersAsync's own comment.

Dependencies. Core (IServiceRegistry, IServiceResolver, IEventBus, IGameLog, IConfigurationInspector), Character (Character), Economy (IEconomyService), Ownership (IOwnershipService, OwnableId, OwnerRef), World (IPropertyService, IWorldContainerService, Door, WorldContainer), Movement (IPawnLocator, for HousingListingComponent's distance check), the S&box engine (Component, GameResource, Rpc, Sync, ResourceLibrary).

Public API. - IHousingServicePurchaseGroupAsync(Character buyer, HousingListingDefinition listing). - IHousingListingRegistryFind(string assetId), Get(string assetId), All. - HousingListingComponent.

Events published. - HousingGroupPurchasing — cancellable, published once eligibility (unowned, affordable) is confirmed but before ownership is assigned or money moves. Mirrors Applejack.World.DoorPurchasing exactly. - HousingGroupPurchased(HousingListingDefinition, OwnableId GroupId, Character Buyer) — published once ownership has been assigned. Mirrors Applejack.World.DoorPurchased.

Persistence. None owned by this module. The group's Ownership record lives under ownership/{groupId} (Ownership module, no different from any other OwnableId); each member's GroupId link lives on that member's own doors/{id}/containers/{id} document (World module). See HousingStore.cs's header comment for why this is deliberate, not a gap.

Future improvements. - Reselling a group as a unit, and what happens to member access grants on resale — ADR-0013's own deliberately deferred open question. - A Manage level or a real "remove a member's access" flow, once Ownership grows either (see Code/Ownerships/README.md's own "Future improvements").