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
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.