Spite up project, added BeltData, some asoited compoents, remvoed unused usings, and removed uneeded comment code.
This commit is contained in:
@@ -37,33 +37,36 @@
|
||||
<ItemGroup>
|
||||
<!-- Production dependencies go here! -->
|
||||
<PackageReference Include="Arch" Version="2.1.0" />
|
||||
<PackageReference Include="Arch-Events" Version="2.1.0" />
|
||||
<PackageReference Include="Arch.LowLevel" Version="1.1.5" />
|
||||
<PackageReference Include="Arch.System" Version="1.1.0" />
|
||||
<PackageReference Include="Chickensoft.GameTools" Version="3.1.18" />
|
||||
<PackageReference Include="NCalc.LambdaCompilation" Version="5.12.0" />
|
||||
<PackageReference Include="NCalcSync" Version="5.12.0" />
|
||||
<PackageReference Include="SjkScripts" Version="1.0.17" />
|
||||
<PackageReference Include="System.IO.Abstractions" Version="22.1.1" />
|
||||
<PackageReference Include="System.IO.Abstractions" Version="22.1.0" />
|
||||
<PackageReference Include="EnvironmentAbstractions" Version="5.0.0" />
|
||||
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0" PrivateAssets="all" OutputItemType="analyzer" />
|
||||
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.3.66" />
|
||||
<PackageReference Include="Chickensoft.AutoInject" Version="2.13.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.3.54" />
|
||||
<PackageReference Include="Chickensoft.AutoInject" Version="2.9.18" PrivateAssets="all" />
|
||||
<PackageReference Include="Chickensoft.Collections" Version="3.1.4" />
|
||||
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="3.0.12" />
|
||||
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.57" />
|
||||
<PackageReference Include="Chickensoft.Introspection" Version="3.0.2" />
|
||||
<PackageReference Include="Chickensoft.Introspection.Generator" Version="3.0.2" PrivateAssets="all" OutputItemType="analyzer" />
|
||||
<PackageReference Include="Chickensoft.Serialization" Version="3.1.0" />
|
||||
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.8.64" />
|
||||
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.8.46" />
|
||||
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.20.0" />
|
||||
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.20.0" PrivateAssets="all" OutputItemType="analyzer" />
|
||||
<PackageReference Include="Chickensoft.UMLGenerator" Version="1.3.1" />
|
||||
<PackageReference Include="Chickensoft.Sync" Version="2.3.0" />
|
||||
<PackageReference Include="Chickensoft.UMLGenerator" Version="1.1.0" />
|
||||
<PackageReference Include="Chickensoft.Sync" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(RunTests)' == 'true'">
|
||||
<!-- Test dependencies go here! -->
|
||||
<!-- Dependencies added here will not be included in release builds. -->
|
||||
<PackageReference Include="Chickensoft.GoDotTest" Version="2.0.33" />
|
||||
<PackageReference Include="Chickensoft.GoDotTest" Version="2.0.27" />
|
||||
<!-- Used to drive test scenes when testing visual code -->
|
||||
<PackageReference Include="Chickensoft.GodotTestDriver" Version="3.1.68" />
|
||||
<PackageReference Include="Chickensoft.GodotTestDriver" Version="3.1.56" />
|
||||
<!-- Bring your own assertion library for tests! -->
|
||||
<!-- We're using Shouldly for this example, but you can use anything. -->
|
||||
<PackageReference Include="Shouldly" Version="4.3.0" />
|
||||
|
||||
2
assets
2
assets
Submodule assets updated: b5ad429c59...37af2de434
@@ -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<IVoxelGridRegistry>
|
||||
{
|
||||
@@ -16,19 +16,21 @@ public partial class ConveyorBeltStraight : Node3D, IProvide<IVoxelGridRegistry>
|
||||
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<IVoxelGridRegistry>
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -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")
|
||||
|
||||
30
src/Items/Components/Tag.cs
Normal file
30
src/Items/Components/Tag.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace FoodFactory.Items;
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
|
||||
public readonly struct Tag : IEquatable<Tag>, IEqualityOperators<Tag, Tag, bool>, IComparisonOperators<Tag, Tag, bool>,
|
||||
IComparable<Tag>
|
||||
{
|
||||
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;
|
||||
}
|
||||
1
src/Items/Components/Tag.cs.uid
Normal file
1
src/Items/Components/Tag.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://1o2e2wou367m
|
||||
@@ -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<Tags>, IReadOnlyCollection<Tag>
|
||||
{
|
||||
@@ -178,30 +174,6 @@ public readonly struct Tags : IEquatable<Tags>, IReadOnlyCollection<Tag>
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct Tag : IEquatable<Tag>, IEqualityOperators<Tag, Tag, bool>, IComparisonOperators<Tag, Tag, bool>,
|
||||
IComparable<Tag>
|
||||
{
|
||||
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<string> _registry = new();
|
||||
|
||||
1
src/Items/Components/Tags.cs.uid
Normal file
1
src/Items/Components/Tags.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://chk03ru27wxw1
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
{
|
||||
T GetItem();
|
||||
}
|
||||
public class TestItem() : IBeltItem, IBeltItemData<Entity>
|
||||
{
|
||||
public float Temp { get; set; }
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
public static PackedScene PotatoScene = ResourceLoader.Load<PackedScene>("res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/food_ingredient_potato.gltf");
|
||||
public static PackedScene OnionScene = ResourceLoader.Load<PackedScene>("res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/food_ingredient_onion.gltf");
|
||||
public static PackedScene ChoppedOnionScene = ResourceLoader.Load<PackedScene>("res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/food_ingredient_onion_chopped.gltf");
|
||||
public Node3D CreateItemVisual()
|
||||
{
|
||||
Node3D node;
|
||||
if (Item.Get<Tags>().Contains(TagRegistry.GetTag("potato")))
|
||||
{
|
||||
node = PotatoScene.Instantiate<Node3D>();
|
||||
}
|
||||
else if (Item.Get<Tags>().ContainsAny(new Tags("sliced")))
|
||||
{
|
||||
node = ChoppedOnionScene.Instantiate<Node3D>();
|
||||
}
|
||||
else if (Item.Get<Tags>().Contains(TagRegistry.GetTag("onion")))
|
||||
{
|
||||
node = OnionScene.Instantiate<Node3D>();
|
||||
}
|
||||
else
|
||||
{
|
||||
node = new MeshInstance3D() { Mesh = new BoxMesh() };
|
||||
}
|
||||
node.GetChildren().OfType<Node3D>().ToList().ForEach(i => i.Scale *= new Vector3(.2f, .2f, .2f));
|
||||
if (Item.TryGet<Color>(out var color))
|
||||
{
|
||||
node.GetChildren().OfType<MeshInstance3D>().FirstOrNone().IfSome(some => some.SetSurfaceOverrideMaterial(0, new StandardMaterial3D() { AlbedoColor = Item.TryGet<Color>(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<Color>(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<string, object> PlaceHolderData = [];
|
||||
|
||||
public Entity GetItem() => Item;
|
||||
|
||||
public Entity Item;
|
||||
}
|
||||
|
||||
public interface IFluidItem
|
||||
|
||||
@@ -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<List<Entity>>();
|
||||
|
||||
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);
|
||||
@@ -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<Entity> 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<Tags>()], [])[0].Recipe;
|
||||
if (recipe.CanProcess(context))
|
||||
{
|
||||
var result = recipe.Process(context, ref builder);
|
||||
var list3 = new List<Entity>();
|
||||
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<Vitamin> 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<Entity> Children);
|
||||
|
||||
public record struct Bacteria(Handle<List<BacteriaData>> Data);
|
||||
public record struct BacteriaData(string Name, double Count);
|
||||
|
||||
public record struct Handle(int Index, int Version);
|
||||
|
||||
@@ -157,7 +175,7 @@ public class BucketStorage<T>
|
||||
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
|
||||
|
||||
1
src/Items/ItemECSTest.cs.uid
Normal file
1
src/Items/ItemECSTest.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c5ik7ke6rrlmn
|
||||
109
src/Math/Ordered1DList.cs
Normal file
109
src/Math/Ordered1DList.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
namespace SJK.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Arch.LowLevel;
|
||||
|
||||
public sealed class Ordered1DList<T> : IDisposable where T : unmanaged
|
||||
{
|
||||
private readonly UnsafeList<Entry> _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<T> list, bool towardsEnd, int index)
|
||||
{
|
||||
_list = list;
|
||||
_towardsEnd = towardsEnd;
|
||||
_index = index;
|
||||
}
|
||||
private readonly Ordered1DList<T> _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();
|
||||
}
|
||||
1
src/Math/Ordered1DList.cs.uid
Normal file
1
src/Math/Ordered1DList.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://uuf56xygihoh
|
||||
1
src/Math/Temperature.cs.uid
Normal file
1
src/Math/Temperature.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://pcjdirermsr7
|
||||
148
src/Math/Weight.cs
Normal file
148
src/Math/Weight.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
public readonly record struct Weight(double Grams)
|
||||
: IComparable<Weight>,
|
||||
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);
|
||||
}
|
||||
1
src/Math/Weight.cs.uid
Normal file
1
src/Math/Weight.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://7e8o324qvsox
|
||||
58
src/Recipes/Blueprint.cs
Normal file
58
src/Recipes/Blueprint.cs
Normal file
@@ -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<string, Blueprint> _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<BlueprintContext, Entity> Factory)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public struct BlueprintContext
|
||||
{
|
||||
public World World;
|
||||
public BlueprintId BluePrintId;
|
||||
}
|
||||
1
src/Recipes/Blueprint.cs.uid
Normal file
1
src/Recipes/Blueprint.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cj088ogl8uqmt
|
||||
14
src/Recipes/BlueprintId.cs
Normal file
14
src/Recipes/BlueprintId.cs
Normal file
@@ -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<Blueprint> _registry = new();
|
||||
public BlueprintId(Blueprint blueprint)
|
||||
{
|
||||
Id = _registry.GetOrCreate(blueprint);
|
||||
}
|
||||
}
|
||||
1
src/Recipes/BlueprintId.cs.uid
Normal file
1
src/Recipes/BlueprintId.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b7kmhd6uamhg
|
||||
231
src/Recipes/Recipe.cs
Normal file
231
src/Recipes/Recipe.cs
Normal file
@@ -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<Temperature>(out var temp) && context.Items[0].TryGet<BurnableTemp>(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<BurnableTemp>();
|
||||
context.Items[0].Add(new BurnedItem(context.Items[0].Get<Temperature>(), "Was Burned as some time thing"));
|
||||
context.Items[0].Set(context.Items[0].Get<Tags>().WithOut("burnable").With("burned"));
|
||||
context.Items[0].Set($"Burned_{context.Items[0].Get<Name>().Value}");
|
||||
if (context.Items[0].Has<Color>())
|
||||
{
|
||||
context.Items[0].Set(context.Items[0].Get<Color>() * 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<Entity> 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<Name>().Value));
|
||||
span[0].Set(new Mass(context.Items[0].Get<Mass>().Value * .5));
|
||||
span[0].Set(span[0].Get<Tags>().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<Temperature>(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<Entity> 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<Tags>().With("cooked").WithOut("raw"));
|
||||
// span[0].Set(context.Entity[0].Get<Temperature>());
|
||||
if (context.Items[0].Has<Color>())
|
||||
{
|
||||
context.Items[0].Set(context.Items[0].Get<Color>() * Colors.Brown);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Items[0].Add(Colors.Brown);
|
||||
}
|
||||
return span[0];
|
||||
}
|
||||
public static void CopyEntities(Span<Entity> from, Span<Entity> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/Recipes/Recipe.cs.uid
Normal file
1
src/Recipes/Recipe.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://152ii3ysj30f
|
||||
12
src/Recipes/RecipeAction.cs
Normal file
12
src/Recipes/RecipeAction.cs
Normal file
@@ -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);
|
||||
}
|
||||
1
src/Recipes/RecipeAction.cs.uid
Normal file
1
src/Recipes/RecipeAction.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dut1goeo1md46
|
||||
37
src/Recipes/RecipeBucket.cs
Normal file
37
src/Recipes/RecipeBucket.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace FoodFactory.Recipes;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public sealed class RecipeBucket
|
||||
{
|
||||
public Dictionary<BlueprintId, CompiledRecipe[]> Single = [];
|
||||
public Dictionary<BlueprintId, CompiledRecipe[]> Ordered = [];
|
||||
public CompiledRecipe[] Unordered = [];
|
||||
public ReadOnlySpan<CompiledRecipe> Resolve(Span<BlueprintId> 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;
|
||||
}
|
||||
}
|
||||
1
src/Recipes/RecipeBucket.cs.uid
Normal file
1
src/Recipes/RecipeBucket.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cfhklflid8ed1
|
||||
20
src/Recipes/RecipeContext.cs
Normal file
20
src/Recipes/RecipeContext.cs
Normal file
@@ -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> entity) : this()
|
||||
{
|
||||
World = world;
|
||||
Items = entity;
|
||||
}
|
||||
|
||||
public readonly Span<Entity> Items;
|
||||
// optional later:
|
||||
// public readonly Machine Machine;
|
||||
// public readonly float Delta;
|
||||
}
|
||||
1
src/Recipes/RecipeContext.cs.uid
Normal file
1
src/Recipes/RecipeContext.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cjamv4y4aikhc
|
||||
20
src/Recipes/RecipeName.cs
Normal file
20
src/Recipes/RecipeName.cs
Normal file
@@ -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);
|
||||
}
|
||||
1
src/Recipes/RecipeName.cs.uid
Normal file
1
src/Recipes/RecipeName.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b635p37fwu0xl
|
||||
26
src/Recipes/RecipeResult.cs
Normal file
26
src/Recipes/RecipeResult.cs
Normal file
@@ -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<bool> Remove; // destroy original
|
||||
|
||||
public RecipeResult(ReadOnlySpan<bool> remove, ReadOnlySpan<ItemBuilder> create) : this()
|
||||
{
|
||||
Remove = remove;
|
||||
Create = create;
|
||||
Mutate = null;
|
||||
}
|
||||
|
||||
public readonly ReadOnlySpan<ItemBuilder> Create; // multi-output
|
||||
|
||||
public readonly Action<RecipeContext>? Mutate; // component changes
|
||||
|
||||
public RecipeResult(Action<RecipeContext> mutate) : this()
|
||||
{
|
||||
Mutate = mutate;
|
||||
}
|
||||
}
|
||||
1
src/Recipes/RecipeResult.cs.uid
Normal file
1
src/Recipes/RecipeResult.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ctyimxkx8bomh
|
||||
34
src/Recipes/RecipeResultBuilder.cs
Normal file
34
src/Recipes/RecipeResultBuilder.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
namespace FoodFactory.Recipes;
|
||||
|
||||
using System;
|
||||
using Arch.Core;
|
||||
|
||||
public ref struct RecipeResultBuilder
|
||||
{
|
||||
private Span<bool> _remove;
|
||||
private Span<ItemBuilder> _create;
|
||||
private int _removeCount;
|
||||
private int _createCount;
|
||||
|
||||
public RecipeResultBuilder(Span<bool> remove, Span<ItemBuilder> 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);
|
||||
|
||||
1
src/Recipes/RecipeResultBuilder.cs.uid
Normal file
1
src/Recipes/RecipeResultBuilder.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ba6ll7cygo6hg
|
||||
@@ -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<RecipeAction, Dictionary<int, RecipeBucket>> _actions = [];
|
||||
Option<Recipe> GetRecipeByName(RecipeName name);
|
||||
RecipeEnumerator GetRecipes(RecipeAction action, int inputs, Tags[] itemTags, BlueprintId[] blueprintIds, RecipeOutput outputCount, Span<int> mapping);
|
||||
}
|
||||
public readonly record struct RecipeInput(RecipeAction Action, int Inputs, Tags[] ItemTags, BlueprintId[] BlueprintIds, RecipeOutput OutputCount);
|
||||
public class Recipes : IRecipes
|
||||
{
|
||||
private readonly Dictionary<RecipeEntryKey, RecipeBucket> _sortedRecipes = [];
|
||||
private readonly Dictionary<RecipeName, Recipe> _recipes = [];
|
||||
public Option<Recipe> 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<int, RecipeBucket>() { [1] = new RecipeBucket() {Single = new Dictionary<BlueprintId, CompiledRecipe[]>(){[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<int> 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 = bucket.Resolve(blueprintIds);
|
||||
return new RecipeEnumerator(recipes, new(action,inputs,itemTags,blueprintIds,outputCount), &Filter, mapping);
|
||||
}
|
||||
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++)
|
||||
private static bool Filter(RecipeInput input, CompiledRecipe compiledRecipe, Span<int> mapping, out RecipeMatch recipeMatch)
|
||||
{
|
||||
var item = recipes[i];
|
||||
if (inputs == 1 && IsValid(itemTags[0], item.ItemEntries[0]))
|
||||
if (input.Inputs == 1 && IsValid(input.ItemTags[0], compiledRecipe.ItemEntries[0]))
|
||||
{
|
||||
list.Add((item.RecipeRef, null));
|
||||
recipeMatch = new RecipeMatch(compiledRecipe.RecipeRef, []);
|
||||
return true;
|
||||
}
|
||||
else if (item.IsOrdered)
|
||||
else if (compiledRecipe.IsOrdered)
|
||||
{
|
||||
for (int ii = 0; ii < itemTags.Length; ii++)
|
||||
for (var ii = 0; ii < input.ItemTags.Length; ii++)
|
||||
{
|
||||
if (!IsValid(itemTags[ii], item.ItemEntries[ii]))
|
||||
if (!IsValid(input.ItemTags[ii], compiledRecipe.ItemEntries[ii]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
list.Add((item.RecipeRef, null));
|
||||
recipeMatch = new RecipeMatch(compiledRecipe.RecipeRef, []);
|
||||
return true;
|
||||
}
|
||||
else if (CanPossiblyMatch(itemTags, item))
|
||||
else if (CanPossiblyMatch(input.ItemTags, compiledRecipe))
|
||||
{
|
||||
if (Match(itemTags, item.ItemEntries, 0, used, mapping))
|
||||
Span<bool> used = stackalloc bool[input.ItemTags.Length];
|
||||
if (Match(input.ItemTags, compiledRecipe.ItemEntries, 0, used, mapping))
|
||||
{
|
||||
list.Add((item.RecipeRef, mapping));
|
||||
recipeMatch = new RecipeMatch(compiledRecipe.RecipeRef, mapping);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
recipeMatch = default;
|
||||
return false;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
private static bool IsValid(Tags tags, CompiledRecipe.ItemEntry compiled)
|
||||
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,14 +103,16 @@ public class Recipes
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
private static bool Match(
|
||||
Tags[] items,
|
||||
CompiledRecipe.ItemEntry[] entries,
|
||||
ItemEntry[] entries,
|
||||
int depth,
|
||||
Span<bool> used,
|
||||
Span<int> mapping)
|
||||
@@ -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 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)
|
||||
{
|
||||
if (!context.Entity[0].Has<Temperature>())
|
||||
{
|
||||
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<Entity> 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<Tags>().With("cooked").WithOut("raw"));
|
||||
span[0].Set(context.Entity[0].Get<Temperature>());
|
||||
return span[0];
|
||||
}
|
||||
}
|
||||
public ref struct RecipeResultBuilder
|
||||
{
|
||||
private Span<bool> _remove;
|
||||
private Span<ItemBuilder> _create;
|
||||
private int _removeCount;
|
||||
private int _createCount;
|
||||
|
||||
public RecipeResultBuilder(Span<bool> remove, Span<ItemBuilder> 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> entity) : this()
|
||||
{
|
||||
World = world;
|
||||
Entity = entity;
|
||||
}
|
||||
|
||||
public readonly Span<Entity> 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<bool> Remove; // destroy original
|
||||
|
||||
public RecipeResult(ReadOnlySpan<bool> remove, ReadOnlySpan<ItemBuilder> create) : this()
|
||||
{
|
||||
Remove = remove;
|
||||
Create = create;
|
||||
Mutate = null;
|
||||
}
|
||||
|
||||
public readonly ReadOnlySpan<ItemBuilder> Create; // multi-output
|
||||
|
||||
public readonly Action<RecipeContext>? Mutate; // component changes
|
||||
|
||||
public RecipeResult(Action<RecipeContext> mutate) : this()
|
||||
{
|
||||
Mutate = mutate;
|
||||
}
|
||||
}
|
||||
public struct CompiledRecipe
|
||||
public class RecipesBuilder
|
||||
{
|
||||
|
||||
public Recipe RecipeRef;
|
||||
public BlueprintId[] InputBlueprints;
|
||||
public ItemEntry[] ItemEntries;
|
||||
public bool IsOrdered;
|
||||
public struct ItemEntry
|
||||
private readonly Dictionary<RecipeEntryKey, BucketBuilder> _data = [];
|
||||
private readonly List<CompiledRecipe> _compiledRecipes = [];
|
||||
public IReadOnlyCollection<CompiledRecipe> CompiledRecipes => _compiledRecipes;
|
||||
public void Add(Recipe recipe)
|
||||
{
|
||||
public bool RequireAll;
|
||||
public Tags InputTags;
|
||||
public Tags ExcludeTags;
|
||||
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))
|
||||
{
|
||||
bucket = new BucketBuilder();
|
||||
_data[key] = bucket;
|
||||
}
|
||||
bucket.Add(compiled, recipe.BlueprintIds ?? []);
|
||||
if (recipe.RecipeOutput == RecipeOutput.Any)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// public record SingleItemRecipe(string Name, Tags Required, Tags Exclude) : Recipe(Name)
|
||||
// {
|
||||
if (!_data.TryGetValue(key2, out bucket))
|
||||
{
|
||||
bucket = new BucketBuilder();
|
||||
_data[key2] = bucket;
|
||||
}
|
||||
bucket.Add(compiled, recipe.BlueprintIds ?? []);
|
||||
}
|
||||
public Dictionary<RecipeEntryKey, RecipeBucket> Build()
|
||||
{
|
||||
var result = new Dictionary<RecipeEntryKey, RecipeBucket>();
|
||||
|
||||
// }
|
||||
// public record MultipleItemRecipe(string Name, params ItemInput[] Inputs) : Recipe(Name)
|
||||
// {
|
||||
|
||||
// }
|
||||
public readonly record struct RecipeName
|
||||
foreach (var (key, bucket) in _data)
|
||||
{
|
||||
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<Blueprint> _registry = new();
|
||||
public BlueprintId(Blueprint blueprint)
|
||||
{
|
||||
Id = _registry.GetOrCreate(blueprint);
|
||||
|
||||
}
|
||||
}
|
||||
public record Blueprint(string Name, Func<BlueprintContext, Entity> Factory)
|
||||
{
|
||||
|
||||
}
|
||||
public struct BlueprintContext
|
||||
{
|
||||
public World World;
|
||||
public BlueprintId BluePrintId;
|
||||
}
|
||||
public sealed class RecipeBucket
|
||||
{
|
||||
// 1 input → direct blueprint lookup
|
||||
public Dictionary<BlueprintId, CompiledRecipe[]> Single = [];
|
||||
|
||||
// ordered multi-input → first item is anchor
|
||||
public Dictionary<BlueprintId, CompiledRecipe[]> Ordered = [];
|
||||
|
||||
// fallback (unordered / no blueprint)
|
||||
public CompiledRecipe[] Unordered = [];
|
||||
/// <summary>
|
||||
/// Resloves Blueprints, if span is length 0, tehn Unordred is returned imdetly
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
public ReadOnlySpan<CompiledRecipe> Resolve(Span<BlueprintId> items)
|
||||
{
|
||||
if (items.Length == 0)
|
||||
{
|
||||
return Unordered;
|
||||
result[key] = bucket.Build();
|
||||
}
|
||||
|
||||
if (items.Length == 1)
|
||||
return result;
|
||||
}
|
||||
private sealed class BucketBuilder
|
||||
{
|
||||
if (Single.TryGetValue(items[0], out var r))
|
||||
return r;
|
||||
private readonly Dictionary<BlueprintId, List<CompiledRecipe>> _single = [];
|
||||
private readonly Dictionary<BlueprintId, List<CompiledRecipe>> _ordered = [];
|
||||
private readonly List<CompiledRecipe> _unordered = [];
|
||||
|
||||
return Unordered;
|
||||
}
|
||||
|
||||
var main = items[0];
|
||||
|
||||
if (Ordered.TryGetValue(main, out var ordered))
|
||||
public void Add(CompiledRecipe recipe, ReadOnlySpan<BlueprintId> inputs)
|
||||
{
|
||||
return ordered;
|
||||
if (inputs.Length == 0)
|
||||
{
|
||||
_unordered.Add(recipe);
|
||||
return;
|
||||
}
|
||||
|
||||
return Unordered;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public RecipeBucket Build()
|
||||
{
|
||||
return new RecipeBucket
|
||||
{
|
||||
Single = ToArrayDict(_single),
|
||||
Ordered = ToArrayDict(_ordered),
|
||||
Unordered = [.. _unordered]
|
||||
};
|
||||
}
|
||||
|
||||
private static List<CompiledRecipe> GetOrCreate(
|
||||
Dictionary<BlueprintId, List<CompiledRecipe>> dict,
|
||||
BlueprintId key)
|
||||
{
|
||||
if (!dict.TryGetValue(key, out var list))
|
||||
{
|
||||
list = new List<CompiledRecipe>(4);
|
||||
dict[key] = list;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static Dictionary<BlueprintId, CompiledRecipe[]> ToArrayDict(
|
||||
Dictionary<BlueprintId, List<CompiledRecipe>> source)
|
||||
{
|
||||
var result = new Dictionary<BlueprintId, CompiledRecipe[]>(source.Count);
|
||||
|
||||
foreach (var (key, list) in source)
|
||||
{
|
||||
result[key] = [.. list];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
src/Recipes/Recipes.cs.uid
Normal file
1
src/Recipes/Recipes.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cp61k5vfvknv8
|
||||
61
src/VoxelGrid/Balancer.cs
Normal file
61
src/VoxelGrid/Balancer.cs
Normal file
@@ -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<IBeltPortHost>, IProvide<IVoxelGridRegistry>
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
private BeltPortHost _insertLogic = default!;
|
||||
public IBeltPortHost Value() => _insertLogic;
|
||||
IVoxelGridRegistry IProvide<IVoxelGridRegistry>.Value() => GridRegistry;
|
||||
[Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn<IVoxelGridRegistry>();
|
||||
private List<BeltPort> _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<BeltPort> OutputPorts => _insertLogic.GetPorts().OfType<BeltPort>().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;
|
||||
}
|
||||
}
|
||||
1
src/VoxelGrid/Balancer.cs.uid
Normal file
1
src/VoxelGrid/Balancer.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://opbkqoaa7x2n
|
||||
@@ -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<IItemRenderer>();
|
||||
public BeltPortProfile Profile => new(GridTransform3D.FromGodot(GlobalTransform), Width, Access);
|
||||
[Dependency] public IItemTransferAnimator ItemTransferAnimator => this.DependOn<IItemTransferAnimator>(() => 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<IBeltPort>(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<IBeltPort, bool> match, Func<IBeltItemInsertLogic> factory)> _bindings
|
||||
= new();
|
||||
|
||||
public BeltPortHost Bind(
|
||||
Func<IBeltPort, bool> match,
|
||||
Func<IBeltItemInsertLogic> factory)
|
||||
{
|
||||
_bindings.Add((match, factory));
|
||||
return this;
|
||||
}
|
||||
private HashSet<IBeltPort> _ports = [];
|
||||
public IBeltItemInsertLogic? Default;
|
||||
|
||||
/// <summary>
|
||||
/// Resolve the insert logic for a port. If no matching bind exists then the default is returned if supplied. Other wise throws an Exception.
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></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<IBeltPort> GetPorts() => _ports;
|
||||
}
|
||||
public interface IItemTransferAnimator
|
||||
{
|
||||
Tween StartTransfer(
|
||||
ConveyorSlice item,
|
||||
Action onFinished = null);
|
||||
}
|
||||
|
||||
public class InstanceItemTransfer : IItemTransferAnimator
|
||||
{
|
||||
public SceneTree Tree = default!;
|
||||
public Func<ConveyorSlice, bool> 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<ConveyorSlice, bool> 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<float>(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;
|
||||
}
|
||||
}
|
||||
|
||||
48
src/VoxelGrid/BeltPortHost.cs
Normal file
48
src/VoxelGrid/BeltPortHost.cs
Normal file
@@ -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<IBeltPort, bool> match, Func<IBeltItemInsertLogic> factory)> _bindings
|
||||
= new();
|
||||
|
||||
public BeltPortHost Bind(
|
||||
Func<IBeltPort, bool> match,
|
||||
Func<IBeltItemInsertLogic> factory)
|
||||
{
|
||||
_bindings.Add((match, factory));
|
||||
return this;
|
||||
}
|
||||
private HashSet<IBeltPort> _ports = [];
|
||||
public IBeltItemInsertLogic? Default;
|
||||
|
||||
/// <summary>
|
||||
/// Resolve the insert logic for a port. If no matching bind exists then the default is returned if supplied. Other wise throws an Exception.
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></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<IBeltPort> GetPorts() => _ports;
|
||||
}
|
||||
1
src/VoxelGrid/BeltPortHost.cs.uid
Normal file
1
src/VoxelGrid/BeltPortHost.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://mimkyombngwg
|
||||
@@ -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<IBeltItem, Node3D> _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<IBeltItem, Node3D> _items = [];
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
70
src/VoxelGrid/ItemSpawner.cs
Normal file
70
src/VoxelGrid/ItemSpawner.cs
Normal file
@@ -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<IBeltPortHost>
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn<IVoxelGridRegistry>();
|
||||
[Dependency] public IBlueprintManger ItemFactory => this.DependOn<IBlueprintManger>();
|
||||
[Dependency] public World World => this.DependOn<World>();
|
||||
[Dependency] public IRecipes Recipes => this.DependOn<IRecipes>();
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
src/VoxelGrid/ItemSpawner.cs.uid
Normal file
1
src/VoxelGrid/ItemSpawner.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://btmbv7oaeps4p
|
||||
17
src/VoxelGrid/ItemSpawner.tscn
Normal file
17
src/VoxelGrid/ItemSpawner.tscn
Normal file
@@ -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
|
||||
@@ -2,39 +2,51 @@ 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<IBeltPortHost>, IProvide<IVoxelGridRegistry>
|
||||
{
|
||||
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<IVoxelGridRegistry>();
|
||||
[Dependency] public IRecipes Recipes => this.DependOn<IRecipes>();
|
||||
IVoxelGridRegistry IProvide<IVoxelGridRegistry>.Value() => GridRegistry;
|
||||
public GridTransform3D VoxelTransform
|
||||
{
|
||||
get => GridTransform3D.FromGodot(GlobalTransform);
|
||||
set => GlobalTransform = value.ToGodot();
|
||||
}
|
||||
private Dictionary<string, object>? _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;
|
||||
if (item is IBeltItemData<Entity> 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<IBeltPortHost>, IProvide<IVoxel
|
||||
|
||||
time.Timeout += () =>
|
||||
{
|
||||
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<Temperature>(out var temp))
|
||||
{
|
||||
return;
|
||||
}
|
||||
temp.Kelvin += new TemperatureDelta(5f, TemperatureUnit.Fahrenheit).KelvinDelta;
|
||||
_itemBeingHeld.Set(temp);
|
||||
|
||||
Span<Entity> items = [_itemBeingHeld];
|
||||
var context = new RecipeContext(World.Worlds[0], items);
|
||||
var builder = new RecipeResultBuilder(stackalloc bool[10], new ItemBuilder[10]);
|
||||
Span<int> mapping = stackalloc int[1];
|
||||
var recipes = Recipes.GetRecipes(new RecipeAction("cook"), 1, [_itemBeingHeld.Get<Tags>()], [], RecipeOutput.Any, mapping);
|
||||
// Span<Entity> created = stackalloc Entity[10];
|
||||
unsafe
|
||||
{
|
||||
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<Tags>(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) && _placeholderItem is not null && v.TryInsert(new TestItem() { PlaceHolderData = _placeholderItem }, LaneSpan.One, 0))
|
||||
if (port.HasValue(out var v) && _itemBeingHeld.Id != -1 && _itemBeingHeld.IsAlive() && v.TryInsert(new TestItem() { Item = _itemBeingHeld }, LaneSpan.One, 0))
|
||||
{
|
||||
_placeholderItem = null;
|
||||
_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<int> Mapping;
|
||||
|
||||
public RecipeMatch(
|
||||
Recipe recipe,
|
||||
ReadOnlySpan<int> 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<CompiledRecipe> _recipes;
|
||||
private readonly RecipeInput _input;
|
||||
private readonly Span<int> _mapping;
|
||||
private readonly delegate*<RecipeInput, CompiledRecipe, Span<int>, out RecipeMatch, bool> _filter;
|
||||
public RecipeEnumerator(ReadOnlySpan<CompiledRecipe> compiledRecipes, RecipeInput input, delegate*<RecipeInput, CompiledRecipe, Span<int>, out RecipeMatch, bool> filter, Span<int> 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<TRecipeEnumerator>(
|
||||
ref TRecipeEnumerator recipes,
|
||||
scoped ref RecipeContext context,
|
||||
scoped ref RecipeResultBuilder builder,
|
||||
delegate*<Entity, void> destroyEntity,
|
||||
out Span<Entity> 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*<Entity, void> destroyEntity,
|
||||
out Span<Entity> 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
106
src/VoxelGrid/SlicerTest.cs
Normal file
106
src/VoxelGrid/SlicerTest.cs
Normal file
@@ -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<IBeltPortHost>, IProvide<IVoxelGridRegistry>
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
private BeltPortHost _insertLogic = default!;
|
||||
public IBeltPortHost Value() => _insertLogic;
|
||||
[Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn<IVoxelGridRegistry>();
|
||||
[Dependency] public IRecipes Recipes => this.DependOn<IRecipes>();
|
||||
IVoxelGridRegistry IProvide<IVoxelGridRegistry>.Value() => GridRegistry;
|
||||
public GridTransform3D VoxelTransform
|
||||
{
|
||||
get => GridTransform3D.FromGodot(GlobalTransform);
|
||||
set => GlobalTransform = value.ToGodot();
|
||||
}
|
||||
private Entity _itemBeingHeld = Entity.Null;
|
||||
private List<Entity> 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<Entity> beltItemData && beltItemData.GetItem().TryGet<Tags>(out var tags) && tags.Contains(TagRegistry.GetTag("sliceable"));
|
||||
bool canInsert(IBeltPort beltPort, IBeltItem item)
|
||||
{
|
||||
if (item is IBeltItemData<Entity> 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<Carbohydrates>());
|
||||
sliced.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
if (_itemBeingHeld.Id == -1)//TODO have a better way of dertming if item is valid, possibly nullable
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<Entity> items = [_itemBeingHeld];
|
||||
var context = new RecipeContext(World.Worlds[0], items);
|
||||
var builder = new RecipeResultBuilder(stackalloc bool[10], new ItemBuilder[10]);
|
||||
Span<int> mapping = stackalloc int[1];
|
||||
// var recipe = new PotatoCookRecipe();
|
||||
var recipes = Recipes.GetRecipes("slice", 1, [_itemBeingHeld.Get<Tags>()], [], 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();
|
||||
}
|
||||
}
|
||||
1
src/VoxelGrid/SlicerTest.cs.uid
Normal file
1
src/VoxelGrid/SlicerTest.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://yec84plemjv1
|
||||
@@ -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<T>
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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<World, float>
|
||||
{
|
||||
private QueryDescription _desc = new QueryDescription().WithAll<Bacteria, Temperature>();
|
||||
public static Resources<List<BacteriaData>> 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<IVoxelGridRegistry>, IProvide<IItemRenderer>
|
||||
public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridRegistry>, IProvide<IItemRenderer>, IProvide<IRecipes>, IProvide<IBlueprintManger>, IProvide<World>
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
private World _world = default!;
|
||||
World IProvide<World>.Value() => _world;
|
||||
private IVoxelGridRegistry _voxelGridRegistry = default!;
|
||||
IVoxelGridRegistry IProvide<IVoxelGridRegistry>.Value() => _voxelGridRegistry;
|
||||
private IBlueprintManger _blueprintManger = default!;
|
||||
IBlueprintManger IProvide<IBlueprintManger>.Value() => _blueprintManger;
|
||||
private Recipes _recipes = default!;
|
||||
IRecipes IProvide<IRecipes>.Value() => _recipes;
|
||||
private IItemRenderer _itemRenderer = default!;
|
||||
IItemRenderer IProvide<IItemRenderer>.Value() => _itemRenderer;
|
||||
Group<float> _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<float>("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<IVoxelGridRegistry>, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user