Seprated many files, removed IDataCompiler with using YamlConverters. Refactored namespaces
This commit is contained in:
@@ -2,6 +2,7 @@ namespace FoodFactory;
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using FoodFactory.Blueprints;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
using FoodFactory.Voxel;
|
using FoodFactory.Voxel;
|
||||||
|
|||||||
129
src/Blueprints/Blueprint.cs
Normal file
129
src/Blueprints/Blueprint.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
// namespace FoodFactory.Blueprints;
|
||||||
|
|
||||||
|
// using System;
|
||||||
|
// using System.Diagnostics;
|
||||||
|
// using System.Diagnostics.CodeAnalysis;
|
||||||
|
// using Arch.Core;
|
||||||
|
// using SharpYaml.Model;
|
||||||
|
// using SJK.Functional;
|
||||||
|
// using Utf8Json;
|
||||||
|
|
||||||
|
// public record Blueprint(string Name, Func<BlueprintContext, Entity> Factory)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public record Blueprint(string Name, Func<BlueprintContext, Entity> Factory)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
121
src/Blueprints/BlueprintContext.cs
Normal file
121
src/Blueprints/BlueprintContext.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
namespace FoodFactory.Blueprints;
|
||||||
|
|
||||||
|
using Arch.Core;
|
||||||
|
|
||||||
|
public struct BlueprintContext
|
||||||
|
{
|
||||||
|
public World World;
|
||||||
|
public BlueprintId BluePrintId;
|
||||||
|
public object PlaceHolderApi;
|
||||||
|
}
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
14
src/Blueprints/BlueprintId.cs
Normal file
14
src/Blueprints/BlueprintId.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace FoodFactory.Blueprints;
|
||||||
|
|
||||||
|
using FoodFactory.Core;
|
||||||
|
|
||||||
|
public readonly record struct BlueprintId
|
||||||
|
{
|
||||||
|
public readonly int Id;
|
||||||
|
public CompiledBlueprint Blueprint() => _registry.GetEntry(Id);
|
||||||
|
private static readonly Registry<CompiledBlueprint> _registry = new();
|
||||||
|
public BlueprintId(CompiledBlueprint blueprint)
|
||||||
|
{
|
||||||
|
Id = _registry.GetOrCreate(blueprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
304
src/Blueprints/BlueprintManger.cs
Normal file
304
src/Blueprints/BlueprintManger.cs
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
namespace FoodFactory.Blueprints;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using FoodFactory.Blueprints.Providers;
|
||||||
|
using FoodFactory.Blueprints.Providers.Converters;
|
||||||
|
using FoodFactory.Items;
|
||||||
|
using Godot;
|
||||||
|
using SharpYaml;
|
||||||
|
|
||||||
|
public interface IBlueprintManger
|
||||||
|
{
|
||||||
|
CompiledBlueprint GetCompiledBlueprint(string name);
|
||||||
|
// ComponentBinderRegistry BinderRegistry { get; }
|
||||||
|
}
|
||||||
|
public class BlueprintManger : IBlueprintManger
|
||||||
|
{
|
||||||
|
public readonly Dictionary<string, CompiledBlueprint> CompiledBlueprints = [];
|
||||||
|
|
||||||
|
// public ComponentBinderRegistry BinderRegistry { get; }
|
||||||
|
|
||||||
|
public BlueprintManger()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
var root = "/home/ronnie/Documents/Godot/Projects/ChickenGameTest/mods";
|
||||||
|
var dir = DirAccess.Open(root);
|
||||||
|
var itemDatas = new List<ItemData>();
|
||||||
|
|
||||||
|
var options = new YamlSerializerOptions()
|
||||||
|
{
|
||||||
|
Converters = [
|
||||||
|
// new ComponentsPatcherConverter(
|
||||||
|
// new(){
|
||||||
|
// [nameof(Temperature)] = typeof(IValueProvider<Temperature>),
|
||||||
|
// [nameof(Tags)] = typeof(IValueProvider<Tags>),
|
||||||
|
// [nameof(Name)] = typeof(IValueProvider<Name>),
|
||||||
|
// [nameof(Mass)] = typeof(IValueProvider<Mass>),
|
||||||
|
// [nameof(Color)] = typeof(IValueProvider<Color>),
|
||||||
|
// [nameof(BurnableTemp)] = typeof(IValueProvider<BurnableTemp>),
|
||||||
|
// }
|
||||||
|
// ),
|
||||||
|
new ComponentTemperatureConverter(),
|
||||||
|
new ComponentTagsConverter(),
|
||||||
|
new ComponentNameConverter(),
|
||||||
|
|
||||||
|
]
|
||||||
|
};
|
||||||
|
foreach (var item in dir.GetFiles())
|
||||||
|
{
|
||||||
|
if (item.EndsWith(".yaml"))
|
||||||
|
{
|
||||||
|
var file = FileAccess.Open(dir.GetCurrentDir() + "/" + item, FileAccess.ModeFlags.Read);
|
||||||
|
var data = YamlSerializer.Deserialize<ItemData>(file.GetAsText(),options);
|
||||||
|
itemDatas.Add(data);
|
||||||
|
// var compiledBlueprint = new CompiledBlueprint
|
||||||
|
// {
|
||||||
|
// // Id = data.Id,
|
||||||
|
// // Signature = new Signature([typeof(BlueprintId), .. types.Where(f => data.Components.ContainsKey(f.Name)).Select(Component.GetComponentType)]),
|
||||||
|
// // Providers = new IValueProvider[data.Components.Count]
|
||||||
|
// // };
|
||||||
|
// // var i = 0;
|
||||||
|
// // foreach (var item2 in data.Components)
|
||||||
|
// // {
|
||||||
|
// // var compiler = Providers[item2.Key];
|
||||||
|
// // var compiled = compiler.CompileUnTyped(item2.Value);
|
||||||
|
// // compiledBlueprint.Providers[i] = compiled;
|
||||||
|
// // i++;
|
||||||
|
// // }
|
||||||
|
// CompiledBlueprints.Add(compiledBlueprint.Id, compiledBlueprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Call a Patch method thingy to adjust exsting data before loading
|
||||||
|
|
||||||
|
CompiledBlueprints = LoadBluprints([.. itemDatas]);
|
||||||
|
}
|
||||||
|
private Dictionary<string, CompiledBlueprint> LoadBluprints(ItemData[] all, Dictionary<string, CompiledBlueprint>? existing = null)
|
||||||
|
{
|
||||||
|
var completed = existing is not null ? new(existing) : new Dictionary<string,CompiledBlueprint>();
|
||||||
|
var queue = new Queue<ItemData>(all);
|
||||||
|
while (queue.Any())
|
||||||
|
{
|
||||||
|
reset:
|
||||||
|
var item = queue.Dequeue();
|
||||||
|
var sources = new List<CompiledBlueprint>();
|
||||||
|
foreach (var c in item.Extend)
|
||||||
|
{
|
||||||
|
if (!completed.ContainsKey(c))
|
||||||
|
{
|
||||||
|
queue.Enqueue(item);
|
||||||
|
goto reset;
|
||||||
|
}
|
||||||
|
sources.Add(completed[c]);
|
||||||
|
}
|
||||||
|
var providers = new Dictionary<Type, List<IValueProvider>>();//TODO Make Blupritns able to hold muiple providers in a array for cases taht build off previouse providers
|
||||||
|
foreach (var blueprint in sources)
|
||||||
|
{
|
||||||
|
foreach (var provider in blueprint.Providers)
|
||||||
|
{
|
||||||
|
if (item.Remove.Contains(provider[0].GetProviderType().Name))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!providers.TryGetValue(provider[0].GetProviderType(), out var providersList))
|
||||||
|
{
|
||||||
|
providers[provider[0].GetProviderType()] = providersList = new();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < provider.Length; i++)
|
||||||
|
{
|
||||||
|
if (provider[i].Mode == ProviderMode.Static)
|
||||||
|
{
|
||||||
|
providersList.Clear();
|
||||||
|
providersList.Add(provider[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var component in item.Components)
|
||||||
|
{
|
||||||
|
// var compiler = Providers[component.Key];
|
||||||
|
var compiledProvider = component.Value;//compiler.CompileUnTyped(component.Value);
|
||||||
|
if (!providers.TryGetValue(compiledProvider.GetProviderType(), out var providersList))
|
||||||
|
{
|
||||||
|
providers[compiledProvider.GetProviderType()] = providersList = new();
|
||||||
|
}
|
||||||
|
providersList.Add(compiledProvider);
|
||||||
|
}
|
||||||
|
var compiled = new CompiledBlueprint()
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
// Traits = new Tags([.. item.Components.Keys]),//TODO need a way for recipies to look in each 'parent/extend' for getting recipes, either iterating each parent pool(recipe behing only in max shared, or each buckert container a copy for each parent)
|
||||||
|
Signature = [.. providers.Keys],
|
||||||
|
Providers = [.. providers.Values.Select(list => list.ToArray())],
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
ex Food-> onion -> red onion
|
||||||
|
if onion id, then onion and red onion bucket have a recipe
|
||||||
|
of for each trait, iterate each bucket, starting from spefic, to top.
|
||||||
|
*/
|
||||||
|
completed.Add(item.Id, compiled);
|
||||||
|
}
|
||||||
|
return completed;
|
||||||
|
}
|
||||||
|
public CompiledBlueprint? GetCompiledBlueprint(string id)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (CompiledBlueprints.TryGetValue(id, out var compiledBlueprint))
|
||||||
|
{
|
||||||
|
return compiledBlueprint;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// public Blueprint GetBlueprint(string name)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// // throw new NotImplementedException();
|
||||||
|
// if (!Blueprints.TryGetValue(name, out var blueprint))
|
||||||
|
// {
|
||||||
|
// //TODO this is where this should look through mods/base game
|
||||||
|
// if (name == "Potato")
|
||||||
|
// {
|
||||||
|
// blueprint = new Blueprint("Potato", static ctx => ctx.World.Create(new Name("Potato_raw"),
|
||||||
|
// new Tags("potato", "raw", "vegetable", "burnable"),
|
||||||
|
// new Temperature(40, TemperatureUnit.Fahrenheit),
|
||||||
|
// ctx.BluePrintId,
|
||||||
|
// new Bacteria(BacterialSystem.Resources.Add([new BacteriaData("slamnala", 400)])),
|
||||||
|
// new BurnableTemp(new Temperature(400, TemperatureUnit.Fahrenheit))));//TODO blueprintID should not be passed, but know when blueprint is created, meaning a rework of Blueprint id register
|
||||||
|
// }
|
||||||
|
// else if (name == "Onion")
|
||||||
|
// {
|
||||||
|
// blueprint = new Blueprint("Onion", static ctx => ctx.World.Create(new Name("Onion_raw"),
|
||||||
|
// new Tags("onion", "raw", "vegetable", "burnable", "sliceable"),
|
||||||
|
// new Temperature(71, TemperatureUnit.Fahrenheit),
|
||||||
|
// ctx.BluePrintId,
|
||||||
|
// new BurnableTemp(new Temperature(400, TemperatureUnit.Fahrenheit)),
|
||||||
|
// new Mass(Weight.FromGrams(110)),
|
||||||
|
// new Carbohydrates(Fiber: 2, Starch: 3, Sugars: new(Glucose: 0, Fructose: 1.2f, Sucrose: 1, Lactose: 0))
|
||||||
|
// ));//TODO blueprintID should not be passed, but know when blueprint is created, meaning a rework of Blueprint id register
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// throw new Exception();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return blueprint;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
48
src/Blueprints/CompiledBlueprint.cs
Normal file
48
src/Blueprints/CompiledBlueprint.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
namespace FoodFactory.Blueprints;
|
||||||
|
|
||||||
|
using Arch.Core;
|
||||||
|
using FoodFactory.Blueprints.Providers;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
|
|
||||||
|
// public sealed class StaticReflectionCompiledNode<T> : IValueProvider<T> where T : struct
|
||||||
|
// {
|
||||||
|
// //TODO Make more performance by only having properties of each method, and share use a list using tuples instead.
|
||||||
|
// // private readonly Dictionary<string, object> _data;
|
||||||
|
// private readonly T _template;
|
||||||
|
|
||||||
|
// public StaticReflectionCompiledNode(Dictionary<string, object> itemData)
|
||||||
|
// {
|
||||||
|
// StructReflection.ApplyValues(ref _template, itemData);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void Resolve(BlueprintContext context, ref T value) => value = _template;
|
||||||
|
// public ProviderMode Mode => ProviderMode.Static;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public sealed class RuntimeReflectionCompiledNode<T> : IValueProvider<T> where T : struct
|
||||||
|
// {
|
||||||
|
// //TODO Make more performance by only having properties of each method, and share use a list using tuples instead.
|
||||||
|
// private readonly Dictionary<string, object> _data;
|
||||||
|
// // private readonly T _template;
|
||||||
|
|
||||||
|
// public RuntimeReflectionCompiledNode(Dictionary<string, object> itemData)
|
||||||
|
// {
|
||||||
|
// _data = itemData;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void Resolve(BlueprintContext context, ref T value) => StructReflection.ApplyValues(ref value, _data);
|
||||||
|
// public ProviderMode Mode => ProviderMode.Modify;
|
||||||
|
|
||||||
|
// }
|
||||||
|
public class CompiledBlueprint
|
||||||
|
{
|
||||||
|
public required string Id { get; init; }
|
||||||
|
public Tags Traits { get; set; }
|
||||||
|
public IValueProvider[][] Providers = [];
|
||||||
|
public Signature Signature;
|
||||||
|
public Entity CreateEmptyItem(BlueprintContext blueprintContext) => blueprintContext.World.Create(Signature);
|
||||||
|
|
||||||
|
}
|
||||||
162
src/Blueprints/Provider/Converters/ComponentTagsConverter.cs
Normal file
162
src/Blueprints/Provider/Converters/ComponentTagsConverter.cs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers.Converters;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
|
using SharpYaml.Serialization;
|
||||||
|
public sealed class ComponentTagsConverter : ItemComponentsConverter<Tags>
|
||||||
|
{
|
||||||
|
public override IValueProvider<Tags> Read(YamlReader reader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == YamlTokenType.StartSequence)
|
||||||
|
{
|
||||||
|
if (reader.GetConverter(typeof(string[])) is not YamlConverter<string[]> converter)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
return new StaticCompiledNode<Tags>(new Tags(converter.Read(reader)));
|
||||||
|
}
|
||||||
|
if (reader.TokenType == YamlTokenType.StartMapping)
|
||||||
|
{
|
||||||
|
string[] with = [];
|
||||||
|
string[] exclude = [];
|
||||||
|
reader.Read();
|
||||||
|
while (reader.TokenType != YamlTokenType.EndMapping)
|
||||||
|
{
|
||||||
|
var key = reader.ScalarValue;
|
||||||
|
reader.Read();
|
||||||
|
if (key == "With")
|
||||||
|
{
|
||||||
|
if (reader.GetConverter(typeof(string[])) is not YamlConverter<string[]> converter)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
with = converter.Read(reader);
|
||||||
|
}
|
||||||
|
if (key == "Except")
|
||||||
|
{
|
||||||
|
if (reader.GetConverter(typeof(string[])) is not YamlConverter<string[]> converter)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
exclude = converter.Read(reader);
|
||||||
|
}
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
return new FactoryCompiledNode<Tags>((in factory, ref tags) => tags.With(with).WithOut(exclude));
|
||||||
|
}
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(YamlWriter writer, IValueProvider<Tags> value) => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers.Converters;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FoodFactory.Math;
|
||||||
|
using SharpYaml.Serialization;
|
||||||
|
|
||||||
|
// public interface IComponentBinder
|
||||||
|
// {
|
||||||
|
// ComponentType ComponentType { get; }
|
||||||
|
// void ApplyUntyped(
|
||||||
|
// Entity existing,
|
||||||
|
// IValueProvider data,
|
||||||
|
// BlueprintContext context);
|
||||||
|
// void ApplyUntyped(
|
||||||
|
// Span<Entity> existing,
|
||||||
|
// IValueProvider data,
|
||||||
|
// BlueprintContext context);
|
||||||
|
// }
|
||||||
|
// public class ComponentBinder<T> : IComponentBinder where T : struct
|
||||||
|
// {
|
||||||
|
// public ComponentType ComponentType => Component<T>.ComponentType;
|
||||||
|
|
||||||
|
// public void ApplyUntyped(
|
||||||
|
// Entity existing,
|
||||||
|
// IValueProvider data,
|
||||||
|
// BlueprintContext context)
|
||||||
|
// {
|
||||||
|
// if (data is IValueProvider<T> dataT)
|
||||||
|
// {
|
||||||
|
// ref var component = ref context.World.Get<T>(existing);
|
||||||
|
// Apply(ref component, dataT, context);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// throw new System.Exception();
|
||||||
|
// }
|
||||||
|
// public void ApplyUntyped(Span<Entity> existing, IValueProvider data, BlueprintContext context)
|
||||||
|
// {
|
||||||
|
// if (data is not IValueProvider<T> dataT)
|
||||||
|
// {
|
||||||
|
// throw new System.Exception();
|
||||||
|
// }
|
||||||
|
// for (int i = 0; i < existing.Length; i++)
|
||||||
|
// {
|
||||||
|
// Apply(ref existing[i].Get<T>(), dataT, context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void Apply(
|
||||||
|
// ref T existing,
|
||||||
|
// IValueProvider<T> data,
|
||||||
|
// BlueprintContext context) => data.Resolve(context, ref existing);
|
||||||
|
// }
|
||||||
|
// public class DefaultBinder<T> : ComponentBinder<T> where T : struct
|
||||||
|
// {
|
||||||
|
// public override void Apply(ref T existing, IValueProvider<T> data, BlueprintContext context);
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public class TemperatureBinder : ComponentBinder<Temperature>
|
||||||
|
// {
|
||||||
|
// public override void Apply(ref Temperature existing, IValueProvider<Temperature> data, BlueprintContext context) => data.Resolve(context, ref existing);
|
||||||
|
|
||||||
|
// }
|
||||||
|
public sealed class ComponentTemperatureConverter : ItemComponentsConverter<Temperature>//, IDataCompiler<Temperature>
|
||||||
|
{
|
||||||
|
// public IValueProvider<Temperature> Compile(object data)
|
||||||
|
// {
|
||||||
|
// if (data is IValueProvider<Temperature> t)
|
||||||
|
// {
|
||||||
|
// return t;
|
||||||
|
// }
|
||||||
|
// if (data is string says)
|
||||||
|
// {
|
||||||
|
// if (says == "ambient")
|
||||||
|
// {
|
||||||
|
// return new AmbientTemperatureProvider();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (data is float f)
|
||||||
|
// {
|
||||||
|
// return new StaticCompiledNode<Temperature>(new Temperature(f));
|
||||||
|
// }
|
||||||
|
// if (data is double d)
|
||||||
|
// {
|
||||||
|
// return new StaticCompiledNode<Temperature>(new Temperature(d));
|
||||||
|
// }
|
||||||
|
// if (data is Dictionary<string, object> dict)
|
||||||
|
// {
|
||||||
|
// return new StaticReflectionCompiledNode<Temperature>(dict);
|
||||||
|
|
||||||
|
// }
|
||||||
|
// throw new NotSupportedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
public override IValueProvider<Temperature>? Read(YamlReader reader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == YamlTokenType.Scalar)
|
||||||
|
{
|
||||||
|
var value = reader.ScalarValue;
|
||||||
|
reader.Read();
|
||||||
|
if (value == "ambient")
|
||||||
|
{
|
||||||
|
return new AmbientTemperatureProvider();
|
||||||
|
}
|
||||||
|
if (float.TryParse(value, out var f))
|
||||||
|
{
|
||||||
|
return new StaticCompiledNode<Temperature>(new Temperature(f));
|
||||||
|
}
|
||||||
|
if (double.TryParse(value, out var d))
|
||||||
|
{
|
||||||
|
return new StaticCompiledNode<Temperature>(new Temperature(f));
|
||||||
|
}
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
if (reader.TokenType == YamlTokenType.StartMapping)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
IValueProvider<Temperature>? provider = null;
|
||||||
|
while (reader.TokenType != YamlTokenType.EndMapping)
|
||||||
|
{
|
||||||
|
var key = reader.ScalarValue;
|
||||||
|
reader.Read();
|
||||||
|
if (key == nameof(Fahrenheit))
|
||||||
|
{
|
||||||
|
provider = new StaticCompiledNode<Temperature>(new Fahrenheit(float.Parse(reader.ScalarValue)));
|
||||||
|
}
|
||||||
|
if (key == nameof(Celsius))
|
||||||
|
{
|
||||||
|
provider = new StaticCompiledNode<Temperature>(new Celsius(float.Parse(reader.ScalarValue)));
|
||||||
|
}
|
||||||
|
if (key == nameof(Kelvin))
|
||||||
|
{
|
||||||
|
provider = new StaticCompiledNode<Temperature>(new Kelvin(float.Parse(reader.ScalarValue)));
|
||||||
|
}
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
return provider??throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(YamlWriter writer, IValueProvider<Temperature> value) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public sealed class AmbientTemperatureProvider : IValueProvider<Temperature>
|
||||||
|
{
|
||||||
|
public ProviderMode Mode => ProviderMode.Static;
|
||||||
|
|
||||||
|
public void Resolve(BlueprintContext context, ref Temperature value)
|
||||||
|
{
|
||||||
|
value.Kelvin = (float)context.PlaceHolderApi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
131
src/Blueprints/Provider/Converters/ComponentsNameConverter.cs
Normal file
131
src/Blueprints/Provider/Converters/ComponentsNameConverter.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers.Converters;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using SharpYaml.Serialization;
|
||||||
|
|
||||||
|
public sealed class ComponentNameConverter : ItemComponentsConverter<Name>
|
||||||
|
{
|
||||||
|
public override IValueProvider<Name> Read(YamlReader reader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == YamlTokenType.Scalar)
|
||||||
|
{
|
||||||
|
var key = reader.GetScalarValue();
|
||||||
|
reader.Read();
|
||||||
|
return new StaticCompiledNode<Name>(new(key));
|
||||||
|
}
|
||||||
|
return base.Read(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(YamlWriter writer, IValueProvider<Name> value) => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
133
src/Blueprints/Provider/Converters/ItemComponentsConverter.cs
Normal file
133
src/Blueprints/Provider/Converters/ItemComponentsConverter.cs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers.Converters;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using SharpYaml.Serialization;
|
||||||
|
|
||||||
|
public abstract class ItemComponentsConverter<T> : YamlConverter<IValueProvider<T>> where T : struct
|
||||||
|
{
|
||||||
|
public override IValueProvider<T> Read(YamlReader reader)
|
||||||
|
{
|
||||||
|
var converter = reader.GetConverter(typeof(T));
|
||||||
|
var value = converter.Read(reader, typeof(T));
|
||||||
|
if (value is not T t)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
return new StaticCompiledNode<T>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Write(YamlWriter writer, IValueProvider<T> value) => throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
// public class ComponentBinderRegistry
|
||||||
|
// {
|
||||||
|
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
||||||
|
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
||||||
|
// {
|
||||||
|
|
||||||
|
// _binder.Add(typeof(T), componentBinder);
|
||||||
|
// }
|
||||||
|
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// var s = world.GetSignature(entity);
|
||||||
|
// for (int i = 0; i < s.Count; i++)
|
||||||
|
// {
|
||||||
|
// if (!_binder.ContainsKey(s.Components[i]))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// var binder = _binder[s.Components[i]];
|
||||||
|
// var type = s.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
||||||
|
// {
|
||||||
|
// var signature = world.GetSignature(entities[0]);
|
||||||
|
// for (int i = 1; i < entities.Length; i++)
|
||||||
|
// {
|
||||||
|
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (int i = 0; i < signature.Count; i++)
|
||||||
|
// {
|
||||||
|
// var binder = _binder[signature.Components[i]];
|
||||||
|
// var type = signature.Components[i].Type;
|
||||||
|
// var context = new BlueprintContext(){World = world};
|
||||||
|
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public abstract class DataNode//(Dictionary<string, object> Data)
|
||||||
|
// {
|
||||||
|
// public abstract DataNodeType NodeType { get; }
|
||||||
|
// // public T Get<T>(string name) => (T)Data[name];
|
||||||
|
// }
|
||||||
|
// public enum DataNodeType
|
||||||
|
// {hthous stomatitis, pharyngitis, adenitis) is a
|
||||||
|
// Value,
|
||||||
|
// Sequence,
|
||||||
|
// Mapping,
|
||||||
|
// Component
|
||||||
|
// }
|
||||||
|
// public sealed class ValueNode(object value) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Value;
|
||||||
|
|
||||||
|
// public object Value { get; set; } = value;
|
||||||
|
|
||||||
|
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
||||||
|
// }
|
||||||
|
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
||||||
|
|
||||||
|
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
||||||
|
// }
|
||||||
|
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
||||||
|
// {
|
||||||
|
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
||||||
|
|
||||||
|
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
||||||
|
|
||||||
|
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
||||||
|
// {
|
||||||
|
// var result = Values.TryGetValue(key, out var node);
|
||||||
|
// value = (T)node!;
|
||||||
|
// return result;
|
||||||
|
|
||||||
|
// }
|
||||||
|
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
||||||
|
// {
|
||||||
|
// private Dictionary<string,string> _data = new();
|
||||||
|
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
||||||
|
// {
|
||||||
|
// var i = 0;
|
||||||
|
// while (reader.ReadIsInObject(ref i))
|
||||||
|
// {
|
||||||
|
// var name = reader.ReadPropertyName();
|
||||||
|
// var value = reader.ReadString();
|
||||||
|
// _data.Add(name, value);
|
||||||
|
// }
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
// public override DataNode? Read(YamlReader reader)
|
||||||
|
// {
|
||||||
|
// // reader.pa
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(YamlWriter writer, DataNode value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
21
src/Blueprints/Provider/DefaultValueProvider.cs
Normal file
21
src/Blueprints/Provider/DefaultValueProvider.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers;
|
||||||
|
using System;
|
||||||
|
using Arch.Core;
|
||||||
|
using Arch.Core.Extensions;
|
||||||
|
|
||||||
|
public sealed class DefaultValueProvider : IValueProvider
|
||||||
|
{
|
||||||
|
private readonly object _object;
|
||||||
|
|
||||||
|
public DefaultValueProvider(Type type, object @object)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
_object = @object;
|
||||||
|
}
|
||||||
|
public ProviderMode Mode => ProviderMode.Static;
|
||||||
|
|
||||||
|
public Type Type { get; }
|
||||||
|
|
||||||
|
public Type GetProviderType() => Type;
|
||||||
|
public void Resolve(BlueprintContext context, Entity entity) => entity.Set(_object);
|
||||||
|
}
|
||||||
16
src/Blueprints/Provider/FactoryCompiledNode.cs
Normal file
16
src/Blueprints/Provider/FactoryCompiledNode.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers;
|
||||||
|
|
||||||
|
public sealed class FactoryCompiledNode<T> : IValueProvider<T>
|
||||||
|
{
|
||||||
|
public delegate void ResolveFunc(in BlueprintContext context, ref T value);
|
||||||
|
private readonly ResolveFunc _factory;
|
||||||
|
|
||||||
|
public ProviderMode Mode => ProviderMode.Modify;
|
||||||
|
|
||||||
|
public FactoryCompiledNode(ResolveFunc factory)
|
||||||
|
{
|
||||||
|
_factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resolve(BlueprintContext context, ref T value) => _factory(context, ref value);
|
||||||
|
}
|
||||||
22
src/Blueprints/Provider/IValueProvider.cs
Normal file
22
src/Blueprints/Provider/IValueProvider.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Arch.Core;
|
||||||
|
using Arch.Core.Extensions;
|
||||||
|
public interface IValueProvider
|
||||||
|
{
|
||||||
|
Type GetProviderType();
|
||||||
|
void Resolve(BlueprintContext context, Entity entity);
|
||||||
|
ProviderMode Mode { get; }
|
||||||
|
}
|
||||||
|
public interface IValueProvider<T> : IValueProvider
|
||||||
|
{
|
||||||
|
Type IValueProvider.GetProviderType() => typeof(T);
|
||||||
|
void Resolve(BlueprintContext context, ref T value);
|
||||||
|
void IValueProvider.Resolve(BlueprintContext context, Entity entity) => Resolve(context, ref entity.Get<T>());
|
||||||
|
}
|
||||||
|
public enum ProviderMode
|
||||||
|
{
|
||||||
|
Static,
|
||||||
|
Modify
|
||||||
|
}
|
||||||
14
src/Blueprints/Provider/StaticCompiledNode.cs
Normal file
14
src/Blueprints/Provider/StaticCompiledNode.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace FoodFactory.Blueprints.Providers;
|
||||||
|
|
||||||
|
public sealed class StaticCompiledNode<T> : IValueProvider<T>
|
||||||
|
{
|
||||||
|
public StaticCompiledNode(T value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Value { get; }
|
||||||
|
|
||||||
|
public void Resolve(BlueprintContext context, ref T value) => value = Value;
|
||||||
|
public ProviderMode Mode => ProviderMode.Static;
|
||||||
|
}
|
||||||
15
src/Core/Components/Converters/TagConverter.cs
Normal file
15
src/Core/Components/Converters/TagConverter.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace FoodFactory.Core.Components.Converters;
|
||||||
|
|
||||||
|
using SharpYaml.Serialization;
|
||||||
|
|
||||||
|
public sealed class TagConverter : YamlConverter<Tag>
|
||||||
|
{
|
||||||
|
public override Tag Read(YamlReader reader)
|
||||||
|
{
|
||||||
|
var tag = reader.GetScalarValue();
|
||||||
|
reader.Read();
|
||||||
|
return Tag.Create(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(YamlWriter writer, Tag value) => writer.WriteScalar(value.Name);
|
||||||
|
}
|
||||||
34
src/Core/Components/Converters/TagsConverter.cs
Normal file
34
src/Core/Components/Converters/TagsConverter.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
namespace FoodFactory.Core.Components.Converters;
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using SharpYaml.Serialization;
|
||||||
|
|
||||||
|
public sealed class TagsConverter : YamlConverter<Tags>
|
||||||
|
{
|
||||||
|
public override Tags Read(YamlReader reader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != YamlTokenType.StartSequence)
|
||||||
|
{
|
||||||
|
throw new System.Exception();
|
||||||
|
}
|
||||||
|
List<string> tags = [];
|
||||||
|
reader.Read();
|
||||||
|
while (reader.TokenType != YamlTokenType.EndSequence)
|
||||||
|
{
|
||||||
|
tags.Add(reader.GetScalarValue());
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
reader.Read();
|
||||||
|
return new Tags(tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(YamlWriter writer, Tags value)
|
||||||
|
{
|
||||||
|
writer.WriteStartSequence();
|
||||||
|
foreach (var item in value)
|
||||||
|
{
|
||||||
|
writer.WriteScalar(item.Name);
|
||||||
|
}
|
||||||
|
writer.WriteEndSequence();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace FoodFactory.Items;
|
namespace FoodFactory.Core.Components;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -16,6 +16,7 @@ public readonly struct Tag : IEquatable<Tag>, IEqualityOperators<Tag, Tag, bool>
|
|||||||
Debug.Assert(id >= 0);
|
Debug.Assert(id >= 0);
|
||||||
_id = id;
|
_id = id;
|
||||||
}
|
}
|
||||||
|
public static Tag Create(string name) => TagRegistry.GetTag(name);
|
||||||
public override bool Equals([NotNullWhen(true)] object? obj) => obj is Tag tag && Equals(tag);
|
public override bool Equals([NotNullWhen(true)] object? obj) => obj is Tag tag && Equals(tag);
|
||||||
public bool Equals(Tag other) => _id == other._id;
|
public bool Equals(Tag other) => _id == other._id;
|
||||||
public override int GetHashCode() => _id;
|
public override int GetHashCode() => _id;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace FoodFactory.Items;
|
namespace FoodFactory.Core.Components;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
@@ -27,6 +27,7 @@ public readonly struct Tags : IEquatable<Tags>, IReadOnlyCollection<Tag>
|
|||||||
|
|
||||||
_index = SortAndDeduplicate(arr);
|
_index = SortAndDeduplicate(arr);
|
||||||
}
|
}
|
||||||
|
public Tags(IEnumerable<string> strings) : this([.. strings]) { }
|
||||||
public override string ToString() => $"Tags: [{string.Join(", ", _tags[_index].Select(t => t.Name))}]";
|
public override string ToString() => $"Tags: [{string.Join(", ", _tags[_index].Select(t => t.Name))}]";
|
||||||
private static readonly Dictionary<TagArrayKey, int> _internedTags = new(){[new TagArrayKey([])] = 0};
|
private static readonly Dictionary<TagArrayKey, int> _internedTags = new(){[new TagArrayKey([])] = 0};
|
||||||
private static readonly List<Tag[]> _tags = [[]];
|
private static readonly List<Tag[]> _tags = [[]];
|
||||||
@@ -50,6 +51,7 @@ public readonly struct Tags : IEquatable<Tags>, IReadOnlyCollection<Tag>
|
|||||||
{
|
{
|
||||||
_index = SortAndDeduplicate(tags);
|
_index = SortAndDeduplicate(tags);
|
||||||
}
|
}
|
||||||
|
public Tags(IEnumerable<Tag> tags) : this([.. tags]) { }
|
||||||
public Tags(ISet<Tag> tags) : this(tags.ToArray())
|
public Tags(ISet<Tag> tags) : this(tags.ToArray())
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -224,49 +226,3 @@ public static class TagRegistry
|
|||||||
// return tag;
|
// return tag;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Registry<TEntry> where TEntry : notnull
|
|
||||||
{
|
|
||||||
private readonly Dictionary<TEntry, int> _data = [];
|
|
||||||
private readonly List<TEntry> _list = [];
|
|
||||||
private readonly object _lock = new();
|
|
||||||
public IReadOnlyList<TEntry> Entries => _list;
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_data.Clear();
|
|
||||||
_list.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public int GetOrCreate(TEntry name)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_data.TryGetValue(name, out var tag))
|
|
||||||
{
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
return CreateNewKey(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public TEntry GetEntry(int index)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if ((uint)index >= (uint)_list.Count)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"The index {index} you are trying to access does not exist in the registry. The registry only has {_list.Count} of type {typeof(TEntry).Name}s");
|
|
||||||
}
|
|
||||||
return _list[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int CreateNewKey(TEntry name)
|
|
||||||
{
|
|
||||||
int index = _list.Count;
|
|
||||||
_list.Add(name);
|
|
||||||
_data[name] = index;
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
49
src/Core/Registry.cs
Normal file
49
src/Core/Registry.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
namespace FoodFactory.Core;
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class Registry<TEntry> where TEntry : notnull
|
||||||
|
{
|
||||||
|
private readonly Dictionary<TEntry, int> _data = [];
|
||||||
|
private readonly List<TEntry> _list = [];
|
||||||
|
private readonly object _lock = new();
|
||||||
|
public IReadOnlyList<TEntry> Entries => _list;
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_data.Clear();
|
||||||
|
_list.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int GetOrCreate(TEntry name)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_data.TryGetValue(name, out var tag))
|
||||||
|
{
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
return CreateNewKey(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public TEntry GetEntry(int index)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if ((uint)index >= (uint)_list.Count)
|
||||||
|
{
|
||||||
|
throw new KeyNotFoundException($"The index {index} you are trying to access does not exist in the registry. The registry only has {_list.Count} of type {typeof(TEntry).Name}s");
|
||||||
|
}
|
||||||
|
return _list[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CreateNewKey(TEntry name)
|
||||||
|
{
|
||||||
|
int index = _list.Count;
|
||||||
|
_list.Add(name);
|
||||||
|
_data[name] = index;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,7 @@ using FoodFactory.Voxel;
|
|||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
using System.Linq;
|
using FoodFactory.Blueprints;
|
||||||
using Arch.Core.Extensions;
|
|
||||||
|
|
||||||
[Meta(typeof(IAutoNode))]
|
[Meta(typeof(IAutoNode))]
|
||||||
public partial class ItemSpawner : Node3D, IProvide<IBeltPortHost>
|
public partial class ItemSpawner : Node3D, IProvide<IBeltPortHost>
|
||||||
@@ -71,7 +70,7 @@ public partial class ItemSpawner : Node3D, IProvide<IBeltPortHost>
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GD.Print(newItem.Get<Tags>());
|
// GD.Print(newItem.Get<Tags>());
|
||||||
dummyItem.Item = newItem;
|
dummyItem.Item = newItem;
|
||||||
if (!beltPort.TryInsert(dummyItem, 0))
|
if (!beltPort.TryInsert(dummyItem, 0))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Arch.Core.Extensions;
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Chickensoft.AutoInject;
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using FoodFactory;
|
using FoodFactory;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Chickensoft.AutoInject;
|
|||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using FoodFactory;
|
using FoodFactory;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
namespace FoodFactory.Items;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Arch.Core;
|
|
||||||
using Arch.Core.Extensions;
|
|
||||||
using FoodFactory.Recipes;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
public interface IDataCompiler
|
|
||||||
{
|
|
||||||
IValueProvider CompileUnTyped(object data);//Use Dicnary and have preset values
|
|
||||||
Type GetCompilerType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IDataCompiler<T> : IDataCompiler
|
|
||||||
{
|
|
||||||
IValueProvider<T> Compile(object data);
|
|
||||||
Type IDataCompiler.GetCompilerType() => typeof(T);
|
|
||||||
IValueProvider IDataCompiler.CompileUnTyped(object data) => Compile(data);
|
|
||||||
}
|
|
||||||
public interface IValueProvider
|
|
||||||
{
|
|
||||||
Type GetProviderType();
|
|
||||||
void Resolve(BlueprintContext context, Entity entity);
|
|
||||||
ProviderMode Mode { get; }
|
|
||||||
}
|
|
||||||
public enum ProviderMode
|
|
||||||
{
|
|
||||||
Static,
|
|
||||||
Modify
|
|
||||||
}
|
|
||||||
public interface IValueProvider<T> : IValueProvider
|
|
||||||
{
|
|
||||||
Type IValueProvider.GetProviderType() => typeof(T);
|
|
||||||
void Resolve(BlueprintContext context, ref T value);
|
|
||||||
void IValueProvider.Resolve(BlueprintContext context, Entity entity) => Resolve(context, ref entity.Get<T>());
|
|
||||||
}
|
|
||||||
public sealed class FactoryCompiledNode<T> : IValueProvider<T>
|
|
||||||
{
|
|
||||||
public delegate void ResolveFunc(in BlueprintContext context, ref T value);
|
|
||||||
private readonly ResolveFunc _factory;
|
|
||||||
|
|
||||||
public ProviderMode Mode => ProviderMode.Modify;
|
|
||||||
|
|
||||||
public FactoryCompiledNode(ResolveFunc factory)
|
|
||||||
{
|
|
||||||
_factory = factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Resolve(BlueprintContext context, ref T value) => _factory(context, ref value);
|
|
||||||
}
|
|
||||||
public sealed class StaticCompiledNode<T> : IValueProvider<T>
|
|
||||||
{
|
|
||||||
public StaticCompiledNode(T value)
|
|
||||||
{
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Value { get; }
|
|
||||||
|
|
||||||
public void Resolve(BlueprintContext context, ref T value) => value = Value;
|
|
||||||
public ProviderMode Mode => ProviderMode.Static;
|
|
||||||
}
|
|
||||||
public sealed class StaticReflectionCompiledNode<T> : IValueProvider<T> where T : struct
|
|
||||||
{
|
|
||||||
//TODO Make more performance by only having properties of each method, and share use a list using tuples instead.
|
|
||||||
// private readonly Dictionary<string, object> _data;
|
|
||||||
private readonly T _template;
|
|
||||||
|
|
||||||
public StaticReflectionCompiledNode(Dictionary<string, object> itemData)
|
|
||||||
{
|
|
||||||
StructReflection.ApplyValues(ref _template, itemData);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Resolve(BlueprintContext context, ref T value) => value = _template;
|
|
||||||
public ProviderMode Mode => ProviderMode.Static;
|
|
||||||
|
|
||||||
}
|
|
||||||
public sealed class RuntimeReflectionCompiledNode<T> : IValueProvider<T> where T : struct
|
|
||||||
{
|
|
||||||
//TODO Make more performance by only having properties of each method, and share use a list using tuples instead.
|
|
||||||
private readonly Dictionary<string, object> _data;
|
|
||||||
// private readonly T _template;
|
|
||||||
|
|
||||||
public RuntimeReflectionCompiledNode(Dictionary<string, object> itemData)
|
|
||||||
{
|
|
||||||
_data = itemData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Resolve(BlueprintContext context, ref T value) => StructReflection.ApplyValues(ref value, _data);
|
|
||||||
public ProviderMode Mode => ProviderMode.Modify;
|
|
||||||
|
|
||||||
}
|
|
||||||
public class CompiledBlueprint
|
|
||||||
{
|
|
||||||
public string Id { get; init; }
|
|
||||||
public Tags Traits { get; set; }
|
|
||||||
public IValueProvider[][] Providers = [];
|
|
||||||
public Signature Signature;
|
|
||||||
public Entity CreateEmptyItem(BlueprintContext blueprintContext) => blueprintContext.World.Create(Signature);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using Arch.Core;
|
using Arch.Core;
|
||||||
using Arch.Core.Extensions;
|
using Arch.Core.Extensions;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using Godot;
|
using Godot;
|
||||||
using SJK.Functional;
|
using SJK.Functional;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ namespace FoodFactory.Items;
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using FoodFactory.Blueprints.Providers;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
using SharpYaml;
|
using SharpYaml;
|
||||||
@@ -12,7 +14,7 @@ public class ItemData
|
|||||||
public string Id { get; set; } = "";
|
public string Id { get; set; } = "";
|
||||||
public string[] Extend { get; set; } = [];
|
public string[] Extend { get; set; } = [];
|
||||||
[YamlConverter(typeof(ComponentsPatcherConverter))]
|
[YamlConverter(typeof(ComponentsPatcherConverter))]
|
||||||
public Dictionary<string, object> Components { get; set; } = [];
|
public Dictionary<string, IValueProvider> Components { get; set; } = [];
|
||||||
public HashSet<string> Remove { get; set; } = [];
|
public HashSet<string> Remove { get; set; } = [];
|
||||||
// public DataNode GetComponent(Type type)
|
// public DataNode GetComponent(Type type)
|
||||||
// {
|
// {
|
||||||
@@ -29,12 +31,12 @@ public class ItemData
|
|||||||
// public DataNode GetComponent<T>() where T : struct => GetComponent(typeof(T));
|
// public DataNode GetComponent<T>() where T : struct => GetComponent(typeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ComponentsPatcherConverter : YamlConverter<Dictionary<string, object>>
|
public class ComponentsPatcherConverter : YamlConverter<Dictionary<string, IValueProvider>>
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, Type> _componentsTypes = new(){
|
private readonly Dictionary<string, Type> _componentsTypes = new(){
|
||||||
[nameof(Temperature)] = typeof(IValueProvider<Temperature>),
|
[nameof(Temperature)] = typeof(IValueProvider<Temperature>),
|
||||||
// [nameof(Tags)] = typeof(IValueProvider<Tags>),
|
[nameof(Tags)] = typeof(IValueProvider<Tags>),
|
||||||
// [nameof(Name)] = typeof(IValueProvider<Name>),
|
[nameof(Name)] = typeof(IValueProvider<Name>),
|
||||||
// [nameof(Mass)] = typeof(IValueProvider<Mass>),
|
// [nameof(Mass)] = typeof(IValueProvider<Mass>),
|
||||||
// [nameof(Godot.Color)] = typeof(IValueProvider<Godot.Color>),
|
// [nameof(Godot.Color)] = typeof(IValueProvider<Godot.Color>),
|
||||||
// [nameof(BurnableTemp)] = typeof(IValueProvider<BurnableTemp>),
|
// [nameof(BurnableTemp)] = typeof(IValueProvider<BurnableTemp>),
|
||||||
@@ -45,9 +47,9 @@ public class ComponentsPatcherConverter : YamlConverter<Dictionary<string, objec
|
|||||||
// _componentsTypes = componentsTypes;
|
// _componentsTypes = componentsTypes;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public override Dictionary<string, object>? Read(YamlReader reader)
|
public override Dictionary<string, IValueProvider>? Read(YamlReader reader)
|
||||||
{
|
{
|
||||||
var dict = new Dictionary<string,object>();
|
var dict = new Dictionary<string,IValueProvider>();
|
||||||
if (reader.TokenType == YamlTokenType.StartMapping)
|
if (reader.TokenType == YamlTokenType.StartMapping)
|
||||||
{
|
{
|
||||||
reader.Read();
|
reader.Read();
|
||||||
@@ -65,15 +67,17 @@ public class ComponentsPatcherConverter : YamlConverter<Dictionary<string, objec
|
|||||||
if (!reader.TryGetCustomConverter(type, out var converter)){
|
if (!reader.TryGetCustomConverter(type, out var converter)){
|
||||||
converter = reader.GetConverter(type);
|
converter = reader.GetConverter(type);
|
||||||
}
|
}
|
||||||
object data;
|
object data = converter.Read(reader, type);
|
||||||
data = converter.Read(reader, type);
|
if (data is not IValueProvider)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// reader.Read();
|
// reader.Read();
|
||||||
dict[key] = data;
|
dict[key] = (IValueProvider)data;
|
||||||
|
|
||||||
}
|
}
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(YamlWriter writer, Dictionary<string, object> value) => throw new NotImplementedException();
|
public override void Write(YamlWriter writer, Dictionary<string, IValueProvider> value) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using Arch.LowLevel;
|
|||||||
using Arch.Persistence;
|
using Arch.Persistence;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using Chickensoft.SaveFileBuilder;
|
using Chickensoft.SaveFileBuilder;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
|
|||||||
@@ -36,16 +36,19 @@ public record struct Fahrenheit(double Value)
|
|||||||
{
|
{
|
||||||
public static implicit operator Fahrenheit(double value) => new(value);
|
public static implicit operator Fahrenheit(double value) => new(value);
|
||||||
public static implicit operator Temperature(Fahrenheit value) => new(value);
|
public static implicit operator Temperature(Fahrenheit value) => new(value);
|
||||||
|
public override readonly string ToString() => $"{Value}°F";
|
||||||
}
|
}
|
||||||
public record struct Celsius(double Value)
|
public record struct Celsius(double Value)
|
||||||
{
|
{
|
||||||
public static implicit operator Celsius(double value) => new(value);
|
public static implicit operator Celsius(double value) => new(value);
|
||||||
public static implicit operator Temperature(Celsius value) => new(value);
|
public static implicit operator Temperature(Celsius value) => new(value);
|
||||||
|
public override readonly string ToString() => $"{Value}°C";
|
||||||
}
|
}
|
||||||
public record struct Kelvin(double Value)
|
public record struct Kelvin(double Value)
|
||||||
{
|
{
|
||||||
public static implicit operator Kelvin(double value) => new(value);
|
public static implicit operator Kelvin(double value) => new(value);
|
||||||
public static implicit operator Temperature(Kelvin value) => new(value);
|
public static implicit operator Temperature(Kelvin value) => new(value);
|
||||||
|
public override readonly string ToString() => $"{Value}°K";
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A temperature value.
|
/// A temperature value.
|
||||||
|
|||||||
@@ -1,545 +0,0 @@
|
|||||||
namespace FoodFactory.Recipes;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Arch.Core;
|
|
||||||
using Arch.Core.Extensions;
|
|
||||||
using FoodFactory.Items;
|
|
||||||
using FoodFactory.Math;
|
|
||||||
using FoodFactory.Voxel;
|
|
||||||
using Godot;
|
|
||||||
using SharpYaml;
|
|
||||||
using SharpYaml.Model;
|
|
||||||
using SharpYaml.Serialization;
|
|
||||||
using SJK.Functional;
|
|
||||||
using Utf8Json;
|
|
||||||
|
|
||||||
public interface IBlueprintManger
|
|
||||||
{
|
|
||||||
Blueprint GetBlueprint(string name);
|
|
||||||
CompiledBlueprint GetCompiledBlueprint(string name);
|
|
||||||
// ComponentBinderRegistry BinderRegistry { get; }
|
|
||||||
}
|
|
||||||
public class BlueprintManger : IBlueprintManger
|
|
||||||
{
|
|
||||||
// private readonly Dictionary<string, Blueprint> _bluePrints = [];
|
|
||||||
// public readonly ComponentBinderRegistry ComponentBinder = new();
|
|
||||||
public readonly Dictionary<string, Blueprint> Blueprints = [];
|
|
||||||
public readonly Dictionary<string, CompiledBlueprint> CompiledBlueprints = [];
|
|
||||||
public readonly Dictionary<string, IDataCompiler> Providers = [];
|
|
||||||
|
|
||||||
// public ComponentBinderRegistry BinderRegistry { get; }
|
|
||||||
|
|
||||||
public BlueprintManger()
|
|
||||||
{
|
|
||||||
// BinderRegistry = new ComponentBinderRegistry();
|
|
||||||
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<Temperature>());
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<Tags>());
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<BurnableTemp>());
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<Bacteria>());
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<Mass>());
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<Carbohydrates>());
|
|
||||||
// BinderRegistry.Add(new ComponentBinder<Name>());
|
|
||||||
|
|
||||||
// Providers.Add(nameof(Temperature), new TemperatureCompiler());
|
|
||||||
Providers.Add(nameof(Tags), new TagsCompiler());
|
|
||||||
Providers.Add(nameof(Name), new NameCompiler());
|
|
||||||
Providers.Add(nameof(Mass), new DefaultCompiler<Mass>());
|
|
||||||
Providers.Add(nameof(Color), new DefaultCompiler<Color>());
|
|
||||||
Providers.Add(nameof(BurnableTemp), new DefaultConverterCompiler<BurnableTemp>(){Converter = data =>
|
|
||||||
{
|
|
||||||
if (data is Dictionary<string,object> dict){
|
|
||||||
if (dict.TryGetValue(nameof(BurnableTemp.Temperature), out var value))
|
|
||||||
{
|
|
||||||
dict[nameof(BurnableTemp.Temperature)] = new Temperature((double)value);
|
|
||||||
}
|
|
||||||
return dict;
|
|
||||||
}
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var root = "/home/ronnie/Documents/Godot/Projects/ChickenGameTest/mods";
|
|
||||||
var dir = DirAccess.Open(root);
|
|
||||||
var cache = new Dictionary<string, CompiledBlueprint>();
|
|
||||||
var types = Assembly.GetAssembly(typeof(Name)).GetTypes();//Temperary mesure
|
|
||||||
var itemDatas = new List<ItemData>();
|
|
||||||
|
|
||||||
var options = new YamlSerializerOptions()
|
|
||||||
{
|
|
||||||
Converters = [
|
|
||||||
// new ComponentsPatcherConverter(
|
|
||||||
// new(){
|
|
||||||
// [nameof(Temperature)] = typeof(IValueProvider<Temperature>),
|
|
||||||
// [nameof(Tags)] = typeof(IValueProvider<Tags>),
|
|
||||||
// [nameof(Name)] = typeof(IValueProvider<Name>),
|
|
||||||
// [nameof(Mass)] = typeof(IValueProvider<Mass>),
|
|
||||||
// [nameof(Color)] = typeof(IValueProvider<Color>),
|
|
||||||
// [nameof(BurnableTemp)] = typeof(IValueProvider<BurnableTemp>),
|
|
||||||
// }
|
|
||||||
// ),
|
|
||||||
new TemperatureCompiler(),
|
|
||||||
|
|
||||||
]
|
|
||||||
};
|
|
||||||
foreach (var item in dir.GetFiles())
|
|
||||||
{
|
|
||||||
if (item.EndsWith(".yaml"))
|
|
||||||
{
|
|
||||||
var file = FileAccess.Open(dir.GetCurrentDir() + "/" + item, FileAccess.ModeFlags.Read);
|
|
||||||
var data = YamlSerializer.Deserialize<ItemData>(file.GetAsText(),options);
|
|
||||||
itemDatas.Add(data);
|
|
||||||
// var compiledBlueprint = new CompiledBlueprint
|
|
||||||
// {
|
|
||||||
// // Id = data.Id,
|
|
||||||
// // Signature = new Signature([typeof(BlueprintId), .. types.Where(f => data.Components.ContainsKey(f.Name)).Select(Component.GetComponentType)]),
|
|
||||||
// // Providers = new IValueProvider[data.Components.Count]
|
|
||||||
// // };
|
|
||||||
// // var i = 0;
|
|
||||||
// // foreach (var item2 in data.Components)
|
|
||||||
// // {
|
|
||||||
// // var compiler = Providers[item2.Key];
|
|
||||||
// // var compiled = compiler.CompileUnTyped(item2.Value);
|
|
||||||
// // compiledBlueprint.Providers[i] = compiled;
|
|
||||||
// // i++;
|
|
||||||
// // }
|
|
||||||
// CompiledBlueprints.Add(compiledBlueprint.Id, compiledBlueprint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CompiledBlueprints = LoadBluprints([.. itemDatas]);
|
|
||||||
}
|
|
||||||
private Dictionary<string, CompiledBlueprint> LoadBluprints(ItemData[] all, Dictionary<string, CompiledBlueprint>? existing = null)
|
|
||||||
{
|
|
||||||
var completed = existing is not null ? new(existing) : new Dictionary<string,CompiledBlueprint>();
|
|
||||||
var queue = new Queue<ItemData>(all);
|
|
||||||
while (queue.Any())
|
|
||||||
{
|
|
||||||
reset:
|
|
||||||
var item = queue.Dequeue();
|
|
||||||
var sources = new List<CompiledBlueprint>();
|
|
||||||
foreach (var c in item.Extend)
|
|
||||||
{
|
|
||||||
if (!completed.ContainsKey(c))
|
|
||||||
{
|
|
||||||
queue.Enqueue(item);
|
|
||||||
goto reset;
|
|
||||||
}
|
|
||||||
sources.Add(completed[c]);
|
|
||||||
}
|
|
||||||
var providers = new Dictionary<Type, List<IValueProvider>>();//TODO Make Blupritns able to hold muiple providers in a array for cases taht build off previouse providers
|
|
||||||
foreach (var blueprint in sources)
|
|
||||||
{
|
|
||||||
foreach (var provider in blueprint.Providers)
|
|
||||||
{
|
|
||||||
if (item.Remove.Contains(provider[0].GetProviderType().Name))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!providers.TryGetValue(provider[0].GetProviderType(), out var providersList))
|
|
||||||
{
|
|
||||||
providers[provider[0].GetProviderType()] = providersList = new();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < provider.Length; i++)
|
|
||||||
{
|
|
||||||
if (provider[i].Mode == ProviderMode.Static)
|
|
||||||
{
|
|
||||||
providersList.Clear();
|
|
||||||
providersList.Add(provider[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var component in item.Components)
|
|
||||||
{
|
|
||||||
var compiler = Providers[component.Key];
|
|
||||||
var compiledProvider = compiler.CompileUnTyped(component.Value);
|
|
||||||
if (!providers.TryGetValue(compiledProvider.GetProviderType(), out var providersList))
|
|
||||||
{
|
|
||||||
providers[compiledProvider.GetProviderType()] = providersList = new();
|
|
||||||
}
|
|
||||||
providersList.Add(compiledProvider);
|
|
||||||
}
|
|
||||||
var compiled = new CompiledBlueprint()
|
|
||||||
{
|
|
||||||
Id = item.Id,
|
|
||||||
// Traits = new Tags([.. item.Components.Keys]),//TODO need a way for recipies to look in each 'parent/extend' for getting recipes, either iterating each parent pool(recipe behing only in max shared, or each buckert container a copy for each parent)
|
|
||||||
Signature = [.. providers.Keys],
|
|
||||||
Providers = [.. providers.Values.Select(list => list.ToArray())],
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
ex Food-> onion -> red onion
|
|
||||||
if onion id, then onion and red onion bucket have a recipe
|
|
||||||
of for each trait, iterate each bucket, starting from spefic, to top.
|
|
||||||
*/
|
|
||||||
completed.Add(item.Id, compiled);
|
|
||||||
}
|
|
||||||
return completed;
|
|
||||||
}
|
|
||||||
public CompiledBlueprint? GetCompiledBlueprint(string id)
|
|
||||||
|
|
||||||
{
|
|
||||||
if (CompiledBlueprints.TryGetValue(id, out var compiledBlueprint))
|
|
||||||
{
|
|
||||||
return compiledBlueprint;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
public Blueprint GetBlueprint(string name)
|
|
||||||
{
|
|
||||||
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
if (!Blueprints.TryGetValue(name, out var blueprint))
|
|
||||||
{
|
|
||||||
//TODO this is where this should look through mods/base game
|
|
||||||
if (name == "Potato")
|
|
||||||
{
|
|
||||||
blueprint = new Blueprint("Potato", static ctx => ctx.World.Create(new Name("Potato_raw"),
|
|
||||||
new Tags("potato", "raw", "vegetable", "burnable"),
|
|
||||||
new Temperature(40, TemperatureUnit.Fahrenheit),
|
|
||||||
ctx.BluePrintId,
|
|
||||||
new Bacteria(BacterialSystem.Resources.Add([new BacteriaData("slamnala", 400)])),
|
|
||||||
new BurnableTemp(new Temperature(400, TemperatureUnit.Fahrenheit))));//TODO blueprintID should not be passed, but know when blueprint is created, meaning a rework of Blueprint id register
|
|
||||||
}
|
|
||||||
else if (name == "Onion")
|
|
||||||
{
|
|
||||||
blueprint = new Blueprint("Onion", static ctx => ctx.World.Create(new Name("Onion_raw"),
|
|
||||||
new Tags("onion", "raw", "vegetable", "burnable", "sliceable"),
|
|
||||||
new Temperature(71, TemperatureUnit.Fahrenheit),
|
|
||||||
ctx.BluePrintId,
|
|
||||||
new BurnableTemp(new Temperature(400, TemperatureUnit.Fahrenheit)),
|
|
||||||
new Mass(Weight.FromGrams(110)),
|
|
||||||
new Carbohydrates(Fiber: 2, Starch: 3, Sugars: new(Glucose: 0, Fructose: 1.2f, Sucrose: 1, Lactose: 0))
|
|
||||||
));//TODO blueprintID should not be passed, but know when blueprint is created, meaning a rework of Blueprint id register
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return blueprint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// public record Blueprint(string Name, Func<BlueprintContext, Entity> Factory)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
public record Blueprint(string Name, Func<BlueprintContext, Entity> Factory)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct BlueprintContext
|
|
||||||
{
|
|
||||||
public World World;
|
|
||||||
public BlueprintId BluePrintId;
|
|
||||||
public object PlaceHolderApi;
|
|
||||||
}
|
|
||||||
// public interface IComponentBinder
|
|
||||||
// {
|
|
||||||
// ComponentType ComponentType { get; }
|
|
||||||
// void ApplyUntyped(
|
|
||||||
// Entity existing,
|
|
||||||
// IValueProvider data,
|
|
||||||
// BlueprintContext context);
|
|
||||||
// void ApplyUntyped(
|
|
||||||
// Span<Entity> existing,
|
|
||||||
// IValueProvider data,
|
|
||||||
// BlueprintContext context);
|
|
||||||
// }
|
|
||||||
// public class ComponentBinder<T> : IComponentBinder where T : struct
|
|
||||||
// {
|
|
||||||
// public ComponentType ComponentType => Component<T>.ComponentType;
|
|
||||||
|
|
||||||
// public void ApplyUntyped(
|
|
||||||
// Entity existing,
|
|
||||||
// IValueProvider data,
|
|
||||||
// BlueprintContext context)
|
|
||||||
// {
|
|
||||||
// if (data is IValueProvider<T> dataT)
|
|
||||||
// {
|
|
||||||
// ref var component = ref context.World.Get<T>(existing);
|
|
||||||
// Apply(ref component, dataT, context);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// throw new System.Exception();
|
|
||||||
// }
|
|
||||||
// public void ApplyUntyped(Span<Entity> existing, IValueProvider data, BlueprintContext context)
|
|
||||||
// {
|
|
||||||
// if (data is not IValueProvider<T> dataT)
|
|
||||||
// {
|
|
||||||
// throw new System.Exception();
|
|
||||||
// }
|
|
||||||
// for (int i = 0; i < existing.Length; i++)
|
|
||||||
// {
|
|
||||||
// Apply(ref existing[i].Get<T>(), dataT, context);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void Apply(
|
|
||||||
// ref T existing,
|
|
||||||
// IValueProvider<T> data,
|
|
||||||
// BlueprintContext context) => data.Resolve(context, ref existing);
|
|
||||||
// }
|
|
||||||
// public class DefaultBinder<T> : ComponentBinder<T> where T : struct
|
|
||||||
// {
|
|
||||||
// public override void Apply(ref T existing, IValueProvider<T> data, BlueprintContext context);
|
|
||||||
|
|
||||||
// }
|
|
||||||
// public class TemperatureBinder : ComponentBinder<Temperature>
|
|
||||||
// {
|
|
||||||
// public override void Apply(ref Temperature existing, IValueProvider<Temperature> data, BlueprintContext context) => data.Resolve(context, ref existing);
|
|
||||||
|
|
||||||
// }
|
|
||||||
public sealed class TemperatureCompiler : YamlConverter<IValueProvider<Temperature>>//, IDataCompiler<Temperature>
|
|
||||||
{
|
|
||||||
// public IValueProvider<Temperature> Compile(object data)
|
|
||||||
// {
|
|
||||||
// if (data is IValueProvider<Temperature> t)
|
|
||||||
// {
|
|
||||||
// return t;
|
|
||||||
// }
|
|
||||||
// if (data is string says)
|
|
||||||
// {
|
|
||||||
// if (says == "ambient")
|
|
||||||
// {
|
|
||||||
// return new AmbientTemperatureProvider();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (data is float f)
|
|
||||||
// {
|
|
||||||
// return new StaticCompiledNode<Temperature>(new Temperature(f));
|
|
||||||
// }
|
|
||||||
// if (data is double d)
|
|
||||||
// {
|
|
||||||
// return new StaticCompiledNode<Temperature>(new Temperature(d));
|
|
||||||
// }
|
|
||||||
// if (data is Dictionary<string, object> dict)
|
|
||||||
// {
|
|
||||||
// return new StaticReflectionCompiledNode<Temperature>(dict);
|
|
||||||
|
|
||||||
// }
|
|
||||||
// throw new NotSupportedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public override IValueProvider<Temperature>? Read(YamlReader reader)
|
|
||||||
{
|
|
||||||
if (reader.TokenType == YamlTokenType.Scalar)
|
|
||||||
{
|
|
||||||
var value = reader.ScalarValue;
|
|
||||||
reader.Read();
|
|
||||||
if (value == "ambient")
|
|
||||||
{
|
|
||||||
return new AmbientTemperatureProvider();
|
|
||||||
}
|
|
||||||
if (float.TryParse(value, out var f))
|
|
||||||
{
|
|
||||||
return new StaticCompiledNode<Temperature>(new Temperature(f));
|
|
||||||
}
|
|
||||||
if (double.TryParse(value, out var d))
|
|
||||||
{
|
|
||||||
return new StaticCompiledNode<Temperature>(new Temperature(f));
|
|
||||||
}
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
if (reader.TokenType == YamlTokenType.StartMapping)
|
|
||||||
{
|
|
||||||
reader.Read();
|
|
||||||
IValueProvider<Temperature>? provider = null;
|
|
||||||
while (reader.TokenType != YamlTokenType.EndMapping)
|
|
||||||
{
|
|
||||||
var key = reader.ScalarValue;
|
|
||||||
reader.Read();
|
|
||||||
if (key == nameof(Fahrenheit))
|
|
||||||
{
|
|
||||||
provider = new StaticCompiledNode<Temperature>(new Fahrenheit(float.Parse(reader.ScalarValue)));
|
|
||||||
}
|
|
||||||
reader.Read();
|
|
||||||
}
|
|
||||||
return provider??throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(YamlWriter writer, IValueProvider<Temperature> value) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
public sealed class AmbientTemperatureProvider : IValueProvider<Temperature>
|
|
||||||
{
|
|
||||||
public ProviderMode Mode => ProviderMode.Static;
|
|
||||||
|
|
||||||
public void Resolve(BlueprintContext context, ref Temperature value)
|
|
||||||
{
|
|
||||||
value.Kelvin = (float)context.PlaceHolderApi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public sealed class DefaultCompiler<T> : IDataCompiler<T> where T : struct
|
|
||||||
{
|
|
||||||
|
|
||||||
public IValueProvider<T> Compile(object data) => new StaticReflectionCompiledNode<T>(data as Dictionary<string, object>);
|
|
||||||
}
|
|
||||||
public sealed class DefaultConverterCompiler<T> : IDataCompiler<T> where T : struct
|
|
||||||
{
|
|
||||||
public required Func<object, Dictionary<string, object>> Converter { get; set; }
|
|
||||||
public IValueProvider<T> Compile(object data) => new StaticReflectionCompiledNode<T>(Converter(data));
|
|
||||||
}
|
|
||||||
public sealed class NameCompiler : IDataCompiler<Name>
|
|
||||||
{
|
|
||||||
public IValueProvider<Name> Compile(object data)
|
|
||||||
{
|
|
||||||
if (data is string s)
|
|
||||||
{
|
|
||||||
return new StaticCompiledNode<Name>(new(s));
|
|
||||||
}
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public sealed class TagsCompiler : IDataCompiler<Tags>
|
|
||||||
{
|
|
||||||
public IValueProvider<Tags> Compile(object data)
|
|
||||||
{
|
|
||||||
if (data is List<object> list)
|
|
||||||
{
|
|
||||||
var cast = list.Cast<string>().ToArray();
|
|
||||||
Tags tag = new(cast);
|
|
||||||
return new StaticCompiledNode<Tags>(tag);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (data is Dictionary<string,object> dict)
|
|
||||||
{
|
|
||||||
var tagsWith = new string[0];
|
|
||||||
if (dict.TryGetValue("With", out var with))
|
|
||||||
{
|
|
||||||
tagsWith = ((List<object>)with).Cast<string>().ToArray();
|
|
||||||
}
|
|
||||||
var tagsWiothout = new string[0];
|
|
||||||
if (dict.TryGetValue("Except", out var except))
|
|
||||||
{
|
|
||||||
tagsWiothout = ((List<object>)except).Cast<string>().ToArray();
|
|
||||||
}
|
|
||||||
return new FactoryCompiledNode<Tags>((in context, ref tags) =>
|
|
||||||
{
|
|
||||||
tags = tags.With(tagsWith).WithOut(tagsWiothout);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// public class ComponentBinderRegistry
|
|
||||||
// {
|
|
||||||
// private readonly Dictionary<ComponentType, IComponentBinder> _binder = [];
|
|
||||||
// public void Add<T>(ComponentBinder<T> componentBinder) where T : struct
|
|
||||||
// {
|
|
||||||
|
|
||||||
// _binder.Add(typeof(T), componentBinder);
|
|
||||||
// }
|
|
||||||
// public void Apply(Entity entity, World world, CompiledBlueprint itemData)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// var s = world.GetSignature(entity);
|
|
||||||
// for (int i = 0; i < s.Count; i++)
|
|
||||||
// {
|
|
||||||
// if (!_binder.ContainsKey(s.Components[i]))
|
|
||||||
// {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// var binder = _binder[s.Components[i]];
|
|
||||||
// var type = s.Components[i].Type;
|
|
||||||
// var context = new BlueprintContext(){World = world};
|
|
||||||
// binder.ApplyUntyped(entity, itemData.Providers[type], context);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// public void Apply(Span<Entity> entities, World world, CompiledBlueprint itemData)
|
|
||||||
// {
|
|
||||||
// var signature = world.GetSignature(entities[0]);
|
|
||||||
// for (int i = 1; i < entities.Length; i++)
|
|
||||||
// {
|
|
||||||
// Debug.Assert(world.GetSignature(entities[i]) == signature);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (int i = 0; i < signature.Count; i++)
|
|
||||||
// {
|
|
||||||
// var binder = _binder[signature.Components[i]];
|
|
||||||
// var type = signature.Components[i].Type;
|
|
||||||
// var context = new BlueprintContext(){World = world};
|
|
||||||
// binder.ApplyUntyped(entities, itemData.Providers[type], context);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
// public abstract class DataNode//(Dictionary<string, object> Data)
|
|
||||||
// {
|
|
||||||
// public abstract DataNodeType NodeType { get; }
|
|
||||||
// // public T Get<T>(string name) => (T)Data[name];
|
|
||||||
// }
|
|
||||||
// public enum DataNodeType
|
|
||||||
// {hthous stomatitis, pharyngitis, adenitis) is a
|
|
||||||
// Value,
|
|
||||||
// Sequence,
|
|
||||||
// Mapping,
|
|
||||||
// Component
|
|
||||||
// }
|
|
||||||
// public sealed class ValueNode(object value) : DataNode
|
|
||||||
// {
|
|
||||||
// public override DataNodeType NodeType => DataNodeType.Value;
|
|
||||||
|
|
||||||
// public object Value { get; set; } = value;
|
|
||||||
|
|
||||||
// public Option<T> As<T>() => Value is T o?Option<T>.Some(o):Option<T>.None;
|
|
||||||
// }
|
|
||||||
// public sealed class SequenceNode(IReadOnlyList<DataNode> values) : DataNode
|
|
||||||
// {
|
|
||||||
// public override DataNodeType NodeType => DataNodeType.Sequence;
|
|
||||||
|
|
||||||
// public IReadOnlyList<DataNode> Values { get; set; } = values;
|
|
||||||
// }
|
|
||||||
// public sealed class MappingNode(IReadOnlyDictionary<string, DataNode> values) : DataNode
|
|
||||||
// {
|
|
||||||
// public override DataNodeType NodeType => DataNodeType.Mapping;
|
|
||||||
|
|
||||||
// public IReadOnlyDictionary<string, DataNode> Values { get; set; } = values;
|
|
||||||
|
|
||||||
// public bool TryGet<T>(string key, [NotNullWhen(true)] out T value) where T : DataNode
|
|
||||||
// {
|
|
||||||
// var result = Values.TryGetValue(key, out var node);
|
|
||||||
// value = (T)node!;
|
|
||||||
// return result;
|
|
||||||
|
|
||||||
// }
|
|
||||||
// public bool TryGet(string key, [NotNullWhen(true)] out DataNode node) => Values.TryGetValue(key, out node!);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public class DataNodeSerlicer : YamlConverter<DataNode>, IJsonFormatter<DataNode>
|
|
||||||
// {
|
|
||||||
// private Dictionary<string,string> _data = new();
|
|
||||||
// public DataNode Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
|
|
||||||
// {
|
|
||||||
// var i = 0;
|
|
||||||
// while (reader.ReadIsInObject(ref i))
|
|
||||||
// {
|
|
||||||
// var name = reader.ReadPropertyName();
|
|
||||||
// var value = reader.ReadString();
|
|
||||||
// _data.Add(name, value);
|
|
||||||
// }
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
// public void Serialize(ref JsonWriter writer, DataNode value, IJsonFormatterResolver formatterResolver) => throw new NotImplementedException();
|
|
||||||
|
|
||||||
// public override DataNode? Read(YamlReader reader)
|
|
||||||
// {
|
|
||||||
// // reader.pa
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void Write(YamlWriter writer, DataNode value)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
namespace FoodFactory.Recipes;
|
|
||||||
|
|
||||||
using FoodFactory.Items;
|
|
||||||
|
|
||||||
public readonly record struct BlueprintId
|
|
||||||
{
|
|
||||||
public readonly int Id;
|
|
||||||
public Blueprint Blueprint() => _registry.GetEntry(Id);
|
|
||||||
private static readonly Registry<Blueprint> _registry = new();
|
|
||||||
public BlueprintId(Blueprint blueprint)
|
|
||||||
{
|
|
||||||
Id = _registry.GetOrCreate(blueprint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,8 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Arch.Core;
|
using Arch.Core;
|
||||||
|
using FoodFactory.Blueprints;
|
||||||
|
using FoodFactory.Blueprints.Providers;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ using Arch.Core;
|
|||||||
using Arch.Core.Extensions;
|
using Arch.Core.Extensions;
|
||||||
using Arch.Core.Extensions.Dangerous;
|
using Arch.Core.Extensions.Dangerous;
|
||||||
using Arch.Relationships;
|
using Arch.Relationships;
|
||||||
|
using FoodFactory.Blueprints;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Items;
|
using FoodFactory.Items;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
public abstract record Recipe(string Name, BlueprintId[]? BlueprintIds, bool[] RequireAll, Tags[] Inputs, Tags[] Exclude, RecipeOutput RecipeOutput, RecipeAction Action = default, bool InputsOrdered = true)
|
public abstract record Recipe(string Name, BlueprintId[]? BlueprintIds, bool[] RequireAll, Tags[] Inputs, Tags[] Exclude, RecipeOutput RecipeOutput, HashSet<Type>? MustHaveComponents = null, RecipeAction Action = default, bool InputsOrdered = true)
|
||||||
{
|
{
|
||||||
public abstract bool CanProcess(in RecipeContext context);
|
public abstract bool CanProcess(in RecipeContext context);
|
||||||
public abstract RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder);
|
public abstract RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ namespace FoodFactory.Recipes;
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using FoodFactory.Blueprints;
|
||||||
|
|
||||||
public sealed class RecipeBucket
|
public sealed class RecipeBucket
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using FoodFactory.Blueprints;
|
||||||
|
using FoodFactory.Core.Components;
|
||||||
using FoodFactory.Equipment;
|
using FoodFactory.Equipment;
|
||||||
using FoodFactory.Items;
|
|
||||||
using SJK.Functional;
|
using SJK.Functional;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Arch.System;
|
|||||||
using Chickensoft.AutoInject;
|
using Chickensoft.AutoInject;
|
||||||
using Chickensoft.Introspection;
|
using Chickensoft.Introspection;
|
||||||
using FoodFactory;
|
using FoodFactory;
|
||||||
|
using FoodFactory.Blueprints;
|
||||||
using FoodFactory.Conveyors;
|
using FoodFactory.Conveyors;
|
||||||
using FoodFactory.Math;
|
using FoodFactory.Math;
|
||||||
using FoodFactory.Recipes;
|
using FoodFactory.Recipes;
|
||||||
|
|||||||
Reference in New Issue
Block a user