Skip to content

Game.Tools.ApplyObjectsSystem

Assembly: Assembly-CSharp (game)
Namespace: Game.Tools

Type: class ApplyObjectsSystem

Base: GameSystemBase

Summary:
ApplyObjectsSystem is an ECS System used by the game to commit temporary (preview/placement/upgrade) entities into their final/original entities. It processes entities carrying the Temp component and coordinates creation, deletion, updates, ownership transfers and buffer updates. The system uses two Burst-compiled IJobChunk jobs (PatchTempReferencesJob and HandleTempEntitiesJob) to operate in parallel over chunks, and it coordinates with other game systems (tool barrier, trigger system, instance-count system and simulation) via command buffers, trigger queues and job dependencies. This is a core system for applying tool actions (place / upgrade / delete objects) in Cities: Skylines 2 modding.


Fields

  • private ToolOutputBarrier m_ToolOutputBarrier
    Holds the barrier used to obtain a command buffer that queues structural changes back to the main entity manager in a thread-safe manner.

  • private ToolSystem m_ToolSystem
    Reference to the tool system that provides context about current tool/action (for example whether the editor mode is active).

  • private SimulationSystem m_SimulationSystem
    Reference to the simulation system used to get the current simulation frame index.

  • private TriggerSystem m_TriggerSystem
    Reference to the trigger system which collects TriggerAction events (ObjectCreated etc.). A NativeQueue is created and either forwarded to this system or disposed.

  • private InstanceCountSystem m_InstanceCountSystem
    Used to obtain instance counts for prefabs (used when enqueueing trigger actions about created objects).

  • private EntityQuery m_TempQuery
    EntityQuery that selects Temp objects (and related Object component) which this system will operate on. Required for update.

  • private EntityQuery m_EconomyParameterQuery
    EntityQuery used to access economy parameters (EconomyParameterData singleton).

  • private EntityArchetype m_PathTargetEventArchetype
    Archetype used to create PathTargetMoved events when path targets (buildings/transport stops) move.

  • private ComponentTypeSet m_AppliedTypes
    Set of component types used to mark an entity as Applied/Created/Updated when a Temp is committed.

  • private ComponentTypeSet m_TempAnimationTypes
    Set of component types related to temp animations (Temp, Animation, BackSide) that are removed when committing an entity.

  • private TypeHandle __TypeHandle
    Internal struct containing cached ComponentTypeHandle / BufferLookup / ComponentLookup handles used when scheduling jobs. Populated by __AssignHandles.

  • private struct PatchTempReferencesJob (nested)
    Burst IJobChunk that scans Temp+Attached+Owner combinations to patch references when temps reference other temps or originals were replaced, and it updates buffers (subobjects, owned vehicles/creatures) to reflect owner changes or removals.

  • private struct HandleTempEntitiesJob (nested)
    Burst IJobChunk that performs main work to commit Temp entities: handles cancellations, deletions, fix parking locations, copy components to originals when prefab references exist, create new entities for temps that become applied, update components and buffers on originals, enqueue triggers for created instances, add Updated/Deleted/SaveInstance markers, and schedule path-target moved events. Contains many helper methods used from job context.

  • private struct TypeHandle (nested)
    Holds all ComponentTypeHandle, ComponentLookup and BufferLookup handles used by the nested jobs and provides __AssignHandles to cache them from a SystemState.

Properties

  • (none public)

Constructors

  • public ApplyObjectsSystem()
    Default constructor generated and preserved for runtime. The actual initialization of queries, archetypes and cached type sets happens in OnCreate.

Methods

  • protected override void OnCreate()
    Initializes references to other systems (ToolOutputBarrier, ToolSystem, SimulationSystem, TriggerSystem, InstanceCountSystem), creates queries (m_TempQuery, m_EconomyParameterQuery), creates event archetype (m_PathTargetEventArchetype), sets up component type sets (m_AppliedTypes, m_TempAnimationTypes) and calls RequireForUpdate for needed queries so the system only runs when temps exist and economy parameters are available.

  • protected override void OnUpdate()
    Main scheduling logic. Prepares a PatchTempReferencesJob and a HandleTempEntitiesJob with all required ComponentTypeHandles/Lookups and other runtime data (simulation frame, economy parameters, editor mode flag, instance counts). Schedules PatchTempReferencesJob (implicitly by the job pipeline) and schedules HandleTempEntitiesJob in parallel across m_TempQuery. It creates a NativeQueue (either via the TriggerSystem or a TempJob queue) and wires up the ToolOutputBarrier command buffer as a ParallelWriter. It adds job handles to the ToolOutputBarrier, TriggerSystem (if enabled), and InstanceCountSystem, and stores the job handle in base.Dependency.

  • private void __AssignQueries(ref SystemState state)
    Called from OnCreateForCompiler to set up any queries used by the generated compiler path. (In this implementation it constructs a temporary EntityQueryBuilder and disposes it; type handle assignment is performed separately.)

  • protected override void OnCreateForCompiler()
    Compiler-time initialization path that calls __AssignQueries and populates type handles via __TypeHandle.__AssignHandles.

  • private void __AssignHandles(ref SystemState state) (on TypeHandle)
    Caches all required EntityTypeHandle, ComponentTypeHandle, ComponentLookup and BufferLookup instances from the provided SystemState for efficient reuse when scheduling jobs.

  • Nested job methods (summarized):

  • PatchTempReferencesJob.Execute(in ArchetypeChunk chunk, ...)
    Iterates chunk entities and:
    • For attached sub-objects: ensures the SubObjects buffers of parents are updated if a parent changed due to temp/original mapping, removing stale entries.
    • For owners: updates Owner components to point to the correct owner (original entity instead of temp) and updates the owning buffers (OwnedVehicle, OwnedCreature or SubObjects) removing from old owner and adding to new one.
  • HandleTempEntitiesJob.Execute(in ArchetypeChunk chunk, ...)
    For each temp entity:

    • If Cancel flag present: calls Cancel() to remove Hidden/mark BatchesUpdated and delete the temp.
    • If Delete flag: calls Delete() which marks the original Deleted and removes ownership/owner components from related subnets if needed, and deletes the temp.
    • If temp.m_Original has a PrefabRef (replacing an existing original): handle upgrades (copy components, reset Destroyed/Damaged flags, copy buffers like MeshColors), update elevation/local transform cache/subnets/subareas/sub-lanes/sub-objects and remove old sub items as needed, call Update() (which marks Updated/Recent/SaveInstance) and CopyToOriginal for attached data.
    • If no PrefabRef: Create() is called which removes temp animation components, possibly removes InterpolatedTransform for static objects, adds Recent if cost > 0, and adds m_AppliedTypes marking the entity applied.
    • FixParkingLocation() is called for parked cars/trains that change prefab to ensure parking location is consistent.
    • When transforms change, Update(temp.m_Original, ...) sets the original Transform, marks lane flags as Obsolete for moving entities (vehicles/creatures), adds Moving and creates PathTargetMoved events for buildings/transport stops.
    • UpdateComponent and UpdateBuffer helpers are used to reflect components/buffer elements from temp entity to original (either set, add or remove components/buffers on original) depending on whether the temp has the component and whether updateValue is requested.
    • RemoveOldSubItems removes created sub-lanes/sub-objects that are owned by the original if they are not present in the new buffers.
    • ShouldSaveInstance determines whether the original should receive a SaveInstance tag when in editor mode (based on owner/installed-upgrades buffers). All structural changes are performed via the EntityCommandBuffer.ParallelWriter (m_CommandBuffer) and trigger enqueueing uses m_TriggerBuffer.
  • Many private helper methods inside HandleTempEntitiesJob:

  • FixParkingLocation, RemoveOldSubItems (two overloads), Cancel, Delete, UpdateComponent, UpdateBuffer, Update (two overloads), CopyToOriginal, Create, ShouldSaveInstance. These encapsulate logic for parking fixes, creating deletion markers, copying and synchronizing component and buffer data between temp and original entities, marking modification costs (Recent component), and producing appropriate event markers (Updated, Deleted, SaveInstance, PathTargetMoved, etc.).

Usage Example

// Typical usage comes from the game systems infrastructure. As a modder you can obtain
// the system instance (read-only or to query its state) like this:

var world = World.DefaultGameObjectInjectionWorld; // or your mod's ECS world
var applySystem = world.GetExistingSystemManaged<Game.Tools.ApplyObjectsSystem>();

// The system runs automatically when Temp entities are present.
// If you need to trigger logic that creates Temp entities, do it via
// the ToolSystem and command buffers provided by the game.
//
// Example: ensure the system will run (it requires Temp entities and Economy parameters)
if (applySystem != null) {
    // You generally don't call OnUpdate manually — the ECS scheduler runs it.
    // To observe changes, schedule jobs that depend on the system's Dependency or
    // add readers to ToolOutputBarrier/InstanceCountSystem as done by the system itself.
}

Note: This system is tightly integrated with game-specific components (Temp, Attached, PrefabRef, Owner, parking-related components, etc.) and with the game's event/trigger systems. When modding, prefer using or interacting with the public ToolSystem / TriggerSystem APIs rather than modifying this system directly. If you override or replace behavior, ensure to respect the EntityCommandBuffer and job dependency patterns used here to avoid race conditions.