Game.NaturalResourceSystem
Assembly:
Assembly-CSharp
Namespace:
Game.Simulation
Type:
class
Base:
CellMapSystem
Summary:
Manages the game's natural resources map (fertility, ore, oil, fish). NaturalResourceSystem stores per-cell NaturalResourceCell entries at a 256x256 resolution and performs periodic regeneration of fertility and fish resources using a Burst-compiled parallel job. It reads pollution and water surface data from GroundPollutionSystem, NoisePollutionSystem and WaterSystem to influence regeneration. The system also provides helper methods to sample resource amounts at world positions and to convert resource amounts to world area. Intended for use in the Cities: Skylines 2 simulation pipeline and modding scenarios; respects ECS job dependencies and uses Burst where appropriate.
Fields
-
public const int MAX_BASE_RESOURCES
Constant = 10000. Represents the maximum base resource value stored per resource type. -
public const int FERTILITY_REGENERATION_RATE
Constant = 800. A fallback / reference regeneration rate used outside of the scheduled job constants. -
public const int FISH_REGENERATION_RATE
Constant = 800. A fallback / reference regeneration rate used outside of the scheduled job constants. -
public const int UPDATES_PER_DAY
Constant = 32. Number of update ticks the system aims to perform per in-game day (informational). -
public static readonly int kTextureSize
Static readonly = 256. The resolution of the natural resource texture (map). This must match the texture size used by GroundPollutionSystem and NoisePollutionSystem. -
public GroundPollutionSystem m_GroundPollutionSystem
Reference to the GroundPollutionSystem used to obtain ground pollution data for fertility regeneration calculations. -
public NoisePollutionSystem m_NoisePollutionSystem
Reference to the NoisePollutionSystem used to obtain noise pollution data relevant to water pollution contribution. -
public WaterSystem m_WaterSystem
Reference to the WaterSystem used to obtain water surface depths and pollution values used for fish calculations. -
private EntityQuery m_PollutionParameterQuery
EntityQuery used to fetch PollutionParameterData singleton (e.g., fertility ground multiplier) required during regeneration. -
(Inner struct)
RegenerateNaturalResourcesJob
(private Burst-compiled IJobParallelFor)
Job fields (brief): - Read-only inputs: fertility/fish regeneration rates, pollution multipliers, random seed, water resolution factor, ground and noise pollution CellMapData, WaterSurfaceData.
- Parallel-writable: CellMapData
m_CellData (NativeDisableParallelForRestriction). - Purpose: For each row (zIndex) of the resource texture, apply fertility regeneration reduced by ground pollution, compute local water depth/pollution aggregates and update fish base/used amounts with randomness and clamped limits.
Properties
public int2 TextureSize { get; }
Returns an int2 containing the texture size (kTextureSize, kTextureSize). Use this to query the resolution of the resource map.
Constructors
public NaturalResourceSystem()
Default constructor. Marked with [Preserve] on the OnCreate method rather than on the ctor; initializes the managed system when created by the world. No special parameters required.
Methods
-
protected override void OnCreate()
Initializes references to GroundPollutionSystem, NoisePollutionSystem and WaterSystem via World.GetOrCreateSystemManaged(). Also prepares an EntityQuery to read PollutionParameterData and creates internal textures/containers for the resource map at kTextureSize. This is called once when the system is created. -
public override JobHandle SetDefaults(Context context)
Called when default values need to be set (for a new game or when resetting). If the Context indicates a new game, this method completes dependencies and fills the whole resource map with procedurally generated base values for fertility, ore and oil using layered Perlin noise. This establishes starting natural resource distribution. Returns a JobHandle for dependency chaining. -
public void PostDeserialize(Context context)
Implements IPostDeserialize. If the deserialized save format does not include the FishResource tag, PostDeserialize calls Update() to ensure fish data is generated/updated to the current format. This helps with backwards compatibility of older saves. -
protected override void OnUpdate()
Called each system update interval. Obtains the WaterSurfaceData (and its dependency JobHandle), verifies consistency of texture sizes (asserts that ground/noise textures match kTextureSize and that water surface resolution is divisible by the resource texture size), then schedules a Burst-compiled RegenerateNaturalResourcesJob via IJobParallelFor to run over the kTextureSize rows. The job receives: - regeneration rates (25 for fertility/fish in the scheduled job),
- pollution multipliers from PollutionParameterData,
- computed water cell factor based on water resolution,
- RandomSeed.Next(),
- read-only CellMapData for ground/noise pollution,
- water surface data,
-
read-write resource cell data. The method registers writer/reader dependencies with the other systems (AddWriter / AddReader / AddSurfaceReader) to maintain proper job dependency ordering.
-
public float ResourceAmountToArea(float amount)
Converts a resource amount (units are in the resource cell scale where MAX_BASE_RESOURCES=10000) into world area: multiplies by the single-cell world area and divides by 10000 to get area in world units. Useful for displaying or calculating how much area a resource quantity corresponds to. -
public static NaturalResourceAmount GetFertilityAmount(float3 position, NativeArray<NaturalResourceCell> map)
Samples fertility at the given world position using bilinear filtering across the resource texture. Returns a NaturalResourceAmount (m_Base and m_Used). -
public static NaturalResourceAmount GetOilAmount(float3 position, NativeArray<NaturalResourceCell> map)
Samples oil at the given world position the same way as fertility. Returns a NaturalResourceAmount. -
public static NaturalResourceAmount GetOreAmount(float3 position, NativeArray<NaturalResourceCell> map)
Samples ore at the given world position the same way as fertility. Returns a NaturalResourceAmount. -
public static NaturalResourceAmount GetFishAmount(float3 position, NativeArray<NaturalResourceCell> map)
Samples fish at the given world position the same way as fertility. Returns a NaturalResourceAmount. -
private static NaturalResourceAmount GetResource(float3 position, NativeArray<NaturalResourceCell> map, Func<NaturalResourceCell, NaturalResourceAmount> getter)
Internal helper that implements sampling and bilinear filtering. Steps: - Computes the cell index from world position (accounting for the map size and texture size).
- Clamps cell indices to valid range (0..kTextureSize-2) so neighbor texels exist for interpolation.
- Reads four neighboring NaturalResourceAmount values (using the provided getter to select fertility/ore/oil/fish).
-
Performs bilinear interpolation based on cell coordinates to return a filtered NaturalResourceAmount (both m_Base and m_Used). Note: This function relies on the static CellMapSystem
.kMapSize and kTextureSize constants to map world positions to texture cells. -
(Inner struct)
RegenerateNaturalResourcesJob.Execute(int zIndex)
Core job execution method. For each cell on the row zIndex: - Reads existing cell, ground and noise pollution values.
- Uses a seeded Random to apply small random adjustments.
- Regenerates fertility: reduces m_Fertility.m_Used by a fixed rate and compensates by a randomized function of ground pollution multiplied by the pollution rate.
- Aggregates water depths and polluted water over the set of water surface samples corresponding to the natural resource cell (water resolution factor is used).
- Computes fish base from aggregated water depth and adjusts fish used towards a target computed from water pollution and noise pollution contributions. Fish values are clamped to [0, MAX_BASE_RESOURCES].
- Writes updated NaturalResourceCell back into the cell data buffer.
Notes: - The job uses BurstCompile and is scheduled as an IJobParallelFor across rows (kTextureSize). - Randomness is generated per cell from RandomSeed.Next() to add small stochastic variation to regeneration.
Usage Example
// Example: initialize system references in OnCreate (already done by system)
// and sample fish amount for a given world position.
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// NaturalResourceSystem.OnCreate will create/assign pollution and water systems and create textures.
}
// Somewhere in game code or a mod:
float3 worldPos = new float3(1000f, 0f, 2000f);
var naturalResourceSystem = World.GetOrCreateSystemManaged<NaturalResourceSystem>();
// Acquire a snapshot of the map buffer (this example assumes you can get a NativeArray snapshot):
NativeArray<NaturalResourceCell> map = naturalResourceSystem.GetData(readOnly: true, out JobHandle dep);
// Make sure dependencies are handled (complete if reading on main thread)
dep.Complete();
NaturalResourceAmount fish = NaturalResourceSystem.GetFishAmount(worldPos, map);
// Convert fish units to world area if needed:
float area = naturalResourceSystem.ResourceAmountToArea(fish.m_Base);
Notes and modding tips: - kTextureSize is fixed at 256 and must line up with ground/noise pollution textures; asserts in OnUpdate enforce this. - The regeneration job uses Burst and must observe thread-safety rules; modifications to job fields should keep NativeContainer usage and dependency management correct. - For backwards-compatibility, PostDeserialize will trigger regeneration if fish data is missing from saves. - When adding readers/writers, the system registers job dependencies with connected systems (ground/noise/water) to avoid race conditions. Make sure custom code respects these dependency models if interacting with the system's buffers.