From 4db51be3748916aff2651615638108d59a629bcb Mon Sep 17 00:00:00 2001 From: ronnie Date: Sun, 10 May 2026 12:33:20 -0400 Subject: [PATCH] Spite up project, added BeltData, some asoited compoents, remvoed unused usings, and removed uneeded comment code. --- ChickenGameTest.csproj | 21 +- assets | 2 +- .../ConveyorBeltStraight.cs | 21 +- .../ConveyorBeltStraight.tscn | 17 +- src/Items/Components/Tag.cs | 30 ++ src/Items/Components/Tag.cs.uid | 1 + src/Items/Components/Tags.cs | 28 -- src/Items/Components/Tags.cs.uid | 1 + src/Items/Item.cs | 50 ++- src/Items/ItemECSTest.cs | 96 +++-- src/Items/ItemECSTest.cs.uid | 1 + src/Math/Ordered1DList.cs | 109 +++++ src/Math/Ordered1DList.cs.uid | 1 + src/Math/Temperature.cs.uid | 1 + src/Math/Weight.cs | 148 +++++++ src/Math/Weight.cs.uid | 1 + src/Recipes/Blueprint.cs | 58 +++ src/Recipes/Blueprint.cs.uid | 1 + src/Recipes/BlueprintId.cs | 14 + src/Recipes/BlueprintId.cs.uid | 1 + src/Recipes/Recipe.cs | 231 ++++++++++ src/Recipes/Recipe.cs.uid | 1 + src/Recipes/RecipeAction.cs | 12 + src/Recipes/RecipeAction.cs.uid | 1 + src/Recipes/RecipeBucket.cs | 37 ++ src/Recipes/RecipeBucket.cs.uid | 1 + src/Recipes/RecipeContext.cs | 20 + src/Recipes/RecipeContext.cs.uid | 1 + src/Recipes/RecipeName.cs | 20 + src/Recipes/RecipeName.cs.uid | 1 + src/Recipes/RecipeResult.cs | 26 ++ src/Recipes/RecipeResult.cs.uid | 1 + src/Recipes/RecipeResultBuilder.cs | 34 ++ src/Recipes/RecipeResultBuilder.cs.uid | 1 + src/Recipes/Recipes.cs | 408 +++++++----------- src/Recipes/Recipes.cs.uid | 1 + src/VoxelGrid/Balancer.cs | 61 +++ src/VoxelGrid/Balancer.cs.uid | 1 + src/VoxelGrid/BeltPort.cs | 144 +------ src/VoxelGrid/BeltPortHost.cs | 48 +++ src/VoxelGrid/BeltPortHost.cs.uid | 1 + src/VoxelGrid/ConveyorItemRender.cs | 29 +- src/VoxelGrid/ItemConveyor.cs | 3 - src/VoxelGrid/ItemSpawner.cs | 70 +++ src/VoxelGrid/ItemSpawner.cs.uid | 1 + src/VoxelGrid/ItemSpawner.tscn | 17 + src/VoxelGrid/OvenTest.cs | 194 ++++++++- src/VoxelGrid/SlicerTest.cs | 106 +++++ src/VoxelGrid/SlicerTest.cs.uid | 1 + src/VoxelGrid/TestItemConveyor.cs | 33 +- src/VoxelGrid/VoxelGridNode.cs | 111 ++++- src/VoxelGrid/VoxelGridNode.tscn | 278 ++++++++---- src/VoxelGrid/VoxelRegistry.cs | 4 - 53 files changed, 1892 insertions(+), 608 deletions(-) create mode 100644 src/Items/Components/Tag.cs create mode 100644 src/Items/Components/Tag.cs.uid create mode 100644 src/Items/Components/Tags.cs.uid create mode 100644 src/Items/ItemECSTest.cs.uid create mode 100644 src/Math/Ordered1DList.cs create mode 100644 src/Math/Ordered1DList.cs.uid create mode 100644 src/Math/Temperature.cs.uid create mode 100644 src/Math/Weight.cs create mode 100644 src/Math/Weight.cs.uid create mode 100644 src/Recipes/Blueprint.cs create mode 100644 src/Recipes/Blueprint.cs.uid create mode 100644 src/Recipes/BlueprintId.cs create mode 100644 src/Recipes/BlueprintId.cs.uid create mode 100644 src/Recipes/Recipe.cs create mode 100644 src/Recipes/Recipe.cs.uid create mode 100644 src/Recipes/RecipeAction.cs create mode 100644 src/Recipes/RecipeAction.cs.uid create mode 100644 src/Recipes/RecipeBucket.cs create mode 100644 src/Recipes/RecipeBucket.cs.uid create mode 100644 src/Recipes/RecipeContext.cs create mode 100644 src/Recipes/RecipeContext.cs.uid create mode 100644 src/Recipes/RecipeName.cs create mode 100644 src/Recipes/RecipeName.cs.uid create mode 100644 src/Recipes/RecipeResult.cs create mode 100644 src/Recipes/RecipeResult.cs.uid create mode 100644 src/Recipes/RecipeResultBuilder.cs create mode 100644 src/Recipes/RecipeResultBuilder.cs.uid create mode 100644 src/Recipes/Recipes.cs.uid create mode 100644 src/VoxelGrid/Balancer.cs create mode 100644 src/VoxelGrid/Balancer.cs.uid create mode 100644 src/VoxelGrid/BeltPortHost.cs create mode 100644 src/VoxelGrid/BeltPortHost.cs.uid create mode 100644 src/VoxelGrid/ItemSpawner.cs create mode 100644 src/VoxelGrid/ItemSpawner.cs.uid create mode 100644 src/VoxelGrid/ItemSpawner.tscn create mode 100644 src/VoxelGrid/SlicerTest.cs create mode 100644 src/VoxelGrid/SlicerTest.cs.uid diff --git a/ChickenGameTest.csproj b/ChickenGameTest.csproj index e44b789..c3fe914 100644 --- a/ChickenGameTest.csproj +++ b/ChickenGameTest.csproj @@ -37,33 +37,36 @@ + + + - + - - + + - + - + - - + + - + - + diff --git a/assets b/assets index b5ad429..37af2de 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b5ad429c59af10bc190d5a2d09c3790a8f4c3620 +Subproject commit 37af2de43458380ee7e86f3635c40bde9ec7093f diff --git a/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.cs b/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.cs index 80ed328..9b96600 100644 --- a/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.cs +++ b/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.cs @@ -1,8 +1,8 @@ +using System.Diagnostics; using ChickenGameTest; using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; -using System; [Meta(typeof(IAutoNode))] public partial class ConveyorBeltStraight : Node3D, IProvide { @@ -16,19 +16,21 @@ public partial class ConveyorBeltStraight : Node3D, IProvide get => GridTransform3D.FromGodot(GlobalTransform); set => GlobalTransform = value.ToGodot(); } + [Node("ConveyorLogic")] + public TestItemConveyor ConveyorLogic { get; set; } = default!; public override void _Ready() { - var node = GetNode("Node") as TestItemConveyor; base._Ready(); + Debug.Assert(ConveyorLogic is not null, $"{nameof(ConveyorLogic)} is not set on {nameof(ConveyorBeltStraight)}, Path {SceneFilePath}"); // GD.PrintS(VoxelTransform.Origin,VoxelTransform.Forward); - node.StartPort = node.CreatePort( + ConveyorLogic.StartPort = ConveyorLogic.CreatePort( new(VoxelTransform.TranslatedLocal(new(1 - Width, 0, 0)).RotateY(2), // Direction.Back, Width, PortAccess.BiDirectional), new BeltTEnd(ConveyorEnd.Start), new LaneSpan(0, 1)); - node.EndPort = node.CreatePort( + ConveyorLogic.EndPort = ConveyorLogic.CreatePort( new(VoxelTransform, //new(GridTransform3D.FromGodot(Transform.TranslatedLocal(Vector3.Left)), // Direction.Front, Width, @@ -36,22 +38,23 @@ public partial class ConveyorBeltStraight : Node3D, IProvide new BeltTEnd(ConveyorEnd.End), new LaneSpan(0, 1)); - node.OtherPorts = [ - node.CreatePort( + ConveyorLogic.OtherPorts = [ + ConveyorLogic.CreatePort( new(VoxelTransform.RotateY90CW(), // Direction.Right, 1, PortAccess.In), - new BeltTOffset(node.Length/2), + new BeltTOffset(ConveyorLogic.Length/2), LaneSpan.One), - node.CreatePort( + ConveyorLogic.CreatePort( new(VoxelTransform.RotateY90CCW(), // Direction.Left, 1, PortAccess.In), - new BeltTOffset(node.Length/2), + new BeltTOffset(ConveyorLogic.Length/2), LaneSpan.One) ]; + } public void OnResolved() { diff --git a/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.tscn b/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.tscn index 32a8f1b..4690c42 100644 --- a/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.tscn +++ b/src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=7 format=3 uid="uid://c4h7mwnfrdesg"] +[gd_scene format=3 uid="uid://c4h7mwnfrdesg"] [ext_resource type="Script" uid="uid://dgyuh6un1qoj4" path="res://src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.cs" id="1_mn8ro"] [ext_resource type="Script" uid="uid://j24fuotdwwx4" path="res://src/VoxelGrid/TestItemConveyor.cs" id="2_1vr1d"] @@ -13,22 +13,23 @@ _data = { } point_count = 2 -[node name="ConveyorBeltStraight" type="Node3D"] +[node name="ConveyorBeltStraight" type="Node3D" unique_id=1032197109] script = ExtResource("1_mn8ro") +Width = 1 -[node name="Node" type="Node" parent="."] +[node name="ConveyorLogic" type="Node" parent="." unique_id=1693852977] script = ExtResource("2_1vr1d") -[node name="conveyor-sides" parent="." instance=ExtResource("2_mn8ro")] +[node name="conveyor-sides" parent="." unique_id=516239399 instance=ExtResource("2_mn8ro")] transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0) -[node name="arrow-basic2" parent="." instance=ExtResource("3_1vr1d")] +[node name="arrow-basic2" parent="." unique_id=1668302786 instance=ExtResource("3_1vr1d")] transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0.21879572, 0) -[node name="Path3D" type="Path3D" parent="."] +[node name="Path3D" type="Path3D" parent="." unique_id=878303794] curve = SubResource("Curve3D_x5qdr") -[node name="Node2" type="Node" parent="." node_paths=PackedStringArray("Path3D", "ItemConveyor")] +[node name="Node2" type="Node" parent="." unique_id=1875202216 node_paths=PackedStringArray("Path3D", "ItemConveyor")] script = ExtResource("4_g7n1f") Path3D = NodePath("../Path3D") -ItemConveyor = NodePath("../Node") +ItemConveyor = NodePath("../ConveyorLogic") diff --git a/src/Items/Components/Tag.cs b/src/Items/Components/Tag.cs new file mode 100644 index 0000000..79a73f3 --- /dev/null +++ b/src/Items/Components/Tag.cs @@ -0,0 +1,30 @@ +namespace FoodFactory.Items; + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; + +public readonly struct Tag : IEquatable, IEqualityOperators, IComparisonOperators, + IComparable +{ + public readonly string Name => TagRegistry.GetName(this); + internal readonly int _id; + + internal Tag(int id) + { + Debug.Assert(id >= 0); + _id = id; + } + 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; + public override string ToString() => Name; + public int CompareTo(Tag other) => _id.CompareTo(other._id); + public static bool operator >(Tag left, Tag right) => left._id > right._id; + public static bool operator >=(Tag left, Tag right) => left._id >= right._id; + public static bool operator <(Tag left, Tag right) => left._id < right._id; + public static bool operator <=(Tag left, Tag right) => left._id <= right._id; + public static bool operator ==(Tag left, Tag right) => left._id == right._id; + public static bool operator !=(Tag left, Tag right) => left._id != right._id; +} diff --git a/src/Items/Components/Tag.cs.uid b/src/Items/Components/Tag.cs.uid new file mode 100644 index 0000000..8581907 --- /dev/null +++ b/src/Items/Components/Tag.cs.uid @@ -0,0 +1 @@ +uid://1o2e2wou367m diff --git a/src/Items/Components/Tags.cs b/src/Items/Components/Tags.cs index 362773a..753d84b 100644 --- a/src/Items/Components/Tags.cs +++ b/src/Items/Components/Tags.cs @@ -2,13 +2,9 @@ namespace FoodFactory.Items; using System; using System.Collections; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Numerics; -using System.Threading; public readonly struct Tags : IEquatable, IReadOnlyCollection { @@ -178,30 +174,6 @@ public readonly struct Tags : IEquatable, IReadOnlyCollection } } -public readonly struct Tag : IEquatable, IEqualityOperators, IComparisonOperators, - IComparable -{ - public readonly string Name => TagRegistry.GetName(this); - internal readonly int _id; - - internal Tag(int id) - { - Debug.Assert(id >= 0); - _id = id; - } - 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; - public override string ToString() => Name; - public int CompareTo(Tag other) => _id.CompareTo(other._id); - public static bool operator >(Tag left, Tag right) => left._id > right._id; - public static bool operator >=(Tag left, Tag right) => left._id >= right._id; - public static bool operator <(Tag left, Tag right) => left._id < right._id; - public static bool operator <=(Tag left, Tag right) => left._id <= right._id; - public static bool operator ==(Tag left, Tag right) => left._id == right._id; - public static bool operator !=(Tag left, Tag right) => left._id != right._id; -} - public static class TagRegistry { private static Registry _registry = new(); diff --git a/src/Items/Components/Tags.cs.uid b/src/Items/Components/Tags.cs.uid new file mode 100644 index 0000000..cec5c02 --- /dev/null +++ b/src/Items/Components/Tags.cs.uid @@ -0,0 +1 @@ +uid://chk03ru27wxw1 diff --git a/src/Items/Item.cs b/src/Items/Item.cs index e6b7a99..6e395a0 100644 --- a/src/Items/Item.cs +++ b/src/Items/Item.cs @@ -2,8 +2,12 @@ namespace ChickenGameTest; using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; +using System.Linq; +using Arch.Core; +using Arch.Core.Extensions; +using FoodFactory.Items; using Godot; +using SJK.Functional; /// /// Items that can be on a belt @@ -16,15 +20,46 @@ public interface IBeltItem : IDisposable delegate void ItemRemoved(IBeltItem item); event ItemRemoved? Disposed; } - -public class TestItem() : IBeltItem +public interface IBeltItemData +{ + T GetItem(); +} +public class TestItem() : IBeltItem, IBeltItemData { - public float Temp { get; set; } public int Width { get; set; } public int Height { get; set; } + public static PackedScene PotatoScene = ResourceLoader.Load("res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/food_ingredient_potato.gltf"); + public static PackedScene OnionScene = ResourceLoader.Load("res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/food_ingredient_onion.gltf"); + public static PackedScene ChoppedOnionScene = ResourceLoader.Load("res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/food_ingredient_onion_chopped.gltf"); + public Node3D CreateItemVisual() + { + Node3D node; + if (Item.Get().Contains(TagRegistry.GetTag("potato"))) + { + node = PotatoScene.Instantiate(); + } + else if (Item.Get().ContainsAny(new Tags("sliced"))) + { + node = ChoppedOnionScene.Instantiate(); + } + else if (Item.Get().Contains(TagRegistry.GetTag("onion"))) + { + node = OnionScene.Instantiate(); + } + else + { + node = new MeshInstance3D() { Mesh = new BoxMesh() }; + } + 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 })); + } + 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 } }; + } - public Node3D CreateItemVisual() => new MeshInstance3D() { Mesh = new BoxMesh() { Size = new(.1f, .1f, .1f) } }; private bool _disposed; public event IBeltItem.ItemRemoved? Disposed; @@ -40,7 +75,10 @@ public class TestItem() : IBeltItem _disposed = true; Disposed?.Invoke(this); } - public Dictionary PlaceHolderData = []; + + public Entity GetItem() => Item; + + public Entity Item; } public interface IFluidItem diff --git a/src/Items/ItemECSTest.cs b/src/Items/ItemECSTest.cs index b85428a..5977aed 100644 --- a/src/Items/ItemECSTest.cs +++ b/src/Items/ItemECSTest.cs @@ -2,10 +2,9 @@ using System; using System.Collections.Generic; -using System.Linq; using Arch.Core; using Arch.Core.Extensions; -using Arch.LowLevel.Jagged; +using Arch.LowLevel; using FoodFactory; using FoodFactory.Items; using FoodFactory.Recipes; @@ -21,8 +20,8 @@ public class Test var bucket = new BucketStorage>(); - var pizza = world.Create(new Name("Pizza"), new Temperature(5f), new MarcoNutrients(5, 5, 10), new MicroNutrients([new Vitamin("D", 5)])); - var turkey = world.Create(new Name("Turkey"), new Temperature(5f), new MarcoNutrients(5, 5, 10)); + var pizza = world.Create(new Name("Pizza"), new Temperature(5f), new MarcoNutrients(5, 5, new()), new MicroNutrients([new Vitamin("D", 5)])); + var turkey = world.Create(new Name("Turkey"), new Temperature(5f), new MarcoNutrients(5, 5, new())); // var componentType = new ComponentType(ComponentRegistry.Size-1, 8); // ComponentRegistry.Add(typeof(LayeredStack2), componentType); @@ -37,7 +36,7 @@ public class Test pizza.Get().Kelvin += .1f; } pizza.Add(new IngredientOf(turkey)); - var a = new List(){pizza}; + var a = new List() { pizza }; turkey.Add(new LayeredStack(bucket.Add(a))); turkey.Add(new LayeredStack2(a)); @@ -70,36 +69,6 @@ public class Test } } ); - var recipes = new Recipes(); - - var item = recipes.TESTBlueprint.Factory(new BlueprintContext(){World = world, BluePrintId = new BlueprintId(recipes.TESTBlueprint)});//world.Create(new Name("Potato_Raw"), new Temperature(71f), new Tags("raw", "potato", "vegetable")); - Span items = [item]; - var context = new RecipeContext(world, items); - var builder = new RecipeResultBuilder(stackalloc bool[10], new ItemBuilder[10]); - // var recipe = new PotatoCookRecipe(); - var recipe = recipes.GetRecipes(new RecipeAction("cook"), 1, [item.Get()], [])[0].Recipe; - if (recipe.CanProcess(context)) - { - var result = recipe.Process(context, ref builder); - var list3 = new List(); - for (int i = 0; i < result.CreateLength; i++) - { - list3.Add(result.Create[i](in context)); - } - if (result.RemoveLength > 0) - { - for (int i = 0; i < result.RemoveLength; i++) - { - GD.Print(result.Remove[i]); - if (result.Remove[i]) - { - world.Destroy(items[i]); - } - } - } - GD.Print(string.Join(',',list3[0].GetAllComponents())); - GD.Print(items[0].IsAlive()); - } } } @@ -109,15 +78,64 @@ internal interface IEntityContainer } public record struct Name(string Value); -public record struct MarcoNutrients(float Fat, float Protein, float Carbohydrate); +public record struct BurnableTemp(Temperature Temperature); +public record struct BurnedItem(Temperature BurnedAt, string Description);//Info about how burnted item is +public record struct MarcoNutrients(Weight Fat, Weight Protein, Carbohydrates Carbohydrate); +public readonly record struct Carbohydrates( + Weight Fiber, + Weight Starch, + SugarProfile Sugars +) +{ + public Weight TotalWeight => + Fiber + Starch + Sugars.TotalWeight; + + public double Calories => + (Fiber.Grams * 2.0) + + (Starch.Grams * 4.0) + + Sugars.Calories; + + public double Sweetness => + Sugars.Sweetness; +} +public readonly record struct SugarProfile( + Weight Glucose, + Weight Fructose, + Weight Sucrose, + Weight Lactose +) +{ + public Weight TotalWeight => + Glucose + Fructose + Sucrose + Lactose; + + public double Calories => + TotalWeight.Grams * 4.0; + + public double Sweetness => + (Glucose.Grams * 0.7) + + (Fructose.Grams * 1.7) + + (Sucrose.Grams * 1.0) + + (Lactose.Grams * 0.2); + + public static SugarProfile operator +( + SugarProfile a, + SugarProfile b) => new( + a.Glucose + b.Glucose, + a.Fructose + b.Fructose, + a.Sucrose + b.Sucrose, + a.Lactose + b.Lactose); +} +public record struct Mass(Weight Value);// Repsenets the apomix weight of an item, should have things like nutrients allready accounted. public record struct MicroNutrients(List Vitamins); -public record struct Vitamin(string Id, float Amount); - +public record struct Vitamin(string Id, Weight Amount); +public record struct Scale(float Value); public record struct IngredientOf(Entity Source); public record struct LayeredStack(Handle Handle); public record struct LayeredStack2(List Children); +public record struct Bacteria(Handle> Data); +public record struct BacteriaData(string Name, double Count); public record struct Handle(int Index, int Version); @@ -157,7 +175,7 @@ public class BucketStorage Version = 1, Occupied = true }; - Array.Resize(ref _slots, _slots.Length + 1); + System.Array.Resize(ref _slots, _slots.Length + 1); _slots[^1] = slot; return new Handle diff --git a/src/Items/ItemECSTest.cs.uid b/src/Items/ItemECSTest.cs.uid new file mode 100644 index 0000000..37710a9 --- /dev/null +++ b/src/Items/ItemECSTest.cs.uid @@ -0,0 +1 @@ +uid://c5ik7ke6rrlmn diff --git a/src/Math/Ordered1DList.cs b/src/Math/Ordered1DList.cs new file mode 100644 index 0000000..4d250e0 --- /dev/null +++ b/src/Math/Ordered1DList.cs @@ -0,0 +1,109 @@ +namespace SJK.Math; + +using System; +using System.Collections.Generic; +using Arch.LowLevel; + +public sealed class Ordered1DList : IDisposable where T : unmanaged +{ + private readonly UnsafeList _values; + public Ordered1DList(int capacity) + { + _values = new(capacity); + } + public record struct Entry(float Position, T Value); + public void Insert(T item, float position) + { + if (_values.Count == 0 || position >= _values[^1].Position) + { + _values.Add(new(position, item)); + return; + } + if (position <= _values[0].Position) + { + _values.Insert(0, new(position, item)); + return; + } + var index = LowerBound(position); + _values.Insert(index, new(position, item)); + SortFromIndex(index); + } + public void RemoveAt(int index) => _values.RemoveAt(index); + public void Clear() => _values.Clear(); + public void MoveAllBy(float offset) + { + for (int i = 0; i < _values.Count; i++) + { + _values[i].Position = _values[i].Position + offset; + } + } + private void SortFromIndex(int index) + { + var entry = _values[index]; + + while (index > 0 && + _values[index - 1].Position > entry.Position) + { + Swap(index, index - 1); + index--; + } + + // bubble right + while (index < _values.Count - 1 && + _values[index + 1].Position < entry.Position) + { + Swap(index, index + 1); + index++; + } + } + private void Swap(int a, int b) => (_values[b], _values[a]) = (_values[a], _values[b]); + private int LowerBound(float pos) + { + int lo = 0; + int hi = _values.Count; + + while (lo < hi) + { + int mid = (lo + hi) >> 1; + + if (_values[mid].Position < pos) + { + lo = mid + 1; + } + else + { + hi = mid; + } + } + + return lo; + } + public Enumerator EnumerateTowardEnd(int startIndex) => new(this, towardsEnd: true, startIndex); + public Enumerator EnumerateTowardStart(int startIndex) => new(this, towardsEnd: false, startIndex); + public ref struct Enumerator + { + public Enumerator(Ordered1DList list, bool towardsEnd, int index) + { + _list = list; + _towardsEnd = towardsEnd; + _index = index; + } + private readonly Ordered1DList _list; + private readonly bool _towardsEnd; + private int _index; + + public bool MoveNext() + { + _index += _towardsEnd ? 1 : -1; + return _index >= 0 && _index < _list._values.Count; + } + public void Remove() + { + _list._values.RemoveAt(_index); + _index -= _towardsEnd ? 1 : -1; + } + + public readonly ref Entry Current => ref _list._values[_index]; + } + public void Dispose() => _values.Dispose(); +} diff --git a/src/Math/Ordered1DList.cs.uid b/src/Math/Ordered1DList.cs.uid new file mode 100644 index 0000000..c0bac8e --- /dev/null +++ b/src/Math/Ordered1DList.cs.uid @@ -0,0 +1 @@ +uid://uuf56xygihoh diff --git a/src/Math/Temperature.cs.uid b/src/Math/Temperature.cs.uid new file mode 100644 index 0000000..c9d09b3 --- /dev/null +++ b/src/Math/Temperature.cs.uid @@ -0,0 +1 @@ +uid://pcjdirermsr7 diff --git a/src/Math/Weight.cs b/src/Math/Weight.cs new file mode 100644 index 0000000..a31fedd --- /dev/null +++ b/src/Math/Weight.cs @@ -0,0 +1,148 @@ +using System; +using System.Globalization; + +public readonly record struct Weight(double Grams) + : IComparable, + IFormattable +{ + // ----------------------------- + // Metric Constants + // ----------------------------- + + public const double GRAMS_PER_KILOGRAM = 1000.0; + public const double GRAMS_PER_CENTIGRAM = 0.01; + public const double GRAMS_PER_MILLIGRAM = 0.001; + + // ----------------------------- + // Imperial Constants + // ----------------------------- + + public const double GRAMS_PER_OUNCE = 28.349523125; + public const double GRAMS_PER_POUND = 453.59237; + + // ----------------------------- + // Factory Methods + // ----------------------------- + + public static Weight FromGrams(double value) + => new(value); + + public static Weight FromKilograms(double value) + => new(value * GRAMS_PER_KILOGRAM); + + public static Weight FromCentigrams(double value) + => new(value * GRAMS_PER_CENTIGRAM); + + public static Weight FromMilligrams(double value) + => new(value * GRAMS_PER_MILLIGRAM); + + public static Weight FromOunces(double value) + => new(value * GRAMS_PER_OUNCE); + + public static Weight FromPounds(double value) + => new(value * GRAMS_PER_POUND); + + // ----------------------------- + // Unit Properties + // ----------------------------- + + public double Kilograms => Grams / GRAMS_PER_KILOGRAM; + public double Centigrams => Grams / GRAMS_PER_CENTIGRAM; + public double Milligrams => Grams / GRAMS_PER_MILLIGRAM; + + public double Ounces => Grams / GRAMS_PER_OUNCE; + public double Pounds => Grams / GRAMS_PER_POUND; + + // ----------------------------- + // Operators + // ----------------------------- + + public static Weight operator +(Weight a, Weight b) + => new(a.Grams + b.Grams); + + public static Weight operator -(Weight a, Weight b) + => new(a.Grams - b.Grams); + + public static Weight operator *(Weight a, double scalar) + => new(a.Grams * scalar); + + public static Weight operator *(double scalar, Weight a) + => new(a.Grams * scalar); + + public static Weight operator /(Weight a, double scalar) + => new(a.Grams / scalar); + + // Ratio + public static double operator /(Weight a, Weight b) + => a.Grams / b.Grams; + + // ----------------------------- + // Comparisons + // ----------------------------- + + public int CompareTo(Weight other) + => Grams.CompareTo(other.Grams); + + // ----------------------------- + // Implicit / Explicit Casts + // ----------------------------- + + // Weight -> double (grams) + public static implicit operator double(Weight weight) + => weight.Grams; + + // double -> Weight (grams) + public static implicit operator Weight(double grams) + => new(grams); + + // ----------------------------- + // Formatting + // ----------------------------- + + public override string ToString() + => ToString("auto", CultureInfo.InvariantCulture); + + public string ToString(string? format, IFormatProvider? provider) + { + provider ??= CultureInfo.InvariantCulture; + format = format?.ToLowerInvariant(); + + return format switch + { + "g" => $"{Grams.ToString("0.##", provider)} g", + "kg" => $"{Kilograms.ToString("0.###", provider)} kg", + "cg" => $"{Centigrams.ToString("0.##", provider)} cg", + "mg" => $"{Milligrams.ToString("0.##", provider)} mg", + + "lb" => $"{Pounds.ToString("0.##", provider)} lb", + "oz" => $"{Ounces.ToString("0.##", provider)} oz", + + "auto" or null => AutoFormat(provider), + + _ => throw new FormatException($"Unknown format '{format}'") + }; + } + + private string AutoFormat(IFormatProvider provider) + { + var abs = Math.Abs(Grams); + + if (abs >= GRAMS_PER_KILOGRAM) + { + return $"{Kilograms.ToString("0.###", provider)} kg"; + } + + if (abs < 1.0) + { + return $"{Milligrams.ToString("0.##", provider)} mg"; + } + + return $"{Grams.ToString("0.##", provider)} g"; + } + + // ----------------------------- + // Common Values + // ----------------------------- + + public static Weight Zero => new(0); +} diff --git a/src/Math/Weight.cs.uid b/src/Math/Weight.cs.uid new file mode 100644 index 0000000..3359ede --- /dev/null +++ b/src/Math/Weight.cs.uid @@ -0,0 +1 @@ +uid://7e8o324qvsox diff --git a/src/Recipes/Blueprint.cs b/src/Recipes/Blueprint.cs new file mode 100644 index 0000000..95afa5f --- /dev/null +++ b/src/Recipes/Blueprint.cs @@ -0,0 +1,58 @@ +namespace FoodFactory.Recipes; + +using System; +using System.Collections.Generic; +using Arch.Core; +using ChickenGameTest; +using FoodFactory.Items; + +public interface IBlueprintManger +{ + Blueprint GetBlueprint(string name); +} +public class BlueprintManger : IBlueprintManger +{ + private readonly Dictionary _bluePrints = []; + public Blueprint GetBlueprint(string name) + { + 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 struct BlueprintContext +{ + public World World; + public BlueprintId BluePrintId; +} diff --git a/src/Recipes/Blueprint.cs.uid b/src/Recipes/Blueprint.cs.uid new file mode 100644 index 0000000..fb14a2e --- /dev/null +++ b/src/Recipes/Blueprint.cs.uid @@ -0,0 +1 @@ +uid://cj088ogl8uqmt diff --git a/src/Recipes/BlueprintId.cs b/src/Recipes/BlueprintId.cs new file mode 100644 index 0000000..228eb70 --- /dev/null +++ b/src/Recipes/BlueprintId.cs @@ -0,0 +1,14 @@ +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/BlueprintId.cs.uid b/src/Recipes/BlueprintId.cs.uid new file mode 100644 index 0000000..b2c4ea4 --- /dev/null +++ b/src/Recipes/BlueprintId.cs.uid @@ -0,0 +1 @@ +uid://b7kmhd6uamhg diff --git a/src/Recipes/Recipe.cs b/src/Recipes/Recipe.cs new file mode 100644 index 0000000..56ed2f9 --- /dev/null +++ b/src/Recipes/Recipe.cs @@ -0,0 +1,231 @@ +namespace FoodFactory.Recipes; + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Arch.Core; +using Arch.Core.Extensions; +using Arch.Core.Extensions.Dangerous; +using FoodFactory.Items; +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 bool CanProcess(in RecipeContext context); + public abstract RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder); +} +public readonly record struct RecipeOutput +{ + public int? Min { get; } + public int? Max { get; } + [MemberNotNullWhen(true, nameof(Min), nameof(Max))] + public bool IsExact => Min.HasValue && Max.HasValue && Min == Max; + [MemberNotNullWhen(true, nameof(Min), nameof(Max))] + public bool IsRange => Min.HasValue && Max.HasValue && Min != Max; + public bool IsUnbounded => Min == null && Max == null; + + public RecipeOutput(int exact) + { + Min = exact; + Max = exact; + } + + public RecipeOutput(int min, int max) + { + Min = min; + Max = max; + } + private RecipeOutput(int? min, int? max) + { + Min = min; + Max = max; + } + + public static RecipeOutput Any => new(null, null); +} +public struct CompiledRecipe +{ + + public Recipe RecipeRef; + // public BlueprintId[] InputBlueprints; + public ItemEntry[] ItemEntries; + public bool IsOrdered; +} +public struct ItemEntry +{ + public bool RequireAll; + public Tags InputTags; + public Tags ExcludeTags; + public BlueprintId? Blueprint; +} +public static class RecipeCompiler +{ + public static CompiledRecipe Compile(Recipe recipe) => new() + { + RecipeRef = recipe, + ItemEntries = BuildEntries(recipe), + // IsOrdered = recipe.InputsOrdered, + }; + private static ItemEntry[] BuildEntries(Recipe recipe) + { + var entries = new ItemEntry[recipe.Inputs.Length]; + + for (var i = 0; i < entries.Length; i++) + { + entries[i] = new ItemEntry + { + RequireAll = recipe.RequireAll[i], + InputTags = recipe.Inputs[i], + ExcludeTags = recipe.Exclude[i], + // Blueprint = recipe.BlueprintIds?[i], + }; + } + + return entries; + } +} +public record BurnItemRecipe : Recipe +{ + public BurnItemRecipe() : base("Burn_item", + BlueprintIds: null, + RequireAll: [false], + Inputs: [new Tags("burnable")], + Exclude: [new Tags("burned")], + RecipeOutput: RecipeOutput.Any, + Action: new RecipeAction("cook"), + InputsOrdered: true) + { + + } + + public override bool CanProcess(in RecipeContext context) + { + if (context.Items[0].TryGet(out var temp) && context.Items[0].TryGet(out var burnableTemp) && temp > burnableTemp.Temperature) + { + return true; + } + return false; + } + public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder) => new(BurnItem); + + private void BurnItem(RecipeContext context) + { + // context.Entity[0].Remove(); + context.Items[0].Add(new BurnedItem(context.Items[0].Get(), "Was Burned as some time thing")); + context.Items[0].Set(context.Items[0].Get().WithOut("burnable").With("burned")); + context.Items[0].Set($"Burned_{context.Items[0].Get().Value}"); + if (context.Items[0].Has()) + { + context.Items[0].Set(context.Items[0].Get() * Colors.Black); + } + else + { + context.Items[0].Add(Colors.Black); + } + } +} +public record OnionSliceRecipe() : Recipe(Name: "Onion_Slice", + BlueprintIds: null, + RequireAll: [false], + Inputs: [new Tags("onion", "sliceable")], + Exclude: [new Tags()], + Action: "slice", + RecipeOutput: new RecipeOutput(2) + ) +{ + public override bool CanProcess(in RecipeContext context) => true; + + public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder) + { + builder.AddRemove(true); + builder.AddCreate(Slice); + builder.AddCreate(Slice); + return builder.Build(); + } + private Entity Slice(in RecipeContext context) + { + Span span = stackalloc Entity[1]; + var signature = context.World.GetSignature(context.Items[0]); + context.World.Create(span, signature, 1); + PotatoCookRecipe.CopyEntities(context.Items, span, context.World); + span[0].Set(new Name("Sliced " + context.Items[0].Get().Value)); + span[0].Set(new Mass(context.Items[0].Get().Value * .5)); + span[0].Set(span[0].Get().With("sliced")); + return span[0]; + } +} +public record PotatoCookRecipe() : Recipe(Name: "Potato_Cook", + BlueprintIds: null, + RequireAll: [false], + Inputs: [new Tags("potato", "raw")], + Exclude: [new Tags()], + InputsOrdered: true, + Action: "cook", + RecipeOutput: new RecipeOutput(1)) +{ + public override bool CanProcess(in RecipeContext context) + { + if (!(context.Items[0].TryGet(out var temp) && temp.Fahrenheit > 350)) + { + return false; + } + return true; + } + + public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder) + { + builder.AddRemove(true); + builder.AddCreate(NewPotato); + return builder.Build(); + } + private Entity NewPotato(in RecipeContext context) + { + Span span = stackalloc Entity[1]; + var signature = context.World.GetSignature(context.Items[0]); + context.World.Create(span, signature, 1); + CopyEntity(context.Items[0], span[0], context.World); + + span[0].Set(new Name("Cooked_Potato")); + span[0].Set(context.Items[0].Get().With("cooked").WithOut("raw")); + // span[0].Set(context.Entity[0].Get()); + if (context.Items[0].Has()) + { + context.Items[0].Set(context.Items[0].Get() * Colors.Brown); + } + else + { + context.Items[0].Add(Colors.Brown); + } + return span[0]; + } + public static void CopyEntities(Span from, Span to, World world) + { + Debug.Assert(from.Length == to.Length); + for (int i = 0; i < from.Length; i++) + { + CopyEntity(from[i], to[i], world); + } + + } + public static void CopyEntity(Entity src, Entity dst, World world) +{ + var srcData = world.GetEntityData(src); + var dstData = world.GetEntityData(dst); + + var components = srcData.Archetype + .GetChunk(srcData.Slot.ChunkIndex) + .Components; + var componentsDst = dstData.Archetype + .GetChunk(dstData.Slot.ChunkIndex) + .Components; + + int srcIndex = srcData.Slot.Index; + int dstIndex = dstData.Slot.Index; + + for (int i = 0; i < components.Length; i++) + { + componentsDst[i].SetValue(components[i].GetValue(srcIndex), dstIndex); + } +} +} diff --git a/src/Recipes/Recipe.cs.uid b/src/Recipes/Recipe.cs.uid new file mode 100644 index 0000000..531d7d7 --- /dev/null +++ b/src/Recipes/Recipe.cs.uid @@ -0,0 +1 @@ +uid://152ii3ysj30f diff --git a/src/Recipes/RecipeAction.cs b/src/Recipes/RecipeAction.cs new file mode 100644 index 0000000..cc5fea7 --- /dev/null +++ b/src/Recipes/RecipeAction.cs @@ -0,0 +1,12 @@ +namespace FoodFactory.Recipes; + +public readonly record struct RecipeAction +{ + public readonly string Value; + public RecipeAction(string value) + { + Value = value.ToLowerInvariant(); + } + public static implicit operator string(RecipeAction name) => name.Value; + public static implicit operator RecipeAction(string name) => new(name); +} diff --git a/src/Recipes/RecipeAction.cs.uid b/src/Recipes/RecipeAction.cs.uid new file mode 100644 index 0000000..f98625d --- /dev/null +++ b/src/Recipes/RecipeAction.cs.uid @@ -0,0 +1 @@ +uid://dut1goeo1md46 diff --git a/src/Recipes/RecipeBucket.cs b/src/Recipes/RecipeBucket.cs new file mode 100644 index 0000000..833703b --- /dev/null +++ b/src/Recipes/RecipeBucket.cs @@ -0,0 +1,37 @@ +namespace FoodFactory.Recipes; + +using System; +using System.Collections.Generic; + +public sealed class RecipeBucket +{ + public Dictionary Single = []; + public Dictionary Ordered = []; + public CompiledRecipe[] Unordered = []; + public ReadOnlySpan Resolve(Span items) + { + if (items.Length == 0) + { + return Unordered; + } + + if (items.Length == 1) + { + if (Single.TryGetValue(items[0], out var r)) + { + return r; + } + + return Unordered; + } + + var main = items[0]; + + if (Ordered.TryGetValue(main, out var ordered)) + { + return ordered; + } + + return Unordered; + } +} diff --git a/src/Recipes/RecipeBucket.cs.uid b/src/Recipes/RecipeBucket.cs.uid new file mode 100644 index 0000000..7b5a68e --- /dev/null +++ b/src/Recipes/RecipeBucket.cs.uid @@ -0,0 +1 @@ +uid://cfhklflid8ed1 diff --git a/src/Recipes/RecipeContext.cs b/src/Recipes/RecipeContext.cs new file mode 100644 index 0000000..e330c35 --- /dev/null +++ b/src/Recipes/RecipeContext.cs @@ -0,0 +1,20 @@ +namespace FoodFactory.Recipes; + +using System; +using Arch.Core; + +public readonly ref struct RecipeContext +{ + public readonly World World; + + public RecipeContext(World world, Span entity) : this() + { + World = world; + Items = entity; + } + + public readonly Span Items; + // optional later: + // public readonly Machine Machine; + // public readonly float Delta; +} diff --git a/src/Recipes/RecipeContext.cs.uid b/src/Recipes/RecipeContext.cs.uid new file mode 100644 index 0000000..fcc7e3d --- /dev/null +++ b/src/Recipes/RecipeContext.cs.uid @@ -0,0 +1 @@ +uid://cjamv4y4aikhc diff --git a/src/Recipes/RecipeName.cs b/src/Recipes/RecipeName.cs new file mode 100644 index 0000000..c802f17 --- /dev/null +++ b/src/Recipes/RecipeName.cs @@ -0,0 +1,20 @@ +namespace FoodFactory.Recipes; + +// public record SingleItemRecipe(string Name, Tags Required, Tags Exclude) : Recipe(Name) +// { + +// } +// public record MultipleItemRecipe(string Name, params ItemInput[] Inputs) : Recipe(Name) +// { + +// } +public readonly record struct RecipeName +{ + public readonly string Name; + public RecipeName(string name) + { + Name = name.ToLowerInvariant(); + } + public static implicit operator string(RecipeName name) => name.Name; + public static implicit operator RecipeName(string name) => new(name); +} diff --git a/src/Recipes/RecipeName.cs.uid b/src/Recipes/RecipeName.cs.uid new file mode 100644 index 0000000..ef2fe27 --- /dev/null +++ b/src/Recipes/RecipeName.cs.uid @@ -0,0 +1 @@ +uid://b635p37fwu0xl diff --git a/src/Recipes/RecipeResult.cs b/src/Recipes/RecipeResult.cs new file mode 100644 index 0000000..9309a04 --- /dev/null +++ b/src/Recipes/RecipeResult.cs @@ -0,0 +1,26 @@ +namespace FoodFactory.Recipes; + +using System; + +public readonly ref struct RecipeResult +{ + public readonly int RemoveLength => Remove.Length; + public readonly int CreateLength => Create.Length; + public readonly ReadOnlySpan Remove; // destroy original + + public RecipeResult(ReadOnlySpan remove, ReadOnlySpan create) : this() + { + Remove = remove; + Create = create; + Mutate = null; + } + + public readonly ReadOnlySpan Create; // multi-output + + public readonly Action? Mutate; // component changes + + public RecipeResult(Action mutate) : this() + { + Mutate = mutate; + } +} diff --git a/src/Recipes/RecipeResult.cs.uid b/src/Recipes/RecipeResult.cs.uid new file mode 100644 index 0000000..1aaa6d0 --- /dev/null +++ b/src/Recipes/RecipeResult.cs.uid @@ -0,0 +1 @@ +uid://ctyimxkx8bomh diff --git a/src/Recipes/RecipeResultBuilder.cs b/src/Recipes/RecipeResultBuilder.cs new file mode 100644 index 0000000..801e146 --- /dev/null +++ b/src/Recipes/RecipeResultBuilder.cs @@ -0,0 +1,34 @@ +namespace FoodFactory.Recipes; + +using System; +using Arch.Core; + +public ref struct RecipeResultBuilder +{ + private Span _remove; + private Span _create; + private int _removeCount; + private int _createCount; + + public RecipeResultBuilder(Span remove, Span create) + { + _remove = remove; + _create = create; + _removeCount = 0; + _createCount = 0; + } + + public void AddRemove(bool value) => _remove[_removeCount++] = value; + public void AddCreate(ItemBuilder item) => _create[_createCount++] = item; + public void Clear() + { + _removeCount = 0; + _createCount = 0; + } + public readonly RecipeResult Build() + => new( + _remove[.._removeCount], + _create[.._createCount]); +} +public delegate Entity ItemBuilder(in RecipeContext ctx); + diff --git a/src/Recipes/RecipeResultBuilder.cs.uid b/src/Recipes/RecipeResultBuilder.cs.uid new file mode 100644 index 0000000..c55a4fa --- /dev/null +++ b/src/Recipes/RecipeResultBuilder.cs.uid @@ -0,0 +1 @@ +uid://ba6ll7cygo6hg diff --git a/src/Recipes/Recipes.cs b/src/Recipes/Recipes.cs index 37f7239..6569051 100644 --- a/src/Recipes/Recipes.cs +++ b/src/Recipes/Recipes.cs @@ -1,82 +1,81 @@ namespace FoodFactory.Recipes; using System; -using System.Collections; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Linq; -using Arch.Core; -using Arch.Core.Extensions; -using FastExpressionCompiler.ImTools; +using ChickenGameTest; using FoodFactory.Items; using Godot; -using Parlot.Fluent; using SJK.Functional; -public class Recipes + +public record struct RecipeEntryKey(RecipeAction Action, int Inputs, BlueprintId? FirstBlueprintId, RecipeOutput OutputsCount); + +public interface IRecipes { - private readonly Dictionary> _actions = []; + Option GetRecipeByName(RecipeName name); + RecipeEnumerator GetRecipes(RecipeAction action, int inputs, Tags[] itemTags, BlueprintId[] blueprintIds, RecipeOutput outputCount, Span mapping); +} +public readonly record struct RecipeInput(RecipeAction Action, int Inputs, Tags[] ItemTags, BlueprintId[] BlueprintIds, RecipeOutput OutputCount); +public class Recipes : IRecipes +{ + private readonly Dictionary _sortedRecipes = []; private readonly Dictionary _recipes = []; public Option GetRecipeByName(RecipeName name) => _recipes.GetValue(name).ToStructOption(); - public Blueprint TESTBlueprint; public Recipes() { - //TODO Utilize the singtaure ssytem to create the item, the have a post proccess step that would be for setting propertied - var rawPotatoBlueprint = TESTBlueprint = new Blueprint("Potato", static ctx => ctx.World.Create(new Name("Potato_raw"), new Tags("potato", "raw", "vegetable"), new Temperature(71, TemperatureUnit.Fahrenheit), ctx.BluePrintId)); - var recipe = new PotatoCookRecipe(); - _recipes.Add(new RecipeName(recipe.Name), recipe); - var compiledRecipe = new CompiledRecipe() { IsOrdered = true, RecipeRef = recipe, InputBlueprints = [new BlueprintId(rawPotatoBlueprint)], ItemEntries = [new CompiledRecipe.ItemEntry() { InputTags = recipe.Inputs[0], ExcludeTags = recipe.Exclude[0], RequireAll = recipe.RequireAll[0] }] }; - _actions.Add(new("cook"), new Dictionary() { [1] = new RecipeBucket() {Single = new Dictionary(){[new BlueprintId(rawPotatoBlueprint)] = [compiledRecipe] }, Unordered = [compiledRecipe] } }); + var builder = new RecipesBuilder(); + builder.Add(new PotatoCookRecipe()); + builder.Add(new BurnItemRecipe()); + builder.Add(new OnionSliceRecipe()); + _sortedRecipes = builder.Build(); + _recipes = builder.CompiledRecipes.Select(f => f.RecipeRef).ToDictionary(k => new RecipeName(k.Name)); } - public List<(Recipe Recipe, int[]? Mapping)> GetRecipes(RecipeAction action, int inputs, Tags[] itemTags, BlueprintId[] blueprintIds) + public unsafe RecipeEnumerator GetRecipes(RecipeAction action, int inputs, Tags[] itemTags, BlueprintId[] blueprintIds, RecipeOutput outputCount, Span mapping) { - var list = new List<(Recipe, int[])>(); Debug.Assert(inputs > 0); Debug.Assert(inputs == itemTags.Length); - if (!_actions.TryGetValue(action, out var inputAmount)) + var key = new RecipeEntryKey(action, inputs, blueprintIds.Length > 0 ? blueprintIds[0] : null, outputCount); + if (!_sortedRecipes.TryGetValue(key, out var bucket)) { - return null; + return new RecipeEnumerator(); } - if (!inputAmount.TryGetValue(inputs, out var blueprints)) - { - return null; - } - var recipes = blueprints.Resolve(blueprintIds); - - - var mapping = new int[itemTags.Length]; - var used = new bool[itemTags.Length]; - for (int i = 0; i < recipes.Length; i++) - { - var item = recipes[i]; - if (inputs == 1 && IsValid(itemTags[0], item.ItemEntries[0])) - { - list.Add((item.RecipeRef, null)); - } - else if (item.IsOrdered) - { - for (int ii = 0; ii < itemTags.Length; ii++) - { - if (!IsValid(itemTags[ii], item.ItemEntries[ii])) - { - continue; - } - } - list.Add((item.RecipeRef, null)); - } - else if (CanPossiblyMatch(itemTags, item)) - { - if (Match(itemTags, item.ItemEntries, 0, used, mapping)) - { - list.Add((item.RecipeRef, mapping)); - } - } - } - return list; + var recipes = bucket.Resolve(blueprintIds); + return new RecipeEnumerator(recipes, new(action,inputs,itemTags,blueprintIds,outputCount), &Filter, mapping); } - private static bool IsValid(Tags tags, CompiledRecipe.ItemEntry compiled) + private static bool Filter(RecipeInput input, CompiledRecipe compiledRecipe, Span mapping, out RecipeMatch recipeMatch) + { + if (input.Inputs == 1 && IsValid(input.ItemTags[0], compiledRecipe.ItemEntries[0])) + { + recipeMatch = new RecipeMatch(compiledRecipe.RecipeRef, []); + return true; + } + else if (compiledRecipe.IsOrdered) + { + for (var ii = 0; ii < input.ItemTags.Length; ii++) + { + if (!IsValid(input.ItemTags[ii], compiledRecipe.ItemEntries[ii])) + { + continue; + } + } + recipeMatch = new RecipeMatch(compiledRecipe.RecipeRef, []); + return true; + } + else if (CanPossiblyMatch(input.ItemTags, compiledRecipe)) + { + Span used = stackalloc bool[input.ItemTags.Length]; + if (Match(input.ItemTags, compiledRecipe.ItemEntries, 0, used, mapping)) + { + recipeMatch = new RecipeMatch(compiledRecipe.RecipeRef, mapping); + return true; + } + } + recipeMatch = default; + return false; + } + private static bool IsValid(Tags tags, ItemEntry compiled) { if (!(compiled.RequireAll ? tags.ContainsAll(compiled.InputTags) : tags.ContainsAny(compiled.InputTags))) { @@ -92,7 +91,7 @@ public class Recipes { foreach (var entry in recipe.ItemEntries) { - bool found = false; + var found = false; foreach (var item in items) { @@ -104,17 +103,19 @@ public class Recipes } if (!found) + { return false; + } } return true; } private static bool Match( - Tags[] items, - CompiledRecipe.ItemEntry[] entries, - int depth, - Span used, - Span mapping) + Tags[] items, + ItemEntry[] entries, + int depth, + Span used, + Span mapping) { if (depth == entries.Length) { @@ -190,7 +191,7 @@ public class Recipes { return [.. mapping]; } - for (int i = 0; i < test.Length; i++) + for (var i = 0; i < test.Length; i++) { if (used[i]) { @@ -215,199 +216,114 @@ public class Recipes return backTrace(0); } } -public abstract record Recipe(string Name, BlueprintId[]? BlueprintIds, bool[] RequireAll, Tags[] Inputs, Tags[] Exclude) +public class RecipesBuilder { - public abstract bool CanProcess(in RecipeContext context); - public abstract RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder); -} -public record PotatoCookRecipe() : Recipe(Name: "Potato_Cook", BlueprintIds: null, RequireAll: [false], Inputs: [new Tags("potato")], Exclude: [new Tags()]) -{ - public override bool CanProcess(in RecipeContext context) + + private readonly Dictionary _data = []; + private readonly List _compiledRecipes = []; + public IReadOnlyCollection CompiledRecipes => _compiledRecipes; + public void Add(Recipe recipe) { - if (!context.Entity[0].Has()) + var compiled = RecipeCompiler.Compile(recipe); + _compiledRecipes.Add(compiled); + var key = new RecipeEntryKey(recipe.Action, recipe.Inputs.Length, recipe.BlueprintIds?[0], recipe.RecipeOutput); + var key2 = new RecipeEntryKey(recipe.Action, recipe.Inputs.Length, recipe.BlueprintIds?[0], RecipeOutput.Any); + //TODO have items automatic added to any if not a zero output recipe + if (!_data.TryGetValue(key, out var bucket)) { - return false; + bucket = new BucketBuilder(); + _data[key] = bucket; } - return true; - } - - public override RecipeResult Process(in RecipeContext context, ref RecipeResultBuilder builder) - { - builder.AddRemove(true); - builder.AddCreate(NewPotato); - return builder.Build(); - } - - private Entity NewPotato(in RecipeContext context) - { - Span span = stackalloc Entity[1]; - var signature = context.World.GetSignature(context.Entity[0]); - context.World.Create(span, signature, 1); - - span[0].Set(new Name("Cooked_Potato")); - span[0].Set(context.Entity[0].Get().With("cooked").WithOut("raw")); - span[0].Set(context.Entity[0].Get()); - return span[0]; - } -} -public ref struct RecipeResultBuilder -{ - private Span _remove; - private Span _create; - private int _removeCount; - private int _createCount; - - public RecipeResultBuilder(Span remove, Span create) - { - _remove = remove; - _create = create; - _removeCount = 0; - _createCount = 0; - } - - public void AddRemove(bool value) => _remove[_removeCount++] = value; - public void AddCreate(ItemBuilder item) => _create[_createCount++] = item; - - public RecipeResult Build() - => new RecipeResult( - _remove.Slice(0, _removeCount), - _create.Slice(0, _createCount)); -} -public delegate Entity ItemBuilder(in RecipeContext ctx); -public readonly ref struct RecipeContext -{ - public readonly World World; - - public RecipeContext(World world, Span entity) : this() - { - World = world; - Entity = entity; - } - - public readonly Span Entity; - // optional later: - // public readonly Machine Machine; - // public readonly float Delta; -} -public readonly ref struct RecipeResult -{ - public readonly int RemoveLength => Remove.Length; - public readonly int CreateLength => Create.Length; - public readonly ReadOnlySpan Remove; // destroy original - - public RecipeResult(ReadOnlySpan remove, ReadOnlySpan create) : this() - { - Remove = remove; - Create = create; - Mutate = null; - } - - public readonly ReadOnlySpan Create; // multi-output - - public readonly Action? Mutate; // component changes - - public RecipeResult(Action mutate) : this() - { - Mutate = mutate; - } -} -public struct CompiledRecipe -{ - - public Recipe RecipeRef; - public BlueprintId[] InputBlueprints; - public ItemEntry[] ItemEntries; - public bool IsOrdered; - public struct ItemEntry - { - public bool RequireAll; - public Tags InputTags; - public Tags ExcludeTags; - } -} -// public record SingleItemRecipe(string Name, Tags Required, Tags Exclude) : Recipe(Name) -// { - -// } -// public record MultipleItemRecipe(string Name, params ItemInput[] Inputs) : Recipe(Name) -// { - -// } -public readonly record struct RecipeName -{ - public readonly string Name; - public RecipeName(string name) - { - Name = name.ToLowerInvariant(); - } - public static implicit operator string(RecipeName name) => name.Name; -} -public readonly record struct RecipeAction -{ - public readonly string Value; - public RecipeAction(string value) - { - Value = value.ToLowerInvariant(); - } - public static implicit operator string(RecipeAction name) => name.Value; -} -public readonly record struct BlueprintId -{ - public readonly int Id; - public Blueprint Blueprint => _registry.GetEntry(Id); - private static Registry _registry = new(); - public BlueprintId(Blueprint blueprint) - { - Id = _registry.GetOrCreate(blueprint); - - } -} -public record Blueprint(string Name, Func Factory) -{ - -} -public struct BlueprintContext -{ - public World World; - public BlueprintId BluePrintId; -} -public sealed class RecipeBucket -{ - // 1 input → direct blueprint lookup - public Dictionary Single = []; - - // ordered multi-input → first item is anchor - public Dictionary Ordered = []; - - // fallback (unordered / no blueprint) - public CompiledRecipe[] Unordered = []; - /// - /// Resloves Blueprints, if span is length 0, tehn Unordred is returned imdetly - /// - /// - /// - public ReadOnlySpan Resolve(Span items) -{ - if (items.Length == 0) + bucket.Add(compiled, recipe.BlueprintIds ?? []); + if (recipe.RecipeOutput == RecipeOutput.Any) { - return Unordered; + return; + } + if (!_data.TryGetValue(key2, out bucket)) + { + bucket = new BucketBuilder(); + _data[key2] = bucket; + } + bucket.Add(compiled, recipe.BlueprintIds ?? []); + } + public Dictionary Build() + { + var result = new Dictionary(); + + foreach (var (key, bucket) in _data) + { + result[key] = bucket.Build(); } - if (items.Length == 1) - { - if (Single.TryGetValue(items[0], out var r)) - return r; + return result; + } + private sealed class BucketBuilder + { + private readonly Dictionary> _single = []; + private readonly Dictionary> _ordered = []; + private readonly List _unordered = []; - return Unordered; + public void Add(CompiledRecipe recipe, ReadOnlySpan inputs) + { + if (inputs.Length == 0) + { + _unordered.Add(recipe); + return; + } + + if (inputs.Length == 1) + { + var list = GetOrCreate(_single, inputs[0]); + list.Add(recipe); + return; + } + + // multi-input → ordered (anchor = first) + if (recipe.IsOrdered) + { + var orderedList = GetOrCreate(_ordered, inputs[0]); + orderedList.Add(recipe); + } + else + { + _unordered.Add(recipe); + } } - var main = items[0]; - - if (Ordered.TryGetValue(main, out var ordered)) + public RecipeBucket Build() { - return ordered; + return new RecipeBucket + { + Single = ToArrayDict(_single), + Ordered = ToArrayDict(_ordered), + Unordered = [.. _unordered] + }; } - return Unordered; -} + private static List GetOrCreate( + Dictionary> dict, + BlueprintId key) + { + if (!dict.TryGetValue(key, out var list)) + { + list = new List(4); + dict[key] = list; + } + + return list; + } + + private static Dictionary ToArrayDict( + Dictionary> source) + { + var result = new Dictionary(source.Count); + + foreach (var (key, list) in source) + { + result[key] = [.. list]; + } + + return result; + } + } } diff --git a/src/Recipes/Recipes.cs.uid b/src/Recipes/Recipes.cs.uid new file mode 100644 index 0000000..29bde9f --- /dev/null +++ b/src/Recipes/Recipes.cs.uid @@ -0,0 +1 @@ +uid://cp61k5vfvknv8 diff --git a/src/VoxelGrid/Balancer.cs b/src/VoxelGrid/Balancer.cs new file mode 100644 index 0000000..3e7d4d1 --- /dev/null +++ b/src/VoxelGrid/Balancer.cs @@ -0,0 +1,61 @@ +namespace ChickenGameTest; + +using Godot; + +using System.Collections.Generic; +using System.Linq; +using Chickensoft.AutoInject; +using Chickensoft.Introspection; + +[Meta(typeof(IAutoNode))] +public partial class Balancer : Node3D, IProvide, IProvide +{ + public override void _Notification(int what) => this.Notify(what); + private BeltPortHost _insertLogic = default!; + public IBeltPortHost Value() => _insertLogic; + IVoxelGridRegistry IProvide.Value() => GridRegistry; + [Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn(); + private List _outPuts = new(); + public GridTransform3D VoxelTransform + { + get => GridTransform3D.FromGodot(GlobalTransform); + set => GlobalTransform = value.ToGodot(); + } + public void OnResolved() + { + _insertLogic = new BeltPortHost(); + _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.Access.HasFlag(PortAccess.In), () => new DelegateInsertBeltItemLogic(CanAccept, CanInsert)); + _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.Access.HasFlag(PortAccess.Out), () => new DelegateInsertBeltItemLogic((_, _) => true, (_, _) => true)); + this.Provide(); + _outPuts = [.. OutputPorts]; + + } + + private bool CanAccept(IBeltPort port, IBeltItem item) + { + foreach (var portOther in OutputPorts) + { + if (portOther.GetPortFacing(GridRegistry).Map(f => f.CanAccept(item, LaneSpan.One, 0)).Or(false)) + { + return true; + } + } + return false; + } + private IEnumerable OutputPorts => _insertLogic.GetPorts().OfType().Where(i => i.Access.HasFlag(PortAccess.Out)); + private bool CanInsert(IBeltPort port, IBeltItem item) + { + for (var i = 0; i < _outPuts.Count; i++) + { + var facing = _outPuts[i].GetPortFacing(GridRegistry); + if (facing.HasValue(out var face) && face.CanAccept(item, LaneSpan.One, 0) && face.TryInsert(item, LaneSpan.One, 0)) + { + var c = _outPuts[i]; + _outPuts.RemoveAt(i); + _outPuts.Add(c); + return true; + } + } + return false; + } +} diff --git a/src/VoxelGrid/Balancer.cs.uid b/src/VoxelGrid/Balancer.cs.uid new file mode 100644 index 0000000..a33e56b --- /dev/null +++ b/src/VoxelGrid/Balancer.cs.uid @@ -0,0 +1 @@ +uid://opbkqoaa7x2n diff --git a/src/VoxelGrid/BeltPort.cs b/src/VoxelGrid/BeltPort.cs index 9f00204..162143e 100644 --- a/src/VoxelGrid/BeltPort.cs +++ b/src/VoxelGrid/BeltPort.cs @@ -1,14 +1,9 @@ namespace ChickenGameTest; using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; -using SJK.Functional; [Tool] [Meta(typeof(IAutoNode))] @@ -21,11 +16,9 @@ public partial class BeltPort : Node3D, IBeltPort [Export] public Direction Face { get; set; } = default!; [Export] public int Width { get; set; } = default!; [Export] public PortAccess Access { get; set; } = default!; - [Export] public Path3D Path { get; set; } = default!; [Export] public string PortName { get; set; } = ""; [Dependency] public IItemRenderer ItemRenderer => this.DependOn(); public BeltPortProfile Profile => new(GridTransform3D.FromGodot(GlobalTransform), Width, Access); - [Dependency] public IItemTransferAnimator ItemTransferAnimator => this.DependOn(() => new CurveItemTransfer() { Curve3D = Path.Curve, Tree = GetTree(), ItemRenderer = ItemRenderer, Transform3D = GlobalTransform }); private VoxelGuid _guid = new(Guid.Empty); public void OnResolved() { @@ -37,26 +30,7 @@ public partial class BeltPort : Node3D, IBeltPort _guid = Grid.Register(this, [.. (this as IBeltPort).Points()]); GD.Print(_guid); } - public override void _Process(double delta) - { - DebugDraw3D.DrawLine(GlobalPosition, GlobalTransform * Face.ToVector(), Colors.Red); - if (Engine.IsEditorHint()) - { - return; - } - for (int i = 0; i < _itemsDummys.Count; i++) - { - _itemsDummys[i] = (_itemsDummys[i].i + (float)delta, _itemsDummys[i].beltItem); - // GD.Print(_itemsDummys[i].i); - ItemRenderer.UpdateTransform(_itemsDummys[i].beltItem, GlobalTransform * Path.Curve.SampleBakedWithRotation(_itemsDummys[i].i)); - if (_itemsDummys[i].i > Path.Curve.GetBakedLength()) - { - _itemsDummys[i].beltItem.Dispose(); - _itemsDummys.RemoveAt(i); - i--; - } - } - } + public override void _Process(double delta) => DebugDraw3D.DrawLine(GlobalPosition, GlobalTransform * Face.ToVector(), Colors.Red); public override void _ExitTree() { @@ -69,20 +43,7 @@ public partial class BeltPort : Node3D, IBeltPort } public bool CanAccept(IBeltItem item, LaneSpan laneSpan, float beltT) => Access.HasFlag(PortAccess.In) && InsertLogic.CanAccept(this, item); - List<(float i, IBeltItem beltItem)> _itemsDummys = []; - public bool TryInsert(IBeltItem item, LaneSpan laneSpan, float beltT) => CanAccept(item, laneSpan, beltT) && InsertLogic.CanInsert(this, item); - // { - // var tween = ItemTransferAnimator.StartTransfer(new(item, beltT) { LaneSpan = laneSpan }, () => GD.Print("Done")); - // // GD.Print("gg "+laneSpan); - // tween.TweenCallback(Callable.From(item.Dispose)); - // // GD.Print(laneSpan); - // // GD.Print(item.ToString()); - // // _itemsDummys.Add((0,item)); - // // item.Dispose(); - // return true; - // throw new System.NotImplementedException(); - // } } public interface IBeltItemInsertLogic @@ -90,106 +51,3 @@ public interface IBeltItemInsertLogic bool CanInsert(IBeltPort beltPort, IBeltItem item); bool CanAccept(IBeltPort beltPort, IBeltItem item); } -public interface IBeltPortHost -{ - IBeltItemInsertLogic ResolveInsertLogic(IBeltPort port); -} -public class BeltPortHost : IBeltPortHost -{ - private readonly List<(Func match, Func factory)> _bindings - = new(); - - public BeltPortHost Bind( - Func match, - Func factory) - { - _bindings.Add((match, factory)); - return this; - } - private HashSet _ports = []; - public IBeltItemInsertLogic? Default; - - /// - /// Resolve the insert logic for a port. If no matching bind exists then the default is returned if supplied. Other wise throws an Exception. - /// - /// - /// - /// - public IBeltItemInsertLogic ResolveInsertLogic(IBeltPort port) - { - _ports.Add(port); - foreach (var (match, factory) in _bindings) - { - if (match(port)) - { - return factory(); - } - } - if (Default is null) - { - throw new Exception($"{nameof(port)} does not have any binding attached that accepts it."); - } - return Default; - } - public IEnumerable GetPorts() => _ports; -} -public interface IItemTransferAnimator -{ - Tween StartTransfer( - ConveyorSlice item, - Action onFinished = null); -} - -public class InstanceItemTransfer : IItemTransferAnimator -{ - public SceneTree Tree = default!; - public Func AcceptFunc = default!; - public Tween StartTransfer(ConveyorSlice item, Action onFinished = null) - { - AcceptFunc(item); - onFinished?.Invoke(); - return Tree.CreateTween(); - throw new NotImplementedException(); - } -} -public class CurveItemTransfer : IItemTransferAnimator -{ - public Curve3D Curve3D = default!; - public IItemRenderer ItemRenderer = default!; - public Func AcceptFunc = default!; - public SceneTree Tree = default!; - public Transform3D Transform3D; - public Tween AnimateAlongCurve( - ConveyorSlice item, - Curve3D curve, - float duration, - IItemRenderer renderer) - { - float length = curve.GetBakedLength(); - - var tween = Tree.CreateTween(); - - tween.TweenMethod( - Callable.From(t => - { - //Transform is not being set when using update transform in a tween, but can set position - // renderer.UpdateTransform(item, Transform3D * curve.SampleBakedWithRotation(t),1/duration); - (renderer as TestItemRendered)._items[item.Item].Transform = Transform3D * Curve3D.SampleBakedWithRotation(t).Translated(-Curve3D.SampleBakedWithRotation(t).Basis.X * item.LaneSpan.Start); - // GD.PrintS(Transform3D * curve.SampleBakedWithRotation(t).Origin,1/duration,(renderer as TestItemRendered)._items[item].GlobalPosition); - }), - 0f, - length, - duration - ); - return tween; - } - public Tween StartTransfer(ConveyorSlice item, Action onFinished = null) - { - var tween = AnimateAlongCurve(item, Curve3D, 1, ItemRenderer); - if (onFinished is not null) - { - tween.TweenCallback(Callable.From(onFinished)); - } - return tween; - } -} diff --git a/src/VoxelGrid/BeltPortHost.cs b/src/VoxelGrid/BeltPortHost.cs new file mode 100644 index 0000000..182b97f --- /dev/null +++ b/src/VoxelGrid/BeltPortHost.cs @@ -0,0 +1,48 @@ +namespace ChickenGameTest; + +using System; +using System.Collections.Generic; + +public interface IBeltPortHost +{ + IBeltItemInsertLogic ResolveInsertLogic(IBeltPort port); +} +public class BeltPortHost : IBeltPortHost +{ + private readonly List<(Func match, Func factory)> _bindings + = new(); + + public BeltPortHost Bind( + Func match, + Func factory) + { + _bindings.Add((match, factory)); + return this; + } + private HashSet _ports = []; + public IBeltItemInsertLogic? Default; + + /// + /// Resolve the insert logic for a port. If no matching bind exists then the default is returned if supplied. Other wise throws an Exception. + /// + /// + /// + /// + public IBeltItemInsertLogic ResolveInsertLogic(IBeltPort port) + { + _ports.Add(port); + foreach (var (match, factory) in _bindings) + { + if (match(port)) + { + return factory(); + } + } + if (Default is null) + { + throw new Exception($"{nameof(port)} does not have any binding attached that accepts it."); + } + return Default; + } + public IEnumerable GetPorts() => _ports; +} diff --git a/src/VoxelGrid/BeltPortHost.cs.uid b/src/VoxelGrid/BeltPortHost.cs.uid new file mode 100644 index 0000000..2b0860f --- /dev/null +++ b/src/VoxelGrid/BeltPortHost.cs.uid @@ -0,0 +1 @@ +uid://mimkyombngwg diff --git a/src/VoxelGrid/ConveyorItemRender.cs b/src/VoxelGrid/ConveyorItemRender.cs index 1618351..fc32f23 100644 --- a/src/VoxelGrid/ConveyorItemRender.cs +++ b/src/VoxelGrid/ConveyorItemRender.cs @@ -1,10 +1,7 @@ namespace ChickenGameTest; -using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Threading.Tasks; using Chickensoft.AutoInject; using Chickensoft.Introspection; using Godot; @@ -55,6 +52,32 @@ public interface IItemRenderer void UpdateTransform(IBeltItem beltItem, Transform3D newTransform, float time); void Remove(IBeltItem beltItem); } +public partial class ItemRenderSimple : Node3D, IItemRenderer +{ + public Dictionary _items = []; + public void Remove(IBeltItem beltItem) + { + if (_items.TryGetValue(beltItem, out var node)) + { + node.QueueFree(); + } + _items.Remove(beltItem); + } + + public void UpdateTransform(IBeltItem beltItem, Transform3D newTransform, float time) + { + if (!_items.TryGetValue(beltItem, out var node)) + { + _items.Add(beltItem, node = beltItem.CreateItemVisual()); + AddChild(node); + beltItem.Disposed += _ => { node.QueueFree(); _items.Remove(beltItem); }; + node.Transform = newTransform; + return; + } + node.Transform = newTransform; + } + public void UpdateTransform(IBeltItem beltItem, Transform3D newTransform) => UpdateTransform(beltItem, newTransform, .25f); +} public partial class TestItemRendered : Node3D, IItemRenderer { public Dictionary _items = []; diff --git a/src/VoxelGrid/ItemConveyor.cs b/src/VoxelGrid/ItemConveyor.cs index 90ca108..0274269 100644 --- a/src/VoxelGrid/ItemConveyor.cs +++ b/src/VoxelGrid/ItemConveyor.cs @@ -1,14 +1,11 @@ namespace ChickenGameTest; -using Chickensoft.Introspection; -using Chickensoft.AutoInject; using Godot; using System; using System.Collections.Generic; using System.Linq; using Chickensoft.Sync.Primitives; using SJK.Functional; -using System.Diagnostics.CodeAnalysis; public interface IMovementConveyor { diff --git a/src/VoxelGrid/ItemSpawner.cs b/src/VoxelGrid/ItemSpawner.cs new file mode 100644 index 0000000..1a2d048 --- /dev/null +++ b/src/VoxelGrid/ItemSpawner.cs @@ -0,0 +1,70 @@ +using Godot; +using System; + +namespace FoodFactory; + +using Arch.Core; +using ChickenGameTest; +using Chickensoft.AutoInject; +using Chickensoft.Introspection; +using FoodFactory.Recipes; +using Godot; + +[Meta(typeof(IAutoNode))] +public partial class ItemSpawner : Node3D, IProvide +{ + public override void _Notification(int what) => this.Notify(what); + + [Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn(); + [Dependency] public IBlueprintManger ItemFactory => this.DependOn(); + [Dependency] public World World => this.DependOn(); + [Dependency] public IRecipes Recipes => this.DependOn(); + private BeltPortHost _insertLogic = default!; + public IBeltPortHost Value() => _insertLogic; + private VoxelGuid _guid; + public GridTransform3D VoxelTransform + { + get => GridTransform3D.FromGodot(GlobalTransform); + set => GlobalTransform = value.ToGodot(); + } + [Export] public string ItemName { get; set; } = default!; + public override void _Ready() + { + _insertLogic = new BeltPortHost + { + Default = new DelegateInsertBeltItemLogic((_, _) => false, (_, _) => false) + }; + var timer = new Timer() { Autostart = true, WaitTime = 1f }; + AddChild(timer); + timer.Timeout += Tick; + this.Provide(); + } + public void OnResolved() => _guid = GridRegistry.Register(this, VoxelTransform.Origin); + + public override void _ExitTree() => GridRegistry.UnRegister(_guid); + public void Tick() + { + var ports = _insertLogic.GetPorts(); + foreach (var item in ports) + { + var port = item.GetPortFacing(GridRegistry); + if (!port.HasValue(out var beltPort)) + { + continue; + } + var itemBlueprint = ItemFactory.GetBlueprint(ItemName); + var dummyItem = new TestItem(); + if (beltPort.CanAccept(dummyItem, LaneSpan.One, 0)) + { + var ctx = new BlueprintContext() { BluePrintId = new BlueprintId(itemBlueprint), World = World }; + dummyItem.Item = itemBlueprint.Factory(ctx); + if (!beltPort.TryInsert(dummyItem, LaneSpan.One, 0)) + { + World.Destroy(dummyItem.Item);//TODO this should not call, but not sure + GD.PushWarning("Item failed to insert into port and removed item, item was destroyed but make sure item to prevent overhead."); + } + } + } + } +} + diff --git a/src/VoxelGrid/ItemSpawner.cs.uid b/src/VoxelGrid/ItemSpawner.cs.uid new file mode 100644 index 0000000..75ec960 --- /dev/null +++ b/src/VoxelGrid/ItemSpawner.cs.uid @@ -0,0 +1 @@ +uid://btmbv7oaeps4p diff --git a/src/VoxelGrid/ItemSpawner.tscn b/src/VoxelGrid/ItemSpawner.tscn new file mode 100644 index 0000000..c41817c --- /dev/null +++ b/src/VoxelGrid/ItemSpawner.tscn @@ -0,0 +1,17 @@ +[gd_scene format=3 uid="uid://bktqs1lw6go4"] + +[ext_resource type="Script" uid="uid://btmbv7oaeps4p" path="res://src/VoxelGrid/ItemSpawner.cs" id="1_3dxrm"] +[ext_resource type="PackedScene" uid="uid://bfwvlnurlcbwk" path="res://assets/kenney_conveyor-kit/Models/GLB format/cover-hopper.glb" id="2_552yl"] +[ext_resource type="Script" uid="uid://ee5aoxi8mjnw" path="res://src/VoxelGrid/BeltPort.cs" id="3_0b0h5"] + +[node name="ItemSpawner" type="Node3D" unique_id=966349707] +script = ExtResource("1_3dxrm") + +[node name="cover-hopper2" parent="." unique_id=2099493372 instance=ExtResource("2_552yl")] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0) + +[node name="Node3D" type="Node3D" parent="." unique_id=430904887] +script = ExtResource("3_0b0h5") +Face = 4 +Width = 1 +Access = 2 diff --git a/src/VoxelGrid/OvenTest.cs b/src/VoxelGrid/OvenTest.cs index 7d1b61c..5915de8 100644 --- a/src/VoxelGrid/OvenTest.cs +++ b/src/VoxelGrid/OvenTest.cs @@ -2,38 +2,50 @@ namespace ChickenGameTest; using System; using System.Collections.Generic; +using System.Diagnostics; +using Arch.Core; +using Arch.Core.Extensions; using Chickensoft.AutoInject; using Chickensoft.Introspection; +using FoodFactory; +using FoodFactory.Items; +using FoodFactory.Recipes; using Godot; using SJK.Functional; [Meta(typeof(IAutoNode))] public partial class OvenTest : Node3D, IProvide, IProvide { - private BeltPortHost _insertLogic; - public IBeltPortHost Value() => _insertLogic; public override void _Notification(int what) => this.Notify(what); + private BeltPortHost _insertLogic = default!; + public IBeltPortHost Value() => _insertLogic; [Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn(); + [Dependency] public IRecipes Recipes => this.DependOn(); IVoxelGridRegistry IProvide.Value() => GridRegistry; public GridTransform3D VoxelTransform { get => GridTransform3D.FromGodot(GlobalTransform); set => GlobalTransform = value.ToGodot(); } - private Dictionary? _placeholderItem = null; - private VoxelGuid _guid = default; + private Entity _itemBeingHeld = Entity.Null; + private VoxelGuid _guid; + public void OnResolved() { _insertLogic = new BeltPortHost(); _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.PortName == "Input", () => new DelegateInsertBeltItemLogic(canAccept, canInsert)); _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.PortName == "OutPut", () => new DelegateInsertBeltItemLogic((_, _) => false, (_, _) => false)); - bool canAccept(IBeltPort port, IBeltItem item) => _placeholderItem is null; + bool canAccept(IBeltPort port, IBeltItem item) => _itemBeingHeld.Id == -1 && !_itemBeingHeld.IsAlive(); bool canInsert(IBeltPort beltPort, IBeltItem item) { - _placeholderItem = (item as TestItem).PlaceHolderData; - item.Dispose(); - GD.Print("Added Item"); - return true; + if (item is IBeltItemData itemData) + { + _itemBeingHeld = itemData.GetItem(); + item.Dispose(); + GD.Print("Added Item"); + return true; + } + throw new NotImplementedException(); } _guid = GridRegistry.Register(this, VoxelTransform.Origin); this.Provide(); @@ -43,22 +55,54 @@ public partial class OvenTest : Node3D, IProvide, IProvide { - if (_placeholderItem is null) + if (_itemBeingHeld.Id == -1 && !_itemBeingHeld.IsAlive())//TODO have a better way of dertming if item is valid, possibly nullable { return; } - _placeholderItem.GetValue("temp").IfSome(some => _placeholderItem["temp"] = (float)some + 1); - if (_placeholderItem.GetValue("temp").Map(f => ((float)f) < 5).Or(true)) + + if (!_itemBeingHeld.TryGet(out var temp)) { return; } - var port = _insertLogic.GetPorts().FirstOrNone(port => port is BeltPort beltPort && beltPort.PortName == "OutPut").Bind(f => f.GetPortFacing(GridRegistry)); - if (port.HasValue(out var v) && _placeholderItem is not null && v.TryInsert(new TestItem() { PlaceHolderData = _placeholderItem }, LaneSpan.One, 0)) + temp.Kelvin += new TemperatureDelta(5f, TemperatureUnit.Fahrenheit).KelvinDelta; + _itemBeingHeld.Set(temp); + + Span items = [_itemBeingHeld]; + var context = new RecipeContext(World.Worlds[0], items); + var builder = new RecipeResultBuilder(stackalloc bool[10], new ItemBuilder[10]); + Span mapping = stackalloc int[1]; + var recipes = Recipes.GetRecipes(new RecipeAction("cook"), 1, [_itemBeingHeld.Get()], [], RecipeOutput.Any, mapping); + // Span created = stackalloc Entity[10]; + unsafe { - _placeholderItem = null; + while (RecipeProcessor.TryProcess( + ref recipes, + ref context, + ref builder, + &DestroyEntity, + out var created + )) + { + Debug.Assert(created.Length <= 1); + + _itemBeingHeld = created[0]; + break; + } } + if (_itemBeingHeld.TryGet(out var tags) && tags.Contains(TagRegistry.GetTag("cooked"))) + { + var port = _insertLogic.GetPorts().FirstOrNone(port => port is BeltPort beltPort && beltPort.PortName == "OutPut").Bind(f => f.GetPortFacing(GridRegistry)); + if (port.HasValue(out var v) && _itemBeingHeld.Id != -1 && _itemBeingHeld.IsAlive() && v.TryInsert(new TestItem() { Item = _itemBeingHeld }, LaneSpan.One, 0)) + { + _itemBeingHeld = Entity.Null; + } + } + }; } + + private static void DestroyEntity(Entity entity) => World.Worlds[entity.WorldId].Destroy(entity); + public override void _ExitTree() { GridRegistry.UnRegister(_guid); @@ -79,3 +123,123 @@ public class DelegateInsertBeltItemLogic : IBeltItemInsertLogic public bool CanAccept(IBeltPort beltPort, IBeltItem item) => _canAccept(beltPort, item); public bool CanInsert(IBeltPort beltPort, IBeltItem item) => _canInsert(beltPort, item); } +public readonly ref struct RecipeMatch +{ + public readonly Recipe Recipe; + public readonly ReadOnlySpan Mapping; + + public RecipeMatch( + Recipe recipe, + ReadOnlySpan mapping) + { + Recipe = recipe; + Mapping = mapping; + } +} +public interface IRecipeEnumerator +{ + RecipeMatch Current { get; } + + bool MoveNext(); +} +public unsafe ref struct RecipeEnumerator : IRecipeEnumerator +{ + public readonly RecipeMatch Current => _match; + private RecipeMatch _match; + private int _index; + private readonly ReadOnlySpan _recipes; + private readonly RecipeInput _input; + private readonly Span _mapping; + private readonly delegate*, out RecipeMatch, bool> _filter; + public RecipeEnumerator(ReadOnlySpan compiledRecipes, RecipeInput input, delegate*, out RecipeMatch, bool> filter, Span mapping) + { + _recipes = compiledRecipes; + _input = input; + _index = -1; + _filter = filter; + _mapping = mapping; + } + public bool MoveNext() + { + _index++; + while (_index < _recipes.Length) + { + if (_filter(_input, _recipes[_index], _mapping, out _match)) + { + break; + } + _index++; + + } + return _index < _recipes.Length; + + } +} +public static class RecipeProcessor +{ + public static unsafe bool TryProcess( + ref TRecipeEnumerator recipes, + scoped ref RecipeContext context, + scoped ref RecipeResultBuilder builder, + delegate* destroyEntity, + out Span resultEntity) + where TRecipeEnumerator : IRecipeEnumerator, allows ref struct + { + resultEntity = default; + + while (recipes.MoveNext()) + { + var entry = recipes.Current; + + var recipe = entry.Recipe; + + if (!recipe.CanProcess(context)) + { + continue; + } + + var result = recipe.Process(context, ref builder); + + ApplyResult( + in context, + result, + destroyEntity, + out resultEntity); + + builder.Clear(); + + return true; + } + + return false; + } + + private static unsafe void ApplyResult( + scoped in RecipeContext context, + scoped RecipeResult result, + delegate* destroyEntity, + out Span created) + { + created = default; + + + result.Mutate?.Invoke(context); + created = new Entity[result.CreateLength]; + for (int i = 0; i < result.CreateLength; i++) + { + created[i] = result.Create[i](in context); + + } + + if (result.RemoveLength > 0) + { + for (var i = 0; i < result.RemoveLength; i++) + { + if (result.Remove[i]) + { + destroyEntity(context.Items[i]); + } + } + } + } +} diff --git a/src/VoxelGrid/SlicerTest.cs b/src/VoxelGrid/SlicerTest.cs new file mode 100644 index 0000000..1943be0 --- /dev/null +++ b/src/VoxelGrid/SlicerTest.cs @@ -0,0 +1,106 @@ +namespace ChickenGameTest; + +using System; +using System.Collections.Generic; +using System.Linq; +using Arch.Core; +using Arch.Core.Extensions; +using Chickensoft.AutoInject; +using Chickensoft.Introspection; +using FoodFactory; +using FoodFactory.Items; +using FoodFactory.Recipes; +using Godot; +using SJK.Functional; + +[Meta(typeof(IAutoNode))] +public partial class SlicerTest : Node3D, IProvide, IProvide +{ + public override void _Notification(int what) => this.Notify(what); + private BeltPortHost _insertLogic = default!; + public IBeltPortHost Value() => _insertLogic; + [Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn(); + [Dependency] public IRecipes Recipes => this.DependOn(); + IVoxelGridRegistry IProvide.Value() => GridRegistry; + public GridTransform3D VoxelTransform + { + get => GridTransform3D.FromGodot(GlobalTransform); + set => GlobalTransform = value.ToGodot(); + } + private Entity _itemBeingHeld = Entity.Null; + private List sliced = []; + private VoxelGuid _guid; + + public void OnResolved() + { + _insertLogic = new BeltPortHost(); + _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.PortName == "Input", () => new DelegateInsertBeltItemLogic(canAccept, canInsert)); + _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.PortName == "OutPut", () => new DelegateInsertBeltItemLogic((_, _) => false, (_, _) => false)); + bool canAccept(IBeltPort port, IBeltItem item) => _itemBeingHeld.Id == -1 && !_itemBeingHeld.IsAlive() && item is IBeltItemData beltItemData && beltItemData.GetItem().TryGet(out var tags) && tags.Contains(TagRegistry.GetTag("sliceable")); + bool canInsert(IBeltPort beltPort, IBeltItem item) + { + if (item is IBeltItemData itemData) + { + _itemBeingHeld = itemData.GetItem(); + item.Dispose(); + GD.Print("Added Item to slicer"); + return true; + } + throw new NotImplementedException(); + } + _guid = GridRegistry.Register(this, VoxelTransform.Origin); + this.Provide(); + + var time = new Timer() { Autostart = true, OneShot = false, WaitTime = .1 }; + AddChild(time); + + time.Timeout += () => + { + + if (sliced.Any()) + { + var port = _insertLogic.GetPorts().FirstOrNone(port => 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] }, LaneSpan.One, 0)) + { + GD.Print(sliced[0].Get()); + sliced.RemoveAt(0); + } + } + if (_itemBeingHeld.Id == -1)//TODO have a better way of dertming if item is valid, possibly nullable + { + return; + } + + Span items = [_itemBeingHeld]; + var context = new RecipeContext(World.Worlds[0], items); + var builder = new RecipeResultBuilder(stackalloc bool[10], new ItemBuilder[10]); + Span mapping = stackalloc int[1]; + // var recipe = new PotatoCookRecipe(); + var recipes = Recipes.GetRecipes("slice", 1, [_itemBeingHeld.Get()], [], new RecipeOutput(2), mapping); + unsafe + { + while (RecipeProcessor.TryProcess( + ref recipes, + ref context, + ref builder, + &DestroyEntity, + out var created + )) + { + _itemBeingHeld = Entity.Null; + sliced.AddRange(created); + break; + } + } + + }; + } + private static void DestroyEntity(Entity entity) => World.Worlds[entity.WorldId].Destroy(entity); + + + public override void _ExitTree() + { + GridRegistry.UnRegister(_guid); + base._ExitTree(); + } +} diff --git a/src/VoxelGrid/SlicerTest.cs.uid b/src/VoxelGrid/SlicerTest.cs.uid new file mode 100644 index 0000000..44588cc --- /dev/null +++ b/src/VoxelGrid/SlicerTest.cs.uid @@ -0,0 +1 @@ +uid://yec84plemjv1 diff --git a/src/VoxelGrid/TestItemConveyor.cs b/src/VoxelGrid/TestItemConveyor.cs index cd4767d..477412b 100644 --- a/src/VoxelGrid/TestItemConveyor.cs +++ b/src/VoxelGrid/TestItemConveyor.cs @@ -8,6 +8,8 @@ using System.Collections.Generic; using System.Linq; using Chickensoft.Sync.Primitives; using SJK.Functional; +using FoodFactory.Recipes; +using Arch.Core; public class Sorted1DList { @@ -258,7 +260,6 @@ public partial class TestItemConveyor : Node, IMovementConveyor var guid = GridRegistry.Register(item, [.. points]); TreeExiting += () => GridRegistry.UnRegister(guid); } - StartPort.TryInsert(new TestItem() { PlaceHolderData = new() { ["temp"] = 0f } }, LaneSpan.Shifted(LaneSpan.One, 0), 0); } //ChatGPT Assisted public BeltObstacle GetDistanceToNextItem( @@ -458,22 +459,22 @@ public partial class TestItemConveyor : Node, IMovementConveyor public const float ITEMSIZE = .2f; private const float ITEMHALFSIZE = ITEMSIZE / 2f; - public override void _Process(double delta) - { - if (StartPort is null || EndPort is null) - { - return; - } - foreach (var item in GetPorts()) - { - for (int ii = 0; ii < item.Profile.Width; ii++) - { - DebugDraw3D.DrawLinePath(_square.Select(i => item.Profile.LocalOffset.ToGodot().TranslatedLocal(i).TranslatedLocal(new Vector3(ii, 0, 0)).Origin).ToArray(), (!Engine.IsEditorHint()) && GetPortFacing(item).HasValue() ? Colors.Green : Colors.Red); + // public override void _Process(double delta) + // { + // if (StartPort is null || EndPort is null) + // { + // return; + // } + // foreach (var item in GetPorts()) + // { + // for (int ii = 0; ii < item.Profile.Width; ii++) + // { + // DebugDraw3D.DrawLinePath(_square.Select(i => item.Profile.LocalOffset.ToGodot().TranslatedLocal(i).TranslatedLocal(new Vector3(ii, 0, 0)).Origin).ToArray(), (!Engine.IsEditorHint()) && GetPortFacing(item).HasValue() ? Colors.Green : Colors.Red); - } - // DebugDraw3D.DrawArrow(item.Profile.LocalOffset.Origin, item.Profile.LocalOffset.LocalToWorld(item.Profile.Face.ToVector()),(!Engine.IsEditorHint())&&GetPortFacing(item).HasValue()?Colors.Green:Colors.Red); - } - } + // } + // // DebugDraw3D.DrawArrow(item.Profile.LocalOffset.Origin, item.Profile.LocalOffset.LocalToWorld(item.Profile.Face.ToVector()),(!Engine.IsEditorHint())&&GetPortFacing(item).HasValue()?Colors.Green:Colors.Red); + // } + // } public ConveyorPort CreatePort(BeltPortProfile profile, BeltT beltT, LaneSpan laneSpan) { diff --git a/src/VoxelGrid/VoxelGridNode.cs b/src/VoxelGrid/VoxelGridNode.cs index 5dc6856..127ccc4 100644 --- a/src/VoxelGrid/VoxelGridNode.cs +++ b/src/VoxelGrid/VoxelGridNode.cs @@ -2,36 +2,90 @@ namespace ChickenGameTest; using System; using System.Collections.Generic; -using System.Linq; +using System.Text.RegularExpressions; +using Arch.Core; +using Arch.Core.Extensions; +using Arch.LowLevel; +using Arch.System; using Chickensoft.AutoInject; using Chickensoft.Introspection; +using FoodFactory; +using FoodFactory.Recipes; using Godot; -using Godot.Collections; -using SJK.Functional; +public class BacterialSystem : BaseSystem +{ + private QueryDescription _desc = new QueryDescription().WithAll(); + public static Resources> Resources = new(); + public BacterialSystem(World world) : base(world) + { + + } + public override void Update(in float t) + { + var delta = t; + World.ParallelQuery(in _desc, (Entity entity, ref Bacteria bacteria, ref Temperature temperature) => + { + var handle = bacteria.Data; + var data = Resources.Get(in handle); + for (int i = 0; i < data.Count; i++) + { + data[i] = data[i] with { Count = BacteriaModel.UpdatePopulation(data[i].Count, temperature.Celsius, delta) }; + // GD.Print(data[i].Count); + if (data[i].Count <= 0.5) + { + data.RemoveAt(i); + i--; + } + } + }); + } +} //Will Liklely be the game instead of a node like this [Meta(typeof(IAutoNode))]// [Tool] -public partial class VoxelGridNode : Node3D, IProvide, IProvide +public partial class VoxelGridNode : Node3D, IProvide, IProvide, IProvide, IProvide, IProvide { public override void _Notification(int what) => this.Notify(what); + private World _world = default!; + World IProvide.Value() => _world; private IVoxelGridRegistry _voxelGridRegistry = default!; IVoxelGridRegistry IProvide.Value() => _voxelGridRegistry; + private IBlueprintManger _blueprintManger = default!; + IBlueprintManger IProvide.Value() => _blueprintManger; + private Recipes _recipes = default!; + IRecipes IProvide.Value() => _recipes; private IItemRenderer _itemRenderer = default!; IItemRenderer IProvide.Value() => _itemRenderer; + Group _systems; public override void _Ready() { // GD.Print(); base._Ready(); _voxelGridRegistry = new VoxelRegistry(); - _itemRenderer = new TestItemRendered(); + _itemRenderer = new ItemRenderSimple(); + _blueprintManger = new BlueprintManger(); + _recipes = new Recipes(); + _world = World.Create(); + _systems = new Group("Items", new BacterialSystem(_world)); + + AddChild(_itemRenderer as Node); Timer timer = new Timer() { WaitTime = .25f, Autostart = true };//TEST AddChild(timer);//TEST // timer.Timeout += _itemRenderer.Tick;//TEST + timer.Timeout += () => + { + _systems.BeforeUpdate(.25f); + _systems.Update(.25f); + _systems.AfterUpdate(.25f); + }; + _systems.Initialize(); this.Provide(); } + + public override void _Input(InputEvent @event) { if (@event.IsActionPressed("ui_up")) @@ -46,4 +100,51 @@ public partial class VoxelGridNode : Node3D, IProvide, IProv } } } + public override void _ExitTree() + { + base._ExitTree(); + _systems.Dispose(); + _world.Dispose(); + } +} +public static class BacteriaModel +{ + // population = current bacteria count + // temperature = degrees Celsius + // deltaTime = elapsed time (hours) + public static double UpdatePopulation( + double population, + double temperature, + double deltaTime) + { + double rate; + + // Very cold -> slight die-off + if (temperature <= 5) + { + rate = -0.1; + } + // Growth zone + else if (temperature < 35) + { + rate = 0.06 * (temperature - 5); + } + // Hot but still survivable + else if (temperature < 60) + { + rate = 1.8 - 0.08 * (temperature - 35); + } + // Dangerous heat -> bacteria die + else + { + rate = -0.8; + } + + // Population update + double newPopulation = + population + (deltaTime * population * rate); + + // Prevent negative bacteria counts + return Math.Max(0, newPopulation); + } } diff --git a/src/VoxelGrid/VoxelGridNode.tscn b/src/VoxelGrid/VoxelGridNode.tscn index 722d5fd..28cbf1a 100644 --- a/src/VoxelGrid/VoxelGridNode.tscn +++ b/src/VoxelGrid/VoxelGridNode.tscn @@ -2,9 +2,12 @@ [ext_resource type="Script" uid="uid://dcrb286hmpli" path="res://src/VoxelGrid/VoxelGridNode.cs" id="1_tsdpe"] [ext_resource type="Script" uid="uid://cnkblltup5guy" path="res://src/VoxelGrid/OvenTest.cs" id="3_r7dgx"] +[ext_resource type="PackedScene" uid="uid://bktqs1lw6go4" path="res://src/VoxelGrid/ItemSpawner.tscn" id="5_mxaon"] [ext_resource type="PackedScene" uid="uid://h00mq2srsbfa" path="res://assets/kenney_conveyor-kit/Models/GLB format/door.glb" id="5_wk2t5"] [ext_resource type="Script" uid="uid://ee5aoxi8mjnw" path="res://src/VoxelGrid/BeltPort.cs" id="6_2wkfx"] [ext_resource type="PackedScene" uid="uid://c4h7mwnfrdesg" path="res://src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.tscn" id="6_mxaon"] +[ext_resource type="Script" uid="uid://opbkqoaa7x2n" path="res://src/VoxelGrid/Balancer.cs" id="7_2wkfx"] +[ext_resource type="Script" uid="uid://yec84plemjv1" path="res://src/VoxelGrid/SlicerTest.cs" id="8_2lg7i"] [sub_resource type="Curve3D" id="Curve3D_mxaon"] _data = { @@ -13,6 +16,9 @@ _data = { } point_count = 2 +[sub_resource type="BoxMesh" id="BoxMesh_2wkfx"] +size = Vector3(1, 1, 2) + [node name="VoxelGridNode" type="Node3D" unique_id=825696340] script = ExtResource("1_tsdpe") @@ -20,108 +26,123 @@ script = ExtResource("1_tsdpe") transform = Transform3D(0.6279494, -0.32487354, 0.70720345, -8.896721e-09, 0.908705, 0.4174389, -0.77825415, -0.26213053, 0.5706208, 4.635174, 2.6038146, 2.739409) [node name="ConveyorBeltStraight5" parent="." unique_id=975225936 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 0) -Width = 1 - -[node name="ConveyorBeltStraight22" parent="." unique_id=81137442 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 2, 0, 0) -Width = 1 - -[node name="ConveyorBeltStraight13" parent="." unique_id=607296315 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 0) -Width = 1 - -[node name="ConveyorBeltStraight26" parent="." unique_id=626657643 instance=ExtResource("6_mxaon")] transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 0) -Width = 1 - -[node name="ConveyorBeltStraight6" parent="." unique_id=264656404 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -1, 0, 0) -Width = 1 - -[node name="ConveyorBeltStraight23" parent="." unique_id=1438072389 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -2, 0, 0) -Width = 1 [node name="ConveyorBeltStraight14" parent="." unique_id=1045608025 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -4, 0, 0) -Width = 1 - -[node name="ConveyorBeltStraight27" parent="." unique_id=899289297 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -3, 0, 0) -Width = 1 +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 0) [node name="ConveyorBeltStraight7" parent="." unique_id=1602707514 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 1) -Width = 1 +transform = Transform3D(-1, 0, -8.742277e-08, 0, 1, 0, 8.742277e-08, 0, -1, 1, 0, 1) + +[node name="ConveyorBeltStraight8" parent="." unique_id=1032197109 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 2) + +[node name="ConveyorBeltStraight24" parent="." unique_id=574723066 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 6) + +[node name="ConveyorBeltStraight25" parent="." unique_id=1584944068 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 6) + +[node name="ConveyorBeltStraight13" parent="." unique_id=490179430 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 2) + +[node name="ConveyorBeltStraight20" parent="." unique_id=1684880263 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 4, 0, 2) + +[node name="ConveyorBeltStraight15" parent="." unique_id=1971663524 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 3) + +[node name="ConveyorBeltStraight23" parent="." unique_id=830278017 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 4, 0, 3) [node name="ConveyorBeltStraight9" parent="." unique_id=1449572266 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 1) -Width = 1 +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 1) + +[node name="ConveyorBeltStraight26" parent="." unique_id=181268712 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 5) + +[node name="ConveyorBeltStraight27" parent="." unique_id=1546024538 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 6) + +[node name="ConveyorBeltStraight28" parent="." unique_id=1945842047 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 4) + +[node name="ConveyorBeltStraight29" parent="." unique_id=116753972 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 8) + +[node name="ConveyorBeltStraight30" parent="." unique_id=903050872 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 9) + +[node name="ConveyorBeltStraight31" parent="." unique_id=848458617 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 7) + +[node name="ConveyorBeltStraight32" parent="." unique_id=889036013 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 8) + +[node name="ConveyorBeltStraight33" parent="." unique_id=992629708 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 9) + +[node name="ConveyorBeltStraight34" parent="." unique_id=795974742 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 7, 0, 9) + +[node name="ConveyorBeltStraight35" parent="." unique_id=601890089 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 5) + +[node name="ConveyorBeltStraight36" parent="." unique_id=2134741630 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 7, 0, 4) + +[node name="ConveyorBeltStraight37" parent="." unique_id=196786809 instance=ExtResource("6_mxaon")] +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 4) [node name="ConveyorBeltStraight10" parent="." unique_id=68139731 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 1) -Width = 1 +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 4, 0, 1) [node name="ConveyorBeltStraight11" parent="." unique_id=358641682 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 7, 0, 1) -Width = 1 +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 1) [node name="ConveyorBeltStraight12" parent="." unique_id=310565328 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 8, 0, 1) -Width = 1 +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 1) [node name="ConveyorBeltStraight17" parent="." unique_id=111805683 instance=ExtResource("6_mxaon")] -transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 9, 0, 1) -Width = 1 +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 1) + +[node name="ConveyorBeltStraight21" parent="." unique_id=764425478 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 2) + +[node name="ConveyorBeltStraight22" parent="." unique_id=1089887693 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 3) [node name="ConveyorBeltStraight18" parent="." unique_id=971476244 instance=ExtResource("6_mxaon")] -transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 9, 0, 0) -Width = 1 +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 0) -[node name="ConveyorBeltStraight19" parent="." unique_id=87035771 instance=ExtResource("6_mxaon")] -transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 9, 0, -1) -Width = 1 +[node name="ConveyorBeltStraight19" parent="." unique_id=1940918727 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 8, 0, -3) -[node name="ConveyorBeltStraight24" parent="." unique_id=904248251 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 2, 0, 1) -Width = 1 +[node name="ConveyorBeltStraight40" parent="." unique_id=1578916497 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 8, 0, -2) -[node name="ConveyorBeltStraight15" parent="." unique_id=533235542 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 1) -Width = 1 +[node name="ConveyorBeltStraight41" parent="." unique_id=1562444632 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 8, 0, -4) -[node name="ConveyorBeltStraight28" parent="." unique_id=2116943332 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 1) -Width = 1 +[node name="ConveyorBeltStraight38" parent="." unique_id=1520289120 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, -3) -[node name="ConveyorBeltStraight8" parent="." unique_id=1109978762 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -1, 0, 1) -Width = 1 - -[node name="ConveyorBeltStraight25" parent="." unique_id=1110001269 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -2, 0, 1) -Width = 1 +[node name="ConveyorBeltStraight39" parent="." unique_id=44974977 instance=ExtResource("6_mxaon")] +transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, -4) [node name="ConveyorBeltStraight16" parent="." unique_id=1178816500 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -4, 0, 1) -Width = 1 - -[node name="ConveyorBeltStraight29" parent="." unique_id=1537356869 instance=ExtResource("6_mxaon")] -transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, -3, 0, 1) -Width = 1 +transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 1) [node name="OvenTest" type="Node3D" parent="." unique_id=824176002] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0) script = ExtResource("3_r7dgx") -[node name="Node3D2" type="Node3D" parent="OvenTest" unique_id=1815100025 node_paths=PackedStringArray("Path")] +[node name="Node3D2" type="Node3D" parent="OvenTest" unique_id=1815100025] transform = Transform3D(1.3113416e-07, 0, 1, 0, 1, 0, -1, 0, 1.3113416e-07, 0, 0, 0) script = ExtResource("6_2wkfx") Face = 4 Width = 1 -Access = 3 -Path = NodePath("Path3D") +Access = 1 PortName = "Input" [node name="Path3D" type="Path3D" parent="OvenTest/Node3D2" unique_id=1525648764] @@ -130,13 +151,12 @@ curve = SubResource("Curve3D_mxaon") [node name="door3" parent="OvenTest/Node3D2" unique_id=351624885 instance=ExtResource("5_wk2t5")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.870017e-08, 0, -0.6001501) -[node name="Node3D3" type="Node3D" parent="OvenTest" unique_id=1033202746 node_paths=PackedStringArray("Path")] +[node name="Node3D3" type="Node3D" parent="OvenTest" unique_id=1033202746] transform = Transform3D(-2.1855693e-07, 0, -1, 0, 1, 0, 1, 0, -2.1855693e-07, 0, 0, 1) script = ExtResource("6_2wkfx") Face = 4 Width = 1 -Access = 3 -Path = NodePath("Path3D2") +Access = 2 PortName = "OutPut" [node name="Path3D2" type="Path3D" parent="OvenTest/Node3D3" unique_id=739562310] @@ -144,3 +164,115 @@ curve = SubResource("Curve3D_mxaon") [node name="door4" parent="OvenTest/Node3D3" unique_id=1602265662 instance=ExtResource("5_wk2t5")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499) + +[node name="door5" parent="OvenTest/Node3D3" unique_id=102838222 instance=ExtResource("5_wk2t5")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499) + +[node name="ItemSpawner" parent="." unique_id=966349707 instance=ExtResource("5_mxaon")] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -1.0023941, 0, 0.0019463301) +ItemName = "Potato" + +[node name="ItemSpawner2" parent="." unique_id=405829395 instance=ExtResource("5_mxaon")] +transform = Transform3D(3.059797e-07, 0, -1, 0, 1, 0, 1, 0, 3.059797e-07, -1, 0, 1) +ItemName = "Onion" + +[node name="ItemSpawner3" parent="." unique_id=422927887 instance=ExtResource("5_mxaon")] +transform = Transform3D(3.059797e-07, 0, -1, 0, 1, 0, 1, 0, 3.059797e-07, -1, 0, 6) +ItemName = "Potato" + +[node name="Balancer" type="Node3D" parent="." unique_id=619243985] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 2) +script = ExtResource("7_2wkfx") + +[node name="Node3D" type="Node3D" parent="Balancer" unique_id=793236513] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 1 + +[node name="Node3D3" type="Node3D" parent="Balancer" unique_id=1846433120] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 2 + +[node name="Node3D4" type="Node3D" parent="Balancer" unique_id=1579207766] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 1) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 1 + +[node name="Node3D2" type="Node3D" parent="Balancer" unique_id=717100096] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 1) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 2 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Balancer" unique_id=383290173] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5) +mesh = SubResource("BoxMesh_2wkfx") + +[node name="Balancer8" type="Node3D" parent="." unique_id=1783081047] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 7, 0, -1) +script = ExtResource("7_2wkfx") + +[node name="Node3D" type="Node3D" parent="Balancer8" unique_id=1818940385] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 1 + +[node name="Node3D3" type="Node3D" parent="Balancer8" unique_id=51764402] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 2 + +[node name="Node3D4" type="Node3D" parent="Balancer8" unique_id=233486636] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 1) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 1 + +[node name="Node3D2" type="Node3D" parent="Balancer8" unique_id=1446214840] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 1) +script = ExtResource("6_2wkfx") +Face = 4 +Width = 1 +Access = 2 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Balancer8" unique_id=556689065] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5) +mesh = SubResource("BoxMesh_2wkfx") + +[node name="Slicer" type="Node3D" parent="." unique_id=566544377] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0, -2) +script = ExtResource("8_2lg7i") + +[node name="Node3D4" type="Node3D" parent="Slicer" unique_id=1206144064] +transform = Transform3D(-1, 0, 8.742277e-08, 0, 1, 0, -8.742277e-08, 0, -1, 0, 0, 0) + +[node name="Path3D" type="Path3D" parent="Slicer/Node3D4" unique_id=894348025] +curve = SubResource("Curve3D_mxaon") + +[node name="door3" parent="Slicer/Node3D4" unique_id=1024066398 instance=ExtResource("5_wk2t5")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.870017e-08, 0, -0.6001501) + +[node name="Node3D5" type="Node3D" parent="Slicer" unique_id=1113082191] +transform = Transform3D(1, 0, -1.7484555e-07, 0, 1, 0, 1.7484555e-07, 0, 1, 0, 0, 0) + +[node name="Path3D2" type="Path3D" parent="Slicer/Node3D5" unique_id=1352328131] +curve = SubResource("Curve3D_mxaon") + +[node name="door4" parent="Slicer/Node3D5" unique_id=1411233670 instance=ExtResource("5_wk2t5")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499) + +[node name="door5" parent="Slicer/Node3D5" unique_id=770270315 instance=ExtResource("5_wk2t5")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499) diff --git a/src/VoxelGrid/VoxelRegistry.cs b/src/VoxelGrid/VoxelRegistry.cs index fb8f3c6..50e3b2e 100644 --- a/src/VoxelGrid/VoxelRegistry.cs +++ b/src/VoxelGrid/VoxelRegistry.cs @@ -1,13 +1,9 @@ namespace ChickenGameTest; -using Chickensoft.GodotNodeInterfaces; -using Chickensoft.Introspection; -using Chickensoft.AutoInject; using Godot; using System; using System.Collections.Generic; using System.Linq; -using ChickenGameTest; using SJK.Functional; public interface IVoxelGridRegistry