Skip to content

Game.Simulation.ParkingFacilityAISystem

Assembly: Game
Namespace: Game.Simulation

Type: class

Base: GameSystemBase

Summary:
ParkingFacilityAISystem is an ECS system that updates ParkingFacility components on a periodic schedule. It uses a Burst-compiled IJobChunk (ParkingFacilityTickJob) to iterate matching building entities, combine installed upgrade stats with prefab data, compute the effective comfort factor (based on Efficiency buffers and prefab ParkingFacilityData), and flip the ParkingSpacesActive flag when needed. When a facility's active state or comfort factor changes the system marks related road/garage lanes and sub-objects with a PathfindUpdated component via an EndFrameBarrier command buffer so pathfinding can react to the change. The job runs in parallel and is designed for high-performance, thread-safe changes to sub-entities (lanes/subnets/subobjects).


Fields

  • private EndFrameBarrier m_EndFrameBarrier
    Used to create an EntityCommandBuffer.ParallelWriter which the job uses to add PathfindUpdated components to lanes/garage lanes. The barrier is also used to register the job handle (AddJobHandleForProducer) so changes are applied safely at the end of the frame.

  • private EntityQuery m_BuildingQuery
    Entity query used to select ParkingFacility entities to process. It reads Game.Buildings.ParkingFacility and excludes ServiceUpgrade, Temp and Deleted tags; RequireForUpdate is called with this query so the system only updates when matching entities exist.

  • private TypeHandle __TypeHandle
    Internal struct holding all Entity/Component/Buffer/Lookup type handles used by the chunk job. __TypeHandle.__AssignHandles(ref SystemState) is called in OnCreateForCompiler to set up these handles.

Properties

  • (none) This system has no public properties. All configuration is internal to the system and its job.

Constructors

  • public ParkingFacilityAISystem()
    Default constructor (marked with [Preserve] on the actual class). No custom construction logic beyond what GameSystemBase provides; initialization happens in OnCreate.

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns 256. This determines the interval (in ticks/frames as used by the game's system scheduler) between updates of this system.

  • public override int GetUpdateOffset(SystemUpdatePhase phase)
    Returns 192. This determines the offset for the update schedule so the system runs at a specific offset in the update cadence.

  • [Preserve] protected override void OnCreate()
    Initializes the EndFrameBarrier and builds the EntityQuery that selects ParkingFacility entities. Calls RequireForUpdate(m_BuildingQuery) so the system only runs when there are matching entities.

  • [Preserve] protected override void OnUpdate()
    Constructs and schedules a Burst-compiled ParkingFacilityTickJob using JobChunkExtensions.ScheduleParallel. The job receives component/buffer lookups and a parallel EntityCommandBuffer from m_EndFrameBarrier. The returned JobHandle is passed into m_EndFrameBarrier.AddJobHandleForProducer and stored in base.Dependency so the ECS world knows about the dependency.

  • protected override void OnCreateForCompiler()
    Internal helper to ensure queries and type handles are assigned when building for the Burst/job pipeline. It calls __AssignQueries and __TypeHandle.__AssignHandles.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] private void __AssignQueries(ref SystemState state)
    Compiler helper (no-op in this implementation; kept for generated-code compatibility).

  • Inner type: private struct ParkingFacilityTickJob : IJobChunk (BurstCompile)

  • Purpose: chunk job that iterates ParkingFacility entities and updates their state. It:
    • Reads PrefabRef, InstalledUpgrade buffers, Efficiency buffers, ParkingFacility component.
    • Uses PrefabRef -> ParkingFacilityData to obtain base prefab stats.
    • Calls UpgradeUtils.CombineStats to apply installed upgrades to the prefab data when present.
    • Computes the effective comfort factor: saturate(prefab.m_ComfortFactor * efficiency).
    • Compares new comfort factor and "parking spaces active" boolean with the stored values on the ParkingFacility component.
    • If changed, updates the ParkingFacility component and then traverses sub-objects/sub-nets/sub-lanes to add a PathfindUpdated component to parking lanes and non-virtual parking lanes and to garage lanes, using an EntityCommandBuffer.ParallelWriter so changes are safe from a job.
  • Notable methods inside job:
    • Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) Iterates entities in chunk, retrieves buffers and components, computes efficiency and calls Tick for each entity.
    • Tick(int jobIndex, Entity entity, ref ParkingFacility parkingFacility, ParkingFacilityData prefabParkingFacilityData, float efficiency) Applies logic to decide whether to flip flags and to update lanes when state changed.
    • UpdateParkingLanes overloads for DynamicBuffer, DynamicBuffer, DynamicBuffer Walks down sub-entity hierarchies (sub-objects -> sub-nets -> sub-lanes) and, for each lane:
      • If a ParkingLane component exists and is not a VirtualLane -> add PathfindUpdated component.
      • Else if a GarageLane component exists -> add PathfindUpdated component. Uses m_CommandBuffer.AddComponent(jobIndex, subLane, default(PathfindUpdated)) to queue the change.

Threading, safety and performance notes: - The job is Burst-compiled and scheduled with ScheduleParallel; care is taken to use ComponentLookup/BufferLookup and an EntityCommandBuffer.ParallelWriter so structural changes are deferred and safe. - The job relies on TryGetComponent / HasComponent on lookups and TryGetBuffer on buffer lookups — these are allowed inside jobs with the appropriate lookups. - The system sets its update interval (256) and offset (192) — meaning it does not run every frame. That reduces cost for relatively static building state.

Components / types referenced (summary): - Game.Buildings.ParkingFacility — per-entity runtime state (flags, comfort factor). - PrefabRef — reference to the building prefab entity which contains static data. - ParkingFacilityData (prefab) — contains base comfort factor and other prefab-level settings. - InstalledUpgrade[] (buffer) — per-building installed upgrade entries which modify prefab stats (via UpgradeUtils.CombineStats). - Efficiency[] (buffer) — used by BuildingUtils.GetEfficiency to compute effective operational efficiency. - Game.Net.ParkingLane / GarageLane — lane component types. ParkingLane has flags (ParkingLaneFlags.VirtualLane) checked to avoid virtual lanes. - Game.Net.SubLane / Game.Net.SubNet / Game.Objects.SubObject — buffers representing hierarchical children of an entity (used to locate lanes belonging to the facility). - PathfindUpdated — component added to lanes/garage lanes to indicate they should re-run pathfinding updates.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // Create or fetch the end-frame barrier used to get a safe parallel ECB for the job
    m_EndFrameBarrier = base.World.GetOrCreateSystemManaged<EndFrameBarrier>();

    // Select ParkingFacility entities and exclude upgrades/temp/deleted tags
    m_BuildingQuery = GetEntityQuery(
        ComponentType.ReadOnly<Game.Buildings.ParkingFacility>(),
        ComponentType.Exclude<Game.Buildings.ServiceUpgrade>(),
        ComponentType.Exclude<Temp>(),
        ComponentType.Exclude<Deleted>());

    RequireForUpdate(m_BuildingQuery);
}

Notes for modders: - If you add or change components used by this system (e.g., add new lane types or change ParkingFacilityData layout), ensure the job's lookups and logic are updated accordingly. - To observe or react to the PathfindUpdated signal, watch for that component on lane entities — the game uses it to trigger pathfinding recalculation. - Because the job runs with a non-trivial update interval/offset, changes to prefab data or installed upgrades may not be propagated instantly; the system is intentionally throttled for performance. If you need immediate updates in a mod, consider calling a manual refresh or creating a separate update path that forces immediate state refresh for specific entities.