Game.UI.InGame.ProgressionUtils
Assembly:
Assembly-CSharp (Game) — typical runtime assembly for Cities: Skylines 2 game code.
Namespace:
Game.UI.InGame
Type:
static class
Base:
System.Object (static utility class)
Summary:
Utility helpers for working with unlock/progression requirements for prefabs (entities). Provides methods to collect transitive unlock requirements (into a NativeParallelHashMap) and to compute the required milestone index for unlocking a given entity by inspecting its UnlockRequirement buffer and related MilestoneData. These helpers interact with Unity.Entities (EntityManager, DynamicBuffer) and Unity.Collections (NativeParallelHashMap), and are intended to be used from game/mod code that queries prefab unlock relationships.
Fields
None
This static utility class does not declare any instance or static fields.
Properties
None
No properties are exposed by this static class.
Constructors
None
This is a static class and has no public constructors. (If needed the runtime may generate a static constructor; none are declared in source.)
Methods
-
public static bool CollectSubRequirements(EntityManager entityManager, Entity prefab, NativeParallelHashMap<Entity, UnlockFlags> requiredPrefabs, UnlockFlags flags = UnlockFlags.RequireAll | UnlockFlags.RequireAny)
Collects transitive unlock requirements for the specified prefab into the provided requiredPrefabs map. -
Parameters:
- entityManager: The EntityManager to query components and buffers from.
- prefab: The prefab (Entity) whose unlock requirements will be walked.
- requiredPrefabs: A caller-provided NativeParallelHashMap
that will be populated with required prefabs (keys) and their aggregated UnlockFlags (values). The map is mutated by the method. - flags: Filter flags used early in the method to short-circuit visiting entries. Default is UnlockFlags.RequireAll | UnlockFlags.RequireAny.
-
Returns:
- bool — The method returns true in the case where a direct self-referential unlock requirement with the RequireAll flag is found in the prefab's UnlockRequirement buffer. For typical usage the caller is primarily interested in the side-effect of requiredPrefabs being filled; the boolean return value indicates the presence of that specific condition.
-
Behavior and notes:
- If prefab == Entity.Null, or the prefab is already present in requiredPrefabs with overlapping flags ((requiredPrefabs[prefab] & flags) != 0), the method returns false and does not traverse further.
- The method uses EntityManager.TryGetBuffer(prefab, out DynamicBuffer
) to read the UnlockRequirement buffer for the prefab. Each UnlockRequirement is expected to contain at least m_Prefab (the required prefab entity) and m_Flags (UnlockFlags). - If a UnlockRequirement references the same prefab (m_Prefab == prefab) and has RequireAll set, the method returns true.
- For each other referenced prefab it:
- Temporarily adds the current prefab to requiredPrefabs to mark traversal,
- Recursively calls CollectSubRequirements for the referenced prefab with that requirement's flags,
- If the recursive call returns true, the referenced prefab is added to requiredPrefabs (or its flags are ORed with existing flags),
- Removes the temporary mark for the current prefab before continuing.
- The method mutates requiredPrefabs and expects the caller to provide and eventually dispose of it. It does not allocate or dispose the map itself.
- The function relies on UnlockRequirement and UnlockFlags definitions (not shown here). Typical flags are RequireAll and RequireAny which control how requirements are aggregated.
- Be careful with recursion and large requirement graphs — although the code avoids revisiting already-marked prefabs via the requiredPrefabs check, deep graphs could still lead to recursion depth.
-
public static int GetRequiredMilestone(EntityManager entityManager, Entity entity)
Compute the highest milestone index required to unlock the given entity based on transitive unlock requirements. -
Parameters:
- entityManager: The EntityManager used to query components.
- entity: The prefab (Entity) whose required milestone is computed.
-
Returns:
- int — The maximum milestone index (component MilestoneData.m_Index) among required prefabs that are marked with RequireAll. Returns 0 if no applicable requirements or milestone components are found.
-
Behavior and notes:
- If the entity does not have an UnlockRequirement component buffer, the method returns 0.
- The method constructs a NativeParallelHashMap
with Allocator.TempJob, calls CollectSubRequirements to fill it, then iterates the map. - For each entry in the map, if the entry's flags have RequireAll set and the referenced prefab has a MilestoneData component, the method reads MilestoneData.m_Index and tracks the highest value found.
- The temporary NativeParallelHashMap is disposed before the method returns.
- This method provides a convenient single-call way to obtain an integer milestone requirement without requiring the caller to manage the map lifetime.
Usage Example
// Example: compute the milestone required to unlock a given prefab (entity).
// This code would run in a context that has access to an EntityManager (e.g., in a System or mod initialization).
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
Entity myPrefab = /* obtain the prefab entity you want to check */;
// Get the required milestone index (0 if none)
int requiredMilestone = ProgressionUtils.GetRequiredMilestone(entityManager, myPrefab);
Debug.Log($"Required milestone index for prefab: {requiredMilestone}");
// Example: If you want to collect the transitive requirements yourself for further processing:
var requiredPrefabs = new NativeParallelHashMap<Entity, UnlockFlags>(16, Allocator.TempJob);
bool specialFlagDetected = ProgressionUtils.CollectSubRequirements(entityManager, myPrefab, requiredPrefabs);
// requiredPrefabs now contains the set of required prefabs and their combined UnlockFlags.
// Remember to dispose the NativeParallelHashMap when done:
requiredPrefabs.Dispose();
Additional notes and recommendations:
- Always dispose any NativeParallelHashMap you allocate (the class methods assume the caller will manage disposal when requiredPrefabs is provided).
- This utility reads DynamicBuffer