Game.Simulation.TransportWatercraftAISystem
Assembly:
{{ This system is part of the game's simulation assembly used by Cities: Skylines 2. (Exact assembly name not present in the source file.) }}
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
{{ TransportWatercraftAISystem is a high-level simulation system that manages watercraft (ships/boats) AI behaviour each simulation tick. It queries for watercraft entities and executes a parallel IJobChunk (TransportWatercraftTickJob) to process vehicle state, routing, pathfinding requests, boarding/unboarding, dispatch handling, maintenance/refuel logic and interaction with transport routes and storage companies. The system integrates with PathfindSetupSystem to enqueue pathfind requests and uses an EndFrameBarrier command buffer to make structural changes. It also schedules boarding work via TransportBoardingHelpers. This system is central to making water-based public and cargo transport operate in the simulation loop. }}
Fields
-
private EndFrameBarrier m_EndFrameBarrier
{{ End-of-frame barrier system used to create a command buffer for structural changes (component add/remove, entity creation) safely from jobs. }} -
private SimulationSystem m_SimulationSystem
{{ Provides simulation-wide data such as the current frame index. Used for scheduling and timed checks (e.g., maintenance, departure frames). }} -
private PathfindSetupSystem m_PathfindSetupSystem
{{ Used to obtain a pathfinding queue writer to schedule pathfinding requests produced by watercraft. }} -
private CityStatisticsSystem m_CityStatisticsSystem
{{ Used when scheduling boarding tasks (for updating statistics upon boarding/completion). }} -
private AchievementTriggerSystem m_AchievementTriggerSystem
{{ Used for achievement/triggers related to boarding or transport events. }} -
private EntityQuery m_VehicleQuery
{{ Query used to select watercraft entities to process. The query requires watercraft current lane, owner, prefab ref, path owner and target, and either cargo or public transport components. }} -
private EntityArchetype m_TransportVehicleRequestArchetype
{{ Archetype used to create TransportVehicleRequest entities when vehicles need a target or dispatch. }} -
private EntityArchetype m_HandleRequestArchetype
{{ Archetype used to create HandleRequest events for notifying that a dispatch/handle has been processed. }} -
private TransportBoardingHelpers.BoardingLookupData m_BoardingLookupData
{{ Helper data used to accelerate boarding lookups and coordinate boarding tasks. }} -
private TypeHandle __TypeHandle
{{ Generated helper struct that caches Entity/ComponentType/Buffer handles for use inside jobs. See nested TypeHandle struct for details. }}
Properties
- {{ This system exposes no public properties in the provided source. Behaviour is controlled via lifecycle methods and the scheduled job. }}
Constructors
public TransportWatercraftAISystem()
{{ Default constructor. System initialization occurs in OnCreate; constructor simply calls base constructor via the generated preserve attribute. }}
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
{{ Returns 16. This controls the scheduling interval for running this system (likely every 16 simulation ticks). }} -
public override int GetUpdateOffset(SystemUpdatePhase phase)
{{ Returns 8. Combined with GetUpdateInterval, this sets the offset in the simulation frame when the system runs. }} -
[Preserve] protected override void OnCreate()
{{ System initialization: - Gets or creates references to EndFrameBarrier, SimulationSystem, PathfindSetupSystem, CityStatisticsSystem and AchievementTriggerSystem.
- Creates BoardingLookupData.
- Configures m_VehicleQuery to select watercraft entities.
- Creates entity archetypes used for transport requests and handle events.
-
Calls RequireForUpdate with the vehicle query (system runs only when there are matching entities). This is where the system registers all dependencies and prerequisites. }}
-
[Preserve] protected override void OnUpdate()
{{ Core scheduling logic: - Constructs a TransportBoardingHelpers.BoardingData helper (temp job allocator).
- Updates boarding lookup data.
- Creates and schedules a parallel TransportWatercraftTickJob that performs the per-vehicle AI tick work across matching chunks.
- Schedules boardingData tasks (boarding/unboarding updates) after the main job.
- Adds the pathfind queue writer to PathfindSetupSystem and registers the job handle with the EndFrameBarrier.
-
Updates base.Dependency with the combined job handle so the ECS scheduler can track dependencies. This method orchestrates the parallel processing of watercraft AI, path requests and boarding operations. }}
-
protected override void OnCreateForCompiler()
{{ Generated helper used by the runtime/compile pipeline to assign component handles and queries. It invokes __AssignQueries and the TypeHandle handle assignment. }} -
private void __AssignQueries(ref SystemState state)
{{ Compiler helper to set up any manual entity queries used for code generation. In this file it contains a placeholder new EntityQueryBuilder(Allocator.Temp).Dispose(); }} -
private struct TypeHandle
{{ Nested struct containing cached EntityTypeHandle, ComponentTypeHandles, ComponentLookup and BufferLookup instances. It has __AssignHandles(ref SystemState state) which initializes all type handles and lookups. This is used to pass handles into the job efficiently. }}
Nested job and job-related members
-
private struct TransportWatercraftTickJob : IJobChunk
{{ The main per-chunk parallel job. It processes watercraft entities in chunks and performs the per-vehicle Tick logic. The job holds many ComponentTypeHandle, BufferTypeHandle and ComponentLookup/BufferLookup fields to read/write components and buffers inside the job. }} -
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{{ Entry point called per chunk. It fetches arrays and buffers for the chunk, iterates entities in the chunk, calls VehicleUtils.CheckUnspawned to handle unspawned vehicles and invokes the Tick(...) method for each entity. After Tick returns, the job writes back modified component instances. }} -
private void Tick(int jobIndex, Entity vehicleEntity, Owner owner, PrefabRef prefabRef, CurrentRoute currentRoute, DynamicBuffer<WatercraftNavigationLane> navigationLanes, DynamicBuffer<Passenger> passengers, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref Watercraft watercraft, ref WatercraftCurrentLane currentLane, ref PathOwner pathOwner, ref Target target, ref Odometer odometer)
{{ Per-vehicle logic handling:- Path reset and resource checks.
- Maintenance / refueling checks using prefab vehicle data.
- Service dispatch processing and target request submission.
- Handling missing targets or failed paths (ReturnToDepot or deletion).
- Handling arrival at path end: boarding, selecting next dispatch, deleting vehicle if no further dispatch.
- Handling boarding state entry/exit and setting next waypoint targets.
- Navigation lane checks and skip-waypoint logic.
- Requesting paths when required. This method coordinates vehicle state transitions (EnRoute, Returning, Boarding, Arriving, RequiresMaintenance, etc.) and uses many helper methods below. }}
-
private void FindPathIfNeeded(Entity vehicleEntity, PrefabRef prefabRef, Entity skipWaypoint, ref WatercraftCurrentLane currentLane, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref PathOwner pathOwner, ref Target target)
{{ Prepares PathfindParameters based on WatercraftData and schedules a pathfind by creating a SetupQueueItem and pushing it to the pathfind queue. It sets PathFlags.Append when skipping a waypoint and handles stable/ignore-flow flags for route-sourced vehicles. }} -
private void CheckNavigationLanes(CurrentRoute currentRoute, DynamicBuffer<WatercraftNavigationLane> navigationLanes, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref WatercraftCurrentLane currentLane, ref PathOwner pathOwner, ref Target target, out Entity skipWaypoint)
{{ Examines navigation lane buffer for an EndOfPath flag. If found and certain conditions hold, it may:- Skip the current waypoint and append the next route waypoint into the path (setting PathFlags.Append).
- Or mark the vehicle as Arriving and adjust the final lane curve position (handles group-targets and fixed lanes). This logic helps vehicles transition from navigation lanes to route stops/waypoints. }}
-
private bool FindNextLane(ref Entity lane)
{{ Utility to find a next sub-lane connected from the given lane using owner/sub-lane buffers. Returns true and updates lane when a next sub-lane is found. }} -
private void ResetPath(Entity vehicleEntity, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref Watercraft watercraft, ref WatercraftCurrentLane currentLane, ref PathOwner pathOwner)
{{ Clears arriving flags, resets navigation path buffers (unless PathFlags.Append), and sets StayOnWaterway flag depending on returning/dummy state. Also resets path elements when appropriate. }} -
private void CheckDummyResources(int jobIndex, Entity vehicleEntity, PrefabRef prefabRef, DynamicBuffer<LoadingResources> loadingResources)
{{ For dummy (traffic/test) cargo vehicles: move requested LoadingResources into the vehicle's Resources buffer up to vehicle capacity, adjusting resource quantities and invoking QuantityUpdated afterwards. Clears the loadingResources buffer. }} -
private void SetNextWaypointTarget(CurrentRoute currentRoute, ref PathOwner pathOwnerData, ref Target targetData)
{{ Advances target to the next waypoint in the route (wraps around) and sets it as the new target in pathOwner/target. }} -
private void CheckServiceDispatches(Entity vehicleEntity, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport)
{{ Keeps at most one active service dispatch per vehicle for each transport type (public/cargo) and selects the highest-priority additional dispatch if present. Ensures internal request count limits. }} -
private void RequestTargetIfNeeded(int jobIndex, Entity entity, ref Game.Vehicles.PublicTransport publicTransport, ref Game.Vehicles.CargoTransport cargoTransport)
{{ When vehicles have no active target requests, this method occasionally (based on simulation frame & bitmasking) creates a TransportVehicleRequest entity to request service/dispatch. The created request uses the request archetype and a RequestGroup to group similar requests. }} -
private bool SelectNextDispatch(int jobIndex, Entity vehicleEntity, CurrentRoute currentRoute, DynamicBuffer<WatercraftNavigationLane> navigationLanes, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref Watercraft watercraft, ref WatercraftCurrentLane currentLane, ref PathOwner pathOwner, ref Target target)
{{ Processes pending service dispatches:- Removes handled dispatches when the vehicle is returning or dispatch counts exceed.
- Rejects dispatches that reference missing components.
- If the dispatch is a transport vehicle request, it assigns the CurrentRoute (if valid), appends the route vehicle to the route buffer and copies route color components to the vehicle for rendering batches.
- Creates HandleRequest event entities to mark the request handled.
- If the dispatch has appended path elements (PathElements buffer), it tries to append the path to the vehicle's path (PathUtils.TryAppendPath), adjusting PathElementTime and target accordingly.
- Clears returning flags and sets StayOnWaterway flags as appropriate. Returns true when a dispatch was successfully selected and applied. }}
-
private void ReturnToDepot(int jobIndex, Entity vehicleEntity, CurrentRoute currentRoute, Owner owner, DynamicBuffer<ServiceDispatch> serviceDispatches, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref PathOwner pathOwner, ref Target target)
{{ Clears dispatches, resets request counts and flags, removes the CurrentRoute component and sets the vehicle target to the owner's depot (owner.m_Owner). Marks vehicle as Returning. }} -
private bool StartBoarding(int jobIndex, Entity vehicleEntity, CurrentRoute currentRoute, PrefabRef prefabRef, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref Target target, bool isCargoVehicle)
{{ Attempts to start boarding when vehicle is at a stop:- If the stop is connected to a boarding vehicle component, prepare boarding via TransportBoardingHelpers.BoardingData.BeginBoarding, handling refuel capability, maintenance state and selecting next storage company for cargo vehicles.
- If the stop is a normal route waypoint, mark RouteSource and return false (boarding not started).
- If neither a stop nor waypoint, clear EnRoute/AbandonRoute flags and remove CurrentRoute. Returns true when boarding has been started. }}
-
private bool StopBoarding(int jobIndex, Entity vehicleEntity, CurrentRoute currentRoute, DynamicBuffer<Passenger> passengers, ref Game.Vehicles.CargoTransport cargoTransport, ref Game.Vehicles.PublicTransport publicTransport, ref Target target, ref Odometer odometer, bool isCargoVehicle, bool forcedStop)
{{ Attempts to end boarding:- Performs checks for forcedStop, passenger readiness and departure frames.
- Updates odometer if refueling, posts quantity/passenger updates, invokes TransportBoardingHelpers.BoardingData.EndBoarding when the vehicle is the current boarding vehicle at the stop.
- Clears boarding/refueling flags when applicable. Returns true when boarding ended (or was appropriately handled). }}
-
private void QuantityUpdated(int jobIndex, Entity vehicleEntity)
{{ Adds an Updated component to the vehicle via the command buffer to notify other systems that the vehicle's cargo quantity changed. }} -
private void PassengersUpdated(int jobIndex, Entity vehicleEntity)
{{ Adds BatchesUpdated component via the command buffer to notify relevant systems that passenger batches changed. }} -
private Entity GetTransportStationFromStop(Entity stop)
{{ Traverses owner chain upward from a stop to find the transport station entity; returns Entity.Null if not found. }} -
private Entity GetStorageCompanyFromStop(Entity stop)
{{ Traverses owner chain upward from a stop to find the storage company owning that stop; returns Entity.Null if not found. }} -
private Entity GetNextStorageCompany(Entity route, Entity currentWaypoint)
{{ Iterates waypoints on the given route after currentWaypoint to find the next waypoint connected to a storage company and returns it, or Entity.Null if none found. }} -
void IJobChunk.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{{ Explicit interface implementation that forwards to the strongly-typed Execute method above. }}
Usage Example
// Example: retrieve the system in a mod and ensure it exists, then force a dependency update
var world = Unity.Entities.World.DefaultGameObjectInjectionWorld;
var transportSystem = world.GetOrCreateSystemManaged<Game.Simulation.TransportWatercraftAISystem>();
// You typically don't call OnUpdate() directly. Instead let the ECS scheduler run systems.
// But you can get system information or ensure the system is created as shown.
{{ Notes for modders: - TransportWatercraftAISystem is responsible for scheduling pathfinding requests using PathfindSetupSystem. If your mod manipulates path queues, ensure you coordinate with PathfindSetupSystem to avoid conflicting writers. - To alter vehicle behavior, modify components used by the system (CurrentRoute, Target, PathOwner, WatercraftCurrentLane, CargoTransport/PublicTransport, Watercraft, etc.) or intercept/produce TransportVehicleRequest and HandleRequest events. - Boarding flow is coordinated through TransportBoardingHelpers types — use those helpers if you need to interact with boarding logic. - Many internal flags are bitmasks (CargoTransportFlags, PublicTransportFlags, PathFlags, WatercraftLaneFlags). Use them when changing vehicle state to match engine expectations. - Because the core per-vehicle logic runs in a parallel job, structural changes (add/remove components, create/delete entities) are done via the EndFrameBarrier command buffer. Mods that create/remove components on these vehicles from main thread should be careful about race conditions with this system. }}