diff --git a/ChickenGameTest.csproj b/ChickenGameTest.csproj
index 88056f2..a27456b 100644
--- a/ChickenGameTest.csproj
+++ b/ChickenGameTest.csproj
@@ -43,6 +43,7 @@
+
diff --git a/mods/raw_onion.yaml b/mods/raw_onion.yaml
new file mode 100644
index 0000000..316fffa
--- /dev/null
+++ b/mods/raw_onion.yaml
@@ -0,0 +1,13 @@
+Id: raw_onion
+
+# TypeMapping:
+# Tags: FoodFactory.Items.Tags
+Components:
+ Name: Raw Onion
+ Tags: ["onion", "raw", "vegetable", "burnable", "sliceable"]
+ Temperature:
+ Fahrenheit: 71.
+ # Bacteria:
+ # - salmonella: 400.
+ BurnableTemp:
+ Temperature: 477.594
diff --git a/mods/raw_potato.yaml b/mods/raw_potato.yaml
new file mode 100644
index 0000000..3fcd09c
--- /dev/null
+++ b/mods/raw_potato.yaml
@@ -0,0 +1,13 @@
+Id: raw_potato
+
+# TypeMapping:
+# Tags: FoodFactory.Items.Tags
+Components:
+ Name: Raw Potato
+ Tags: ["potato", "raw", "vegetable", "burnable"]
+ Temperature:
+ Fahrenheit: 71.
+ # Bacteria:
+ # - salmonella: 400.
+ BurnableTemp:
+ Temperature: 100.
diff --git a/mods/raw_red_onion.yaml b/mods/raw_red_onion.yaml
new file mode 100644
index 0000000..e377cfb
--- /dev/null
+++ b/mods/raw_red_onion.yaml
@@ -0,0 +1,15 @@
+Id: raw_red_onion
+
+Extend:
+ - raw_onion
+# TypeMapping:
+# Tags: FoodFactory.Items.Tags
+Components:
+ Name: Raw Red Onion
+ Color:
+ R: 1
+ G: 0
+ B: 0
+ Tags:
+ With: ["red"]
+ Except: ["sliceable"]
diff --git a/src/Equipment/ItemSpawner.cs b/src/Equipment/ItemSpawner.cs
index 8e88301..801a83d 100644
--- a/src/Equipment/ItemSpawner.cs
+++ b/src/Equipment/ItemSpawner.cs
@@ -9,6 +9,8 @@ using FoodFactory.Voxel;
using FoodFactory.Math;
using FoodFactory.Items;
using FoodFactory.Conveyors;
+using System.Linq;
+using Arch.Core.Extensions;
[Meta(typeof(IAutoNode))]
public partial class ItemSpawner : Node3D, IProvide
@@ -52,12 +54,25 @@ public partial class ItemSpawner : Node3D, IProvide
{
continue;
}
- var itemBlueprint = ItemFactory.GetBlueprint(ItemName);
+ var itemBlueprint = ItemFactory.GetCompiledBlueprint(ItemName);
var dummyItem = new TestItem();
if (beltPort.CanAccept(dummyItem, 0))
{
- var ctx = new BlueprintContext() { BluePrintId = new BlueprintId(itemBlueprint), World = World };
- dummyItem.Item = itemBlueprint.Factory(ctx);
+ var ctx = new BlueprintContext() { /*BluePrintId = new BlueprintId(itemBlueprint),*/ World = World };
+
+ var newItem = itemBlueprint.CreateEmptyItem(ctx);
+ // ItemFactory.BinderRegistry.Apply(newItem, ctx.World, itemBlueprint);
+ foreach (var providers in itemBlueprint.Providers)
+ {
+ var type = providers[0].GetProviderType();
+ for (int i = 0; i < providers.Length; i++)
+ {
+ ComponentBinder.Apply(type, newItem, providers[i], ctx);
+
+ }
+ }
+ GD.Print(newItem.Get());
+ dummyItem.Item = newItem;
if (!beltPort.TryInsert(dummyItem, 0))
{
World.Destroy(dummyItem.Item);//TODO this should not call, but not sure
diff --git a/src/Equipment/OvenTest.cs b/src/Equipment/OvenTest.cs
index 776cb59..1778c29 100644
--- a/src/Equipment/OvenTest.cs
+++ b/src/Equipment/OvenTest.cs
@@ -86,6 +86,10 @@ public partial class OvenTest : Node3D, IProvide, IProvide, IProvide port is BeltPort beltPort && beltPort.PortName == "OutPut").Bind(f => f.GetPortFacing(GridRegistry));
if (port.HasValue(out var v) && v.TryInsert(new TestItem() { Item = sliced[0] }, 0))
{
- GD.Print(sliced[0].Get());
sliced.RemoveAt(0);
}
}
diff --git a/src/Items/Components/Tags.cs b/src/Items/Components/Tags.cs
index 481707f..246272c 100644
--- a/src/Items/Components/Tags.cs
+++ b/src/Items/Components/Tags.cs
@@ -39,6 +39,7 @@ public readonly struct Tags : IEquatable, IReadOnlyCollection
var key = new TagArrayKey(tags);
if (!_internedTags.TryGetValue(key, out var interned))
{
+ interned = _internedTags.Count;
_tags.Add(tags);
_internedTags[key] = _tags.Count - 1;
}
diff --git a/src/Items/IDataCompiler.cs b/src/Items/IDataCompiler.cs
new file mode 100644
index 0000000..b1b1b92
--- /dev/null
+++ b/src/Items/IDataCompiler.cs
@@ -0,0 +1,108 @@
+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/IDataCompiler.cs.uid b/src/Items/IDataCompiler.cs.uid
new file mode 100644
index 0000000..4ab86a5
--- /dev/null
+++ b/src/Items/IDataCompiler.cs.uid
@@ -0,0 +1 @@
+uid://caur7nt65ia2o
diff --git a/src/Items/Item.cs b/src/Items/Item.cs
index f1afeb7..2baff0a 100644
--- a/src/Items/Item.cs
+++ b/src/Items/Item.cs
@@ -36,6 +36,7 @@ public class TestItem() : IBeltItem, IBeltItemData
public Node3D CreateItemVisual()
{
Node3D node;
+ var tags = Item.Get().ToArray();
if (Item.Get().Contains(TagRegistry.GetTag("potato")))
{
node = PotatoScene.Instantiate();
@@ -55,7 +56,7 @@ public class TestItem() : IBeltItem, IBeltItemData
node.GetChildren().OfType().ToList().ForEach(i => i.Scale *= new Vector3(.2f, .2f, .2f));
if (Item.TryGet(out var color))
{
- node.GetChildren().OfType().FirstOrNone().IfSome(some => some.SetSurfaceOverrideMaterial(0, new StandardMaterial3D() { AlbedoColor = Item.TryGet(out var color) ? color : Colors.White }));
+ node.GetChildren().OfType().FirstOrNone().IfSome(some => some.SetSurfaceOverrideMaterial(0, new StandardMaterial3D() { AlbedoColor = color }));
}
return node;
// return new MeshInstance3D() { Mesh = new BoxMesh() { Size = new(.1f, .1f, .1f) }, MaterialOverride = new StandardMaterial3D() { AlbedoColor = Item.TryGet(out var color) ? color : Colors.White } };
diff --git a/src/Items/ItemData.cs b/src/Items/ItemData.cs
new file mode 100644
index 0000000..a0f48ab
--- /dev/null
+++ b/src/Items/ItemData.cs
@@ -0,0 +1,79 @@
+namespace FoodFactory.Items;
+
+using System;
+using System.Collections.Generic;
+using FoodFactory.Math;
+using FoodFactory.Recipes;
+using SharpYaml;
+using SharpYaml.Serialization;
+
+public class ItemData
+{
+ public string Id { get; set; } = "";
+ public string[] Extend { get; set; } = [];
+ [YamlConverter(typeof(ComponentsPatcherConverter))]
+ public Dictionary Components { get; set; } = [];
+ public HashSet Remove { get; set; } = [];
+ // public DataNode GetComponent(Type type)
+ // {
+ // if (!Components.TryGetValue(type.Name, out var value))
+ // {
+ // throw new System.Exception();
+ // }
+ // if (value is Dictionary thing)
+ // {
+ // return new DataNode(thing);
+ // }
+ // return new DataNode(new() { ["Value"] = value });
+ // }
+ // public DataNode GetComponent() where T : struct => GetComponent(typeof(T));
+}
+
+public class ComponentsPatcherConverter : YamlConverter>
+{
+ private readonly Dictionary _componentsTypes = new(){
+ [nameof(Temperature)] = typeof(IValueProvider),
+ // [nameof(Tags)] = typeof(IValueProvider),
+ // [nameof(Name)] = typeof(IValueProvider),
+ // [nameof(Mass)] = typeof(IValueProvider),
+ // [nameof(Godot.Color)] = typeof(IValueProvider),
+ // [nameof(BurnableTemp)] = typeof(IValueProvider),
+ };
+
+ // public ComponentsPatcherConverter(Dictionary componentsTypes)
+ // {
+ // _componentsTypes = componentsTypes;
+ // }
+
+ public override Dictionary? Read(YamlReader reader)
+ {
+ var dict = new Dictionary();
+ if (reader.TokenType == YamlTokenType.StartMapping)
+ {
+ reader.Read();
+ }
+ while (reader.TokenType != YamlTokenType.EndMapping)
+ {
+ var key = reader.ScalarValue;
+ reader.Read();
+ var d = reader.ScalarValue;
+
+ if (!_componentsTypes.TryGetValue(key, out var type))
+ {
+ type = typeof(object);
+ }
+ if (!reader.TryGetCustomConverter(type, out var converter)){
+ converter = reader.GetConverter(type);
+ }
+ object data;
+ data = converter.Read(reader, type);
+
+ // reader.Read();
+ dict[key] = data;
+
+ }
+ return dict;
+ }
+
+ public override void Write(YamlWriter writer, Dictionary value) => throw new NotImplementedException();
+}
diff --git a/src/Items/ItemData.cs.uid b/src/Items/ItemData.cs.uid
new file mode 100644
index 0000000..524dfb1
--- /dev/null
+++ b/src/Items/ItemData.cs.uid
@@ -0,0 +1 @@
+uid://ymjkr070i83c
diff --git a/src/Items/ItemECSTest.cs b/src/Items/ItemECSTest.cs
index 46e99f9..1979a40 100644
--- a/src/Items/ItemECSTest.cs
+++ b/src/Items/ItemECSTest.cs
@@ -1,7 +1,10 @@
namespace FoodFactory;
+using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
+using System.Reflection;
using Arch.Core;
using Arch.Core.Extensions;
using Arch.Core.Utils;
@@ -11,7 +14,10 @@ using Chickensoft.Introspection;
using Chickensoft.SaveFileBuilder;
using FoodFactory.Items;
using FoodFactory.Math;
+using FoodFactory.Recipes;
using Godot;
+using SharpYaml;
+using SharpYaml.Serialization;
using Utf8Json;
public class Test
@@ -63,7 +69,86 @@ public class Test
var worldJson = serializer.ToJson(world);
// GD.Print(worldJson);
var otherWorld = serializer.FromJson(worldJson);
+ foreach (var item in ComponentRegistry.TypeToComponentType.Keys)
+ {
+ if (item is null)
+ {
+ continue;
+ }
+ GD.Print(item.Name);
+ GD.Print(item.Namespace);
+ GD.Print(item.FullName);
+ }
+ string yaml = @"
+ Id: potato_raw
+ # TypeMapping:
+ # Tags: FoodFactory.Items.Tags
+ Components:
+ Name: Raw Potato
+ Tags:
+ - potato
+ - vegetable
+ - raw
+ - burnable
+ Temperature:
+ -
+ $type: temperature
+ Kelvin : 500.
+
+ Bacteria:
+ - salmonella: !!float 400.
+ BurnableTemp: !!float 400.
+ ";
+ var options = new YamlSerializerOptions()
+ {
+ // Converters = [new Recipes.DataNodeSerlicer()]
+ // PolymorphismOptions = new YamlPolymorphismOptions
+ // {
+ // DerivedTypeMappings =
+ // {
+ // [typeof(DataNode)] =
+ // [
+ // new YamlDerivedType(typeof(SequenceNode), "sequence"){Tag = "!sequence"},
+ // new YamlDerivedType(typeof(MappingNode), "mapping"){Tag = "!mapping"},
+ // new YamlDerivedType(typeof(ValueNode), "value"){Tag = "!value"}
+ // ],
+ // [typeof(object)] =
+ // [
+ // new YamlDerivedType(typeof(Temperature), "temperature") { Tag = "!temperature"}
+ // ]
+
+ // },
+ // },
+ };
+ // var test = YamlSerializer.Serialize(new ItemData()
+ // {
+ // Id = "potato_raw",
+ // Components = { [nameof(Name)] = new ValueNode("Raw Potato") ,
+ // [nameof(Temperature)] = new ValueNode(100f),
+ // [nameof(Tags)] = new SequenceNode([new ValueNode("potato"), new ValueNode("vegetable"), new ValueNode("food"),new ValueNode("raw"),new ValueNode("burnable")])}
+ // }, options);
+ // GD.Print(test);
+ var result = YamlSerializer.Deserialize(yaml,options);
+ var names = result.Components.Keys.ToArray();
+ var list3 = new List();
+ foreach (var item in Assembly.GetAssembly(typeof(Name)).GetTypes())
+ {
+ if (!names.Contains(item.Name))
+ {
+ continue;
+ }
+ list3.Add(item);
+ }
+ // var types = names.Select(f => Type.GetType(f)).ToArray();
+ // var names2 = new Type[]{typeof(Name), typeof(Temperature), typeof(Tags)};
+var componentTypes = list3.Select(Component.GetComponentType).ToArray();
+
+ Entity entite = world.Create(componentTypes);
+ // var reg = new ComponentBinderRegistry();
+ // reg.Add(new TemperatureBinder());
+ // reg.Apply(entite,world,result);
+ // GD.Print(string.Join(',',entite.GetAllComponents()));
// ISaveChunk saveChunk =new SaveChunk(
// chunk =>
// {
diff --git a/src/Items/StructReflection.cs b/src/Items/StructReflection.cs
new file mode 100644
index 0000000..06ee213
--- /dev/null
+++ b/src/Items/StructReflection.cs
@@ -0,0 +1,96 @@
+namespace FoodFactory.Items;
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+public static class StructReflection
+{
+ public static void ApplyValues(
+ ref T target,
+ Dictionary values)
+ where T : struct
+ {
+ object boxed = target;
+
+ Type type = typeof(T);
+
+ foreach (var kvp in values)
+ {
+ string name = kvp.Key;
+ object value = kvp.Value;
+
+ // Try property first
+ var prop = type.GetProperty(
+ name,
+ BindingFlags.Public |
+ BindingFlags.Instance);
+
+ if (prop != null && prop.CanWrite)
+ {
+ object converted = ConvertValue(value, prop.PropertyType);
+ prop.SetValue(boxed, converted);
+ continue;
+ }
+
+ // Then field
+ var field = type.GetField(
+ name,
+ BindingFlags.Public |
+ BindingFlags.Instance);
+
+ if (field != null)
+ {
+ object converted = ConvertValue(value, field.FieldType);
+ field.SetValue(boxed, converted);
+ continue;
+ }
+
+ throw new Exception(
+ $"Member '{name}' not found on {type.Name}");
+ }
+
+ target = (T)boxed;
+ }
+
+ private static object ConvertValue(object value, Type targetType)
+ {
+ if (value == null)
+ return null!;
+
+ Type valueType = value.GetType();
+
+ if (targetType.IsAssignableFrom(valueType))
+ return value;
+
+ return Convert.ChangeType(value, targetType);
+ }
+}
+/*
+static RefSetter CreateFieldSetter(FieldInfo field)
+{
+ var target = Expression.Parameter(typeof(T).MakeByRefType(), "target");
+ var value = Expression.Parameter(typeof(TValue), "value");
+
+ var fieldExp = Expression.Field(target, field);
+
+ var assign = Expression.Assign(fieldExp, value);
+
+ return Expression.Lambda>(
+ assign,
+ target,
+ value
+ ).Compile();
+}
+static RefSetter CreatePropertySetter(PropertyInfo prop)
+{
+ var target = Expression.Parameter(typeof(T).MakeByRefType(), "target");
+ var value = Expression.Parameter(typeof(TValue), "value");
+
+ var call = Expression.Call(target, prop.SetMethod!, value);
+
+ return Expression
+ .Lambda>(call, target, value)
+ .Compile();
+}
+*/
diff --git a/src/Items/StructReflection.cs.uid b/src/Items/StructReflection.cs.uid
new file mode 100644
index 0000000..900f188
--- /dev/null
+++ b/src/Items/StructReflection.cs.uid
@@ -0,0 +1 @@
+uid://bpw4csgtk7qwf
diff --git a/src/Math/Temperature.cs b/src/Math/Temperature.cs
index 2679009..e2c7abf 100644
--- a/src/Math/Temperature.cs
+++ b/src/Math/Temperature.cs
@@ -32,7 +32,21 @@ public enum TemperatureUnit
///
Fahrenheit
}
-
+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 record struct Celsius(double Value)
+{
+ public static implicit operator Celsius(double value) => new(value);
+ public static implicit operator Temperature(Celsius value) => new(value);
+}
+public record struct Kelvin(double Value)
+{
+ public static implicit operator Kelvin(double value) => new(value);
+ public static implicit operator Temperature(Kelvin value) => new(value);
+}
///
/// A temperature value.
///
@@ -53,7 +67,18 @@ public struct Temperature : IFormattable, IComparable,
/// The value of the temperature.
public Temperature(double kelvin) : this() { _kelvin = kelvin; }
-
+ public Temperature(Fahrenheit fahrenheit)
+ {
+ _kelvin = FahrenheitToKelvin(fahrenheit.Value);
+ }
+ public Temperature(Celsius celsius)
+ {
+ _kelvin = CelsiusToKelvin(celsius.Value);
+ }
+ public Temperature(Kelvin kelvin)
+ {
+ _kelvin = kelvin.Value;
+ }
///
/// Creates a new temperature with the specified value in the
/// specified unit of measurement.
@@ -90,6 +115,11 @@ public struct Temperature : IFormattable, IComparable,
set => _kelvin = value;
}
+ public Kelvin KelvinMeasurement
+ {
+ readonly get => _kelvin;
+ set => _kelvin = value.Value;
+ }
///
/// Gets or sets the temperature value in Celsius.
@@ -98,6 +128,11 @@ public struct Temperature : IFormattable, IComparable,
{
readonly get => KelvinToCelsius(_kelvin); set => _kelvin = CelsiusToKelvin(value);
}
+ public Celsius CelsiusMeasurement
+ {
+ readonly get => KelvinToCelsius(_kelvin);
+ set => _kelvin = CelsiusToKelvin(value.Value);
+ }
///
/// Gets or sets the temperature value in Fahrenheit.
@@ -106,6 +141,11 @@ public struct Temperature : IFormattable, IComparable,
{
readonly get => KelvinToFahrenheit(_kelvin); set => _kelvin = FahrenheitToKelvin(value);
}
+ public Fahrenheit FahrenheitMeasurement
+ {
+ readonly get => KelvinToFahrenheit(_kelvin);
+ set => _kelvin = FahrenheitToKelvin(value.Value);
+ }
///
/// Gets the temperature value in the specified unit of measurement.
diff --git a/src/Recipes/Blueprint.cs b/src/Recipes/Blueprint.cs
index c096ec9..826fb81 100644
--- a/src/Recipes/Blueprint.cs
+++ b/src/Recipes/Blueprint.cs
@@ -2,21 +2,201 @@ 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 = [];
+ // 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)
{
- if (!_bluePrints.TryGetValue(name, out var blueprint))
+
+ // throw new NotImplementedException();
+ if (!Blueprints.TryGetValue(name, out var blueprint))
{
//TODO this is where this should look through mods/base game
if (name == "Potato")
@@ -47,6 +227,10 @@ public class BlueprintManger : IBlueprintManger
return blueprint;
}
}
+// public record Blueprint(string Name, Func Factory)
+// {
+
+// }
public record Blueprint(string Name, Func Factory)
{
@@ -56,4 +240,306 @@ 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