Skip to content

Game.Tools.NetToolSystem

Assembly: Assembly-CSharp
Namespace: Game.Tools

Type: public class

Base: ToolBaseSystem

Summary:
NetToolSystem is the in-game tool/controller that implements building/placing/upgrading/replacing "nets" (roads, rails, pipes, lanes, etc.) in Cities: Skylines 2. It manages input actions, snapping logic, control point handling, creation definition generation (via ECS CreationDefinition/NetCourse objects), upgrade/replace workflows, and coordinates with Unity ECS jobs (Burst jobs) for heavy geometry and search work (snap search trees, parallel jobs, surface/height readers). The system exposes UI modes (Straight, SimpleCurve, ComplexCurve, Continuous, Grid, Replace, Point), persistent per-prefab tool preferences, and supports editor vs. game mode behavior (including lane containers and service upgrades).


Nested types (important)

  • public enum Mode
  • Straight, SimpleCurve, ComplexCurve, Continuous, Grid, Replace, Point — tool placement modes.

  • private class NetToolPreferences

  • Stores per-prefab-group preferences (mode, snap, elevation, elevationStep, parallel settings, underground) and has Save/Load helpers.

  • private enum State

  • Default, Applying, Cancelling — internal state for apply/cancel workflow (especially for Replace mode).

  • public struct UpgradeState

  • Holds per-upgrade state used during replace/upgrade flows (flags, subreplacement info, prefab reference).

  • public struct PathEdge

  • Used by CreatePath to represent a path element: entity, invert, upgrade flag.

  • public struct PathItem : ILessThan<PathItem>

  • Helper for Dijkstra-like pathfinding used by CreatePath (contains node/edge/cost).

  • Job structs (Burst-compiled):

  • SnapJob : IJob — snap/search logic; queries search trees and computes best snap positions and snap lines, writes to native lists.
  • FixControlPointsJob : IJob — fixes control points after temp/entity updates.
  • CreateDefinitionsJob : IJob — turns control points & upgrade states into ECS CreationDefinition + NetCourse entities (the final "definitions" that the output barrier will turn into actual creations).

Fields

  • private Mode m_Mode
    Current user-selected mode (backing field for property mode).

  • private float m_Elevation
    Current elevation offset for placement.

  • private float m_ElevationStep
    Step amount used when elevating via mouse/keyboard.

  • private int m_ParallelCount
    Number of parallel lanes/courses requested.

  • private float m_ParallelOffset
    Offset used for parallel course generation.

  • private bool m_Underground
    Whether underground replace mode is selected (Replace mode only).

  • private Snap m_SelectedSnap
    Currently selected snapping mask.

  • private ToolOutputBarrier m_ToolOutputBarrier
    ECS barrier used to emit creation definitions.

  • private TerrainSystem m_TerrainSystem
    Terrain system reference (height reading).

  • private WaterSystem m_WaterSystem
    Water system reference (surface/velocity reading).

  • private Game.Net.SearchSystem m_NetSearchSystem
    Search tree for nets (used by snapping).

  • private Game.Objects.SearchSystem m_ObjectSearchSystem
    Static object search tree.

  • private Game.Zones.SearchSystem m_ZoneSearchSystem
    Zone search tree (lot/grid snapping).

  • private CityConfigurationSystem m_CityConfigurationSystem
    City settings (left-hand traffic etc).

  • private AudioManager m_AudioManager
    For UI/feedback sounds.

  • private NetInitializeSystem m_NetInitializeSystem
    Helper that knows net relationships/replace-ability.

  • EntityQuery fields: m_DefinitionQuery, m_TempQuery, m_EdgeQuery, m_NodeQuery, m_SoundQuery, m_ContainerQuery

  • Various queries used to determine existing temp/definition state and to detect whether apply is allowed.

  • Input action proxies: m_DowngradeNetEdge, m_PlaceNetControlPoint, m_PlaceNetEdge, m_PlaceNetNode, m_ReplaceNetEdge, m_UndoNetControlPoint, m_UpgradeNetEdge, m_DiscardUpgrade, m_DiscardDowngrade, m_DiscardReplace

  • Bound to configured key/mouse actions.

  • State and control data:

  • private bool m_ApplyBlocked — apply/cancel blocking flag.
  • private NativeList<ControlPoint> m_ControlPoints — the live control points for the current placement/replace action (NativeList used by jobs).
  • private NativeList<SnapLine> m_SnapLines — produced lines for guide/snap visualization.
  • private NativeList<UpgradeState> m_UpgradeStates — upgrade states for replace flows.
  • private NativeReference<Entity> m_StartEntity — used by Snap job to track start entity for continuous snapping.
  • private NativeReference<Entity> m_LastSnappedEntity — last snapped entity for sound / logic decisions.
  • private NativeReference<int> m_LastControlPointsAngle — last angle used for snap-sounds.
  • private NativeReference<AppliedUpgrade> m_AppliedUpgrade — temporary applied-upgrade data used when applying replace/upgrade.
  • plus various other helper fields: m_LastRaycastPoint, m_ApplyStartPoint, m_State, m_RandomSeed, preferences dictionaries, type handles.

(There are many other private/internal fields in the source; above are the most relevant for modders.)


Properties

  • public override string toolID => "Net Tool"
    Identifier of the tool.

  • public override int uiModeIndex => (int)actualMode
    UI mode index mapped from actualMode.

  • public Mode mode { get; set; }
    Selected mode (setter triggers SaveToolPreferences and marks tool update).

  • public Mode actualMode { get; }
    Effective mode: enforces upgrade-only, disables Grid/Replace when not allowed, or flips Point mode out of game mode.

  • public float elevation { get; set; }
    Placement elevation (setter saves preferences and forces update).

  • public float elevationStep { get; set; }
    Elevation step used for mouse dragging/keyboard.

  • public int parallelCount { get; set; }
    Number of parallel courses requested (setter saves preferences).

  • public int actualParallelCount { get; }
    Returns effective parallel count (respects allowParallel/allowGrid).

  • public float parallelOffset { get; set; }
    Offset between parallel courses.

  • public bool underground { get; set; }
    Underground flag (used for Replace mode).

  • public override bool allowUnderground { get; }
    Overrides to permit underground only while Replace and if allowed for selected prefab.

  • public override Snap selectedSnap { get; set; }
    Current Snap selection; setter saves preferences and forces update.

  • public NetPrefab prefab { get; set; }
    Selected net prefab (setter updates internal flags such as allowParallel, allowReplace, upgradeOnly; calls LoadToolPreferences and fires EventPrefabChanged).

  • public NetLanePrefab lane { get; set; }
    When operating on a lane container (editor mode), selected lane prefab.

  • public bool upgradeOnly { get; private set; }
    True if current prefab is upgrade-only.

  • public bool allowParallel { get; private set; }
    True if parallel placement allowed for selected prefab.

  • public bool allowGrid { get; private set; }
    True if grid mode is allowed.

  • public bool allowReplace { get; private set; }
    True if replace mode allowed for the selected prefab.

  • public bool serviceUpgrade { get; private set; }
    True if prefab is a service upgrade.

  • private protected override IEnumerable<IProxyAction> toolActions
    Returns the input actions bound to the tool.


Constructors

  • public NetToolSystem()
    Default ctor. The system is initialized by the ECS world lifecycle; important initialization occurs in OnCreate.

Methods

  • protected override void OnCreate()
    Initialize system references, NativeLists/NativeReferences, input actions, default preferences. Creates / gets required subsystems (TerrainSystem, WaterSystem, SearchSystems) and initial setup.

  • protected override void OnDestroy()
    Dispose NativeLists / NativeReferences and cleanup.

  • protected override void OnStartRunning()
    Clears state when the system starts running (reset control points, flags, apply state, random seed, etc).

  • protected override void OnGamePreload(Purpose purpose, GameMode mode)
    Called prior to game load; resets per-pref settings.

  • private protected override void UpdateActions()
    Updates enabled/disabled state of tool input actions based on actualMode, current control point count, Replace-specific state machine, and whether apply is allowed.

  • public override void GetUIModes(List<ToolMode> modes)
    Adds available UI modes (and hides modes that are not allowed).

  • public override PrefabBase GetPrefab()
    Returns selected prefab or lane container prefab when in lane mode/editor.

  • public override bool TrySetPrefab(PrefabBase prefab)
    Set tool prefab from a generic PrefabBase (NetPrefab or NetLanePrefab).

  • public override void InitializeRaycast()
    Configures the tool raycast system per current prefab/mode/elevation/snap masks. This affects what types (Terrain, Water, Net, StaticObjects) will be raycasted and which layers/masks used.

  • public override void ElevationUp() / ElevationDown() / ElevationScroll()
    Adjust elevation and handle switching between overground/underground prefab variants when required by PlaceableNetData.

  • public override void SetUnderground(bool underground)
    Only allows toggling underground in Replace mode.

  • public override void GetAvailableSnapMask(out Snap onMask, out Snap offMask)
    Public wrapper that calls static helper to compute which snap options are available for current prefab/mode/editor flags.

  • private static void GetAvailableSnapMask(NetGeometryData prefabGeometryData, PlaceableNetData placeableNetData, Mode mode, bool editorMode, bool laneContainer, bool underground, out Snap onMask, out Snap offMask)
    Computes allowed Snap mask combinations based on geometry flags, lane-container, editor mode, underground, and Replace mode special cases.

  • private void LoadToolPreferences() / private void SaveToolPreferences() / public void ResetToolPreferences()
    Save/load per-prefab-group preferences (mode, snap, elevation, parallel settings) into a dictionary keyed by prefab group; Reset clears and restores defaults.

  • public NativeList<ControlPoint> GetControlPoints(out JobHandle dependencies)
    Gives access to the native control point list (returns current dependency).

  • public NativeList<SnapLine> GetSnapLines(out JobHandle dependencies)
    Get snap lines.

  • protected override JobHandle OnUpdate(JobHandle inputDeps)
    Main update entry. Handles input actions, state machine for apply/cancel/replace, scheduling of snap/fix/create jobs, and calls Update (which handles raycast-driven control point updates). Returns combined JobHandle representing scheduled background work.

  • private JobHandle Update(JobHandle inputDeps, bool fullUpdate)
    Updates control point state when not in Replace mode: runs a SnapControlPoints job when raycast changes, updates course definitions via UpdateCourse when necessary.

  • private JobHandle UpdateStartEntity(JobHandle inputDeps)
    Small job that scans DefinitionQuery to detect a start entity (used in continuous/guide snapping).

  • private JobHandle SnapControlPoints(JobHandle inputDeps, bool removeUpgrade)
    Prepares and schedules the Burst-compiled SnapJob (heavy snap/search logic). Sets up component lookups, search trees, terrain/water readers and returns scheduled job handle. SnapJob populates m_ControlPoints.last with the best snap point and produces snap lines & upgrade states.

  • private JobHandle FixControlPoints(JobHandle inputDeps)
    Schedules FixControlPointsJob which reconciles ControlPoints' original entity references against Temp replacement data (ensures control points reference the right Temp/created entities).

  • private JobHandle UpdateCourse(JobHandle inputDeps, bool removeUpgrade)
    Destroys existing definitions (via barrier) and schedules CreateDefinitionsJob to convert control points into CreationDefinition + NetCourse entities for final application.

  • private JobHandle Cancel(JobHandle inputDeps, bool singleFrameOnly = false)
    Cancel flow: handles both Replace and placement modes. In Replace, toggles Cancelling/Applying states and sets up removal UI; otherwise removes last control point and re-snaps.

  • private JobHandle Apply(JobHandle inputDeps, bool singleFrameOnly = false)
    Apply flow: If not enough control points starts "Applying" state (for continuous elevation dragging) else builds definitions or kicks off replace/upgrade; plays audio and schedules jobs as needed.

  • protected override bool GetRaycastResult(out ControlPoint controlPoint) and overloads
    Raycast wrapper that filters and converts raw raycast results into ControlPoint, with Replace-mode entity filtering (e.g., prefer edge when node upgrades are disabled).

  • private void SetAppliedUpgrade(bool removing)
    Helper used in Replace to compute the AppliedUpgrade structure from m_UpgradeStates and the current control points.

  • public static void CreatePath(ControlPoint startPoint, ControlPoint endPoint, NativeList<PathEdge> path, NetData prefabNetData, PlaceableNetData placeableNetData, ref ComponentLookup<Edge> edgeData, ref ComponentLookup<Game.Net.Node> nodeData, ref ComponentLookup<Curve> curveData, ref ComponentLookup<PrefabRef> prefabRefData, ref ComponentLookup<NetData> prefabNetDatas, ref BufferLookup<ConnectedEdge> connectedEdgeData)
    Static helper that creates a sequence (path) of PathEdge elements between start and end control points. Supports trivial same-node/edge cases and a Dijkstra-like search over connected edges to find a minimal-cost path that is compatible with required layers/upgrade flags. Used in Replace mode to determine which edges/nodes are part of the replacement path.

  • public static void AddControlPoints(NativeList<ControlPoint> controlPoints, NativeList<UpgradeState> upgradeStates, NativeReference<AppliedUpgrade> appliedUpgrade, ControlPoint startPoint, ControlPoint endPoint, NativeList<PathEdge> path, Snap snap, bool removeUpgrade, bool leftHandTraffic, bool editorMode, NetGeometryData prefabGeometryData, RoadData prefabRoadData, PlaceableNetData placeableNetData, SubReplacement subReplacement, ref ComponentLookup<Owner> ownerData, ref ComponentLookup<Edge> edgeData, ref ComponentLookup<Game.Net.Node> nodeData, ref ComponentLookup<Curve> curveData, ref ComponentLookup<Composition> compositionData, ref ComponentLookup<Upgraded> upgradedData, ref ComponentLookup<EdgeGeometry> edgeGeometryData, ref ComponentLookup<PrefabRef> prefabRefData, ref ComponentLookup<NetData> prefabNetData, ref ComponentLookup<NetCompositionData> prefabCompositionData, ref ComponentLookup<RoadComposition> prefabRoadCompositionData, ref BufferLookup<ConnectedEdge> connectedEdgeData, ref BufferLookup<SubReplacement> subReplacementData)
    Builds the explicit ControlPoint sequence (and parallel UpgradeState list) used by CreateDefinitionsJob from a path computed by CreatePath plus the start/end control points. This handles converting edges into two control points (start/end), applying offsets for differing widths, building per-edge UpgradeState entries (Add/Remove flags, sub-replacements), and handles node upgrades.

  • private static bool IsNearEnd(Entity edge, Curve curve, float3 position, bool invert, ref ComponentLookup<EdgeGeometry> edgeGeometryData)
    Heuristic used by AddControlPoints to decide whether crosswalk/side adjustments should be applied at path ends.

  • Utility/private helpers: GetSurfaceHeights, CheckElevationRange, HandleWorldSize, FindParent, HandleLotGrid, HandleZoneGrid, HandleExistingObjects, HandleExistingGeometry, HandleControlPoints, AdjustControlPointHeight, AdjustMiddlePoint, HandleStartDirection, HandleGuideLines, HandleGeometry, HandleCurve, SnapShoreline, Create parallel/complex/grid/continuous/simple/straight course helpers, LinearizeElevation, GetCoursePos, InvertCourse, CalculatedInverseWeight, CreateParallelCourses, etc.

  • Many of these are used inside the SnapJob and CreateDefinitionsJob flows and implement geometry math, snapping heuristics, grid handling, subdivision, parallel course creation, guide lines, and owner/attachment handling for editor mode.

Usage Example

// Typical override in a derived system or when initializing the tool system:
[Preserve]
protected override void OnCreate()
{
    base.OnCreate();

    // NetToolSystem does the same initialization internally:
    // - Acquires needed subsystems (TerrainSystem, WaterSystem, SearchSystems)
    // - Creates native lists and references for control points, snap lines etc.
    // - Hooks up input actions and default preferences.
    // Example (taken from the system):
    m_ToolOutputBarrier = World.GetOrCreateSystemManaged<ToolOutputBarrier>();
    m_TerrainSystem = World.GetOrCreateSystemManaged<TerrainSystem>();
    m_WaterSystem = World.GetOrCreateSystemManaged<WaterSystem>();
    m_ControlPoints = new NativeList<ControlPoint>(4, Allocator.Persistent);
    m_SnapLines = new NativeList<SnapLine>(10, Allocator.Persistent);
    m_UpgradeStates = new NativeList<UpgradeState>(4, Allocator.Persistent);
    m_StartEntity = new NativeReference<Entity>(Allocator.Persistent);
    // ...
}

Notes for modders: - NetToolSystem is tightly integrated with the game's ECS pipeline. The heavy lifting is done in three Burst jobs (SnapJob, FixControlPointsJob, CreateDefinitionsJob), so modifications that touch snapping/searching/definition creation should either: - Reuse the provided jobs and component lookups, or - Provide alternative jobs that follow the same patterns (component lookups, search tree readers, Terrain/Water readers) and properly register readers with those systems. - For UI/behavior changes (modes, preferences, input bindings), prefer using the public properties and TrySetPrefab/GetPrefab helpers and the tool's event hooks (EventPrefabChanged). - The Replace workflow is complex: it uses pathfinding (CreatePath) and UpgradeState sequences. When altering upgrade flags or replacement logic, ensure you update both AddControlPoints and CreateDefinitionsJob handling so CreationDefinitions contain correct Upgraded/SubReplacement buffers.

If you want, I can: - Produce a shorter cheat-sheet listing only the most important public surface you can call/observe when writing a mod. - Extract and document specific methods or nested job inputs/outputs in more depth (e.g., SnapJob fields and how to feed it).