Registering a business type

Every field of AiBusinessRegistration, what your layouts must satisfy, how to tell the registration succeeded, and the mistakes that come up most.

Registration is explicit. BusinessBridge never scans for custom businesses, and it never infers a layout. You name the business type, you supply the layouts, and you declare the AI templates that may use them.

Registration fields

FieldRequiredWhat it is
ProviderIdyes Stable id of your mod. Used for replace, for UnregisterProvider, and in diagnostics.
BusinessTypeNameyes A business type you have already registered with the game. It must carry ba:businesstag_allowplayercreation and have a suitableBuildingType; vanilla AI ignores layouts of types without that tag.
LayoutNameyes The logical AI layout name, shared by all of your building sizes. Vanilla matches AiBusinessDefault.buildingLayout to it case-sensitively. A file in LayoutFiles must therefore be named <LayoutName>.json, because the name is taken from the path; every AiBusinessLayout.Name in LayoutContents must equal it too, but there you pass the name yourself, so the asset it came from can be called anything.
LayoutContentsthis or LayoutFiles Your layouts as text: AiBusinessLayout(name, json), one per building size/version. The beta-2 transport, for layouts that ship inside your AssetBundle. See Shipping layouts.
LayoutFilesthis or LayoutContents BusinessLayoutSet JSON files on disk in the game's own format — one per building size/version. The original beta-1 transport, still supported. Set either list, or both; two layouts for one size/version are rejected either way.
TemplateDonorBusinessTypeyes A vanilla business type whose shipped AI templates supply the structural values BusinessBridge does not invent: schedule, sign appearance, logo font and colours. Pick one whose stores feel like yours.
Templatesyes, at least one One entry per AI business identity. Vanilla creates one AiBusinessDefault per business name.

Per template

FieldRequiredWhat it is
BusinessNameyes The AI business name. Vanilla looks templates up by name, so it must be unique across every AI template in the game. A name already used by vanilla, by another provider, or twice in your own list is dropped with a message.
GoodsSourceyes for independents Import or Wholesale — how an independent rival stocks its shelves.
CorporationRivalIdno Leave empty for an independent rival. A special rival id (or "*") makes it a corporate template, which the game may also use for rival low-demand defense. Accepted only when your layouts cover every special-rival building size of your building type, because rival defense ignores layout size. Until then, corporate templates are dropped with an explanatory message.

What comes from where

BusinessBridge copies from the donor: schedule (days, open flag, opening hours, work shifts), sign appearance, logo font and colours. It takes from you: business type, business name, layout, goods source, rival id, and the logo shapes declared on your own business type. The donor object itself is never modified.

What your layout must satisfy

A registration is rejected as a whole — nothing stored, nothing injected, no half-applied state — if any of this fails:

  • ProviderId, BusinessTypeName and LayoutName are non-empty
  • the business type exists, has ba:businesstag_allowplayercreation, and has a suitableBuildingType
  • at least one layout is supplied, through LayoutContents, LayoutFiles or both
  • every layout parses and is a BusinessLayoutSet for this business type (a file must also exist)
  • each layout's name equals LayoutName — the file name for LayoutFiles, the Name you passed for LayoutContents
  • BuildingSize is non-empty, BuildingVersion is 1 or more, and no two layouts claim the same size/version, whichever list they arrived in
  • every item in the layout is a real item in this build
  • every product a shelf sells is a real item, and any primary product of the business type is a demanded product — new-game city generation indexes demanded products and would otherwise throw
  • at least one shelf actually sells something
  • TemplateDonorBusinessType exists and has vanilla AI templates of the kind each of your templates needs
  • at least one template survives

Individual templates are dropped, with a message, rather than failing the whole registration: a duplicate or already-used business name, an unsupported goods source, a corporate template without full size coverage, or a donor type with no template of the required kind.

A layout for a building size that no building in the city actually has is reported as a note, not a rejection — the AI simply never gets to use it.

Verifying the registration succeeded

  1. Read the result. Register never throws. RegistrationResult.Accepted tells you whether anything was stored; TemplatesCreated and TemplatesActive tell you how much survived, and Messages explains every decision. Log result.ToString() unconditionally.
  2. Check the log. Every registration decision is written to BusinessBridge's own log, so you can see why something was dropped without asking a player for Player.log.
  3. Check a support bundle. registrations.json lists every registration with its layouts, templates and validation messages, and cache-state.json reports how many templates are live and how many are yours. See Compatibility, diagnostics and release.
  4. Start a new game. An existing save proves less: new-city generation is where demanded products and layout coverage really get exercised.

Common integration mistakes

MessageCause
business type X is not registered You registered with BusinessBridge before registering the type with the game. Register the type first.
lacks ba:businesstag_allowplayercreation Vanilla AI ignores such layouts entirely. Add the tag to your business type.
layout name 'X' must equal LayoutName 'Y' All sizes of one layout share one logical name. For a LayoutFiles entry, rename the file to <LayoutName>.json; for LayoutContents, pass LayoutName as the AiBusinessLayout.Name instead of the asset's own name.
no layouts: set LayoutFiles, LayoutContents, or both The registration supplied neither.
layout content 'X' could not be read The text is not valid BusinessLayoutSet JSON. The message carries the parser's own reason and position.
a layout in LayoutContents has no Name Name stands in for the file name and must be set — pass your LayoutName.
a second layout for <size> Two layouts claim one building size and version, whether they arrived as files, as content, or one of each.
primary product X is not a demanded product New-game generation would throw. Mark the product as demanded.
no shelf sells a product The AI store would sell nothing. Check playerItemPurchaserSettings on your shelves.
donor type X has no vanilla AI templates That vanilla type ships none of the kind you asked for. Pick another donor.
that AI business name is already used Business names are the lookup key for templates and must be unique game-wide.
corporate template dropped: ... layouts cover only ... Rival defense ignores layout size. Cover every special-rival size, or keep the template independent.
the AI template cache does not match this game build BusinessBridge could not verify the game's cache on this build and stayed inactive. Nothing was stored and vanilla AI is untouched.
{# GoatCounter's own count.js, served from this site rather than from a third-party host. The context processor decides whether this page may be counted at all; see core/context_processors.py. Both scripts are deferred, so the settings file below runs first and has set window.goatcounter.referrer before count.js reads it. #}