Skip to content

Game.CountWorkplacesSystem

Assembly: Assembly-CSharp
Namespace: Game.Simulation

Type: class

Base: GameSystemBase, IDefaultSerializable, ISerializable

Summary:
Counts and aggregates workplace information across all relevant entities in the simulation. This system collects: - free workplaces reported by companies (FreeWorkplaces component), - total workplace capacity provided by buildings/companies (WorkProvider + WorkplaceData), while respecting property renting (PropertyRenter → uses the property's prefab/spawnable building level) and excluding outside connections, destroyed/deleted/temp entities. Work counts are accumulated using NativeAccumulator (parallel-safe) and produced every update step (scheduled as a parallel IJobChunk). The system also supports serialization/deserialization and a backward-compatibility fallback for older economy data versions.


Fields

  • private EntityQuery m_WorkplaceQuery
    Holds the entity query used to find all entities that should be considered when counting workplaces (requires WorkProvider and either PropertyRenter or Building; excludes OutsideConnection, Destroyed, Deleted, Temp).

  • private NativeAccumulator<Workplaces> m_FreeWorkplaces
    Parallel accumulator used to collect free workplaces reported by FreeWorkplaces components across chunks. Allocated with Allocator.Persistent and cleared each update after producing results.

  • private NativeAccumulator<Workplaces> m_TotalWorkplaces
    Parallel accumulator used to collect total workplace capacities computed from WorkProvider and WorkplaceData. Also Allocator.Persistent.

  • public Workplaces m_LastFreeWorkplaces
    Cached result produced from m_FreeWorkplaces.GetResult() during OnUpdate; represents last computed free workplaces per level.

  • public Workplaces m_LastTotalWorkplaces
    Cached result produced from m_TotalWorkplaces.GetResult() during OnUpdate; represents last computed total workplaces per level.

  • private TypeHandle __TypeHandle
    Internal struct containing EntityTypeHandle, ComponentTypeHandle and ComponentLookup handles used by the job; assigned in OnCreateForCompiler / __AssignHandles.

  • (nested) CountWorkplacesJob (private Burst-compiled struct implementing IJobChunk)
    Per-chunk job that:

  • accumulates FreeWorkplaces components into m_FreeWorkplaces,
  • iterates WorkProvider entities, resolves the prefab and possibly the property prefab to determine building level, reads WorkplaceData complexity, and computes number of workplaces using EconomyUtils.CalculateNumberOfWorkplaces, accumulating results into m_TotalWorkplaces.

  • (nested) TypeHandle (private struct)
    Holds the read-only type/lookup handles and exposes __AssignHandles to grab them from a SystemState.

Properties

  • None (the system exposes getters as methods rather than properties).

Constructors

  • public CountWorkplacesSystem()
    Default constructor (empty). The real initialization is done in OnCreate.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns 16. The system requests updates at this interval (i.e., effectively runs every 16 frames/steps based on engine scheduling).

  • public Workplaces GetFreeWorkplaces()
    Returns m_LastFreeWorkplaces (the last-computed free workplaces).

  • public Workplaces GetUnemployedWorkspaceByLevel()
    Returns a Workplaces value where each level i contains the cumulative sum of free workplaces from level 0 up to i (i.e., prefix sums of m_LastFreeWorkplaces). Useful for querying available jobs by level bracket.

  • public Workplaces GetTotalWorkplaces()
    Returns m_LastTotalWorkplaces (the last-computed total workplace capacities).

  • [Preserve] protected override void OnCreate()
    Initializes the entity query (requires WorkProvider and either PropertyRenter or Building; excludes OutsideConnection, Destroyed, Deleted, Temp), allocates the NativeAccumulator objects (persistent), and calls RequireForUpdate(m_WorkplaceQuery) so the system only runs when relevant entities exist. Also assigns other necessary initialization for the system.

  • [Preserve] protected override void OnDestroy()
    Disposes the NativeAccumulator instances and calls base.OnDestroy().

  • public void SetDefaults(Context context)
    Resets cached results to default Workplaces values and clears the accumulators.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Writes m_LastFreeWorkplaces and m_LastTotalWorkplaces into the serializer.

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader
    Reads back saved workplace data. If reader.context.version >= Version.economyFix it reads two Workplaces values into m_LastFreeWorkplaces and m_LastTotalWorkplaces. For older versions it reads an old format (an array of 5 ints) into a temporary NativeArray and discards it (compat fallback).

  • [Preserve] protected override void OnUpdate()
    Main scheduling method: grabs results from the accumulators (m_FreeWorkplaces.GetResult / m_TotalWorkplaces.GetResult), caches them into m_LastFreeWorkplaces and m_LastTotalWorkplaces, clears the accumulators, constructs CountWorkplacesJob with component handles and parallel writers, and schedules it via JobChunkExtensions.ScheduleParallel(jobData, m_WorkplaceQuery, base.Dependency). The job executes in parallel over matching chunks to accumulate fresh totals for the next update.

  • private void __AssignQueries(ref SystemState state)
    Compiler-generated helper (currently empty besides a temporary EntityQueryBuilder disposal).

  • protected override void OnCreateForCompiler()
    Compiler helper: calls __AssignQueries and __TypeHandle.__AssignHandles to prepare internal handles when the system is constructed by generated code.

  • (nested job) CountWorkplacesJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    Per-chunk logic:

  • If chunk has FreeWorkplaces components, it sums free counts for each entity and level and accumulates into m_FreeWorkplaces.
  • Iterates entities in the chunk with WorkProvider: obtains prefab via PrefabRef lookup, determines building level:
    • If entity has PropertyRenter: follows PropertyRenter.m_Property to its prefab and, if it has SpawnableBuildingData, uses that m_Level.
    • Otherwise, if it has Building and that building has m_RoadEdge == Entity.Null, it skips that entity.
  • Reads WorkplaceData for the resolved prefab and computes workplaces using EconomyUtils.CalculateNumberOfWorkplaces(maxWorkers, complexity, buildingLevel).
  • Accumulates computed workplaces into m_TotalWorkplaces.

Notes: job uses ComponentLookup for non-chunk components (PrefabRef, PropertyRenter, Building, SpawnableBuildingData, WorkplaceData) and ComponentTypeHandle for chunked components (FreeWorkplaces, WorkProvider).

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_WorkplaceQuery = GetEntityQuery(new EntityQueryDesc
    {
        All = new ComponentType[1] { ComponentType.ReadOnly<WorkProvider>() },
        Any = new ComponentType[2]
        {
            ComponentType.ReadOnly<PropertyRenter>(),
            ComponentType.ReadOnly<Building>()
        },
        None = new ComponentType[4]
        {
            ComponentType.ReadOnly<Game.Objects.OutsideConnection>(),
            ComponentType.ReadOnly<Destroyed>(),
            ComponentType.ReadOnly<Deleted>(),
            ComponentType.ReadOnly<Temp>()
        }
    });
    m_FreeWorkplaces = new NativeAccumulator<Workplaces>(Allocator.Persistent);
    m_TotalWorkplaces = new NativeAccumulator<Workplaces>(Allocator.Persistent);
    RequireForUpdate(m_WorkplaceQuery);
}

Additional tips: - The system uses NativeAccumulator with AsParallelWriter inside the job; ensure jobs are completed/queried via the system dependency to avoid race conditions. - Serialization expects the Workplaces struct layout compatible with current economy version; older saves use a 5-int format (handled in Deserialize). - GetUpdateInterval returns 16 — the system intentionally runs at a lower frequency than every frame to reduce cost. Adjust or respect this interval when interacting with its results.