Skip to content

Game.ProductionSpecializationSystem

Assembly:
Namespace: Game.Simulation

Type: class

Base: GameSystemBase, IDefaultSerializable, ISerializable, IPostDeserialize

Summary:
Manages accumulation and application of production-based specialization bonuses for the city. Producers enqueue produced resources (ProducedResource) into a NativeQueue; this system processes the queue on a regular interval using a Burst-compiled job (SpecializationJob) to add amounts into the city's SpecializationBonus dynamic buffer and applies a small decay (floor(0.999 * value)) each update. The system supports serialization/deserialization of queued production so pending bonuses persist across saves, and ensures the city's specialization buffer exists after deserialization when needed.


Fields

  • public static readonly int kUpdatesPerDay
    Holds the constant update frequency divisor used to compute the system update interval relative to an in-game day (set to 512). Used by GetUpdateInterval to determine how often the system runs.

  • private CitySystem m_CitySystem
    Reference to the CitySystem for obtaining the city Entity. Acquired in OnCreate via World.GetOrCreateSystemManaged().

  • private EntityQuery m_BonusQuery
    EntityQuery used to detect the presence of SpecializationBonus buffers in the world. Used during PostDeserialize to decide whether to add the buffer to the city.

  • private NativeQueue<ProducedResource> m_ProductionQueue
    Persistent NativeQueue storing produced resources that need to be applied to the city's specialization bonuses. Producers enqueue ProducedResource items here (possibly from jobs) and this system dequeues and applies them during OnUpdate.

  • private JobHandle m_QueueWriters
    Aggregated JobHandle of producers that wrote to m_ProductionQueue. Combined with internal dependency to ensure queue writers complete before processing/serializing the queue.

  • private TypeHandle __TypeHandle
    Internal generated type handle that stores component/buffer lookups (here it contains the BufferLookup for SpecializationBonus). Assigned in OnCreateForCompiler.

  • private struct TypeHandle.__Game_City_SpecializationBonus_RW_BufferLookup (inside TypeHandle)
    BufferLookup handle used by the specialization job to access the city's SpecializationBonus dynamic buffer.

  • public struct ProducedResource
    Nested struct representing a single produced resource entry with fields:

  • Resource m_Resource — which resource type was produced.
  • int m_Amount — amount produced (can be aggregated with others of same resource type during serialization).

  • private struct SpecializationJob
    Burst-compiled IJob that:

  • Gets the city's SpecializationBonus dynamic buffer via BufferLookup.
  • Dequeues all ProducedResource items from the NativeQueue.
  • Ensures the buffer length is sufficient for the resource index and adds zeroed entries as needed.
  • Adds the produced amounts to the corresponding buffer entries.
  • Applies a decay (floor(0.999 * value)) to every entry in the buffer after applying all queued production for this update.

Properties

  • (no public C# properties)
    This system exposes functionality via methods (GetQueue, AddQueueWriter) rather than C# auto-properties. Use GetQueue(out JobHandle) to obtain the queue reference and current producer dependencies.

Constructors

  • public ProductionSpecializationSystem()
    Default constructor. Most initialization is performed in OnCreate (this constructor is kept for compatibility and code generation patterns).

Methods

  • public override int GetUpdateInterval(SystemUpdatePhase phase)
    Returns the system's update interval in ticks. Uses kUpdatesPerDay to compute a per-update interval (262144 / kUpdatesPerDay).

  • public NativeQueue<ProducedResource> GetQueue(out JobHandle deps)
    Provides producers access to the internal production queue so they can enqueue ProducedResource items. Outputs current aggregated writer dependencies via the out parameter deps (the value of m_QueueWriters) so callers can chain dependencies properly.

  • public void AddQueueWriter(JobHandle handle)
    Called by producer systems/jobs to register their JobHandle as a writer to the queue. This method combines the incoming handle with m_QueueWriters to ensure the queue's writer dependencies are tracked and respected when this system processes or serializes the queue.

  • protected override void OnCreate()
    Initializes system references and structures:

  • Obtains CitySystem.
  • Creates an EntityQuery for SpecializationBonus.
  • Allocates the persistent NativeQueue for produced resources.

  • protected override void OnDestroy()
    Disposes of the persistent m_ProductionQueue. Completes outstanding writers as necessary (m_QueueWriters should be completed before dispose implicitly via serialization or job scheduling patterns).

  • protected override void OnUpdate()
    Schedules the Burst SpecializationJob to process the production queue:

  • Populates the job's BufferLookup using internal handles and the system state.
  • Passes in the NativeQueue and city entity.
  • Schedules the job with dependencies combined from m_QueueWriters and base.Dependency.
  • Updates m_QueueWriters to the returned dependency so future writers are chained.

  • public void SetDefaults(Context context)
    Clears m_ProductionQueue. Used to reset state for new games or defaults.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Serializes the current pending production amounts into a compact array form:

  • Completes m_QueueWriters to ensure producers are finished.
  • Aggregates queued production amounts per resource index into a temporary NativeArray sized EconomyUtils.ResourceCount.
  • Writes the number of entries (highest non-empty index + 1) followed by aggregated amounts for each index. The queue is drained during this process.

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader
    Deserializes queued production:

  • Clears current queue.
  • Reads the number of resource entries and then each aggregated value.
  • For each positive value, enqueues a ProducedResource with the correct Resource (via EconomyUtils.GetResource(index)) and amount.

  • public void PostDeserialize(Context context)
    After deserialization, ensures the city's SpecializationBonus dynamic buffer exists if needed:

  • If the context purpose is NewGame or LoadGame and the world has no SpecializationBonus buffers (m_BonusQuery.IsEmptyIgnoreFilter), adds a SpecializationBonus buffer to the city entity.

  • private void __AssignQueries(ref SystemState state)
    Generated helper used by the compiled/IL tooling to assign entity queries. Implementation here is minimal (creates and disposes a builder) — kept for codegen compatibility.

  • protected override void OnCreateForCompiler()
    Internal codegen helper that calls __AssignQueries and assigns TypeHandle buffer lookups for use by the job.

Usage Example

// Example: producer job/system enqueues produced resources for the ProductionSpecializationSystem
var productionSystem = World.GetOrCreateSystemManaged<Game.Simulation.ProductionSpecializationSystem>();

// If you have a JobHandle for your producer job, register it:
productionSystem.AddQueueWriter(myProducerJobHandle);

// Get the queue and current aggregated writer deps (optional)
JobHandle deps;
var queue = productionSystem.GetQueue(out deps);

// Enqueue a produced resource (e.g., 10 units of some resource):
queue.Enqueue(new Game.Simulation.ProductionSpecializationSystem.ProducedResource {
    m_Resource = EconomyUtils.GetResource(/* resource index */),
    m_Amount = 10
});

// The ProductionSpecializationSystem will process the queue in OnUpdate, applying values
// to the city's SpecializationBonus buffer and applying the decay each tick.

Notes: - Producers running as jobs should register their job handles with AddQueueWriter so the system can correctly synchronize before processing or serializing the queue. - Serialization aggregates queued items by resource index before writing to save space. During Serialize the queue is drained; Deserialize reconstructs queued entries. - The SpecializationJob is Burst-compiled and runs on the worker threads; it relies on the BufferLookup to access the city buffer and the NativeQueue to read produced resources.