Skip to content

Game.Simulation.CityServiceStatisticsSystem

Assembly:
Assembly-CSharp

Namespace:
Game.Simulation

Type:
class

Base:
GameSystemBase

Summary:
CityServiceStatisticsSystem is a simulation system that aggregates city service worker statistics every so often and pushes them into the CityStatisticsSystem. It scans entities that provide work (WorkProvider) and have employee buffers (Employee) and CityServiceUpkeep, grouped by their prefab's service type. For each service it counts actual workers and maximum worker capacity, then enqueues StatisticsEvent entries (CityServiceWorkers and CityServiceMaxWorkers) into the CityStatisticsSystem's event queue. The main per-chunk work is done in a Burst-compiled IJobChunk (ProcessCityServiceStatisticsJob) and is scheduled as a parallel job filtered by an UpdateFrame shared component so only chunks for the current update frame are processed.


Fields

  • private EntityQuery m_CityServiceGroup
    Used to select entities that will be processed. The query requires ReadOnly WorkProvider, a ReadOnly Employee buffer, ReadOnly CityServiceUpkeep and ReadOnly UpdateFrame.

  • private SimulationSystem m_SimulationSystem
    Reference to the simulation system from which a frameIndex is read to compute the update frame.

  • private CityStatisticsSystem m_CityStatisticsSystem
    Reference to the system that collects city statistics; used to obtain and write to the statistics event queue.

  • private TypeHandle __TypeHandle
    Helper struct that caches component/buffer/lookups handles (WorkProvider, Employee buffer, PrefabRef, ServiceObjectData, ServiceData). Assigned via __AssignHandles.

  • (nested) ProcessCityServiceStatisticsJob (private, BurstCompile, IJobChunk)
    Job-local fields:

  • [ReadOnly] public ComponentTypeHandle<WorkProvider> m_WorkProviderType
  • [ReadOnly] public ComponentTypeHandle<PrefabRef> m_PrefabType
  • [ReadOnly] public BufferTypeHandle<Employee> m_EmployeeType
  • [ReadOnly] public SharedComponentTypeHandle<UpdateFrame> m_UpdateFrameType
  • [ReadOnly] public ComponentLookup<ServiceObjectData> m_ServiceObjectDatas
  • [ReadOnly] public ComponentLookup<ServiceData> m_ServiceDatas
  • public uint m_UpdateFrameIndex
  • public NativeQueue<StatisticsEvent>.ParallelWriter m_StatisticsEventQueue
    Description: For matching chunks (by UpdateFrame), the job iterates entities in the chunk, uses prefab -> ServiceObjectData -> ServiceData to map objects to a service index, accumulates per-service counts: number of providers, total max workers, and actual employee count (buffer length). It uses temporary NativeArray of length 14 to accumulate per-service values and then enqueues one or two StatisticsEvent entries per service that had providers.

Properties

  • None (no public properties are declared on this system).

Constructors

  • public CityServiceStatisticsSystem()
    Default constructor. Marked with [Preserve] on methods like OnCreate; constructor is empty in the compiled code.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns 512. The system should run at an interval determined by this value (system-specific scheduling within the game's simulation pipeline).

  • [Preserve] protected override void OnCreate()
    Initializes the system:

  • Creates m_CityServiceGroup entity query requiring WorkProvider, Employee buffer, CityServiceUpkeep and UpdateFrame.
  • Acquires references to SimulationSystem and CityStatisticsSystem via World.GetOrCreateSystemManaged(). This sets up the system to be able to schedule the chunk job and write stats.

  • [Preserve] protected override void OnUpdate()
    Schedules the Burst-compiled ProcessCityServiceStatisticsJob as a parallel IJobChunk:

  • Computes updateFrame (SimulationUtils.GetUpdateFrame(..., 32, 16)) to select which shared UpdateFrame to process this tick.
  • Prepares component/buffer/lookup type handles from cached __TypeHandle via InternalCompilerInterface.Get* helpers and GetSharedComponentTypeHandle.
  • Obtains a StatisticsEvent queue from CityStatisticsSystem (GetStatisticsEventQueue) and uses AsParallelWriter() to feed it from multiple threads.
  • Schedules the job over m_CityServiceGroup with JobChunkExtensions.ScheduleParallel and combines dependencies.
  • Registers the system as a writer with CityStatisticsSystem.AddWriter(base.Dependency) to ensure proper synchronization.

  • private void __AssignQueries(ref SystemState state)
    Compiler helper in generated code. Currently creates an EntityQueryBuilder (temporary) and disposes it. In OnCreateForCompiler this is invoked to ensure queries get assigned in code-gen scenarios.

  • protected override void OnCreateForCompiler()
    Compiler helper called to assign cached type handles and queries for the Ahead-Of-Time compiled version. Calls __AssignQueries and __TypeHandle.__AssignHandles.

  • (nested) TypeHandle.__AssignHandles(ref SystemState state)
    Assigns the ComponentTypeHandle/BufferTypeHandle/ComponentLookup fields used by the job by calling state.GetComponentTypeHandle/GetBufferTypeHandle/GetComponentLookup. This must be called before using the TypeHandle to acquire handles in jobs.

  • (nested) ProcessCityServiceStatisticsJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    Core per-chunk worker:

  • Checks the chunk's UpdateFrame shared component index against m_UpdateFrameIndex; returns early if it doesn't match.
  • Reads WorkProvider array, PrefabRef array, and Employee buffers from the chunk.
  • Uses ComponentLookup to map prefab -> ServiceObjectData and then ComponentLookup to map to a service index.
  • Uses three temporary NativeArray (length 14) to accumulate per-service: current worker count, total max workers, and provider count.
  • After processing entities in the chunk, for each service that had providers, enqueues two StatisticsEvent objects (one for CityServiceWorkers with actual worker count, and one for CityServiceMaxWorkers with max worker capacity) with m_Parameter set to the service index.

Notes on implementation details: - The job is Burst-compiled and scheduled in parallel. - The job uses temporary NativeArray allocations per chunk (Allocator.Temp) sized to 14 — the service types count is implied to be 14. - The UpdateFrame mechanism ensures only entities belonging to the computed update frame are processed, reducing duplicate processing across frames.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // typical initialization performed by the system (same as in the game's implementation)
    m_CityServiceGroup = GetEntityQuery(new EntityQueryDesc
    {
        All = new ComponentType[]
        {
            ComponentType.ReadOnly<WorkProvider>(),
            ComponentType.ReadOnly<Employee>(),
            ComponentType.ReadOnly<CityServiceUpkeep>(),
            ComponentType.ReadOnly<UpdateFrame>()
        }
    });
    m_SimulationSystem = World.GetOrCreateSystemManaged<SimulationSystem>();
    m_CityStatisticsSystem = World.GetOrCreateSystemManaged<CityStatisticsSystem>();
}

Additional notes: - If you want to extend or debug this system in a mod, be careful with the UpdateFrame/sharing and the expected service count (14). You can intercept or read the CityStatisticsSystem's event queue to observe the generated StatisticsEvent entries. The job expects PrefabRef -> ServiceObjectData -> ServiceData to be present for service objects; entities missing these mappings are ignored.