riversong code showcase

This commit is contained in:
Daniele Marotta
2026-05-21 15:52:18 +02:00
commit 4c9eea1c02
462 changed files with 23406 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
namespace DanieleMarotta.RiversongCodeShowcase
{
public class EntityCache : IEntityCache
{
private Dictionary<int, Cache> _caches = new();
public void CreateCache<T>(int key, Predicate<T> filter) where T : Entity
{
if (!_caches.TryGetValue(key, out var cache))
{
cache = new Cache<T>();
_caches.Add(key, cache);
}
((Cache<T>)cache).Filter = filter;
}
public List<T> Get<T>(int key) where T : Entity
{
if (!_caches.TryGetValue(key, out var cache))
{
cache = new Cache<T>();
_caches.Add(key, cache);
}
return ((Cache<T>)cache).Entities;
}
public void OnAdded(Entity entity)
{
foreach (var cache in _caches.Values) cache.TryAdd(entity);
}
public void OnRemoved(Entity entity)
{
foreach (var cache in _caches.Values) cache.TryRemove(entity);
}
private abstract class Cache
{
public void TryAdd(Entity entity)
{
if (FilterEntity(entity)) Add(entity);
}
public void TryRemove(Entity entity)
{
if (FilterEntity(entity)) Remove(entity);
}
protected abstract bool FilterEntity(Entity entity);
protected abstract void Add(Entity entity);
protected abstract void Remove(Entity entity);
}
private class Cache<T> : Cache where T : Entity
{
public Predicate<T> Filter { get; set; }
public List<T> Entities { get; } = new();
protected override bool FilterEntity(Entity entity)
{
return entity is T typedEntity && Filter.Invoke(typedEntity);
}
protected override void Add(Entity entity)
{
Entities.Add((T)entity);
}
protected override void Remove(Entity entity)
{
Entities.Remove((T)entity);
}
}
}
}

View File

@@ -0,0 +1,67 @@
using System.Collections.Generic;
namespace DanieleMarotta.RiversongCodeShowcase
{
public static class EntityCacheExtensions
{
public static List<Building> GetHarvesterBuildings(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.HarvesterBuildings);
}
public static List<Building> GetHunterBuildings(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.HunterBuildings);
}
public static List<Building> GetFarmBuildings(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.FarmBuildings);
}
public static List<Building> GetProducers(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.ProducerBuildings);
}
public static List<Building> GetProviders(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.ProviderBuildings);
}
public static List<Building> GetBuildingsWithWorkers(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.BuildingsWithWorkers);
}
public static List<Building> GetHouses(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.HouseBuildings);
}
public static List<Building> GetTentBuildings(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.TentBuildings);
}
public static List<Building> GetStorageBuildings(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.StorageBuildings);
}
public static List<Building> GetStorageRequestBuildings(this IEntityCache entityCache)
{
return entityCache.Get<Building>((int)EntityCacheKeys.StorageRequestBuildings);
}
public static List<Agent> GetHunterAgents(this IEntityCache entityCache)
{
return entityCache.Get<Agent>((int)EntityCacheKeys.HunterAgents);
}
public static List<Agent> GetCritterAgents(this IEntityCache entityCache)
{
return entityCache.Get<Agent>((int)EntityCacheKeys.CritterAgents);
}
}
}

View File

@@ -0,0 +1,39 @@
namespace DanieleMarotta.RiversongCodeShowcase
{
public enum EntityCacheKeys
{
Invalid,
#region Buildings
HarvesterBuildings,
HunterBuildings,
FarmBuildings,
ProducerBuildings,
ProviderBuildings,
BuildingsWithWorkers,
HouseBuildings,
StorageBuildings,
StorageRequestBuildings,
TentBuildings,
#endregion
#region Agents
HunterAgents,
CritterAgents
#endregion
}
}

View File

@@ -0,0 +1,71 @@
using System;
using Cysharp.Threading.Tasks;
namespace DanieleMarotta.RiversongCodeShowcase
{
[GameSystemGroup(typeof(EarlyGameSystemGroup))]
[InitializeAfter(typeof(PreLoadAssetsSystem))]
public class EntityCacheSystem : GameSystem, IInitializable, IDisposable
{
[InjectService]
private IEntityCollection _entityCollection;
[InjectService]
private IEntityCache _entityCache;
[InjectService]
private GameConfig _config;
public EntityCacheSystem(IServiceLocator serviceLocator) : base(serviceLocator)
{
}
public UniTask InitializeAsync()
{
CreateCaches();
foreach (var entity in _entityCollection.GetInternalEntityList(typeof(Entity))) _entityCache.OnAdded(entity);
var callbacks = _entityCollection.On<Entity>();
callbacks.Added += _entityCache.OnAdded;
callbacks.Removed += _entityCache.OnRemoved;
return UniTask.CompletedTask;
}
private void CreateCaches()
{
_entityCache.CreateCache<Building>((int)EntityCacheKeys.HarvesterBuildings, b => b.Definition.HarvestedResource);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.HunterBuildings, b => b.Definition.TargetCritter);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.FarmBuildings, b => b.Definition.IsFarm);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.ProducerBuildings, b => b.Definition.Recipe);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.ProviderBuildings, b => b.Definition.ProvidedProducts.Count > 0);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.BuildingsWithWorkers, b => b.Definition.WorkerCount > 0);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.HouseBuildings, b => b.Definition.IsHouse);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.StorageBuildings, b => b.Definition.IsStorage);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.StorageRequestBuildings, b => b.Definition.IsStorage);
_entityCache.CreateCache<Building>((int)EntityCacheKeys.TentBuildings, b => b.Definition == _config.Population.TentBuilding.Asset);
_entityCache.CreateCache<Agent>(
(int)EntityCacheKeys.HunterAgents,
a =>
{
ref var jobState = ref a.GetJobStateRW();
return jobState.Job == AgentJob.Hunter;
});
_entityCache.CreateCache<Agent>(
(int)EntityCacheKeys.CritterAgents,
a =>
{
ref var critterState = ref a.GetCritterStateRW();
return critterState.IsCritter;
});
}
public void Dispose()
{
var callbacks = _entityCollection.On<Entity>();
callbacks.Added -= _entityCache.OnAdded;
callbacks.Removed -= _entityCache.OnRemoved;
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
namespace DanieleMarotta.RiversongCodeShowcase
{
public interface IEntityCache
{
void CreateCache<T>(int key, Predicate<T> filter) where T : Entity;
List<T> Get<T>(int key) where T : Entity;
void OnAdded(Entity entity);
void OnRemoved(Entity entity);
}
}