using System; using Cysharp.Threading.Tasks; using Unity.Burst; using Unity.Collections; using Unity.Jobs; using Unity.Mathematics; using UnityEngine; namespace DanieleMarotta.RiversongCodeShowcase { [RequiresWorldReadyForUpdate] [GameSystemGroup(typeof(EarlyGameSystemGroup))] public class UpdateFertilityMapSystem : GameSystem, IInitializable, IDisposable, IUpdatable { [InjectService] private GameConfig _config; [InjectService] private World _world; [InjectService] private ISignalBus _signalBus; public UpdateFertilityMapSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public UniTask InitializeAsync() { _signalBus.Subscribe(OnBuildingPlacementAnimationStarted); _signalBus.Subscribe(OnRoadTileUpdated); return UniTask.CompletedTask; } public void Dispose() { _signalBus.Unsubscribe(OnBuildingPlacementAnimationStarted); _signalBus.Unsubscribe(OnRoadTileUpdated); } public void Update() { var blockMap = _world.BlockMap.GetNativeArray(); var fertility = _world.Fertility.GetNativeArray(); var delta = _config.Terrain.FertilityRegenarationRate * Time.deltaTime; new UpdateFertilityMapJob { BlockMap = blockMap, Fertility = fertility, Delta = delta }.Schedule(fertility.Length, _world.Size.x) .Complete(); } private void OnBuildingPlacementAnimationStarted(BuildingPlacementAnimationStartedSignal signal) { foreach (var tile in TileRange.From(signal.Rect)) _world.Fertility.GetValueRW(tile).CurrentFertility = 0; } private void OnRoadTileUpdated(RoadTileUpdatedSignal signal) { if (!signal.RoadTileAdded) return; _world.Fertility.GetValueRW(signal.Tile).CurrentFertility = 0; } [BurstCompile] private struct UpdateFertilityMapJob : IJobParallelFor { [ReadOnly] public NativeArray BlockMap; public NativeArray Fertility; public float Delta; [BurstCompile] public void Execute(int index) { var value = Fertility[index]; if ((BlockMap[index] & BlockReason.ClearGrassMask) != 0 || value.CurrentFertility >= value.MaxFertility) return; value.CurrentFertility = math.min(value.CurrentFertility + Delta, value.MaxFertility); Fertility[index] = value; } } } }