diff --git a/src/Api/IFoodFactoryApi.cs b/src/Api/IFoodFactoryApi.cs index 0bc9d11..cc0b165 100644 --- a/src/Api/IFoodFactoryApi.cs +++ b/src/Api/IFoodFactoryApi.cs @@ -2,6 +2,7 @@ namespace FoodFactory; using System; using System.Collections.Generic; +using FoodFactory.Blueprints; using FoodFactory.Conveyors; using FoodFactory.Recipes; using FoodFactory.Voxel; diff --git a/src/Blueprints/Blueprint.cs b/src/Blueprints/Blueprint.cs new file mode 100644 index 0000000..d458d14 --- /dev/null +++ b/src/Blueprints/Blueprint.cs @@ -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 Factory) +// { + +// } +// public record Blueprint(string Name, Func Factory) +// { + +// } +// public class ComponentBinderRegistry +// { +// private readonly Dictionary _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Recipes/Blueprint.cs.uid b/src/Blueprints/Blueprint.cs.uid similarity index 100% rename from src/Recipes/Blueprint.cs.uid rename to src/Blueprints/Blueprint.cs.uid diff --git a/src/Blueprints/BlueprintContext.cs b/src/Blueprints/BlueprintContext.cs new file mode 100644 index 0000000..6ac26ab --- /dev/null +++ b/src/Blueprints/BlueprintContext.cs @@ -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 _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Blueprints/BlueprintId.cs b/src/Blueprints/BlueprintId.cs new file mode 100644 index 0000000..a1942a7 --- /dev/null +++ b/src/Blueprints/BlueprintId.cs @@ -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 _registry = new(); + public BlueprintId(CompiledBlueprint blueprint) + { + Id = _registry.GetOrCreate(blueprint); + } +} diff --git a/src/Recipes/BlueprintId.cs.uid b/src/Blueprints/BlueprintId.cs.uid similarity index 100% rename from src/Recipes/BlueprintId.cs.uid rename to src/Blueprints/BlueprintId.cs.uid diff --git a/src/Blueprints/BlueprintManger.cs b/src/Blueprints/BlueprintManger.cs new file mode 100644 index 0000000..2137bf2 --- /dev/null +++ b/src/Blueprints/BlueprintManger.cs @@ -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 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(); + + var options = new YamlSerializerOptions() + { + Converters = [ + // new ComponentsPatcherConverter( + // new(){ + // [nameof(Temperature)] = typeof(IValueProvider), + // [nameof(Tags)] = typeof(IValueProvider), + // [nameof(Name)] = typeof(IValueProvider), + // [nameof(Mass)] = typeof(IValueProvider), + // [nameof(Color)] = typeof(IValueProvider), + // [nameof(BurnableTemp)] = typeof(IValueProvider), + // } + // ), + 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(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 LoadBluprints(ItemData[] all, Dictionary? existing = null) + { + var completed = existing is not null ? new(existing) : new Dictionary(); + var queue = new Queue(all); + while (queue.Any()) + { + reset: + var item = queue.Dequeue(); + var sources = new List(); + foreach (var c in item.Extend) + { + if (!completed.ContainsKey(c)) + { + queue.Enqueue(item); + goto reset; + } + sources.Add(completed[c]); + } + var providers = new Dictionary>();//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 _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Blueprints/CompiledBlueprint.cs b/src/Blueprints/CompiledBlueprint.cs new file mode 100644 index 0000000..be78924 --- /dev/null +++ b/src/Blueprints/CompiledBlueprint.cs @@ -0,0 +1,48 @@ +namespace FoodFactory.Blueprints; + +using Arch.Core; +using FoodFactory.Blueprints.Providers; +using FoodFactory.Core.Components; + +// public sealed class StaticReflectionCompiledNode : IValueProvider 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 _data; +// private readonly T _template; + +// public StaticReflectionCompiledNode(Dictionary 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 : IValueProvider 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 _data; +// // private readonly T _template; + +// public RuntimeReflectionCompiledNode(Dictionary 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); + +} diff --git a/src/Blueprints/Provider/Converters/ComponentTagsConverter.cs b/src/Blueprints/Provider/Converters/ComponentTagsConverter.cs new file mode 100644 index 0000000..7d02e3d --- /dev/null +++ b/src/Blueprints/Provider/Converters/ComponentTagsConverter.cs @@ -0,0 +1,162 @@ +namespace FoodFactory.Blueprints.Providers.Converters; + +using System; +using FoodFactory.Core.Components; +using SharpYaml.Serialization; +public sealed class ComponentTagsConverter : ItemComponentsConverter +{ + public override IValueProvider Read(YamlReader reader) + { + if (reader.TokenType == YamlTokenType.StartSequence) + { + if (reader.GetConverter(typeof(string[])) is not YamlConverter converter) + { + throw new Exception(); + } + return new StaticCompiledNode(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 converter) + { + throw new Exception(); + } + with = converter.Read(reader); + } + if (key == "Except") + { + if (reader.GetConverter(typeof(string[])) is not YamlConverter converter) + { + throw new Exception(); + } + exclude = converter.Read(reader); + } + reader.Read(); + } + return new FactoryCompiledNode((in factory, ref tags) => tags.With(with).WithOut(exclude)); + } + throw new NotSupportedException(); + } + + public override void Write(YamlWriter writer, IValueProvider value) => throw new NotImplementedException(); +} +// public class ComponentBinderRegistry +// { +// private readonly Dictionary _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Blueprints/Provider/Converters/ComponentTemperatureConverter.cs b/src/Blueprints/Provider/Converters/ComponentTemperatureConverter.cs new file mode 100644 index 0000000..c7ef19b --- /dev/null +++ b/src/Blueprints/Provider/Converters/ComponentTemperatureConverter.cs @@ -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 existing, +// IValueProvider data, +// BlueprintContext context); +// } +// public class ComponentBinder : IComponentBinder where T : struct +// { +// public ComponentType ComponentType => Component.ComponentType; + +// public void ApplyUntyped( +// Entity existing, +// IValueProvider data, +// BlueprintContext context) +// { +// if (data is IValueProvider dataT) +// { +// ref var component = ref context.World.Get(existing); +// Apply(ref component, dataT, context); +// return; +// } +// throw new System.Exception(); +// } +// public void ApplyUntyped(Span existing, IValueProvider data, BlueprintContext context) +// { +// if (data is not IValueProvider dataT) +// { +// throw new System.Exception(); +// } +// for (int i = 0; i < existing.Length; i++) +// { +// Apply(ref existing[i].Get(), dataT, context); +// } +// } + +// public void Apply( +// ref T existing, +// IValueProvider data, +// BlueprintContext context) => data.Resolve(context, ref existing); +// } +// public class DefaultBinder : ComponentBinder where T : struct +// { +// public override void Apply(ref T existing, IValueProvider data, BlueprintContext context); + +// } +// public class TemperatureBinder : ComponentBinder +// { +// public override void Apply(ref Temperature existing, IValueProvider data, BlueprintContext context) => data.Resolve(context, ref existing); + +// } +public sealed class ComponentTemperatureConverter : ItemComponentsConverter//, IDataCompiler +{ + // public IValueProvider Compile(object data) + // { + // if (data is IValueProvider t) + // { + // return t; + // } + // if (data is string says) + // { + // if (says == "ambient") + // { + // return new AmbientTemperatureProvider(); + // } + // } + // if (data is float f) + // { + // return new StaticCompiledNode(new Temperature(f)); + // } + // if (data is double d) + // { + // return new StaticCompiledNode(new Temperature(d)); + // } + // if (data is Dictionary dict) + // { + // return new StaticReflectionCompiledNode(dict); + + // } + // throw new NotSupportedException(); + // } + + public override IValueProvider? 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(new Temperature(f)); + } + if (double.TryParse(value, out var d)) + { + return new StaticCompiledNode(new Temperature(f)); + } + throw new NotImplementedException(); + } + if (reader.TokenType == YamlTokenType.StartMapping) + { + reader.Read(); + IValueProvider? provider = null; + while (reader.TokenType != YamlTokenType.EndMapping) + { + var key = reader.ScalarValue; + reader.Read(); + if (key == nameof(Fahrenheit)) + { + provider = new StaticCompiledNode(new Fahrenheit(float.Parse(reader.ScalarValue))); + } + if (key == nameof(Celsius)) + { + provider = new StaticCompiledNode(new Celsius(float.Parse(reader.ScalarValue))); + } + if (key == nameof(Kelvin)) + { + provider = new StaticCompiledNode(new Kelvin(float.Parse(reader.ScalarValue))); + } + reader.Read(); + } + return provider??throw new NotSupportedException(); + } + throw new NotImplementedException(); + } + + public override void Write(YamlWriter writer, IValueProvider value) => throw new NotImplementedException(); + + public sealed class AmbientTemperatureProvider : IValueProvider + { + public ProviderMode Mode => ProviderMode.Static; + + public void Resolve(BlueprintContext context, ref Temperature value) + { + value.Kelvin = (float)context.PlaceHolderApi; + } + } +} +// public class ComponentBinderRegistry +// { +// private readonly Dictionary _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Blueprints/Provider/Converters/ComponentsNameConverter.cs b/src/Blueprints/Provider/Converters/ComponentsNameConverter.cs new file mode 100644 index 0000000..72ef545 --- /dev/null +++ b/src/Blueprints/Provider/Converters/ComponentsNameConverter.cs @@ -0,0 +1,131 @@ +namespace FoodFactory.Blueprints.Providers.Converters; + +using System; +using SharpYaml.Serialization; + +public sealed class ComponentNameConverter : ItemComponentsConverter +{ + public override IValueProvider Read(YamlReader reader) + { + if (reader.TokenType == YamlTokenType.Scalar) + { + var key = reader.GetScalarValue(); + reader.Read(); + return new StaticCompiledNode(new(key)); + } + return base.Read(reader); + } + + public override void Write(YamlWriter writer, IValueProvider value) => throw new NotImplementedException(); +} +// public class ComponentBinderRegistry +// { +// private readonly Dictionary _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Blueprints/Provider/Converters/ItemComponentsConverter.cs b/src/Blueprints/Provider/Converters/ItemComponentsConverter.cs new file mode 100644 index 0000000..e8b779f --- /dev/null +++ b/src/Blueprints/Provider/Converters/ItemComponentsConverter.cs @@ -0,0 +1,133 @@ +namespace FoodFactory.Blueprints.Providers.Converters; + +using System; + +using SharpYaml.Serialization; + +public abstract class ItemComponentsConverter : YamlConverter> where T : struct +{ + public override IValueProvider 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); + } + + + public override void Write(YamlWriter writer, IValueProvider value) => throw new NotSupportedException(); +} +// public class ComponentBinderRegistry +// { +// private readonly Dictionary _binder = []; +// public void Add(ComponentBinder 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 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 Data) +// { +// public abstract DataNodeType NodeType { get; } +// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; +// } +// public sealed class SequenceNode(IReadOnlyList values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Sequence; + +// public IReadOnlyList Values { get; set; } = values; +// } +// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode +// { +// public override DataNodeType NodeType => DataNodeType.Mapping; + +// public IReadOnlyDictionary Values { get; set; } = values; + +// public bool TryGet(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, IJsonFormatter +// { +// private Dictionary _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(); +// } +// } diff --git a/src/Blueprints/Provider/DefaultValueProvider.cs b/src/Blueprints/Provider/DefaultValueProvider.cs new file mode 100644 index 0000000..0fe760c --- /dev/null +++ b/src/Blueprints/Provider/DefaultValueProvider.cs @@ -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); +} diff --git a/src/Blueprints/Provider/FactoryCompiledNode.cs b/src/Blueprints/Provider/FactoryCompiledNode.cs new file mode 100644 index 0000000..8f9327a --- /dev/null +++ b/src/Blueprints/Provider/FactoryCompiledNode.cs @@ -0,0 +1,16 @@ +namespace FoodFactory.Blueprints.Providers; + +public sealed class FactoryCompiledNode : IValueProvider +{ + 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); +} diff --git a/src/Blueprints/Provider/IValueProvider.cs b/src/Blueprints/Provider/IValueProvider.cs new file mode 100644 index 0000000..95475f1 --- /dev/null +++ b/src/Blueprints/Provider/IValueProvider.cs @@ -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 : 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()); +} +public enum ProviderMode +{ + Static, + Modify +} diff --git a/src/Blueprints/Provider/StaticCompiledNode.cs b/src/Blueprints/Provider/StaticCompiledNode.cs new file mode 100644 index 0000000..de6c091 --- /dev/null +++ b/src/Blueprints/Provider/StaticCompiledNode.cs @@ -0,0 +1,14 @@ +namespace FoodFactory.Blueprints.Providers; + +public sealed class StaticCompiledNode : IValueProvider +{ + 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; +} diff --git a/src/Core/Components/Converters/TagConverter.cs b/src/Core/Components/Converters/TagConverter.cs new file mode 100644 index 0000000..658e3bd --- /dev/null +++ b/src/Core/Components/Converters/TagConverter.cs @@ -0,0 +1,15 @@ +namespace FoodFactory.Core.Components.Converters; + +using SharpYaml.Serialization; + +public sealed class TagConverter : YamlConverter +{ + 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); +} diff --git a/src/Core/Components/Converters/TagsConverter.cs b/src/Core/Components/Converters/TagsConverter.cs new file mode 100644 index 0000000..6c9b43b --- /dev/null +++ b/src/Core/Components/Converters/TagsConverter.cs @@ -0,0 +1,34 @@ +namespace FoodFactory.Core.Components.Converters; + +using System.Collections.Generic; +using SharpYaml.Serialization; + +public sealed class TagsConverter : YamlConverter +{ + public override Tags Read(YamlReader reader) + { + if (reader.TokenType != YamlTokenType.StartSequence) + { + throw new System.Exception(); + } + List 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(); + } +} diff --git a/src/Items/Components/Tag.cs b/src/Core/Components/Tag.cs similarity index 91% rename from src/Items/Components/Tag.cs rename to src/Core/Components/Tag.cs index 79a73f3..89eeeaa 100644 --- a/src/Items/Components/Tag.cs +++ b/src/Core/Components/Tag.cs @@ -1,4 +1,4 @@ -namespace FoodFactory.Items; +namespace FoodFactory.Core.Components; using System; using System.Diagnostics; @@ -16,6 +16,7 @@ public readonly struct Tag : IEquatable, IEqualityOperators Debug.Assert(id >= 0); _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 bool Equals(Tag other) => _id == other._id; public override int GetHashCode() => _id; diff --git a/src/Items/Components/Tag.cs.uid b/src/Core/Components/Tag.cs.uid similarity index 100% rename from src/Items/Components/Tag.cs.uid rename to src/Core/Components/Tag.cs.uid diff --git a/src/Items/Components/Tags.cs b/src/Core/Components/Tags.cs similarity index 83% rename from src/Items/Components/Tags.cs rename to src/Core/Components/Tags.cs index 246272c..69708fc 100644 --- a/src/Items/Components/Tags.cs +++ b/src/Core/Components/Tags.cs @@ -1,4 +1,4 @@ -namespace FoodFactory.Items; +namespace FoodFactory.Core.Components; using System; using System.Collections; @@ -27,6 +27,7 @@ public readonly struct Tags : IEquatable, IReadOnlyCollection _index = SortAndDeduplicate(arr); } + public Tags(IEnumerable strings) : this([.. strings]) { } public override string ToString() => $"Tags: [{string.Join(", ", _tags[_index].Select(t => t.Name))}]"; private static readonly Dictionary _internedTags = new(){[new TagArrayKey([])] = 0}; private static readonly List _tags = [[]]; @@ -50,6 +51,7 @@ public readonly struct Tags : IEquatable, IReadOnlyCollection { _index = SortAndDeduplicate(tags); } + public Tags(IEnumerable tags) : this([.. tags]) { } public Tags(ISet tags) : this(tags.ToArray()) { @@ -224,49 +226,3 @@ public static class TagRegistry // return tag; // } } - -public class Registry where TEntry : notnull -{ - private readonly Dictionary _data = []; - private readonly List _list = []; - private readonly object _lock = new(); - public IReadOnlyList 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; - } -} diff --git a/src/Items/Components/Tags.cs.uid b/src/Core/Components/Tags.cs.uid similarity index 100% rename from src/Items/Components/Tags.cs.uid rename to src/Core/Components/Tags.cs.uid diff --git a/src/Core/Registry.cs b/src/Core/Registry.cs new file mode 100644 index 0000000..841c025 --- /dev/null +++ b/src/Core/Registry.cs @@ -0,0 +1,49 @@ +namespace FoodFactory.Core; + +using System.Collections.Generic; + +public class Registry where TEntry : notnull +{ + private readonly Dictionary _data = []; + private readonly List _list = []; + private readonly object _lock = new(); + public IReadOnlyList 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; + } +} diff --git a/src/Equipment/ItemSpawner.cs b/src/Equipment/ItemSpawner.cs index 801a83d..972fa5c 100644 --- a/src/Equipment/ItemSpawner.cs +++ b/src/Equipment/ItemSpawner.cs @@ -9,8 +9,7 @@ using FoodFactory.Voxel; using FoodFactory.Math; using FoodFactory.Items; using FoodFactory.Conveyors; -using System.Linq; -using Arch.Core.Extensions; +using FoodFactory.Blueprints; [Meta(typeof(IAutoNode))] public partial class ItemSpawner : Node3D, IProvide @@ -71,7 +70,7 @@ public partial class ItemSpawner : Node3D, IProvide } } - GD.Print(newItem.Get()); + // GD.Print(newItem.Get()); dummyItem.Item = newItem; if (!beltPort.TryInsert(dummyItem, 0)) { diff --git a/src/Equipment/OvenTest.cs b/src/Equipment/OvenTest.cs index 1778c29..8a735f4 100644 --- a/src/Equipment/OvenTest.cs +++ b/src/Equipment/OvenTest.cs @@ -7,6 +7,7 @@ using Arch.Core.Extensions; using Chickensoft.AutoInject; using Chickensoft.Introspection; using FoodFactory.Conveyors; +using FoodFactory.Core.Components; using FoodFactory.Items; using FoodFactory.Math; using FoodFactory.Recipes; diff --git a/src/Equipment/SlicerTest.cs b/src/Equipment/SlicerTest.cs index cb96945..e43d4c9 100644 --- a/src/Equipment/SlicerTest.cs +++ b/src/Equipment/SlicerTest.cs @@ -9,6 +9,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using FoodFactory; using FoodFactory.Conveyors; +using FoodFactory.Core.Components; using FoodFactory.Items; using FoodFactory.Math; using FoodFactory.Recipes; diff --git a/src/Equipment/StackerTest.cs b/src/Equipment/StackerTest.cs index 9d0e359..7230279 100644 --- a/src/Equipment/StackerTest.cs +++ b/src/Equipment/StackerTest.cs @@ -10,6 +10,7 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; using FoodFactory; using FoodFactory.Conveyors; +using FoodFactory.Core.Components; using FoodFactory.Items; using FoodFactory.Math; using FoodFactory.Recipes; diff --git a/src/Items/IDataCompiler.cs b/src/Items/IDataCompiler.cs deleted file mode 100644 index b1b1b92..0000000 --- a/src/Items/IDataCompiler.cs +++ /dev/null @@ -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 : IDataCompiler -{ - IValueProvider 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 : 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()); -} -public sealed class FactoryCompiledNode : IValueProvider -{ - 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 : IValueProvider -{ - 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 : IValueProvider 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 _data; - private readonly T _template; - - public StaticReflectionCompiledNode(Dictionary 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 : IValueProvider 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 _data; - // private readonly T _template; - - public RuntimeReflectionCompiledNode(Dictionary 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); - -} diff --git a/src/Items/Item.cs b/src/Items/Item.cs index 2baff0a..3f8c77e 100644 --- a/src/Items/Item.cs +++ b/src/Items/Item.cs @@ -6,6 +6,7 @@ using System.Linq; using Arch.Core; using Arch.Core.Extensions; using FoodFactory.Conveyors; +using FoodFactory.Core.Components; using FoodFactory.Math; using Godot; using SJK.Functional; diff --git a/src/Items/ItemData.cs b/src/Items/ItemData.cs index a0f48ab..0419052 100644 --- a/src/Items/ItemData.cs +++ b/src/Items/ItemData.cs @@ -2,6 +2,8 @@ namespace FoodFactory.Items; using System; using System.Collections.Generic; +using FoodFactory.Blueprints.Providers; +using FoodFactory.Core.Components; using FoodFactory.Math; using FoodFactory.Recipes; using SharpYaml; @@ -12,7 +14,7 @@ public class ItemData public string Id { get; set; } = ""; public string[] Extend { get; set; } = []; [YamlConverter(typeof(ComponentsPatcherConverter))] - public Dictionary Components { get; set; } = []; + public Dictionary Components { get; set; } = []; public HashSet Remove { get; set; } = []; // public DataNode GetComponent(Type type) // { @@ -29,12 +31,12 @@ public class ItemData // public DataNode GetComponent() where T : struct => GetComponent(typeof(T)); } -public class ComponentsPatcherConverter : YamlConverter> +public class ComponentsPatcherConverter : YamlConverter> { private readonly Dictionary _componentsTypes = new(){ [nameof(Temperature)] = typeof(IValueProvider), - // [nameof(Tags)] = typeof(IValueProvider), - // [nameof(Name)] = typeof(IValueProvider), + [nameof(Tags)] = typeof(IValueProvider), + [nameof(Name)] = typeof(IValueProvider), // [nameof(Mass)] = typeof(IValueProvider), // [nameof(Godot.Color)] = typeof(IValueProvider), // [nameof(BurnableTemp)] = typeof(IValueProvider), @@ -45,9 +47,9 @@ public class ComponentsPatcherConverter : YamlConverter? Read(YamlReader reader) + public override Dictionary? Read(YamlReader reader) { - var dict = new Dictionary(); + var dict = new Dictionary(); if (reader.TokenType == YamlTokenType.StartMapping) { reader.Read(); @@ -65,15 +67,17 @@ public class ComponentsPatcherConverter : YamlConverter value) => throw new NotImplementedException(); + public override void Write(YamlWriter writer, Dictionary value) => throw new NotImplementedException(); } diff --git a/src/Items/ItemECSTest.cs b/src/Items/ItemECSTest.cs index 1979a40..6c43cf0 100644 --- a/src/Items/ItemECSTest.cs +++ b/src/Items/ItemECSTest.cs @@ -12,6 +12,7 @@ using Arch.LowLevel; using Arch.Persistence; using Chickensoft.Introspection; using Chickensoft.SaveFileBuilder; +using FoodFactory.Core.Components; using FoodFactory.Items; using FoodFactory.Math; using FoodFactory.Recipes; diff --git a/src/Math/Temperature.cs b/src/Math/Temperature.cs index e2c7abf..5939444 100644 --- a/src/Math/Temperature.cs +++ b/src/Math/Temperature.cs @@ -36,16 +36,19 @@ public record struct Fahrenheit(double Value) { public static implicit operator Fahrenheit(double 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 static implicit operator Celsius(double 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 static implicit operator Kelvin(double value) => new(value); public static implicit operator Temperature(Kelvin value) => new(value); + public override readonly string ToString() => $"{Value}°K"; } /// /// A temperature value. diff --git a/src/Recipes/Blueprint.cs b/src/Recipes/Blueprint.cs deleted file mode 100644 index 826fb81..0000000 --- a/src/Recipes/Blueprint.cs +++ /dev/null @@ -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 _bluePrints = []; - // public readonly ComponentBinderRegistry ComponentBinder = new(); - public readonly Dictionary Blueprints = []; - public readonly Dictionary CompiledBlueprints = []; - public readonly Dictionary Providers = []; - - // public ComponentBinderRegistry BinderRegistry { get; } - - public BlueprintManger() - { - // BinderRegistry = new ComponentBinderRegistry(); - - // BinderRegistry.Add(new ComponentBinder()); - // BinderRegistry.Add(new ComponentBinder()); - // BinderRegistry.Add(new ComponentBinder()); - // BinderRegistry.Add(new ComponentBinder()); - // BinderRegistry.Add(new ComponentBinder()); - // BinderRegistry.Add(new ComponentBinder()); - // BinderRegistry.Add(new ComponentBinder()); - - // Providers.Add(nameof(Temperature), new TemperatureCompiler()); - Providers.Add(nameof(Tags), new TagsCompiler()); - Providers.Add(nameof(Name), new NameCompiler()); - Providers.Add(nameof(Mass), new DefaultCompiler()); - Providers.Add(nameof(Color), new DefaultCompiler()); - Providers.Add(nameof(BurnableTemp), new DefaultConverterCompiler(){Converter = data => - { - if (data is Dictionary 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(); - var types = Assembly.GetAssembly(typeof(Name)).GetTypes();//Temperary mesure - var itemDatas = new List(); - - var options = new YamlSerializerOptions() - { - Converters = [ - // new ComponentsPatcherConverter( - // new(){ - // [nameof(Temperature)] = typeof(IValueProvider), - // [nameof(Tags)] = typeof(IValueProvider), - // [nameof(Name)] = typeof(IValueProvider), - // [nameof(Mass)] = typeof(IValueProvider), - // [nameof(Color)] = typeof(IValueProvider), - // [nameof(BurnableTemp)] = typeof(IValueProvider), - // } - // ), - 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(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 LoadBluprints(ItemData[] all, Dictionary? existing = null) - { - var completed = existing is not null ? new(existing) : new Dictionary(); - var queue = new Queue(all); - while (queue.Any()) - { - reset: - var item = queue.Dequeue(); - var sources = new List(); - foreach (var c in item.Extend) - { - if (!completed.ContainsKey(c)) - { - queue.Enqueue(item); - goto reset; - } - sources.Add(completed[c]); - } - var providers = new Dictionary>();//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 Factory) -// { - -// } -public record Blueprint(string Name, Func 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 existing, -// IValueProvider data, -// BlueprintContext context); -// } -// public class ComponentBinder : IComponentBinder where T : struct -// { -// public ComponentType ComponentType => Component.ComponentType; - -// public void ApplyUntyped( -// Entity existing, -// IValueProvider data, -// BlueprintContext context) -// { -// if (data is IValueProvider dataT) -// { -// ref var component = ref context.World.Get(existing); -// Apply(ref component, dataT, context); -// return; -// } -// throw new System.Exception(); -// } -// public void ApplyUntyped(Span existing, IValueProvider data, BlueprintContext context) -// { -// if (data is not IValueProvider dataT) -// { -// throw new System.Exception(); -// } -// for (int i = 0; i < existing.Length; i++) -// { -// Apply(ref existing[i].Get(), dataT, context); -// } -// } - -// public void Apply( -// ref T existing, -// IValueProvider data, -// BlueprintContext context) => data.Resolve(context, ref existing); -// } -// public class DefaultBinder : ComponentBinder where T : struct -// { -// public override void Apply(ref T existing, IValueProvider data, BlueprintContext context); - -// } -// public class TemperatureBinder : ComponentBinder -// { -// public override void Apply(ref Temperature existing, IValueProvider data, BlueprintContext context) => data.Resolve(context, ref existing); - -// } -public sealed class TemperatureCompiler : YamlConverter>//, IDataCompiler -{ - // public IValueProvider Compile(object data) - // { - // if (data is IValueProvider t) - // { - // return t; - // } - // if (data is string says) - // { - // if (says == "ambient") - // { - // return new AmbientTemperatureProvider(); - // } - // } - // if (data is float f) - // { - // return new StaticCompiledNode(new Temperature(f)); - // } - // if (data is double d) - // { - // return new StaticCompiledNode(new Temperature(d)); - // } - // if (data is Dictionary dict) - // { - // return new StaticReflectionCompiledNode(dict); - - // } - // throw new NotSupportedException(); - // } - - public override IValueProvider? 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(new Temperature(f)); - } - if (double.TryParse(value, out var d)) - { - return new StaticCompiledNode(new Temperature(f)); - } - throw new NotImplementedException(); - } - if (reader.TokenType == YamlTokenType.StartMapping) - { - reader.Read(); - IValueProvider? provider = null; - while (reader.TokenType != YamlTokenType.EndMapping) - { - var key = reader.ScalarValue; - reader.Read(); - if (key == nameof(Fahrenheit)) - { - provider = new StaticCompiledNode(new Fahrenheit(float.Parse(reader.ScalarValue))); - } - reader.Read(); - } - return provider??throw new NotSupportedException(); - } - throw new NotImplementedException(); - } - - public override void Write(YamlWriter writer, IValueProvider value) => throw new NotImplementedException(); - - public sealed class AmbientTemperatureProvider : IValueProvider - { - public ProviderMode Mode => ProviderMode.Static; - - public void Resolve(BlueprintContext context, ref Temperature value) - { - value.Kelvin = (float)context.PlaceHolderApi; - } - } -} -public sealed class DefaultCompiler : IDataCompiler where T : struct -{ - - public IValueProvider Compile(object data) => new StaticReflectionCompiledNode(data as Dictionary); -} -public sealed class DefaultConverterCompiler : IDataCompiler where T : struct -{ - public required Func> Converter { get; set; } - public IValueProvider Compile(object data) => new StaticReflectionCompiledNode(Converter(data)); -} -public sealed class NameCompiler : IDataCompiler -{ - public IValueProvider Compile(object data) - { -if (data is string s) - { - return new StaticCompiledNode(new(s)); - } - throw new NotSupportedException(); - } -} -public sealed class TagsCompiler : IDataCompiler -{ - public IValueProvider Compile(object data) - { - if (data is List list) - { - var cast = list.Cast().ToArray(); - Tags tag = new(cast); - return new StaticCompiledNode(tag); - - } - if (data is Dictionary dict) - { - var tagsWith = new string[0]; - if (dict.TryGetValue("With", out var with)) - { - tagsWith = ((List)with).Cast().ToArray(); - } - var tagsWiothout = new string[0]; - if (dict.TryGetValue("Except", out var except)) - { - tagsWiothout = ((List)except).Cast().ToArray(); - } - return new FactoryCompiledNode((in context, ref tags) => - { - tags = tags.With(tagsWith).WithOut(tagsWiothout); - }); - } - throw new NotSupportedException(); - } -} -// public class ComponentBinderRegistry -// { -// private readonly Dictionary _binder = []; -// public void Add(ComponentBinder 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 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 Data) -// { -// public abstract DataNodeType NodeType { get; } -// // public T Get(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 As() => Value is T o?Option.Some(o):Option.None; -// } -// public sealed class SequenceNode(IReadOnlyList values) : DataNode -// { -// public override DataNodeType NodeType => DataNodeType.Sequence; - -// public IReadOnlyList Values { get; set; } = values; -// } -// public sealed class MappingNode(IReadOnlyDictionary values) : DataNode -// { -// public override DataNodeType NodeType => DataNodeType.Mapping; - -// public IReadOnlyDictionary Values { get; set; } = values; - -// public bool TryGet(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, IJsonFormatter -// { -// private Dictionary _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(); -// } -// } diff --git a/src/Recipes/BlueprintId.cs b/src/Recipes/BlueprintId.cs deleted file mode 100644 index 228eb70..0000000 --- a/src/Recipes/BlueprintId.cs +++ /dev/null @@ -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 _registry = new(); - public BlueprintId(Blueprint blueprint) - { - Id = _registry.GetOrCreate(blueprint); - } -} diff --git a/src/Recipes/ComponetBinder.cs b/src/Recipes/ComponetBinder.cs index 4c50c99..fffb842 100644 --- a/src/Recipes/ComponetBinder.cs +++ b/src/Recipes/ComponetBinder.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using System.Reflection; using Arch.Core; +using FoodFactory.Blueprints; +using FoodFactory.Blueprints.Providers; using FoodFactory.Items; using FoodFactory.Recipes; diff --git a/src/Recipes/Recipe.cs b/src/Recipes/Recipe.cs index 28b15b2..4870cbd 100644 --- a/src/Recipes/Recipe.cs +++ b/src/Recipes/Recipe.cs @@ -8,11 +8,13 @@ using Arch.Core; using Arch.Core.Extensions; using Arch.Core.Extensions.Dangerous; using Arch.Relationships; +using FoodFactory.Blueprints; +using FoodFactory.Core.Components; using FoodFactory.Items; using FoodFactory.Math; 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? MustHaveComponents = null, RecipeAction Action = default, bool InputsOrdered = true) { public abstract bool CanProcess(in RecipeContext context); public abstract RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder); diff --git a/src/Recipes/RecipeBucket.cs b/src/Recipes/RecipeBucket.cs index 833703b..02b180e 100644 --- a/src/Recipes/RecipeBucket.cs +++ b/src/Recipes/RecipeBucket.cs @@ -2,6 +2,7 @@ namespace FoodFactory.Recipes; using System; using System.Collections.Generic; +using FoodFactory.Blueprints; public sealed class RecipeBucket { diff --git a/src/Recipes/Recipes.cs b/src/Recipes/Recipes.cs index cdc9650..d7c9954 100644 --- a/src/Recipes/Recipes.cs +++ b/src/Recipes/Recipes.cs @@ -4,8 +4,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using FoodFactory.Blueprints; +using FoodFactory.Core.Components; using FoodFactory.Equipment; -using FoodFactory.Items; using SJK.Functional; diff --git a/src/VoxelGrid/VoxelGridNode.cs b/src/VoxelGrid/VoxelGridNode.cs index 42a00f6..5be1b50 100644 --- a/src/VoxelGrid/VoxelGridNode.cs +++ b/src/VoxelGrid/VoxelGridNode.cs @@ -8,6 +8,7 @@ using Arch.System; using Chickensoft.AutoInject; using Chickensoft.Introspection; using FoodFactory; +using FoodFactory.Blueprints; using FoodFactory.Conveyors; using FoodFactory.Math; using FoodFactory.Recipes;