riversong code showcase
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class ConstructionSiteManager : GameSystem, IInitializable, IDisposable, IUpdatable
|
||||
{
|
||||
private const int SpatialLookupCellSize = 5;
|
||||
|
||||
private const int StorageCapacity = 100;
|
||||
|
||||
[InjectService]
|
||||
private GameConfig _config;
|
||||
|
||||
[InjectService]
|
||||
private IScene _scene;
|
||||
|
||||
[InjectService]
|
||||
private ISignalBus _signalBus;
|
||||
|
||||
[InjectService]
|
||||
private IEntityCollection _entityCollection;
|
||||
|
||||
[InjectService]
|
||||
private ITileSpace _tileSpace;
|
||||
|
||||
[InjectService]
|
||||
private IProductStorageManager _productStorageManager;
|
||||
|
||||
[InjectService]
|
||||
private IProductCatalog _productCatalog;
|
||||
|
||||
[InjectService]
|
||||
private IProductStackFactory _productStackFactory;
|
||||
|
||||
[InjectService]
|
||||
private IAgentFactory _agentFactory;
|
||||
|
||||
private Dictionary<int, GameObject> _visualizations = new();
|
||||
|
||||
private SpatialLookup<(ConstructionSite, GameObject)> _spatialLookup = new(SpatialLookupCellSize);
|
||||
|
||||
private MaterialPropertyBlock _materialPropertyBlock;
|
||||
|
||||
public ConstructionSiteManager(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public UniTask InitializeAsync()
|
||||
{
|
||||
_signalBus.Subscribe<BuildingPlacementAnimationCompletedSignal>(OnBuildingPlaced);
|
||||
_signalBus.Subscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
||||
_signalBus.Subscribe<DoDeleteToolSignal>(OnDoDeleteTool);
|
||||
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_signalBus.Unsubscribe<BuildingPlacementAnimationCompletedSignal>(OnBuildingPlaced);
|
||||
_signalBus.Unsubscribe<CollectDeletedGameObjectsSignal>(OnCollectDeletedGameObjects);
|
||||
_signalBus.Unsubscribe<DoDeleteToolSignal>(OnDoDeleteTool);
|
||||
}
|
||||
|
||||
private void OnBuildingPlaced(BuildingPlacementAnimationCompletedSignal signal)
|
||||
{
|
||||
var constructionSite = _entityCollection.Create<ConstructionSite>();
|
||||
|
||||
constructionSite.Building = signal.Building;
|
||||
constructionSite.Rect = signal.Rect;
|
||||
constructionSite.Orientation = signal.Orientation;
|
||||
_productStorageManager.InitializeProductStorage(constructionSite, StorageCapacity);
|
||||
_agentFactory.InitializeAgentSource(constructionSite);
|
||||
|
||||
_entityCollection.Add(constructionSite);
|
||||
|
||||
_ = CreateVisualizationAsync(constructionSite);
|
||||
}
|
||||
|
||||
private async UniTask CreateVisualizationAsync(ConstructionSite constructionSite)
|
||||
{
|
||||
var position = _tileSpace.GetRectWorldCenter(constructionSite.Rect);
|
||||
var rotation = constructionSite.Orientation.ToQuaternion();
|
||||
var folder = _scene.SceneFolders.Buildings;
|
||||
|
||||
var visualization = await constructionSite.Building.Visualization.InstantiateAsync(position, rotation, folder);
|
||||
ReplaceMaterials(visualization);
|
||||
|
||||
_visualizations.Add(constructionSite.Id, visualization);
|
||||
_spatialLookup.Add((constructionSite, visualization), constructionSite.Rect, constructionSite.Id);
|
||||
}
|
||||
|
||||
private void ReplaceMaterials(GameObject gameObject)
|
||||
{
|
||||
var material = _config.Buildings.ConstructionSiteMaterial;
|
||||
|
||||
using var renderersScope = ListPool<Renderer>.Get(out var renderers);
|
||||
gameObject.GetComponentsInChildren(renderers);
|
||||
|
||||
_materialPropertyBlock ??= new MaterialPropertyBlock();
|
||||
|
||||
foreach (var renderer in renderers) MaterialReplacementCache.ReplaceRendererMaterials(renderer, material, _materialPropertyBlock);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
using var toCompleteScope = ListPool<ConstructionSite>.Get(out var toComplete);
|
||||
|
||||
foreach (ConstructionSite constructionSite in _entityCollection.GetInternalEntityList(typeof(ConstructionSite)))
|
||||
if (_visualizations.ContainsKey(constructionSite.Id) && AllBuildingMaterialsFetched(constructionSite))
|
||||
toComplete.Add(constructionSite);
|
||||
|
||||
foreach (var constructionSite in toComplete)
|
||||
{
|
||||
_entityCollection.Remove(constructionSite.Id);
|
||||
|
||||
_visualizations.Remove(constructionSite.Id, out var visualization);
|
||||
_spatialLookup.Remove(constructionSite.Rect, constructionSite.Id);
|
||||
|
||||
constructionSite.Building.Visualization.ReleaseInstance(visualization);
|
||||
|
||||
_signalBus.Raise(new ConstructionCompletedSignal(constructionSite));
|
||||
}
|
||||
}
|
||||
|
||||
private bool AllBuildingMaterialsFetched(ConstructionSite constructionSite)
|
||||
{
|
||||
ref var storage = ref constructionSite.GetStorageRW();
|
||||
|
||||
foreach (var (product, amount) in constructionSite.Building.BuildingMaterials)
|
||||
{
|
||||
var handle = _productCatalog.GetHandle(product);
|
||||
if (storage.AvailableNow(handle) < amount) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnCollectDeletedGameObjects(CollectDeletedGameObjectsSignal signal)
|
||||
{
|
||||
if ((signal.Filter & DeletedGameObjectsFilter.Buildings) == 0) return;
|
||||
|
||||
using var lookupResultScope = ListPool<(ConstructionSite, GameObject)>.Get(out var lookupResult);
|
||||
_spatialLookup.Find(signal.Rect, lookupResult);
|
||||
|
||||
foreach (var (_, visualization) in lookupResult) signal.GameObjects.Add(visualization);
|
||||
}
|
||||
|
||||
private void OnDoDeleteTool(DoDeleteToolSignal signal)
|
||||
{
|
||||
using var lookupResultScope = ListPool<(ConstructionSite, GameObject)>.Get(out var lookupResult);
|
||||
_spatialLookup.Find(signal.Rect, lookupResult);
|
||||
|
||||
foreach (var (constructionSite, visualization) in lookupResult)
|
||||
{
|
||||
_productStackFactory.CreateProductStacksFrom(constructionSite);
|
||||
|
||||
_entityCollection.Remove(constructionSite.Id);
|
||||
_visualizations.Remove(constructionSite.Id);
|
||||
_spatialLookup.Remove(constructionSite.Rect, constructionSite.Id);
|
||||
|
||||
constructionSite.Building.Visualization.ReleaseInstance(visualization);
|
||||
|
||||
_signalBus.Raise(new ConstructionSiteDeletedSignal(constructionSite));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user