Skip to content

Game.Objects.OutsideConnectionInitializeSystem

Assembly:
Namespace: Game.Objects

Type: class

Base: GameSystemBase, IPostDeserialize

Summary: Initializes localization indices for outside-connection prefabs (e.g., incoming/outgoing road/train/ship/air connections) in Cities: Skylines 2. This system: - Collects existing outside connections and remembers their transfer types, positions and chosen localization indices. - For newly created outside-connection entities, chooses a RandomLocalizationIndex either by reusing a nearby existing connection's index (when appropriate) or by generating new random indices according to the prefab's LocalizationCount buffer. - Runs its work using Burst-compiled IJobChunk jobs and Native containers for performance. - Implements a PostDeserialize upgrade path to backfill RandomLocalizationIndex for saved worlds from versions prior to Version.outsideConnNames.

Key behaviors: - Nearby reuse threshold: 10000f (squared distance — corresponds to ~100 units distance). - Uses RandomSeed.Next() to obtain randomness for index generation. - Uses ComponentLookup and BufferLookup to inspect prefab data (OutsideConnectionData, LocalizationCount).


Fields

  • private const float kNearbyMaxDistanceSqr = 10000f Defines the squared maximum distance for considering an existing outside connection "nearby" a new one (used when attempting to reuse localization indices from nearby connections).

  • private EntityQuery m_ExistingQuery Query selecting existing OutsideConnection entities that already have RandomLocalizationIndex (and are not Temp/Created) so their indices can be collected.

  • private EntityQuery m_CreatedQuery Query selecting newly created OutsideConnection entities (Created + OutsideConnection) that require localization initialization.

  • private TypeHandle __TypeHandle Holds cached ComponentTypeHandle / BufferTypeHandle / Lookup handles used when scheduling the chunk jobs. These are assigned during compiler-time helper methods (see __AssignHandles).

{{ Additional notes }} - The system also contains nested structs used as jobs and small helper structs (OutsideConnectionInfo, TypeHandle) declared as private types. - NativeList is used at runtime to temporarily collect connection info for nearest-index lookup; allocated with Allocator.TempJob and disposed after job completion.

Properties

  • This system exposes no public properties.

{{ YOUR_INFO }} - Internally it uses type handles and lookups assigned through __TypeHandle.__AssignHandles(ref SystemState) during system creation for efficient chunk access. Public surface is limited to the behavior of the system via ECS lifecycle methods.

Constructors

  • public OutsideConnectionInitializeSystem() Default constructor. The system uses [Preserve] attributes on lifecycle methods to ensure they are retained by stripping tools.

{{ YOUR_INFO }} - Construction is typical for ECS systems — you don't normally instantiate it manually; the game/world creates and manages it. Initialization of queries and requirement for update occurs in OnCreate.

Methods

  • protected override void OnCreate() : System.Void Sets up the EntityQuery instances:
  • m_ExistingQuery — OutsideConnection entities that already have RandomLocalizationIndex (exclude Temp/Created).
  • m_CreatedQuery — newly created OutsideConnection entities that need RandomLocalizationIndex assigned. Calls RequireForUpdate(m_CreatedQuery) so the system runs only when there are created outside connections.

{{ YOUR_INFO }} - This prepares the system to both collect existing connections and initialize new ones in OnUpdate.

  • protected override void OnUpdate() : System.Void Main runtime work:
  • Allocates a NativeList sized to hold existing + created entity counts.
  • Schedules a CollectOutsideConnectionsJob (parallel) on m_ExistingQuery to fill the list with info for existing connections.
  • Constructs and schedules InitializeLocalizationJob for m_CreatedQuery which:
    • For each created entity, if the prefab has LocalizationCount:
    • If prefab's localization buffer has length 1 and a nearby compatible existing connection exists, reuse that connection's RandomLocalizationIndex.
    • Otherwise, generate one or more random indices using RandomLocalizationIndex.GenerateRandomIndices with a Random obtained from RandomSeed.
    • If after generation indices.Length == 1, the new connection is also added to the shared NativeList so subsequent entities may reuse it.
  • Disposes the NativeList with the job dependency to ensure correct lifetime.

{{ YOUR_INFO }} - Uses InternalCompilerInterface to obtain component and buffer type handles from cached TypeHandle fields. - Jobs are scheduled with BurstCompile and use chunk-based iteration for performance.

  • public void PostDeserialize(Context context) : System.Void Upgrade/backfill logic executed after deserialization:
  • If the serialized context version is older than Version.outsideConnNames, finds OutsideConnection entities that are missing RandomLocalizationIndex.
  • Iterates these entities on the main thread: if their prefab has LocalizationCount buffer, will either reuse a nearby connection's index (when buffer.Length == 1 and nearby exists) or generate random indices.
  • Adds a RandomLocalizationIndex buffer to entities that need it and fills it accordingly.

{{ YOUR_INFO }} - This method ensures backwards compatibility by assigning localization indices to connections created before the game stored them explicitly in save data.

  • private static OutsideConnectionTransferType GetTransferType(Entity prefab, ref ComponentLookup<OutsideConnectionData> outsideConnectionData) : OutsideConnectionTransferType Returns the OutsideConnectionTransferType for the given prefab entity by looking up its OutsideConnectionData component. If the component is missing, returns OutsideConnectionTransferType.None.

{{ YOUR_INFO }} - This central helper is used by both jobs and PostDeserialize to determine which transfer types a prefab participates in (e.g., passengers, cargo, mail, etc.).

  • private static bool TryGetNearestConnectionRandomIndex(NativeList<OutsideConnectionInfo> connections, OutsideConnectionTransferType transferType, float3 position, out RandomLocalizationIndex randomIndex) : bool Searches the provided connections list for the nearest connection that has a transfer type compatible with the requested transferType. If a suitable connection is found within kNearbyMaxDistanceSqr, sets randomIndex to that connection's RandomLocalizationIndex and returns true. Otherwise returns false.

{{ YOUR_INFO }} - Uses squared distance comparison for performance (math.distancesq). - The compatibility check uses bitwise AND: (item.m_TransferType & transferType) != OutsideConnectionTransferType.None.

  • protected override void OnCreateForCompiler() : System.Void Compiler-time helper that calls __AssignQueries and __TypeHandle.__AssignHandles(ref SystemState) to initialize internal handles. Typically used by generated/compiled code paths.

{{ YOUR_INFO }} - Not part of regular runtime logic; used to satisfy codegen expectations in the project.

  • private void __AssignQueries(ref SystemState state) : System.Void Internal helper stub (present to satisfy generated code model). In this decompiled form it only calls new EntityQueryBuilder(Allocator.Temp).Dispose().

{{ YOUR_INFO }} - Present for codegen/compilation requirements.

Nested/Burst job structs (summarized):

  • CollectOutsideConnectionsJob : IJobChunk
  • Fields: ComponentTypeHandle (read-only), ComponentTypeHandle (read-only), BufferTypeHandle (read-only), ComponentLookup (read-only), NativeList.ParallelWriter m_OutsideConnections.
  • Execute: inspects chunks of existing outside-connection entities, and for each entity whose RandomLocalizationIndex buffer has length == 1, adds an OutsideConnectionInfo (transfer type, position, index) to m_OutsideConnections. Runs in parallel across chunks and is BurstCompiled.

{{ YOUR_INFO }} - This job collects candidate indices for reuse when initializing new connections.

  • InitializeLocalizationJob : IJobChunk
  • Fields: EntityTypeHandle (read-only), PrefabRef and Transform handles (read-only), RandomLocalizationIndex buffer handle (read-write), ComponentLookup (read-only), BufferLookup (read-only), NativeList (by value), RandomSeed m_RandomSeed.
  • Execute: for each created entity in the chunk tries to initialize its RandomLocalizationIndex buffer:
    • If prefab has LocalizationCount buffer:
    • If buffer.Length == 1 and TryGetNearestConnectionRandomIndex(...) found a nearby index within allowed range, reuse that index.
    • Otherwise generate new random indices using RandomLocalizationIndex.GenerateRandomIndices.
    • If indices.Length == 1, add the new connection to the m_OutsideConnections list so it may be reused by subsequent created entities processed later.

{{ YOUR_INFO }} - Uses per-entity Random derived from the provided RandomSeed to ensure deterministic randomness.

Usage Example

// The system is registered/created by the game ECS and runs automatically.
// Example illustrating the core idea performed in OnUpdate:

// 1) Collect existing outside connections (positions, transfer types, chosen indices)
var outsideConnections = new NativeList<OutsideConnectionInfo>(initialCapacity, Allocator.TempJob);
var collectJobHandle = JobChunkExtensions.ScheduleParallel(new CollectOutsideConnectionsJob {
    m_PrefabRefType = /* component type handle */,
    m_TransformType = /* component type handle */,
    m_RandomLocalizationIndexType = /* buffer type handle */,
    m_OutsideConnectionData = /* component lookup */,
    m_OutsideConnections = outsideConnections.AsParallelWriter()
}, existingQuery, dependency);

// 2) Initialize created outside connections using collected data
var initJob = new InitializeLocalizationJob {
    m_EntityType = /* entity handle */,
    m_PrefabRefType = /* component type handle */,
    m_TransformType = /* component type handle */,
    m_RandomLocalizationIndexType = /* buffer type handle (RW) */,
    m_OutsideConnectionData = /* lookup */,
    m_LocalizationCounts = /* buffer lookup on prefabs */,
    m_OutsideConnections = outsideConnections,
    m_RandomSeed = RandomSeed.Next()
};
dependency = JobChunkExtensions.Schedule(initJob, createdQuery, collectJobHandle);

// 3) Dispose temp list when jobs complete
outsideConnections.Dispose(dependency);

{{ YOUR_INFO }} - You normally don't call these jobs directly; the system's OnUpdate orchestrates them automatically when there are created outside connection entities. - The PostDeserialize method provides a main-thread fallback/upgrade path for older save versions that did not serialize connection names/indices.