Game.UI.InGame.EmployeesSection
Assembly:
Assembly-CSharp (game/mod assembly)
Namespace:
Game.UI.InGame
Type:
class
Base:
InfoSectionBase
Summary:
EmployeesSection is an in-game UI info section that collects and exposes employee-related data for the currently selected entity or district. It determines whether the section should be visible, scans buildings (or district buildings) for renters/employees and workplaces, and accumulates employee counts, maximum workplace capacity and education-distribution data (EmploymentData) for both employees and workplaces. The class uses Entity Queries and Unity.Collections (NativeArray/NativeList) and is intended for use with the game's ECS-style EntityManager and prefab systems. It also writes its collected properties to a JSON writer via OnWriteProperties.
Fields
-
private EntityQuery m_DistrictBuildingQuery
Holds an EntityQuery configured to find buildings that belong to districts and that either have a Renter or an Employee component, excluding Temp and Deleted. Used to enumerate buildings in the selected district when the selection is a district. -
private NativeList<Entity> districtBuildings
A persistent NativeListallocated with Allocator.Persistent. It is created in OnCreate and disposed in OnDestroy. Used as a container when enumerating district buildings (the current code uses temporary NativeArray results from the query rather than this list directly, but the list is allocated and cleared/reset by the section).
Properties
-
protected override string group => "EmployeesSection"
Returns the UI grouping identifier for this info section. Used by the base InfoSectionBase to identify the section. -
private int employeeCount { get; set; }
Accumulated number of employees found for the current selection (entity or district) during the latest update. -
private int maxEmployees { get; set; }
Accumulated maximum number of employee slots (workplaces) for the current selection (entity or district) during the latest update. -
private EmploymentData educationDataEmployees { get; set; }
Aggregated EmploymentData describing the education/skill distribution of current employees (used to present education levels in the UI). -
private EmploymentData educationDataWorkplaces { get; set; }
Aggregated EmploymentData describing the education/skill distribution of available workplace slots (used to compare supply vs demand). -
private NativeList<Entity> districtBuildings { get; set; }
Same as the field above; present as a property backing the NativeList allocation used by the section.
Constructors
public EmployeesSection()
Default constructor. Marked with [Preserve] in code for AOT/stripping reasons. Initialization of queries and NativeList is done in OnCreate rather than the constructor.
Methods
-
protected override void OnCreate()
Initializes the section. Builds m_DistrictBuildingQuery with All = Building, PrefabRef, CurrentDistrict; Any = Renter or Employee; None = Temp, Deleted. Allocates districtBuildings as a persistent NativeList. Marked with [Preserve]. -
protected override void OnDestroy()
Disposes the persistent NativeList (districtBuildings) and calls base.OnDestroy() to clean up other base resources. Marked with [Preserve]. -
protected override void Reset()
Resets accumulated counters and aggregated EmploymentData (employeeCount, maxEmployees, educationDataEmployees, educationDataWorkplaces) and clears the districtBuildings list. Called by the base to prepare the section for reuse between selections/updates. -
private bool Visible()
Determines whether the section should be visible for the current selection. If the selected entity is a District + Area, delegates to DisplayForDistrict(); otherwise uses HasEmployees(selectedEntity, selectedPrefab). The return value indicates whether the section is generally relevant (before also checking maxEmployees > 0 during OnUpdate). -
private bool HasEmployees(Entity entity, Entity prefab)
Checks whether the given entity (and its prefab if needed) should be considered an employee/workplace source. It considers: - If the entity has a Renter buffer and is not a Park, inspects renters to see if a renter entity has CompanyData + Employee + WorkProvider.
- If the Renter buffer is empty but the prefab has SpawnableBuildingData, uses the associated ZonePrefab to determine whether the area type is Commercial or Industrial (which counts as workplaces).
-
If the entity itself has Employee and WorkProvider components it is considered valid. Returns true if the entity/prefab contain employees or relevant workplaces.
-
private bool DisplayForDistrict()
Runs m_DistrictBuildingQuery to gather entities, their CurrentDistrict and PrefabRef component arrays, iterates them and returns true if any building that belongs to the selected district passes HasEmployees. Uses temporary NativeArray allocations and disposes them in a finally block. -
protected override void OnUpdate()
Primary per-frame update for the section. Sets base.visible = Visible(). If visible, runs AddEmployees() to accumulate counts and employment data, then sets base.visible = (maxEmployees > 0) so the section is only visible when there is some workplace capacity. -
protected override void OnProcess()
Empty override in this implementation; reserved for per-frame UI processing beyond update accumulation. -
private void AddEmployees()
Top-level logic to add employee/workplace data for the current selection. Adds "ServiceUsage" tooltip key if the selected entity has ServiceUsage component. If the selection is a District + Area, calls UpdateForDistricts() to scan district buildings; otherwise calls AddEmployees(entity) for the single selected entity. -
private void UpdateForDistricts()
Enumerates buildings using m_DistrictBuildingQuery (component arrays for CurrentDistrict and PrefabRef) and for each building in the selected district that HasEmployees, calls AddEmployees(entity). Uses temporary NativeArrays and ensures they are disposed. -
private void AddEmployees(Entity entity)
Core accumulation routine for a single building/entity. Steps: - Resolve the building prefab and the actual company entity (GetEntity) to inspect employees.
- Determine building level from SpawnableBuildingData (either from the building's prefab or from the property renter's property prefab if present).
- If the target entity (company or building) has an Employee DynamicBuffer and a WorkProvider, it:
- Adds the number of employees buffer.Length to employeeCount.
- Retrieves workplace complexity from the building prefab WorkplaceData and computes workplacesData via EmploymentData.GetWorkplacesData(maxWorkers, buildingLevel, complexity).
- Adds workplacesData.total to maxEmployees and aggregates educationDataWorkplaces.
- Computes and adds educationDataEmployees using EmploymentData.GetEmployeesData(buffer, workplacesData.total - buffer.Length) — the second parameter accounts for unfilled slots.
-
This method relies on the presence of components: PrefabRef, Employee buffer, WorkProvider, WorkplaceData and optional SpawnableBuildingData.
-
private Entity GetEntity(Entity entity)
If the entity is not a Park and has a Renter DynamicBuffer, iterates renters and returns the first renter Entity that has CompanyData (this is the company entity that actually holds employees). If no such renter/company is found, returns the original entity. -
public override void OnWriteProperties(IJsonWriter writer)
Writes collected properties to the provided JSON writer: "employeeCount", "maxEmployees", "educationDataEmployees", and "educationDataWorkplaces". This allows the UI JSON consumer to access the accumulated statistics.
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Create an EntityQuery that targets district buildings with renters or employees.
m_DistrictBuildingQuery = GetEntityQuery(new EntityQueryDesc
{
All = new ComponentType[3]
{
ComponentType.ReadOnly<Building>(),
ComponentType.ReadOnly<PrefabRef>(),
ComponentType.ReadOnly<CurrentDistrict>()
},
Any = new ComponentType[2]
{
ComponentType.ReadOnly<Renter>(),
ComponentType.ReadOnly<Employee>()
},
None = new ComponentType[2]
{
ComponentType.Exclude<Temp>(),
ComponentType.Exclude<Deleted>()
}
});
// Allocate persistent list for district buildings (disposed in OnDestroy).
districtBuildings = new NativeList<Entity>(Allocator.Persistent);
}
Notes and implementation remarks: - The class uses Unity.Entities EntityManager and ECS-style components extensively; it expects various game-specific components (Building, PrefabRef, CurrentDistrict, Renter, Employee, WorkProvider, WorkplaceData, SpawnableBuildingData, ZonePrefab, CompanyData, ServiceUsage, District, Area). - When enumerating query results, temporary NativeArray allocations are used and properly disposed in finally blocks to avoid leaking native memory. - EmploymentData aggregation relies on game types EmploymentData and WorkplaceComplexity to compute distributions; these types are combined via operator overloads (e.g., employmentDataWorkplaces += workplacesData). - The class uses [Preserve] on lifecycle methods/ctor to prevent code stripping for AOT builds.