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 = 10000fDefines 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_ExistingQueryQuery selecting existing OutsideConnection entities that already have RandomLocalizationIndex (and are not Temp/Created) so their indices can be collected. -
private EntityQuery m_CreatedQueryQuery selecting newly created OutsideConnection entities (Created + OutsideConnection) that require localization initialization. -
private TypeHandle __TypeHandleHolds 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.VoidSets 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.VoidMain 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.VoidUpgrade/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) : OutsideConnectionTransferTypeReturns 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) : boolSearches 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.VoidCompiler-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.VoidInternal 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.