riversong code showcase
This commit is contained in:
114
Source/Riversong/Game/World/Agents/ConstructionAgentSystem.cs
Normal file
114
Source/Riversong/Game/World/Agents/ConstructionAgentSystem.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[GameSystemGroup(typeof(DayOnlyAgentSpawnSystemsGroup))]
|
||||
public class ConstructionAgentSystem : GameSystem, IUpdatable
|
||||
{
|
||||
private const int FetchRange = 20;
|
||||
|
||||
[InjectService]
|
||||
private GameConfig _config;
|
||||
|
||||
[InjectService]
|
||||
private World _world;
|
||||
|
||||
[InjectService]
|
||||
private IEntityCollection _entityCollection;
|
||||
|
||||
[InjectService]
|
||||
private IEntityCache _entityCache;
|
||||
|
||||
[InjectService]
|
||||
private IProductCatalog _productCatalog;
|
||||
|
||||
[InjectService]
|
||||
private IAgentFactory _agentFactory;
|
||||
|
||||
[InjectService]
|
||||
private ITileSpace _tileSpace;
|
||||
|
||||
[InjectService]
|
||||
private IBuildingSpatialQuery _buildingSpatialQuery;
|
||||
|
||||
public ConstructionAgentSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var agentDefinition = (AgentDefinition)_config.Agents.GenericAgent.Asset;
|
||||
|
||||
foreach (ConstructionSite constructionSite in _entityCollection.GetInternalEntityList(typeof(ConstructionSite)))
|
||||
TryFetch(constructionSite, constructionSite.Rect, constructionSite.Building.BuildingMaterials, agentDefinition);
|
||||
|
||||
foreach (var house in _entityCache.GetHouses())
|
||||
{
|
||||
ref var needsState = ref house.GetNeedsStateRW();
|
||||
if (needsState.UpgradeState != TierUpgradeState.FetchingMaterials) continue;
|
||||
|
||||
var products = house.Definition.HouseTiers[house.TierIndex].UpgradeMaterials;
|
||||
TryFetch(house, house.Rect, products, agentDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
private void TryFetch<T>(T source, TileRect sourceRect, List<ProductAmountAuthoring> products, AgentDefinition agentDefinition)
|
||||
where T : class, IProductStorageEntity, IAgentSourceEntity
|
||||
{
|
||||
if (!_agentFactory.CanSpawnAgent(source)) return;
|
||||
|
||||
ref var sourceStorage = ref source.GetStorageRW();
|
||||
|
||||
foreach (var (product, needed) in products)
|
||||
{
|
||||
var productHandle = _productCatalog.GetHandle(product);
|
||||
|
||||
sourceStorage.Get(productHandle, out var count, out var putReservations, out _);
|
||||
|
||||
var remaining = needed - count - putReservations;
|
||||
if (remaining <= 0) continue;
|
||||
|
||||
if (!FindFetchDestination(source.Id, sourceRect, productHandle, out var destinationRect, out var destinationEntity)) continue;
|
||||
|
||||
sourceStorage.ReservePutting(productHandle, 1);
|
||||
|
||||
ref var destinationStorage = ref destinationEntity.GetStorageRW();
|
||||
destinationStorage.ReserveTaking(productHandle, 1);
|
||||
|
||||
var position = _tileSpace.TileToWorld(sourceRect.Center);
|
||||
var agent = _agentFactory.CreateVillager(agentDefinition, source, position);
|
||||
|
||||
IntentQueue.Fetch(
|
||||
ref agent.GetIntentQueueRW(),
|
||||
sourceRect,
|
||||
source.Id,
|
||||
destinationRect,
|
||||
destinationEntity.Id,
|
||||
productHandle,
|
||||
1,
|
||||
PathTraversalRules.GenericAgent | PathTraversalRules.UpdateFailedPathCache);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool FindFetchDestination(int sourceId, TileRect sourceRect, int productHandle, out TileRect destinationRect, out IProductStorageEntity destinationEntity)
|
||||
{
|
||||
var productStackFound = _world.ProductStacks.FindClosest(sourceRect, FetchRange, productHandle, 1, out var productStack);
|
||||
var storageFound = _buildingSpatialQuery.FindStorageForFetch(sourceId, sourceRect, FetchRange, productHandle, out var storageBuilding);
|
||||
if (productStackFound || storageFound)
|
||||
{
|
||||
var productStackDistance = productStackFound ? TileMath.StepCount(sourceRect, productStack.Tile) : int.MaxValue;
|
||||
var storageDistance = storageFound ? TileMath.StepCount(sourceRect, storageBuilding.Rect) : int.MaxValue;
|
||||
|
||||
destinationRect = productStackDistance < storageDistance ? TileRect.OneTile(productStack.Tile) : storageBuilding.Rect;
|
||||
destinationEntity = productStackDistance < storageDistance ? productStack : storageBuilding;
|
||||
return true;
|
||||
}
|
||||
|
||||
destinationRect = TileRect.Empty;
|
||||
destinationEntity = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user