Game.UI.InGame.MilestoneUISystem
Assembly: Assembly-CSharp
Namespace: Game.UI.InGame
Type: class
Base: UISystemBase, IXPMessageHandler
Summary:
MilestoneUISystem is the in-game UI system responsible for gathering milestone-related data from ECS (entities/components), preparing JSON bindings for the UI, and publishing milestone/XP events to the UI. It collects milestone lists/details, determines unlocked assets/features/services/policies for each milestone, sends XP messages to the UI, and indicates when milestones are reached. The system heavily uses EntityQuery, NativeArray/NativeList and temporary allocators (Allocator.TempJob), so pay attention to proper disposal and job/static-safety when interacting with it from mods. It requires several game systems (PrefabSystem, XPSystem, CitySystem, MilestoneSystem, ImageSystem, CityConfigurationSystem, TutorialSystem) and reads components such as MilestoneData, PrefabData, UIObjectData and various Unlock/DevTree related components.
Fields
-
private PrefabSystem m_PrefabSystem
Holds a reference to the game's PrefabSystem used to resolve prefabs (MilestonePrefab, ServicePrefab, PrefabBase, FeaturePrefab, PolicyPrefab, etc.) and access prefab metadata (names, icons, colors). -
private IXPSystem m_XPSystem
Reference to the XP/leveling system used to transfer messages into this UI system and for milestone XP related info. -
private CitySystem m_CitySystem
Used to read city-level data such as the city's total XP. -
private IMilestoneSystem m_XpMilestoneSystem
Reference to the milestone progression system used to obtain last/next required XP values. -
private ImageSystem m_ImageSystem
Used to fetch placeholder icons and thumbnails for assets/services. -
private CityConfigurationSystem m_CityConfigurationSystem
Provides city configuration flags that affect milestone details (for example, whether map tiles are unlocked globally). -
private TutorialSystem m_TutorialSystem
Reference to tutorial system (present but not heavily used in this class). -
private EntityQuery m_MilestoneLevelQuery
EntityQuery to access the singleton MilestoneLevel component (current achieved milestone). -
private EntityQuery m_MilestoneQuery
Query for all milestone prefabs (PrefabData + MilestoneData) excluding deleted/temp. -
private EntityQuery m_LockedMilestoneQuery
Query for milestones which are still locked (PrefabData + MilestoneData + Locked). -
private EntityQuery m_ModifiedMilestoneQuery
Query used to detect changes to milestone entities (Created/Deleted/Updated) — used to refresh UI bindings. -
private EntityQuery m_MilestoneReachedEventQuery
Query for MilestoneReachedEvent components (used to detect newly reached milestones). -
private EntityQuery m_UnlockableAssetQuery
Query for unlockable assets (prefabs with UIObjectData, ServiceObjectData, UnlockRequirement). -
private EntityQuery m_UnlockableZoneQuery
Query for unlockable zones (zone prefabs with UIObjectData, UnlockRequirement and variants with PlaceableObjectData). -
private EntityQuery m_DevTreeNodeQuery
Query for dev tree nodes (DevTreeNodeData) used to determine services present in dev tree. -
private EntityQuery m_UnlockableFeatureQuery
Query for feature-type unlockables (FeatureData + UIObjectData + UnlockRequirement). -
private EntityQuery m_UnlockablePolicyQuery
Query for policy unlockables (PolicyData + UIObjectData + UnlockRequirement). -
private EntityArchetype m_UnlockEventArchetype
Archetype created for unlock event entities (Event + Unlock) if the system needs to spawn unlock events. -
private GetterValueBinding<int> m_AchievedMilestoneBinding
Binding used to expose the currently achieved milestone index to the UI as "milestone.achievedMilestone". -
private GetterValueBinding<bool> m_MaxMilestoneReachedBinding
Binding used to expose whether maximum milestone has been reached (no locked milestones remain). -
private GetterValueBinding<int> m_AchievedMilestoneXPBinding
Binding exposing the XP earned for the achieved milestone (last required XP). -
private GetterValueBinding<int> m_NextMilestoneXPBinding
Binding exposing next milestone XP requirement. -
private GetterValueBinding<int> m_TotalXPBinding
Binding exposing the city's total XP to the UI. -
private RawEventBinding m_XpMessageAddedBinding
Event binding used to publish XPMessage events to the UI (milestone.xpMessageAdded). -
private RawValueBinding m_MilestonesBinding
Raw binding that enumerates milestones and writes a JSON array for the UI. -
private ValueBinding<Entity> m_UnlockedMilestoneBinding
Binding that stores the most recently unlocked milestone entity (for notification popups). -
private RawMapBinding<Entity> m_MilestoneDetailsBinding
Map binding that provides detailed info for a specific milestone entity. -
private RawMapBinding<Entity> m_MilestoneUnlocksBinding
Map binding that provides the list of unlocks (features, services, assets, policies) for a milestone. -
private RawMapBinding<Entity> m_UnlockDetailsBinding
Map binding used to get details for a single unlockable prefab (icon, title/description ids, locked state).
(There are several more small private helper structs and lists used inside methods; the list above covers the main persistent fields.)
Properties
- This type exposes no public properties.
Constructors
public MilestoneUISystem()
Default constructor — exists for ECS system creation. The real initialization is performed in OnCreate.
Methods
-
protected override void OnCreate()
Initializes references to required systems (PrefabSystem, XPSystem, CitySystem, MilestoneSystem, ImageSystem, CityConfigurationSystem, TutorialSystem). Creates EntityQuery instances used for milestones/unlockables/dev tree and sets up the unlock event archetype. Registers all UI bindings (value & raw bindings, event bindings) used to feed the UI with milestone lists, details and XP messages. -
protected override void OnGameLoaded(Context serializationContext)
Resets the cached unlocked milestone binding (clears any pending unlocked milestone) when a game is loaded. -
protected override void OnUpdate()
Updates the getter bindings (achieved milestone, xp values, total xp) each frame. Checks for MilestoneReachedEvent entities and publishes newly reached milestones to the UI (PublishReachedMilestones). Updates milestones & milestone details bindings when milestone events or modifications are present. Transfers messages from the XP system into this UI system via the XPSystem.TransferMessages(this) call. -
public void AddMessage(XPMessage message)
Part of IXPMessageHandler — serializes an XPMessage to JSON and triggers the "milestone.xpMessageAdded" UI event if the binding is active. The message contains amount and reason; the method writes them as a milestone.XPMessage object. -
private int GetAchievedMilestone()
Reads the current achieved milestone index from the MilestoneLevel singleton component. Returns 0 if MilestoneLevel is missing. -
private bool IsMaxMilestoneReached()
Returns true when there are no locked milestones remaining (uses m_LockedMilestoneQuery). -
private int GetAchievedMilestoneXP()
Returns the lastRequiredXP from the MilestoneSystem (m_XpMilestoneSystem). -
private int GetNextMilestoneXP()
Returns nextRequiredXP from the MilestoneSystem. -
private int GetTotalXP()
Returns the city's total XP (m_CitySystem.XP). -
private void PublishReachedMilestones()
Determines the highest-index milestone from current MilestoneReachedEvent components, updates the unlocked milestone binding (if blocking popups are enabled and unlock-all is not active), sends telemetry and achievement progress notifications. Uses m_UnlockedMilestoneBinding to store/display the new unlocked milestone. -
private int GetMilestoneIndex(Entity milestoneEntity)
Helper to safely read MilestoneData.m_Index from a milestone entity. Returns -1 if the entity is null or does not have MilestoneData. -
private void BindMilestones(IJsonWriter writer)
Writes the array of all milestones to the supplied IJsonWriter. Uses GetSortedMilestones to obtain milestones sorted by index and writes: entity, index, major flag, locked flag. -
private NativeArray<ComparableMilestone> GetSortedMilestones(Allocator allocator)
Collects entities + MilestoneData via m_MilestoneQuery, builds an array of ComparableMilestone and sorts them by index. Caller must dispose the returned NativeArray after use. -
private void BindMilestoneDetails(IJsonWriter writer, Entity milestone)
Writes detailed information for a single milestone (index, xpRequirement, reward, devTreePoints, mapTiles, loanLimit) as well as visual data from MilestonePrefab (image, colors) and locked state. Writes null if the entity is invalid. -
private void BindMilestoneUnlocks(IJsonWriter writer, Entity milestoneEntity)
Collects and sorts unlockable features, zones, services and policies unlocked by the specified milestone, then writes a combined JSON array describing each unlock (different JSON types for Feature, Asset, Service, Policy). The method uses many helper functions to collect and sort unlocks, filtering by unlock requirements. -
private NativeList<Entity> GetUnlockedZones(Entity milestoneEntity, Allocator allocator)
Returns a list of zone prefabs that are unlocked at the supplied milestone. Uses m_UnlockableZoneQuery and FilterUnlockedPrefabs. -
private NativeList<AssetInfo> GetSortedZones(NativeList<Entity> unlockedZones, Allocator allocator)
Converts unlocked zone entities into AssetInfo structs with two-tiered UI priority and sorts them. Returns a NativeListallocated with the provided allocator. -
private void BindAsset(IJsonWriter writer, AssetInfo asset, PrefabBase assetPrefab, NativeList<Entity> assetThemes)
Writes a milestone.Asset JSON object containing entity, name, icon (thumbnail or placeholder), and theme list for the asset. The assetThemes list is filled via GetThemes. -
private NativeList<Entity> GetUnlockedDevTreeServices(Entity milestoneEntity, Allocator allocator)
Collects services that appear in the dev tree and filters them to those unlocked by the given milestone. Uses m_DevTreeNodeQuery and FilterUnlockedPrefabs. -
private NativeList<Entity> GetUnlockedAssets(Entity milestoneEntity, Allocator allocator)
Returns a list of unlockable assets whose unlock requirements are satisfied at this milestone (via FilterUnlockedPrefabs). -
private NativeList<UIObjectInfo> GetSortedPolicies(Entity milestoneEntity, Allocator allocator)
Gathers unlockable policies for the milestone, sorts them using UIObjectInfo.GetSortedObjects and returns the sorted list. -
private NativeList<Entity> FilterUnlockedPrefabs(NativeArray<Entity> prefabs, Entity milestoneEntity, Allocator allocator)
Core filter used throughout: for every candidate prefab, it collects sub-requirements (ProgressionUtils.CollectSubRequirements) and inspects UnlockFlags to determine whether the prefab is unlocked at the specified milestone. It returns the prefabs whose "RequireAll" milestone requirement resolves to the given milestone entity. The method uses a temporary NativeParallelHashMap and must dispose it internally. -
private NativeList<UIObjectInfo> GetSortedUnlockedFeatures(Entity milestoneEntity, Allocator allocator)
Gathers unlockable features for a milestone, sorts them, and removes the "Map Tiles" feature if global unlockMapTiles is enabled in city configuration. -
private NativeList<ServiceInfo> GetSortedServices(NativeList<Entity> unlockedDevTreeServices, NativeList<Entity> unlockedAssets, Allocator allocator)
Combines services discovered through dev tree nodes and services referenced by unlocked assets into a unique sorted list (by UI priority). Marks whether the service was unlocked via dev tree or indirectly via assets. -
private void FilterAndSortAssets(NativeList<AssetInfo> result, Entity serviceEntity, NativeList<Entity> unlockedAssets)
Filters unlocked assets by service (ServiceObjectData.m_Service == serviceEntity), builds AssetInfo entries and sorts them by UI priorities into the provided result list. -
private void GetThemes(NativeList<Entity> result, Entity assetEntity)
Reads the ObjectRequirementElement dynamic buffer on the asset entity and collects any requirement entities that have ThemeData, returning those as themes for the asset. -
private void BindUnlockDetails(IJsonWriter writer, Entity unlockEntity)
Writes detailed unlock information for a single unlockable entity: delegates to BindFeatureUnlock, BindServiceUnlock, BindAssetUnlock or BindPolicyUnlock depending on the prefab's component types. Writes null when the entity is not valid or lacks required components. -
private void BindFeatureUnlock(IJsonWriter writer, Entity featureEntity, bool locked)
Writes milestone.UnlockDetails JSON for a feature prefab: icon, title/description ids, locked state and hasDevTree (false for features). -
private void BindServiceUnlock(IJsonWriter writer, Entity serviceEntity, bool locked)
Writes unlock details for a service, includes hasDevTree flag computed with HasDevTree. -
private bool HasDevTree(Entity serviceEntity)
Checks whether a service has any DevTreeNodeData entries (scans m_DevTreeNodeQuery) and returns true if any node references the service. -
private void BindAssetUnlock(IJsonWriter writer, Entity assetEntity, bool locked)
Writes unlock details for a generic asset prefab (using thumbnail or placeholder) and title/description ids based on the prefab name. -
private void BindPolicyUnlock(IJsonWriter writer, Entity policyEntity, bool locked)
Writes unlock details for a policy prefab: icon, localized title/description ids, locked state and hasDevTree=false.
(Several small helper structs are declared inside the class: ComparableMilestone, ServiceInfo, AssetInfo — used for sorting.)
Usage Example
// Example: get the MilestoneUISystem and send an XP message to be displayed in UI.
// Note: XPMessage and XPReason are game types; construct as appropriate from game assemblies.
var world = World.DefaultGameObjectInjectionWorld; // or the game's world instance
var milestoneUI = world.GetOrCreateSystemManaged<Game.UI.InGame.MilestoneUISystem>();
// Create an XPMessage (structure fields depend on game; this is illustrative)
XPMessage msg = new XPMessage {
amount = 50,
reason = XPReason.BuildingPlaced
};
// Send to UI system — it will publish the event if bindings are active.
milestoneUI.AddMessage(msg);
Additional notes for modders: - Bindings exposed by this system: "milestone.achievedMilestone", "milestone.maxMilestoneReached", "milestone.achievedMilestoneXP", "milestone.nextMilestoneXP", "milestone.totalXP", "milestone.xpMessageAdded", "milestone.milestones", "milestone.unlockedMilestone", "milestone.milestoneDetails", "milestone.milestoneUnlocks", "milestone.unlockDetails". - Many methods allocate temporary NativeArray/NativeList with Allocator.TempJob — the system disposes them where appropriate, but if you copy/adapt any code be sure to dispose temp allocations. - To modify or hook into milestone unlocking, consider listening to MilestoneReachedEvent components or using the provided UI bindings rather than altering system internals.