118 lines
3.4 KiB
C#
118 lines
3.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cysharp.Threading.Tasks;
|
|
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
using UnityEngine.Pool;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
[Service(typeof(IRoadFactory))]
|
|
public class RoadManagerSystem : GameSystem, IInitializable, IDisposable, IUpdatable, IRoadFactory
|
|
{
|
|
[InjectService]
|
|
protected GameConfig _config;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
[InjectService]
|
|
private ISignalBus _signalBus;
|
|
|
|
private readonly List<List<int2>> _pendingTiles = new();
|
|
|
|
private float _placeTileTimer;
|
|
|
|
public RoadManagerSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public UniTask InitializeAsync()
|
|
{
|
|
_signalBus.Subscribe<DoDeleteToolSignal>(OnDoDeleteToolSignal);
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_signalBus.Unsubscribe<DoDeleteToolSignal>(OnDoDeleteToolSignal);
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
PlaceTiles();
|
|
}
|
|
|
|
private void PlaceTiles()
|
|
{
|
|
if (_pendingTiles.Count == 0)
|
|
{
|
|
_placeTileTimer = 0;
|
|
return;
|
|
}
|
|
|
|
_placeTileTimer += Time.unscaledDeltaTime;
|
|
if (_placeTileTimer < _config.Roads.PlaceTileInterval) return;
|
|
|
|
for (var i = _pendingTiles.Count - 1; i >= 0; i--)
|
|
{
|
|
var tileQueue = _pendingTiles[i];
|
|
while (tileQueue.Count > 0)
|
|
{
|
|
var tile = tileQueue[0];
|
|
tileQueue.RemoveAt(0);
|
|
if (_world.RoadNetwork.IsRoadTile(tile)) continue;
|
|
|
|
_world.RoadNetwork.AddRoadTile(tile);
|
|
UpdateTilesAround(tile);
|
|
|
|
_signalBus.Raise(new RoadTileUpdatedSignal(tile, true));
|
|
|
|
_placeTileTimer = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
if (tileQueue.Count == 0)
|
|
{
|
|
_pendingTiles.RemoveAt(i);
|
|
ListPool<int2>.Release(tileQueue);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnDoDeleteToolSignal(DoDeleteToolSignal signal)
|
|
{
|
|
using var deletedTilesScope = ListPool<int2>.Get(out var deletedTiles);
|
|
|
|
foreach (var tile in TileRange.From(signal.Rect))
|
|
{
|
|
if (!_world.RoadNetwork.IsRoadTile(tile)) continue;
|
|
|
|
_world.RoadNetwork.RemoveRoadTile(tile);
|
|
UpdateTilesAround(tile);
|
|
|
|
deletedTiles.Add(tile);
|
|
}
|
|
|
|
foreach (var tile in deletedTiles) _signalBus.Raise(new RoadTileUpdatedSignal(tile, false));
|
|
}
|
|
|
|
private void UpdateTilesAround(int2 tile)
|
|
{
|
|
if (tile.x > 0) _world.RoadNetwork.UpdateRoadTile(tile + new int2(-1, 0));
|
|
if (tile.y < _world.Size.x - 1) _world.RoadNetwork.UpdateRoadTile(tile + new int2(1, 0));
|
|
if (tile.y > 0) _world.RoadNetwork.UpdateRoadTile(tile + new int2(0, -1));
|
|
if (tile.y < _world.Size.y - 1) _world.RoadNetwork.UpdateRoadTile(tile + new int2(0, 1));
|
|
}
|
|
|
|
public void CreateRoad(int2 startTile, int2 endTile)
|
|
{
|
|
var tileQueue = ListPool<int2>.Get();
|
|
_pendingTiles.Add(tileQueue);
|
|
|
|
TileMath.WalkLine(startTile, endTile, tileQueue.Add);
|
|
}
|
|
}
|
|
} |