Skip to content

Game.UI.InGame.PrefabUISystem

Assembly: Game
Namespace: Game.UI.InGame

Type: class

Base: UISystemBase

Summary:
PrefabUISystem is a UI-facing ECS system responsible for exposing prefab metadata to the UI (prefab lists, details, requirements, properties and effects). It collects prefab-related data from the game's EntityManager and PrefabSystem (icons, thumbnails, requirements, construction costs, properties, effects, etc.), formats it through IJsonWriter bindings and keeps bound UI values up to date when relevant entity queries change. It also builds and manages a set of binder helpers used to translate component data into UI-friendly JSON structures.


Fields

  • private const string kGroup
    Provides the binding root group name ("prefabs") used for UI bindings.

  • private PrefabSystem m_PrefabSystem
    Cached reference to the PrefabSystem (used to fetch Prefab objects and prefabs' metadata).

  • private UniqueAssetTrackingSystem m_UniqueAssetTrackingSystem
    Cached reference to system that tracks unique assets (to determine unique/placed state).

  • private ImageSystem m_ImageSystem
    Cached reference used for retrieving icons and placeholder images.

  • private Entity m_RequirementEntity
    A temporary entity created to hold a buffer of UnlockRequirement items used when composing requirement lists.

  • private Entity m_TutorialRequirementEntity
    A sentinel entity used to represent tutorial-related unlock requirements.

  • private EntityQuery m_ThemeQuery
    EntityQuery for theme/UI object lookup used when binding themes.

  • private EntityQuery m_ModifiedThemeQuery
    EntityQuery that selects modified themes (to refresh bindings when theme changes).

  • private EntityQuery m_UnlockedPrefabQuery
    EntityQuery for unlocked prefabs (used to decide when to refresh prefab details map).

  • private EntityQuery m_PollutionConfigQuery
    EntityQuery to obtain pollution UI configuration prefab used by PollutionBinder.

  • private EntityQuery m_ManualUITagsConfigQuery
    EntityQuery used to read manual UI tag configuration data.

  • private GetterValueBinding<Dictionary<string, string>> m_UITagsBinding
    Binding object for manual UI tags mapping exposed to the UI.

  • private RawValueBinding m_ThemesBinding
    Raw binding that writes theme list data to the UI (group: "prefabs", key: "themes").

  • private RawMapBinding<Entity> m_PrefabDetailsBinding
    Raw map binding that writes per-prefab detailed data (group: "prefabs", key: "prefabDetails").

  • private int m_UnlockRequirementVersion
    Version counter for UnlockRequirementData component order version tracking (used to detect changes).

  • private int m_UITagVersion
    Version counter for ManualUITagsConfigurationData changes.

  • private bool m_Initialized
    Flag set after the system is initialised and bindings are ready (set in OnGameLoaded).

Properties

  • public override GameMode gameMode { get; }
    Returns the game mode for which this UI system is active. Implementation returns GameMode.Game.

  • public List<IPrefabEffectBinder> effectBinders { get; private set; }
    List of effect binders used to produce the prefab "effects" JSON array. Built on initialization (BuildDefaultEffectBinders).

  • public List<IPrefabPropertyBinder> constructionCostBinders { get; private set; }
    List of property binders used to determine construction cost shown in prefab details. Built on initialization (BuildDefaultConstructionCostBinders).

  • public List<IPrefabPropertyBinder> propertyBinders { get; private set; }
    List of property binders used to produce the prefab "properties" JSON array. Built on initialization (BuildDefaultPropertyBinders).

Constructors

  • public PrefabUISystem()
    Default constructor (preserved). The heavy initialization is done in OnCreate and OnGameLoaded. The constructor is empty/preserved to satisfy ECS system creation.

Methods

  • protected override void OnCreate()
    Initializes cached system references, creates temporary entities/buffers used for requirements, creates the EntityQueries, and registers data bindings:
  • Gets PrefabSystem, UniqueAssetTrackingSystem, ImageSystem.
  • Creates m_RequirementEntity with an UnlockRequirement buffer and m_TutorialRequirementEntity.
  • Sets up queries for themes, modified themes, unlocked prefabs, pollution config, manual UI tag config.
  • Adds bindings:

    • m_ThemesBinding -> BindThemes
    • m_PrefabDetailsBinding -> BindPrefabDetails
    • m_UITagsBinding -> BindManualUITags
  • protected override void OnGameLoaded(Context serializationContext)
    Called after game load. If enabled, marks the system initialized and builds the default binders for construction cost, properties and effects so that BindPrefabDetails and others can return full data.

  • protected override void OnUpdate()
    Runs each frame tick for the system. It:

  • Updates theme binding if modified themes query has changes.
  • Checks component order versions for UnlockRequirementData and ManualUITagsConfigurationData and updates prefab details / manual UI tags accordingly.
  • Updates internal version counters.

  • private Dictionary<string, string> BindManualUITags()
    Reads ManualUITagsConfiguration prefab (if available), uses reflection to extract UITagPrefab fields, and returns a dictionary mapping tag keys to uiTag strings for UI consumption.

  • private void BindThemes(IJsonWriter writer)
    Collects theme UI object info, writes an array of theme entries with entity id, name, icon (fallbacks to placeholder icon). Uses UIObjectInfo.GetSortedObjects.

  • private void BindPrefabDetails(IJsonWriter writer, Entity entity)
    Binding entry used by m_PrefabDetailsBinding: writes detailed prefab JSON for the requested entity (or null if not initialized or prefab isn't valid). It computes whether the entity is a unique asset and placed unique asset via UniqueAssetTrackingSystem, then calls the overload below.

  • public void BindPrefabDetails(IJsonWriter writer, Entity entity, bool unique, bool placed)
    Main implementation for writing a PrefabDetails JSON object. It:

  • Resolves owner prefab for net-subobjects (uses SubObject.MakeOwner flag).
  • Checks PrefabData enabled on the entity and owner.
  • Fetches PrefabBase instances and obtains title/description ids via GetTitleAndDescription.
  • Writes fields: entity, name, uiTag, icon (thumbnail), dlc (content prerequisite), preview, titleId, descriptionId, locked, unique, placed.
  • Binds nested sections: constructionCost (BindConstructionCost), effects (BindEffects), properties (BindProperties), requirements (BindPrefabRequirements).

  • public void GetTitleAndDescription(Entity prefabEntity, out string titleId, out string descriptionId)
    Utility to determine correct title and description localization keys based on prefab type (UIAssetMenuPrefab/ServicePrefab, UIAssetCategoryPrefab, upgrade/service upgrade, or default asset). Falls back to obsolete ID name when prefab is missing.

  • private static List<IPrefabEffectBinder> BuildDefaultEffectBinders()
    Creates default effect binder list: CityModifierBinder, LocalModifierBinder, LeisureProviderBinder.

  • public void BindEffects(IJsonWriter binder, Entity prefabEntity)
    Iterates effectBinders, counts and then invokes each binder that Matches to write the effects array.

  • private static List<IPrefabPropertyBinder> BuildDefaultConstructionCostBinders()
    Creates default construction cost binder list (ConstructionCostBinder and several component-based binders for different prefab types).

  • public void BindConstructionCost(IJsonWriter binder, Entity prefabEntity)
    If initialized, finds the first matching constructionCostBinder and invokes it to write cost property. If none match or not initialized, writes null.

  • private List<IPrefabPropertyBinder> BuildDefaultPropertyBinders()
    Creates the large default list of property binders used to expose many kinds of prefab properties (required resource, upkeep, power production, water pipes, capacities for medical/fire/prison/education/etc., pollution, storage, transport stops, etc.). Many of these binders are either small classes here or system instances (e.g., UpkeepPropertyBinderSystem).

  • public void BindProperties(IJsonWriter binder, Entity prefabEntity)
    Counts and invokes property binders that Match to produce an array of property entries.

  • public void BindPrefabRequirements(IJsonWriter writer, Entity prefabEntity)
    Writes unlocking/requirements for the prefab. If the entity is a UIGroupElement it delegates to BindUIGroupRequirements; otherwise it calls BindRequirements.

  • private void BindUIGroupRequirements(IJsonWriter writer, Entity prefabEntity)
    Handles UI group elements: collects lowest requirements across group elements and writes a combined requirement set (merging if multiple options exist). Uses a temporary m_RequirementEntity to aggregate alternative requirements.

  • private int FindLowestRequirements(Entity prefabEntity, NativeList<Entity> requirements, int score = -1)
    Recursively finds the best (lowest "score") unlock requirements among UI group elements. Uses ProgressionUtils.CollectSubRequirements and score heuristics based on milestone, dev tree node positions, and unlock requirement specifics. Returns computed score and fills requirements list.

  • private void BindRequirements(IJsonWriter writer, Entity prefabEntity)
    Top level requirements binder: collects devTreeNodes and unlockRequirements via GetRequirements, calls VerifyRequirements to normalize, and writes both requireAll and requireAny arrays via overloaded BindRequirements.

  • private void VerifyRequirements(NativeParallelHashMap<Entity, UnlockFlags> devTreeNodes, NativeParallelHashMap<Entity, UnlockFlags> unlockRequirements)
    Adjusts flags when only a single 'RequireAny' entry exists to promote it to 'RequireAll' for simpler UI presentation.

  • private void BindRequirements(IJsonWriter writer, UnlockFlags flag, Entity milestone, NativeParallelHashMap<Entity, UnlockFlags> devTreeNodes, NativeParallelHashMap<Entity, UnlockFlags> unlockRequirements)
    Writes either the "requireAll" or "requireAny" array: includes milestone (if any), dev tree nodes and unlock requirement prefabs converted into JSON entries. Uses helper binders for each entry type.

  • private void GetRequirements(Entity prefabEntity, out Entity milestone, NativeParallelHashMap<Entity, UnlockFlags> devTreeNodes, NativeParallelHashMap<Entity, UnlockFlags> unlockRequirements)
    Collects sub-requirements for a prefab via ProgressionUtils.CollectSubRequirements, splits them into categories (milestone with highest index; dev tree nodes; unlock requirement prefabs), and also maps tutorial-related requirements to the m_TutorialRequirementEntity.

  • private void BindMilestoneRequirement(IJsonWriter binder, Entity entity)
    Writes a MilestoneRequirement JSON object with entity, index and locked state.

  • private void BindDevTreeNodeRequirement(IJsonWriter binder, Entity entity)
    Writes a DevTreeNodeRequirement JSON object with entity, name and locked state using DevTreeNodePrefab metadata.

  • private void BindUnlockRequirement(IJsonWriter binder, Entity entity)
    Dispatches unlock requirement prefab types and writes the appropriate requirement subtype object:

  • TutorialRequirement
  • StrictObjectBuiltRequirement -> BindObjectBuiltRequirement
  • ZoneBuiltRequirement -> BindZoneBuiltRequirement
  • CitizenRequirement -> BindCitizenRequirement
  • ProcessingRequirement -> BindProcessingRequirement
  • ObjectBuiltRequirement -> BindOnBuildRequirement
  • PrefabUnlockedRequirement -> BindPrefabUnlockedRequirement
  • UnlockRequirementPrefab (unknown / generic) -> BindUnknownUnlockRequirement

  • private void BindTutorialRequirement(IJsonWriter binder, Entity entity)
    Writes a simple TutorialRequirement entry (entity + locked = true).

  • private void BindObjectBuiltRequirement(IJsonWriter binder, Entity entity, StrictObjectBuiltRequirementPrefab prefab)
    Writes StrictObjectBuiltRequirement JSON with icon, requirement name, minimumCount, isUpgrade, plus common unlock properties.

  • private void BindZoneBuiltRequirement(IJsonWriter binder, Entity entity, ZoneBuiltRequirementPrefab prefab)
    Writes ZoneBuiltRequirement JSON with icon, requiredTheme, requiredZone, requiredType, minimumSquares, minimumCount, minimumLevel, plus common unlock properties.

  • private void BindCitizenRequirement(IJsonWriter binder, Entity entity, CitizenRequirementPrefab cr)
    Writes CitizenRequirement JSON with minimumPopulation and minimumHappiness plus common unlock properties.

  • private void BindProcessingRequirement(IJsonWriter binder, Entity entity, ProcessingRequirementPrefab prefab)
    Writes ProcessingRequirement JSON with icon, resourceType, minimumProducedAmount plus common properties.

  • private void BindOnBuildRequirement(IJsonWriter binder, Entity entity, ObjectBuiltRequirementPrefab prefab)
    Writes ObjectBuiltRequirement JSON with name and minimumCount plus common properties.

  • private void BindPrefabUnlockedRequirement(IJsonWriter binder, Entity entity, PrefabUnlockedRequirementPrefab prefab)
    Writes PrefabUnlockedRequirement JSON (uses BindUnlockRequirementProperties for common fields).

  • private void BindUnknownUnlockRequirement(IJsonWriter binder, Entity entity, UnlockRequirementPrefab prefab)
    Writes a generic UnlockRequirement JSON using common unlock properties.

  • private void BindUnlockRequirementProperties(IJsonWriter binder, Entity entity, UnlockRequirementPrefab prefab)
    Writes common fields for unlock requirements: entity id, labelId (if present), progress and locked boolean based on Enabled Locked component.

  • private static List<IPrefabPropertyBinder> BuildDefaultPropertyBinders()
    (Described earlier) builds the long list of property binders used in BindProperties.

  • Plus many nested binder classes and structs defined inside the same file (IPrefabEffectBinder, CityModifierBinder, LocalModifierBinder, LeisureProviderBinder, IPrefabPropertyBinder and multiple specialized binders like ComponentIntPropertyBinder, ConstructionCostBinder, ConsumptionBinder, PollutionBinder, ElectricityPropertyBinder and its subclass binders, UpkeepPropertyBinderSystem (a GameSystemBase), StorageLimitBinder, PowerProductionBinder, TransformerCapacityBinder, TransformerInputBinder, TransformerOutputBinder, ElectricityConnectionBinder, WaterConnectionBinder, JailCapacityBinder, TransportStopBinder, RequiredResourceBinder, UpkeepModifierBinder, etc.) which actually implement matching/counting/formatting logic used by BindEffects/BindProperties/BindConstructionCost.

Note: Many helper binders access other systems (ResourceSystem, ObjectToolSystem, ImageSystem, UniqueAssetTrackingSystem) and EntityManager buffers/components to compute accurate UI values (e.g., tree cost variants, electricity capacity ranges, upkeep calculation, required resources, transport stop counts, pollution keys, etc.).

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // PrefabUISystem's OnCreate will cache PrefabSystem/ImageSystem, create temp entities and register bindings:
    // - "prefabs.themes" (BindThemes)
    // - "prefabs.prefabDetails" (BindPrefabDetails)
    // - "prefabs.manualUITags" (BindManualUITags)
    //
    // After the game loads, OnGameLoaded will call BuildDefault*Binders to prepare effect/property binders.
}

If you are writing a mod that needs to extend or reuse PrefabUISystem functionality: - You can obtain the system via World.GetOrCreateSystemManaged() and call BindPrefabDetails directly with a custom IJsonWriter to inspect the prepared JSON data for a prefab entity. - To add custom property/effect binders you could inject them by replacing or augmenting the property/effect binder lists after OnGameLoaded (be aware of initialization order and that PrefabUISystem expects its default binders to be built on load).