removed code that was commented out, and a bunch of obsolete classes.

This commit is contained in:
2026-04-19 01:29:28 -04:00
parent e7ef3896b0
commit 7d25f6d448
12 changed files with 211 additions and 1334 deletions

View File

@@ -21,51 +21,31 @@ public partial class ConveyorBeltStraight : Node3D
// Direction.Back,
Width,
PortAccess.BiDirectional),
new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.Start),
new BeltTEnd(ConveyorEnd.Start),
new LaneSpan(0, 1));
// GD.Print(VoxelTransform.Origin,GridTransform3D.FromGodot(Transform.TranslatedLocal(Vector3.Left)).Origin);
node.EndPort = node.CreatePort(
new(VoxelTransform, //new(GridTransform3D.FromGodot(Transform.TranslatedLocal(Vector3.Left)),
// Direction.Front,
Width,
PortAccess.BiDirectional),
new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.End),
new BeltTEnd(ConveyorEnd.End),
new LaneSpan(0, 1));
// node.OtherPorts = [
// node.CreatePort(
// new(VoxelTransform.RotateY90CW(),
// // Direction.Right,
// 1,
// PortAccess.In),
// new ItemConveyor.BeltTOffset(node.Length/2),
// LaneSpan.One),
// node.CreatePort(
// new(VoxelTransform.RotateY90CCW(),
// // Direction.Left,
// 1,
// PortAccess.In),
// new ItemConveyor.BeltTOffset(node.Length/2),
// LaneSpan.One)
// ];
// new ConveyorPort(this,
// new BeltPortProfile(VoxelPos, Direction.Back, 1, PortAccess.BiDirectional),
// new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.Start),
// (item, offset) =>
// {
// var obstacle = node.GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, 0, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// },
// (item, offset) => { _items.Insert(0, new(item, offset)); return true;});
// node.EndPort = new ConveyorPort(this,
// new BeltPortProfile(VoxelPos, Direction.Front, 1, PortAccess.BiDirectional),
// new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.End),
// (item, offset) =>
// {
// var obstacle = node.GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, node.Length, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// // return ItemConveyor.ITEMSIZE < GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardStart, Length, SpeedMagnitude, LaneSpan.One);
// },
// (item, offset) => { _items.Add(new(item, offset)); return true;});
node.OtherPorts = [
node.CreatePort(
new(VoxelTransform.RotateY90CW(),
// Direction.Right,
1,
PortAccess.In),
new BeltTOffset(node.Length/2),
LaneSpan.One),
node.CreatePort(
new(VoxelTransform.RotateY90CCW(),
// Direction.Left,
1,
PortAccess.In),
new BeltTOffset(node.Length/2),
LaneSpan.One)
];
}
}

View File

@@ -89,14 +89,14 @@ public sealed class ConveyorPort : IBeltPort
{
public BeltPortProfile Profile { get; }
public IMovementConveyor Conveyor { get; }
public ItemConveyor.BeltT BeltT { get; }
public BeltT BeltT { get; }
private readonly Func<IBeltItem, float, LaneSpan, bool>? _canAccept;
private readonly Func<IBeltItem, float, LaneSpan, bool>? _accept;
public ConveyorPort(
IMovementConveyor conveyor,
BeltPortProfile profile,
ItemConveyor.BeltT beltT,
BeltT beltT,
Func<IBeltItem, float, LaneSpan, bool>? canAccept,
Func<IBeltItem, float, LaneSpan, bool>? accept)
{

View File

@@ -1,83 +0,0 @@
namespace ChickenGameTest;
using System;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface IEquipment : IProvide<IEquipmentContext>//INode3D,
{
EquipmentId Id { get; set; }
}
[Tool]
[Meta(typeof(IAutoNode))]
public partial class Equipment() : Node3D, IEquipment
{
public override void _Notification(int what)
{
if (what == NotificationTransformChanged)
{
OnNotificationTransformChanged();
}
// if (Engine.IsEditorHint())
// {
// return;
// }
this.Notify(what);
}
public EquipmentId Id { get; set; } = new(Guid.NewGuid());
[Signal] public delegate void TickEventHandler();
[Export]public Vector3I GridPos { get; set; }
[Dependency] protected IVoxelGridQuery<LayeredEquipment> Grid => this.DependOn<IVoxelGridQuery<LayeredEquipment>>();
protected IEquipmentContext _equipmentContext { get; set; } = default!;
public override void _Ready()
{
this.SetNotifyTransform(true);
base._Ready();
// if (Engine.IsEditorHint())
// {
// return;
// }
_equipmentContext = new eqitpTest(this);
this.Provide();
Timer timer = new Timer(){WaitTime = .25f, Autostart = true};
AddChild(timer);
timer.Timeout += EmitSignalTick;
// timer.Timeout += () => Position += Vector3.One;
}
public void OnResolved()
{
GD.Print(Grid);
(Grid as EquipmentVoxelGrid).AddEquipment(GridPos, this);
GD.Print("Added Self");
}
IEquipmentContext IProvide<IEquipmentContext>.Value() => _equipmentContext;
public void OnNotificationTransformChanged()
{
GD.Print("Transform changed, now" , Position);
var newPos = new Vector3I(Mathf.RoundToInt(Position.X),Mathf.RoundToInt(Position.Y),Mathf.RoundToInt(Position.Z));
if (newPos == GridPos)
{
return;
}
GridPos = newPos;
// Transform = Transform.Origin = newPos;;
}
}
public record EquipmentId(Guid Id);
public interface IEquipmentContext
{
Equipment GetEquipment();
EquipmentId GetEquipmentId();
}
public record eqitpTest(Equipment Equipment) : IEquipmentContext
{
public Equipment GetEquipment() => Equipment;
public EquipmentId GetEquipmentId() => Equipment.Id;
}

View File

@@ -1 +0,0 @@
uid://bhh1c4a5gep6o

View File

@@ -28,18 +28,18 @@ public interface IMovementConveyor
// float GetAvailableTravel(ItemConveyor.BeltDirection beltDirection, LaneSpanT itemSpan, float maxDistance);
// IBeltSlotProfile GetPortFacingStart();
// IBeltSlotProfile GetPortFacingEnd();
ItemConveyor.BeltDirection GetBeltDirection();
BeltDirection GetBeltDirection();
// Option<ConveyorSlice> GetItemTowardStart();
// Option<ConveyorSlice> GetItemTowardEnd();
// Option<ConveyorSlice> GetItemTowardInput();
// Option<ConveyorSlice> GetItemTowardOutput();
IEnumerable<Sorted1DList<ConveyorSlice>.ItemHandle> EnumerateTowardEnd();
IEnumerable<Sorted1DList<ConveyorSlice>.ItemHandle> EnumerateTowardStart();
ItemConveyor.IBeltMovement GetMovementPolicy();
IBeltMovement GetMovementPolicy();
// IList<ConveyorSlice> Items { get; }
IOption<IBeltPort> GetPortFacing(IBeltPort slot);
BeltObstacle GetDistanceToNextItem(ItemConveyor.BeltDirection beltDirection, float itemBeltT, float maxDistToCheck, LaneSpan laneSpan, HashSet<IMovementConveyor>? visted = null);
ConveyorPort CreatePort(BeltPortProfile profile, ItemConveyor.BeltT beltT, LaneSpan laneSpan);
BeltObstacle GetDistanceToNextItem(BeltDirection beltDirection, float itemBeltT, float maxDistToCheck, LaneSpan laneSpan, HashSet<IMovementConveyor>? visted = null);
ConveyorPort CreatePort(BeltPortProfile profile, BeltT beltT, LaneSpan laneSpan);
}
public readonly struct ConveyorItemHandle
{
@@ -60,551 +60,13 @@ public readonly struct ConveyorItemHandle
public void Remove() => _remove();
public void Replace(ConveyorSlice slice) => _replace(slice);
}
[Meta(typeof(IAutoNode))]
public partial class ItemConveyor : Node, IVoxelNode
{
// public record ItemPair(IBeltItem Item, float BeltT);
public override void _Notification(int what) => this.Notify(what);
[Export] public int Length { get; set; } = 1;
// [Export] public float Speed { get; set; } = .05f;
private readonly AutoValue<float> _speed = new(.05f);
public IAutoValue<float> Speed => _speed;
public float SignedSpeed
{
get => _speed.Value;
set => _speed.Value = value;
}
public float SpeedMagnitude
{
get => Mathf.Abs(_speed.Value);
set => _speed.Value = Mathf.Abs(value) * Mathf.Sign(_speed.Value);
}
public bool IsReversed { get => Mathf.Sign(_speed.Value) < 0; set => _speed.Value = SpeedMagnitude * (value ? -1 : 1); }
[Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn<IVoxelGridRegistry>();
[Dependency] public IBeltMovement MovementSystem => this.DependOn<IBeltMovement>(() => new IndividualMovement());
public const float ITEMSIZE = .2f;
private const float ITEMHALFSIZE = ITEMSIZE / 2f;
//Basci port for simple conveyor, asuming no rever,
private List<ConveyorPort> _ports = [
new(){//EjectFace
Face = Direction.Front,
Direction= PortAccess.InOut,
LocalOffset = Vector3I.Zero,
BeltT = new BeltTEnd(ConveyorEnd.End),
PullPush = TransferMode.PushPull,
},
new(){//PullFace
Face = Direction.Back,
Direction= PortAccess.InOut,
LocalOffset = Vector3I.Zero,
BeltT = new BeltTEnd(ConveyorEnd.Start),
PullPush = TransferMode.PushPull//Or none, PlateUp has grtabber and none grabby varietns
},
new(){//PullFace
Face = Direction.Right,
Direction= PortAccess.BiDirectional,
LocalOffset = Vector3I.Zero,
BeltT = new BeltTOffset(.5f),
},
new(){//PullFace
Face = Direction.Left,
Direction= PortAccess.BiDirectional,
LocalOffset = Vector3I.Zero,
BeltT = new BeltTOffset(.5f),
},
new(){//PullFace
Face = Direction.Up,
Direction= PortAccess.BiDirectional,
LocalOffset = Vector3I.Zero,
BeltT = new BeltTOffset(.5f),
}
];
public ConveyorPort GetInputPort() => _ports.First(item => (item.PullPush & TransferMode.Pull)>0 && item.BeltT == (SignedSpeed >= 0 ? new BeltTEnd(ConveyorEnd.Start):new BeltTEnd(ConveyorEnd.End)));//Cache this
public ConveyorPort GetOutputPort() => _ports.First(item => (item.PullPush & TransferMode.Push)>0 && item.BeltT == (SignedSpeed < 0 ? new BeltTEnd(ConveyorEnd.Start):new BeltTEnd(ConveyorEnd.End)));//Cache this
public ConveyorPort GetStartPort() => _ports.First(item => item.BeltT == new BeltTEnd(ConveyorEnd.Start));
public ConveyorPort GetEndPort() => _ports.First(item => item.BeltT == new BeltTEnd(ConveyorEnd.End));
// public ConveyorPort GetPortInDirectionOfTravel() => Speed >= 0 ? GetOutputPort() : GetInputPort();
//needs better name
// private IEnumerable<ConveyorPort> ActivePorts(TransferMode p) => _ports.Where(item => item.PullPush == p);
public void OnResolved()
{
// GD.Print(SlotExtesion.MapSlotToFacingSlot(Vector3I.Zero,Direction.Back,2,new(2,0,1),Direction.Front,3));
// GD.Print(SlotExtesion.MapSlotToFacingSlot(new(2,0,1),Direction.Front,3,Vector3I.Zero,Direction.Back,2));
GridRegistry.Register(this);
Timer timer = new Timer() { WaitTime = .25f, Autostart = true };//TEST
AddChild(timer);//TEST
timer.Timeout += OnTick;//TEST
for (int i = 0; i < _ports.Count; i++)
{
var port = _ports[i];
if (port.Access.HasFlag(PortAccess.In)){
port.AcceptItemFunc = (item, belt) =>
{
GD.PrintS("============================",port.Access,item,belt,port.BeltT);
if (port.BeltT is BeltTEnd end)
{
return TryInsertAtEnd(end.End, item);
}
if (port.BeltT is BeltTOffset offset && TryFindLocalInsertion(offset.T,ITEMHALFSIZE,out var point))
{
InsertInMiddleWithoutCheck(item, point);
return true;
}
return false;
};
_ports[i] = port;
}
}
// MovementSystem.OnItemMoved += static (item, segments, delta) => GD.PrintS(item, string.Join(',', segments.ToArray().Select(i => $"({i.Conveyor},{i.StartT},{i.EndT}")));
}
public override void _ExitTree()
{
base._ExitTree();
GridRegistry.UnRegister(Id);
}
public void OnTick()//TEMP METHOOD FOR TESTING
{
if (Input.IsActionPressed("ui_up"))
{
SignedSpeed = -SignedSpeed;
}
if (VoxelPosition == Vector3I.Forward*-2 && TryInsertAtEnd(ConveyorEnd.Start, new TestItem(){Height = 1, Width = 1, Temp = 1}))
InsertAtEndWithoutCheck(ConveyorEnd.Start,new TestItem(){Height = 1, Width = 1, Temp = 1});
MovementSystem.AdvanceBelt(this,1f);
return;
// if (_items.Count <= 0)
// {
// return;
// }
// if (Speed == 0)
// {
// return;
// }
// GD.Print("Thing: " + Speed + " "+ GetConveyorPortFacing(GetOutputPort()));
// var distToEnd = DistanceFromEnd(Speed < 0 ? ConveyorEnd.Start : ConveyorEnd.End);
// var maxSpeed = Mathf.Min(Mathf.Abs(Speed), distToEnd) * Mathf.Sign(Speed);
// if (maxSpeed == 0)
// {
// return;
// }
// // GD.Print()
// for (int i = 0; i < _items.Count; i++)
// {
// _items[i] = _items[i] with { BeltT = Mathf.Clamp(_items[i].BeltT + maxSpeed, 0, Length) };
// GD.Print($"Item:{_items[i].Item}, Position:{_items[i].BeltT}");
// }
// // _items.ForEach((item) => item = item = Mathf.Clamp(item.Position + maxSpeed, 0, Length));
// var list = _items.Where(item=> Speed>=0?item.BeltT >= Length:item.BeltT <= 0).ToList();
// // GD.Print(list.Count);
// foreach (var item in list)
// {
// GD.Print($"Item:{item.Item}, Position:{item.BeltT}");
// //TEST
// var v = GetConveyorPortFacing(GetOutputPort());
// if (v.HasValue)
// {
// GD.PrintS(v.Value.Port.LocalOffset,v.Value.Port.BeltT,v.Value.Port.Direction,v.Value.Port.PullPush,v.Value.Port.Face);
// if(v.Value.Conveyor.TryInsertAtEnd((v.Value.Port.BeltT as BeltTEnd).End, item.Item))
// {
// GD.Print("Item Moved");
// _items.Remove(item);
// }
// }
// //Move Item Into Other COnveyor with offset, this means a item could therolitcly move two the end of another conveyor, but need to decide if that should keep moving recurively, opr make items only move one conveyor max at atime
// }
}
public float? GetAvailableTravelForFrontItem(bool accountForNextConveyor = false) => GetBeltDirection() switch
{
BeltDirection.TowardStart => AnyItems() ? GetAvailableTravel(0, BeltDirection.TowardStart, accountForNextConveyor) : null,
BeltDirection.TowardEnd => AnyItems() ? GetAvailableTravel(ItemsCount - 1, BeltDirection.TowardEnd, accountForNextConveyor) : null,
BeltDirection.NotMoving => null,
_ => throw new NotSupportedException(),
};
public float GetAvailableSpaceFromEnd(ConveyorEnd end) => end switch
{
ConveyorEnd.Start => AnyItems()?_items[0].BeltT - ITEMSIZE:Length -ITEMHALFSIZE,
ConveyorEnd.End => AnyItems()?_items[^1].BeltT + ITEMSIZE : ITEMHALFSIZE,
_ => throw new NotSupportedException(),
};
public float GetAvailableTravel(
int itemIndex,
BeltDirection direction,
bool accountForNextConveyor = false
)
{
if (itemIndex < 0 || itemIndex >= _items.Count)
throw new IndexOutOfRangeException(
$"{nameof(itemIndex)}={itemIndex}, Count={_items.Count}"
);
var item = _items[itemIndex];
// Determine neighbor and boundary
bool towardEnd = direction == BeltDirection.TowardEnd;
float limit;
if (towardEnd)
{
var other = GetConveyorPortFacing(GetEndPort());
// Next item or belt end
limit = (itemIndex + 1 < _items.Count)
? _items[itemIndex + 1].BeltT - ITEMSIZE
: Length + (accountForNextConveyor && other.HasValue && other.Value.Port.BeltT is BeltTEnd end ? other.Value.Conveyor.GetAvailableSpaceFromEnd(end.End) : -ITEMHALFSIZE);
}
else
{
var other = GetConveyorPortFacing(GetStartPort());
// Previous item or belt start
limit = (itemIndex - 1 >= 0)
? _items[itemIndex - 1].BeltT + ITEMSIZE
: accountForNextConveyor && other.HasValue && other.Value.Port.BeltT is BeltTEnd end ? other.Value.Conveyor.GetAvailableSpaceFromEnd(end.End) : ITEMHALFSIZE;
}
float available = towardEnd
? limit - item.BeltT
: item.BeltT - limit;
return Mathf.Max(0f, available);
}
public enum ConveyorEnd { Start, End }
public static ConveyorEnd SwapEnd(ConveyorEnd end) => end switch
{
ConveyorEnd.Start => ConveyorEnd.End,
ConveyorEnd.End => ConveyorEnd.Start,
_ => throw new NotSupportedException($"{end}"),
};
public float DistanceFromEnd(ConveyorEnd end) => end switch
{
ConveyorEnd.Start => _items.Count == 0 ? Length : _items[0].BeltT,
ConveyorEnd.End => _items.Count == 0 ? Length : Length - _items[^1].BeltT,
_ => throw new NotSupportedException($"{end}"),
};
public float GetTravelDistanceInDirection(BeltDirection direction) => direction switch
{
BeltDirection.TowardEnd => _items.Count == 0 ? Length : _items[0].BeltT,
BeltDirection.TowardStart => _items.Count == 0 ? Length : Length - _items[^1].BeltT,
BeltDirection.NotMoving => 0,
_ => throw new NotSupportedException($"{direction}"),
};
public enum BeltDirection : sbyte {
TowardStart = -1,
NotMoving = 0,
TowardEnd = 1
}
public bool TryFindLocalInsertion(
float beltT,
float maxDistance,
out float resultT
)
{
throw new NotImplementedException();
// float minAllowed = Mathf.Max(ITEMHALFSIZE, beltT - maxDistance);
// float maxAllowed = Mathf.Min(Length - ITEMHALFSIZE, beltT + maxDistance);
// if (minAllowed > maxAllowed)
// {
// resultT = default;
// return false;
// }
// if (_items.Count == 0)
// {
// resultT = Mathf.Clamp(beltT, minAllowed, maxAllowed);
// return true;
// }
// int index = _items.BinarySearch(
// new(null!, beltT),
// Comparer<ConveyorSlice>.Create(
// (a, b) => a.BeltT.CompareTo(b.BeltT)
// )
// );
// if (index < 0)
// {
// index = ~index;
// }
// float gapMin = index > 0
// ? _items[index - 1].BeltT + ITEMSIZE
// : ITEMHALFSIZE;
// float gapMax = index < _items.Count
// ? _items[index].BeltT - ITEMSIZE
// : Length - ITEMHALFSIZE;
// // Intersect gap with allowed window
// gapMin = Mathf.Max(gapMin, minAllowed);
// gapMax = Mathf.Min(gapMax, maxAllowed);
// if (gapMin > gapMax)
// {
// resultT = default;
// return false;
// }
// resultT = Mathf.Clamp(beltT, gapMin, gapMax);
// return true;
}
public BeltDirection GetBeltDirection() => _speed.Value switch
{
0 => BeltDirection.NotMoving,
> 0 => BeltDirection.TowardEnd,
< 0 => BeltDirection.TowardStart,
_ => throw new NotSupportedException($"{nameof(Speed)} with value {Speed} is not Supported")
};
/// <summary>
/// Returns the Item that would be Leading the Belt based off the direction of the belt, or null if no items or Speed is zero.
/// </summary>
/// <returns>The Leading Item</returns> <summary>
///
/// </summary>
/// <returns></returns>
public ConveyorSlice? GetFirstItem() => GetBeltDirection() switch
{
BeltDirection.TowardStart => _items.Any() ? _items[0] : null,
BeltDirection.TowardEnd => _items.Any() ? _items[^1] : null,
BeltDirection.NotMoving => null,
_ => null
};
/// <summary>
/// Returns the Last item that would be oppsite the Leading Item, or null if there is no items or Speed is zero.
/// </summary>
/// <returns>The last Item in Secuance</returns> <summary>
///
/// </summary>
/// <returns></returns>
public ConveyorSlice? GetLastItem() => GetBeltDirection() switch
{
BeltDirection.TowardStart => _items.Any() ? _items[0] : null,
BeltDirection.TowardEnd => _items.Any() ? _items[^1] : null,
BeltDirection.NotMoving => null,
_ => null
};
public bool AnyItems() => _items.Any();
public int ItemsCount => _items.Count;
private void InsertInMiddleWithoutCheck(IBeltItem item, float beltT)
{
throw new NotImplementedException();
_items.Add(new(item, beltT));
// _items.Sort(Comparer<ConveyorSlice>.Create(
// (a, b) => a.BeltT.CompareTo(b.BeltT)));
}
// public float SpaceToInsertFromEnd(ConveyorEnd end)//Needs to know if belt space exists in next/previous
// {
// var distToEnd = DistanceFromEnd(end);
// var other = GetConveyorPortFacing(GetOutputPort());
// if (!other.HasValue || other.Value.Port.BeltT != new BeltTEnd(SwapEnd(end)) || other.Value.Port.Direction == PortAccess.Out)
// {
// return Mathf.Max(0, distToEnd - ITEMHALFSIZE);
// }
// return distToEnd + other.Value.Conveyor.DistanceFromEnd(SwapEnd(end));//Should Be space to inset, but needs to be serpate into 2 functons to prevent stgackoverflow
// }
public bool TryInsertAtEnd(ConveyorEnd end, IBeltItem itemStack)
{
var space = DistanceFromEnd(end);
if (space >= ITEMHALFSIZE)
{
InsertAtEndWithoutCheck(end, itemStack);
return true;
}
return false;
}
private void InsertAtEndWithoutCheck(ConveyorEnd end, IBeltItem item, float offset = 0)
{
ConveyorSlice itemPair = new(item, end switch { ConveyorEnd.Start => offset, ConveyorEnd.End => Length - offset, _ => throw new NotSupportedException() });
if (end == ConveyorEnd.Start)
{
_items.Insert(0, itemPair);
}
else
{
_items.Add(itemPair);
}
}
private (ItemConveyor Conveyor, ConveyorPort Port)? GetConveyorPortFacing(ConveyorPort port, Predicate<ConveyorPort>? predicate = default)
{
predicate ??= _ => true;
var pos = VoxelPosition + port.LocalOffset + port.Face.ToVector();
var others = GridRegistry.Get<ItemConveyor>(pos);
foreach (var item in others)
{
var otherPorts = item._ports.Where(otherPort => otherPort.Face.Reverse() == port.Face && predicate(otherPort));
GD.Print("ports "+string.Join(',',otherPorts.Select(i=>i.BeltT)));
if (otherPorts.Any())
{
return (item, otherPorts.First());
}
}
return null;
}
public Guid Id { get; set; }
[Export]
public Vector3I VoxelPosition { get; set; }
[Export]
public Direction VoxelRotation { get; set; } = Direction.Front;//test
public IEnumerable<Vector3I> Shape => [Vector3I.Zero];
private readonly AutoList<ConveyorSlice> _items = [];
public IAutoList<ConveyorSlice> Items => _items;
public struct ConveyorPort : IBeltSlotProfile// May chagne to record
{
public Vector3I LocalOffset;
public BeltT BeltT;
public Direction Face;
public TransferMode PullPush;
public PortAccess Direction;
public Func<IBeltItem, float, bool>? AcceptItemFunc;
public Func<IBeltItem, float, bool>? CanAcceptItemFunc;
public IMovementConveyor MovementConveyor;
public readonly Vector3I Position => LocalOffset;
public readonly int Width => 1;
public readonly PortAccess Access => Direction;
public Guid Id => throw new NotImplementedException();
public Vector3I VoxelPosition => LocalOffset;
public Direction VoxelRotation => throw new NotImplementedException();
public IEnumerable<Vector3I> Shape => [new Vector3I(0, 0, 0)];
// readonly Direction IBeltSlotProfile.Direction => Face;
[MemberNotNullWhen(true,nameof(CanAcceptItemFunc))]
[MemberNotNullWhen(true,nameof(AcceptItemFunc))]
public readonly bool CanAcceptItem(IBeltItem beltItem, LaneSpan laneSpan, float beltT = 0)
{
if (CanAcceptItemFunc is null || AcceptItemFunc is null || !Access.HasFlag(PortAccess.In) )//|| LaneSpan.Encapsulates(new(0, (ushort)Width), laneSpan))
{
return false;
}
return CanAcceptItemFunc(beltItem, beltT);
}
public readonly bool TryInsertItem(IBeltItem beltItem, LaneSpan laneSpan, float beltT = 0)
{
if (!CanAcceptItem(beltItem, laneSpan, beltT))
{
return false;
}
return AcceptItemFunc(beltItem, beltT);
}
}
public abstract record BeltT();
public record BeltTEnd(ConveyorEnd End) : BeltT();
public record BeltTOffset(float T) : BeltT();
// public enum PortAccess : byte
// {
// In,
// Out,
// InOut,
// BiDirectional = InOut
// }
// [Flags]
// public enum TransferMode : byte//Need Better Name
// {
// None = 0,
// Push = 1,
// Pull = 2,
// PushPull = Push | Pull
// }
public interface IBeltMovement
{
void AdvanceBelt(ItemConveyor conveyor, float delta);
void AdvanceBelt(IMovementConveyor conveyor, float delta);
// event ItemMoved? OnItemMoved;
// delegate void ItemMoved(
// IBeltItem item,
// ReadOnlySpan<ItemMovementSegment> segments,
// float deltaTime
// );
}
public sealed class IndividualMovement : IBeltMovement
{
public void AdvanceBelt(ItemConveyor conveyor, float delta)
{
if (!conveyor.AnyItems())
{
return;
}
var beltDirection = conveyor.GetBeltDirection();
if (beltDirection == BeltDirection.NotMoving)
{
return;
}
var towardStart = beltDirection == BeltDirection.TowardStart;
var next = conveyor.GetConveyorPortFacing(conveyor.GetOutputPort());
if (towardStart)
{
for (int i = 0; i < conveyor.ItemsCount; i++)
{
var possibleItemTravel = conveyor.GetAvailableTravelForFrontItem(next.HasValue);
var maxSpeed = Mathf.Min(conveyor.SpeedMagnitude * delta, possibleItemTravel.Value) * Mathf.Sign(conveyor.SignedSpeed);//Or possibly (int)BeltDirection, givn that they stgore the sign as part of the enum
if (maxSpeed == 0)
{
return;
}
var endT = Mathf.Clamp(conveyor._items[i].BeltT + maxSpeed, 0, conveyor.Length);
conveyor._items[i] = conveyor._items[i] with { BeltT = endT };
if (endT <= 0)
{
// segments.Add(new(next.Value.Conveyor, ));
if (next.Value.Port.TryInsertItem(conveyor._items[i].Item, LaneSpan.One))
{
GD.Print("Item Moved");
conveyor._items.Remove(conveyor._items[i]);
i--;
}
}
}
}
else
{
for (int i = conveyor.ItemsCount-1; i >=0 ; i--)
{
var possibleItemTravel = conveyor.GetAvailableTravelForFrontItem(next.HasValue);
var maxSpeed = Mathf.Min(conveyor.SpeedMagnitude * delta, possibleItemTravel.Value) * Mathf.Sign(conveyor.SignedSpeed);//Or possibly (int)BeltDirection, givn that they stgore the sign as part of the enum
if (maxSpeed == 0)
{
return;
}
var endT = Mathf.Clamp(conveyor._items[i].BeltT + maxSpeed, 0, conveyor.Length);
conveyor._items[i] = conveyor._items[i] with { BeltT = endT };
if (endT >= conveyor.Length)
{
// segments.Add(new(next.Value.Conveyor, ));
if (next.Value.Port.TryInsertItem(conveyor._items[i].Item, LaneSpan.One))
{
GD.Print("Item Moved");
conveyor._items.Remove(conveyor._items[i]);
i--;
}
}
}
}
}
public void AdvanceBelt(IMovementConveyor conveyor, float delta)
{
// GD.Print(conveyor.Items);
@@ -651,101 +113,101 @@ public enum BeltDirection : sbyte {
}
public sealed class StrictMovement : IBeltMovement
{
// public event IBeltMovement.ItemMoved? OnItemMoved;
// // public event IBeltMovement.ItemMoved? OnItemMoved;
public void AdvanceBelt(ItemConveyor conveyor, float delta)
{
if (!conveyor.AnyItems())
{
return;
}
var beltDirection = conveyor.GetBeltDirection();
if (beltDirection == BeltDirection.NotMoving)
{
return;
}
var towardStart = beltDirection == BeltDirection.TowardStart;
// GD.Print("Thing: " + Speed + " "+ conveyor.GetConveyorPortFacing(conveyor.GetOutputPort()));
// var moveItemsIntoNextBelt = false;
var next = conveyor.GetConveyorPortFacing(conveyor.GetOutputPort());
var possibleItemTravel = conveyor.GetAvailableTravelForFrontItem(next.HasValue);
// public void AdvanceBelt(ItemConveyor conveyor, float delta)
// {
// if (!conveyor.AnyItems())
// {
// return;
// }
// var beltDirection = conveyor.GetBeltDirection();
// if (beltDirection == BeltDirection.NotMoving)
// {
// return;
// }
// var towardStart = beltDirection == BeltDirection.TowardStart;
// // GD.Print("Thing: " + Speed + " "+ conveyor.GetConveyorPortFacing(conveyor.GetOutputPort()));
// // var moveItemsIntoNextBelt = false;
// var next = conveyor.GetConveyorPortFacing(conveyor.GetOutputPort());
// var possibleItemTravel = conveyor.GetAvailableTravelForFrontItem(next.HasValue);
// // return;
// if (!possibleItemTravel.HasValue)
// {
// //There is no items, this should not be called
// throw new NotSupportedException("This should not e possible if there is no items or the belt is not moving, it should have returend before");
// }
// // if (next.HasValue && next.Value.Port.BeltT is BeltTEnd beltTEnd && (next.Value.Port.Direction == PortAccess.In || next.Value.Port.Direction == PortAccess.BiDirectional))
// // {
// // possibleItemTravel += next.Value.Conveyor.DistanceFromEnd(beltTEnd.End);
// // moveItemsIntoNextBelt = true;
// // }
// // var itemPair = conveyor.GetFirstItem();
// // var distToEnd = conveyor.GetAvailableTravel(conveyor.ItemsCount - 1, beltDirection);//(Speed < 0 ? ConveyorEnd.Start : ConveyorEnd.End);
// var maxSpeed = Mathf.Min(conveyor.SpeedMagnitude * delta, possibleItemTravel.Value) * Mathf.Sign(conveyor.SignedSpeed);//Or possibly (int)BeltDirection, givn that they stgore the sign as part of the enum
// if (maxSpeed == 0)
// {
// // var fI = conveyor.GetAvailableTravelForFrontItem();
// // if (fI.HasValue && fI.Value <= 0 && next.Value.Port.TryInsertItem(conveyor.GetFirstItem().Value.Item, LaneSpan.One))
// // {
// // GD.Print("Item Moved");
// // conveyor._items.Remove(conveyor.GetFirstItem().Value);
// // }
// return;
if (!possibleItemTravel.HasValue)
{
//There is no items, this should not be called
throw new NotSupportedException("This should not e possible if there is no items or the belt is not moving, it should have returend before");
}
// if (next.HasValue && next.Value.Port.BeltT is BeltTEnd beltTEnd && (next.Value.Port.Direction == PortAccess.In || next.Value.Port.Direction == PortAccess.BiDirectional))
// {
// possibleItemTravel += next.Value.Conveyor.DistanceFromEnd(beltTEnd.End);
// moveItemsIntoNextBelt = true;
// }
// List<ConveyorSlice> toMove = [];
// // Dictionary<IBeltItem, List<ItemMovementSegment>> moves = [];
// for (int i = 0; i < conveyor.ItemsCount; i++)
// {
// // List<ItemMovementSegment> segments = [];
// // var startT = conveyor._items[i].BeltT;
// var endT = Mathf.Clamp(conveyor._items[i].BeltT + maxSpeed, 0, conveyor.Length);
// conveyor._items[i] = conveyor._items[i] with { BeltT = endT };
// // segments.Add(new(conveyor, startT, towardStart? Mathf.Max(endT, 0) : Mathf.Min(endT, conveyor.Length),Mathf.Abs(maxSpeed)));
// if (towardStart ? (endT <= 0) : endT >= conveyor.Length)
// {
// toMove.Add(conveyor._items[i]);
// // segments.Add(new(next.Value.Conveyor, ));
// }
// // moves.Add(conveyor._items[i].Item, segments);
// var itemPair = conveyor.GetFirstItem();
// var distToEnd = conveyor.GetAvailableTravel(conveyor.ItemsCount - 1, beltDirection);//(Speed < 0 ? ConveyorEnd.Start : ConveyorEnd.End);
var maxSpeed = Mathf.Min(conveyor.SpeedMagnitude * delta, possibleItemTravel.Value) * Mathf.Sign(conveyor.SignedSpeed);//Or possibly (int)BeltDirection, givn that they stgore the sign as part of the enum
if (maxSpeed == 0)
{
// var fI = conveyor.GetAvailableTravelForFrontItem();
// if (fI.HasValue && fI.Value <= 0 && next.Value.Port.TryInsertItem(conveyor.GetFirstItem().Value.Item, LaneSpan.One))
// GD.Print($"Item: {conveyor._items[i].Item}, Position:{endT}");
// }
// // conveyor._items.ForEach((item) => item = item = Mathf.Clamp(item.Position + maxSpeed, 0, Length));
// // var list = _items.Where(item=> Speed>=0?item.BeltT >= Length:item.BeltT <= 0).ToList();
// // GD.Print(list.Count);
// if (next.HasValue)
// {
// foreach (var item in toMove)
// {
// GD.Print($"Item: {item.Item}, Position:{item.BeltT} -----------------");
// //TEST
// // var v = GetConveyorPortFacing(GetOutputPort());
// // if (v.HasValue)//Should be true if items are > Length
// // {
// // GD.PrintS(v.Value.Port.LocalOffset,v.Value.Port.BeltT,v.Value.Port.Direction,v.Value.Port.PullPush,v.Value.Port.Face);
// // var end = (next.Value.Port.BeltT as BeltTEnd).End;
// // next.Value.Conveyor.InsertAtEndWithoutCheck(end, item.Item);
// if (next.Value.Port.TryInsertItem(item.Item, item.LaneSpan))
// {
// GD.Print("Item Moved");
// conveyor._items.Remove(conveyor.GetFirstItem().Value);
// conveyor._items.Remove(item);
// }
return;
}
List<ConveyorSlice> toMove = [];
// Dictionary<IBeltItem, List<ItemMovementSegment>> moves = [];
for (int i = 0; i < conveyor.ItemsCount; i++)
{
// List<ItemMovementSegment> segments = [];
// var startT = conveyor._items[i].BeltT;
var endT = Mathf.Clamp(conveyor._items[i].BeltT + maxSpeed, 0, conveyor.Length);
conveyor._items[i] = conveyor._items[i] with { BeltT = endT };
// segments.Add(new(conveyor, startT, towardStart? Mathf.Max(endT, 0) : Mathf.Min(endT, conveyor.Length),Mathf.Abs(maxSpeed)));
if (towardStart ? (endT <= 0) : endT >= conveyor.Length)
{
toMove.Add(conveyor._items[i]);
// segments.Add(new(next.Value.Conveyor, ));
}
// moves.Add(conveyor._items[i].Item, segments);
GD.Print($"Item: {conveyor._items[i].Item}, Position:{endT}");
}
// conveyor._items.ForEach((item) => item = item = Mathf.Clamp(item.Position + maxSpeed, 0, Length));
// var list = _items.Where(item=> Speed>=0?item.BeltT >= Length:item.BeltT <= 0).ToList();
// GD.Print(list.Count);
if (next.HasValue)
{
foreach (var item in toMove)
{
GD.Print($"Item: {item.Item}, Position:{item.BeltT} -----------------");
//TEST
// var v = GetConveyorPortFacing(GetOutputPort());
// if (v.HasValue)//Should be true if items are > Length
// {
// GD.PrintS(v.Value.Port.LocalOffset,v.Value.Port.BeltT,v.Value.Port.Direction,v.Value.Port.PullPush,v.Value.Port.Face);
// var end = (next.Value.Port.BeltT as BeltTEnd).End;
// next.Value.Conveyor.InsertAtEndWithoutCheck(end, item.Item);
if (next.Value.Port.TryInsertItem(item.Item, item.LaneSpan))
{
GD.Print("Item Moved");
conveyor._items.Remove(item);
}
}
}
}
// }
// }
// }
public void AdvanceBelt(IMovementConveyor conveyor, float delta) => throw new NotImplementedException();
}
}
public struct ConveyorSlice(IBeltItem item, float beltT = 0)
{
@@ -777,12 +239,26 @@ public readonly struct LaneSpan : IEquatable<LaneSpan>
public static bool operator ==(LaneSpan a, LaneSpan b) => a.Equals(b);
public static bool operator !=(LaneSpan a, LaneSpan b) => !a.Equals(b);
}
public static class Extersions
public enum BeltDirection : sbyte
{
public static ItemConveyor.BeltDirection DirectionTo(this ItemConveyor.ConveyorEnd end) => end switch
TowardStart = -1,
NotMoving = 0,
TowardEnd = 1
}
public enum ConveyorEnd { Start, End }
public abstract record BeltT();
public record BeltTEnd(ConveyorEnd End) : BeltT();
public record BeltTOffset(float T) : BeltT();
public static class ConveyorExtensions
{
ItemConveyor.ConveyorEnd.Start => ItemConveyor.BeltDirection.TowardStart,
ItemConveyor.ConveyorEnd.End => ItemConveyor.BeltDirection.TowardEnd,
public static BeltDirection DirectionTo(this ConveyorEnd end) => end switch
{
ConveyorEnd.Start => BeltDirection.TowardStart,
ConveyorEnd.End => BeltDirection.TowardEnd,
_ => throw new NotImplementedException(),
};
public static ConveyorEnd Swap(this ConveyorEnd end) => end switch { ConveyorEnd.Start => ConveyorEnd.End, ConveyorEnd.End => ConveyorEnd.Start, _ => throw new NotSupportedException() };
}

View File

@@ -1,131 +0,0 @@
namespace ChickenGameTest;
using System;
using System.Collections.Generic;
using System.Linq;
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
[Meta(typeof(IAutoNode))]
public partial class SlotComponentNode
: Node3D , IEquipmentComponent
{
public override void _Notification(int what) => this.Notify(what);
[Export] public SlotDirection Direction;
[Export] public Vector3I LocalCellOffset;
[Dependency] protected IVoxelGridQuery<LayeredEquipment> Grid => this.DependOn<IVoxelGridQuery<LayeredEquipment>>();
[Dependency] protected IEquipmentContext EquipmentContext =>this.DependOn<IEquipmentContext>();
[Dependency] protected IEquipmentComponentRegistry ComponentRegistry => this.DependOn<IEquipmentComponentRegistry>();
public EquipmentId EquipmentId => EquipmentContext.GetEquipmentId();
// SO instead of using an hidden list of compeonts on the equimpent, have the equpment provide an reggistery that compnents depend on to register themselves to, and allow for muitple of the same type.
public void OnResolved()
{
GD.PrintS(EquipmentContext, Grid);
EquipmentContext.GetEquipment().Tick += Tick;
ComponentRegistry.Register(this);
GD.Print("Added Tick Listener");
}
private void Tick()
{
Grid.GetVoxel(EquipmentContext.GetEquipment().GridPos + LocalCellOffset/*TODO Acount for Direction*/).IfAny(e =>
{
var slots = e.SelectMany(ee => ee.GetChildren().OfType<SlotComponentNode>().Where(_=> true/*Where slot faces this one and is not output*/)).ToList();
// slots.First().AcceptItem(new TestItem());//For testing accuming adding item, should probly sort and cascade so progatrion stops when out of items, but should only be one result, as each componet is one face
});
// GD.Print("Tryied moveing items test");
}
public bool AcceptItem(IBeltItem itemStack)
{
return true;
}
public override void _ExitTree()
{
base._ExitTree();
EquipmentContext.GetEquipment().Tick -= Tick;
ComponentRegistry.Unregister(this);
}
// public Vector3I GetSlotCell() {
// return Equipment.GetOccupiedCell() + LocalCellOffset;
// }
// public Vector3 GetSlotWorldPosition() {
// return Grid.CellToWorld(GetSlotCell());
// }
}
public interface IEquipmentComponentRegistry {
void Register<T>(T component)
where T : class, IEquipmentComponent;
void Unregister<T>(T component)
where T : class, IEquipmentComponent;
T? Get<T>(EquipmentId id)
where T : class, IEquipmentComponent;
IReadOnlyList<T> GetAll<T>(EquipmentId id)
where T : class, IEquipmentComponent;
}public sealed class EquipmentComponentRegistry
: IEquipmentComponentRegistry {
private readonly Dictionary<
EquipmentId,
Dictionary<Type, List<object>>
> _map = new();
public void Register<T>(T component)
where T : class, IEquipmentComponent {
GD.Print(component);
if (!_map.TryGetValue(component.EquipmentId, out var types)) {
types = new();
_map[component.EquipmentId] = types;
}
var type = typeof(T);
if (!types.TryGetValue(type, out var list)) {
list = new();
types[type] = list;
}
list.Add(component);
}
public T? Get<T>(EquipmentId id)
where T : class, IEquipmentComponent {
if (_map.TryGetValue(id, out var types) &&
types.TryGetValue(typeof(T), out var list))
return list[0] as T;
return null;
}
public IReadOnlyList<T> GetAll<T>(EquipmentId id)
where T : class, IEquipmentComponent {
if (_map.TryGetValue(id, out var types) &&
types.TryGetValue(typeof(T), out var list))
return list.Cast<T>().ToList();
return Array.Empty<T>();
}
public void Unregister<T>(T component)
where T : class, IEquipmentComponent {
if (_map.TryGetValue(component.EquipmentId, out var types) &&
types.TryGetValue(typeof(T), out var list))
list.Remove(component);
}
}
public interface IEquipmentComponent {
EquipmentId EquipmentId { get; }
}

View File

@@ -1 +0,0 @@
uid://drsqsmj0bn1ob

View File

@@ -1 +0,0 @@
uid://dao8u7hn0yadp

View File

@@ -181,7 +181,7 @@ public class Sorted1DList<T>
public partial class TestItemConveyor : Node, IMovementConveyor
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public ItemConveyor.IBeltMovement MovementSystem => this.DependOn<ItemConveyor.IBeltMovement>(() => new ItemConveyor.IndividualMovement());
[Dependency] public IBeltMovement MovementSystem => this.DependOn<IBeltMovement>(() => new IndividualMovement());
[Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn<IVoxelGridRegistry>();
// private readonly AutoList<ConveyorSlice> _items = [];
// public IAutoList<ConveyorSlice> Items => _items;
@@ -236,35 +236,9 @@ public partial class TestItemConveyor : Node, IMovementConveyor
// public IEnumerable<ConveyorSlice> EnumerateTowardEnd() => _items;
// public IEnumerable<ConveyorSlice> EnumerateTowardStart() => _items.Reverse();
public ItemConveyor.BeltDirection GetBeltDirection() => IsReversed ? ItemConveyor.BeltDirection.TowardStart : ItemConveyor.BeltDirection.TowardEnd;
public ItemConveyor.IBeltMovement GetMovementPolicy() => MovementSystem;
public BeltDirection GetBeltDirection() => IsReversed ? BeltDirection.TowardStart : BeltDirection.TowardEnd;
public IBeltMovement GetMovementPolicy() => MovementSystem;
public IEnumerable<IBeltPort> GetPorts() => [StartPort, EndPort, .. OtherPorts];
// public IEnumerable<IBeltSlotProfile> GetPorts() => [StartPort, EndPort,
// new ItemConveyor.ConveyorPort(){
// BeltT = new ItemConveyor.BeltTOffset(.5f),
// Face = Direction.Right,
// Direction = PortAccess.InOut,
// PullPush = TransferMode.Passive,
// MovementConveyor = this,
// LocalOffset = Position,
// },
// new ItemConveyor.ConveyorPort(){
// BeltT = new ItemConveyor.BeltTOffset(.5f),
// Face = Direction.Left,
// Direction = PortAccess.InOut,
// PullPush = TransferMode.Passive,
// MovementConveyor = this,
// LocalOffset = Position,
// },
// new ItemConveyor.ConveyorPort(){
// BeltT = new ItemConveyor.BeltTOffset(.5f),
// Face = Direction.Up,
// Direction = PortAccess.In,
// PullPush = TransferMode.Passive,
// MovementConveyor = this,
// LocalOffset = Position,
// }
// ];Path3D.Curve.SampleBakedWithRotation(b.BeltT).Basis.X*b.Item.Width
public void OnResolved()
{
if (Engine.IsEditorHint())
@@ -274,26 +248,6 @@ public partial class TestItemConveyor : Node, IMovementConveyor
var timer = new Timer() { WaitTime = .05f, Autostart = true };
AddChild(timer);
timer.Timeout += () => MovementSystem.AdvanceBelt(this, (float)timer.WaitTime);
// Items.Add(new ConveyorSlice(new TestItem(), 0));
// StartPort = new ConveyorPort(this,
// new BeltPortProfile(Position, Direction.Back, 1, PortAccess.BiDirectional),
// new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.Start),
// (item, offset) =>
// {
// var obstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, 0, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// },
// (item, offset) => { _items.Insert(0, new(item, offset)); return true;});
// EndPort = new ConveyorPort(this,
// new BeltPortProfile(Position, Direction.Front, 1, PortAccess.BiDirectional),
// new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.End),
// (item, offset) =>
// {
// var obstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, Length, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// // return ItemConveyor.ITEMSIZE < GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardStart, Length, SpeedMagnitude, LaneSpan.One);
// },
// (item, offset) => { _items.Add(new(item, offset)); return true;});
if (StartPort is null || EndPort is null)
{
throw new Exception();
@@ -304,31 +258,16 @@ public partial class TestItemConveyor : Node, IMovementConveyor
GridRegistry.Register(item, [.. points]);
}
StartPort.TryInsert(new TestItem(), LaneSpan.Shifted(LaneSpan.One, 0), 0);
// StartPort.TryInsert(new TestItem(), LaneSpan.Sh fted(LaneSpan.One,1), 0);
// Items.Insert(new ConveyorSlice(new TestItem(), 0));
// _items.Add(new (new TestItem()));
}
public override void _Ready()
{
// _itemsBinding = _items.Bind();
// _itemsBinding.OnModify(() =>
// {
// });
// OnResolved();
base._Ready();
//test
}
//ChatGPT Assisted
public BeltObstacle GetDistanceToNextItem(
ItemConveyor.BeltDirection beltDirection,
BeltDirection beltDirection,
float itemBeltT,
float maxDistToCheck,
LaneSpan laneSpan,
HashSet<IMovementConveyor>? visited = null)
{
if (beltDirection == ItemConveyor.BeltDirection.NotMoving)
if (beltDirection == BeltDirection.NotMoving)
{
throw new NotSupportedException();
}
@@ -339,14 +278,14 @@ public partial class TestItemConveyor : Node, IMovementConveyor
return new BeltObstacle(0);
}
bool towardStart = beltDirection == ItemConveyor.BeltDirection.TowardStart;
bool towardStart = beltDirection == BeltDirection.TowardStart;
// 1⃣ Try to find next item on this conveyor
var nextItem = FindNextLocalItem(towardStart, itemBeltT, laneSpan);
// GD.Print(nextItem);
if (nextItem.HasValue(out var item))
{
return new ItemBeltObstacle(MathF.Abs(itemBeltT - item.BeltT) - ItemConveyor.ITEMSIZE, item, laneSpan);
return new ItemBeltObstacle(MathF.Abs(itemBeltT - item.BeltT) - ITEMSIZE, item, laneSpan);
// return MathF.Abs(itemBeltT - item.BeltT);//TODO UseLaneSpan inadditon
}
@@ -415,7 +354,7 @@ public partial class TestItemConveyor : Node, IMovementConveyor
return new BoundaryBeltObstacle(distanceToBoundary);
}
if (conveyorPort.BeltT is not ItemConveyor.BeltTEnd end)
if (conveyorPort.BeltT is not BeltTEnd end)
{
return new BoundaryBeltObstacle(distanceToBoundary);
}
@@ -427,7 +366,7 @@ public partial class TestItemConveyor : Node, IMovementConveyor
}
var nextDirection = DirectionAwayFromEnd(end.End);
var startT = end.End == ItemConveyor.ConveyorEnd.Start
var startT = end.End == ConveyorEnd.Start
? 0f
: conveyorPort.Conveyor.Length;
@@ -447,8 +386,6 @@ public partial class TestItemConveyor : Node, IMovementConveyor
visited
);
return recursiveDistance with { Distance = recursiveDistance.Distance + distanceToBoundary };
// return new BeltObstacle(recursiveDistance.Kind, recursiveDistance.DistanceToCenter + distanceToBoundary, recursiveDistance.LaneSpan, recursiveDistance.Conveyor, recursiveDistance.Item,null);
// return distanceToBoundary + recursiveDistance;
}
private IOption<ConveyorPort> FindFacingConveyorPort(
IBeltPort slot)
@@ -524,10 +461,12 @@ public partial class TestItemConveyor : Node, IMovementConveyor
return new LaneSpan((ushort)newStart, (ushort)newEnd).ToOption();
}
private ItemConveyor.BeltDirection DirectionAwayFromEnd(ItemConveyor.ConveyorEnd conveyorEnd) => conveyorEnd switch { ItemConveyor.ConveyorEnd.Start => ItemConveyor.BeltDirection.TowardEnd, ItemConveyor.ConveyorEnd.End => ItemConveyor.BeltDirection.TowardStart };
private BeltDirection DirectionAwayFromEnd(ConveyorEnd conveyorEnd) => conveyorEnd switch { ConveyorEnd.Start => BeltDirection.TowardEnd, ConveyorEnd.End => BeltDirection.TowardStart, _ => throw new NotSupportedException() };
public IEnumerable<Sorted1DList<ConveyorSlice>.ItemHandle> EnumerateTowardEnd() => Items.EnumerateTowardEnd();
public IEnumerable<Sorted1DList<ConveyorSlice>.ItemHandle> EnumerateTowardStart() => Items.EnumerateTowardStart();
private static Vector3[] _Square = [new(-.5f, .5f, -.5f), new(.5f, .5f, -.5f), new(.5f, -.5f, -.5f), new(-.5f, -.5f, -.5f), new(-.5f, .5f, -.5f)];
private static readonly Vector3[] _square = [new(-.5f, .5f, -.5f), new(.5f, .5f, -.5f), new(.5f, -.5f, -.5f), new(-.5f, -.5f, -.5f), new(-.5f, .5f, -.5f)];
public const float ITEMSIZE = .2f;
private const float ITEMHALFSIZE = ITEMSIZE / 2f;
public override void _Process(double delta)
{
@@ -539,48 +478,36 @@ public partial class TestItemConveyor : Node, IMovementConveyor
{
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.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);
}
}
public ConveyorPort CreatePort(BeltPortProfile profile, ItemConveyor.BeltT beltT, LaneSpan laneSpan)
public ConveyorPort CreatePort(BeltPortProfile profile, BeltT beltT, LaneSpan laneSpan)
{
// var towardStartEnd = beltT is ItemConveyor.BeltTEnd end && end.End == ItemConveyor.ConveyorEnd.End;
bool accept(IBeltItem item, float offset, LaneSpan lane)
{
if (beltT is ItemConveyor.BeltTEnd end)
if (beltT is BeltTEnd end)
{
var startBeltT = end.End == ItemConveyor.ConveyorEnd.Start ? 0 : Length;
var obstacle = GetDistanceToNextItem(ItemConveyor.SwapEnd(end.End).DirectionTo(), startBeltT, offset, lane);
var startBeltT = end.End == ConveyorEnd.Start ? 0 : Length;
var obstacle = GetDistanceToNextItem(end.End.Swap().DirectionTo(), startBeltT, offset, lane);
var distanceAllowed = obstacle.Distance;
return ItemConveyor.ITEMSIZE < distanceAllowed;
return ITEMSIZE < distanceAllowed;
}
else if (beltT is ItemConveyor.BeltTOffset endOffset)
else if (beltT is BeltTOffset endOffset)
{
return HasClearance(endOffset.T, lane);
// var lowerObstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardStart, endOffset.T, ItemConveyor.ITEMSIZE,LaneSpan.One);
// var upperObstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, endOffset.T, ItemConveyor.ITEMSIZE,LaneSpan.One);
// var lowerDistanceAllowed = lowerObstacle.DistanceToCenter - (lowerObstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// var upperObstacleAllowed = upperObstacle.DistanceToCenter - (upperObstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// return ItemConveyor.ITEMSIZE < lowerDistanceAllowed && ItemConveyor.ITEMSIZE < upperObstacleAllowed;
}
throw new NotImplementedException();
}
// if (beltT is ItemConveyor.BeltTEnd end && end.End == ItemConveyor.ConveyorEnd.End){
// accept = (IBeltItem item, float offset) =>
// {
// var obstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardStart, Length, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// };
// }
bool tryInsert(IBeltItem item, float offset, LaneSpan laneSpan)
{
if (beltT is ItemConveyor.BeltTEnd end)
if (beltT is BeltTEnd end)
{
if (end.End == ItemConveyor.ConveyorEnd.End)
if (end.End == ConveyorEnd.End)
{
Items.Insert(new(item, Length - offset) { LaneSpan = laneSpan });
// _items.Add(new(item, Length-offset));
@@ -592,7 +519,7 @@ public partial class TestItemConveyor : Node, IMovementConveyor
}
return true;
}
else if (beltT is ItemConveyor.BeltTOffset endOffset)
else if (beltT is BeltTOffset endOffset)
{
if (!HasClearance(endOffset.T, LaneSpan.One))
@@ -622,16 +549,16 @@ public partial class TestItemConveyor : Node, IMovementConveyor
private bool HasClearance(float centerT, LaneSpan span)
{
var lower = GetDistanceToNextItem(
ItemConveyor.BeltDirection.TowardStart,
BeltDirection.TowardStart,
centerT,
ItemConveyor.ITEMSIZE,
ITEMSIZE,
span
);
var upper = GetDistanceToNextItem(
ItemConveyor.BeltDirection.TowardEnd,
BeltDirection.TowardEnd,
centerT,
ItemConveyor.ITEMSIZE,
ITEMSIZE,
span
);
@@ -643,67 +570,14 @@ public partial class TestItemConveyor : Node, IMovementConveyor
upper.Distance;// -
// (upper.IsItem ? ItemConveyor.ITEMSIZE : 0);
return ItemConveyor.ITEMSIZE < lowerAllowed &&
ItemConveyor.ITEMSIZE < upperAllowed;
return ITEMSIZE < lowerAllowed &&
ITEMSIZE < upperAllowed;
}
}
// Items.Add(new ConveyorSlice(new TestItem(), 0));
// StartPort = new ConveyorPort(this,
// new BeltPortProfile(Position, Direction.Back, 1, PortAccess.BiDirectional),
// new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.Start),
// (item, offset) =>
// {
// var obstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, 0, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// },
// (item, offset) => { _items.Insert(0, new(item, offset)); return true;});
// EndPort = new ConveyorPort(this,
// new BeltPortProfile(Position, Direction.Front, 1, PortAccess.BiDirectional),
// new ItemConveyor.BeltTEnd(ItemConveyor.ConveyorEnd.End),
// (item, offset) =>
// {
// var obstacle = GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardEnd, Length, offset, LaneSpan.One);
// return ItemConveyor.ITEMSIZE < obstacle.DistanceToCenter - (obstacle.IsItem ? ItemConveyor.ITEMSIZE : 0);
// // return ItemConveyor.ITEMSIZE < GetDistanceToNextItem(ItemConveyor.BeltDirection.TowardStart, Length, SpeedMagnitude, LaneSpan.One);
// },
// (item, offset) => { _items.Add(new(item, offset)); return true;});
//TODO Should liklely account for max search distance where the conveyorm may be needed to know
public record class BeltObstacle(float Distance)
{
// public ObstacleKind Kind { get; }
// public BeltObstacle()
// {
// }
// public float DistanceToCenter { get; } // always center / reference
// public LaneSpan LaneSpan { get; } // only meaningful for Item
// public ConveyorSlice? Item { get; } // only if Kind == Item
// public IMovementConveyor? Conveyor { get; } // boundary case
// public IBeltPort? Port { get; } // Port case
// public bool IsItem => Kind == ObstacleKind.Item;
// public bool IsBoundary => Kind == ObstacleKind.Boundary;
}
// public enum ObstacleKind
// {
// None,
// Item,
// Boundary,
// }
public record ItemBeltObstacle(float Distance, ConveyorSlice Item, LaneSpan LaneSpan) : BeltObstacle(Distance)
{
}
public record BoundaryBeltObstacle(float DistanceToBoundary) : BeltObstacle(DistanceToBoundary)
{
}
public record PortBeltObstacle(float DistanceToBoundary, LaneSpan LaneSpan, IBeltPort BeltPort) : BoundaryBeltObstacle(DistanceToBoundary)
{
}
public record class BeltObstacle(float Distance);
public record ItemBeltObstacle(float Distance, ConveyorSlice Item, LaneSpan LaneSpan) : BeltObstacle(Distance);
public record BoundaryBeltObstacle(float DistanceToBoundary) : BeltObstacle(DistanceToBoundary);
public record PortBeltObstacle(float DistanceToBoundary, LaneSpan LaneSpan, IBeltPort BeltPort) : BoundaryBeltObstacle(DistanceToBoundary);

View File

@@ -11,11 +11,9 @@ using SJK.Functional;
//Will Liklely be the game instead of a node like this
[Meta(typeof(IAutoNode))]// [Tool]
public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridQuery<LayeredEquipment>>, IProvide<IEquipmentComponentRegistry>, IProvide<IVoxelGridRegistry>, IProvide<IItemRenderer>
public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridRegistry>, IProvide<IItemRenderer>
{
public override void _Notification(int what) => this.Notify(what);
private IVoxelGridQuery<LayeredEquipment> _voxelGrid = default!;
IVoxelGridQuery<LayeredEquipment> IProvide<IVoxelGridQuery<LayeredEquipment>>.Value() => _voxelGrid;
private IVoxelGridRegistry _voxelGridRegistry = default!;
IVoxelGridRegistry IProvide<IVoxelGridRegistry>.Value() => _voxelGridRegistry;
@@ -25,8 +23,6 @@ public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridQuery<LayeredEqu
{
GD.Print();
base._Ready();
_voxelGrid = new EquipmentVoxelGrid();
_equipmentComponentRegistry = new EquipmentComponentRegistry();
_voxelGridRegistry = new VoxelRegistry();
_itemRenderer = new TestItemRendered();
AddChild(_itemRenderer as Node);
@@ -35,150 +31,4 @@ public partial class VoxelGridNode : Node3D, IProvide<IVoxelGridQuery<LayeredEqu
// timer.Timeout += _itemRenderer.Tick;//TEST
this.Provide();
}
public override void _Process(double delta)
{
base._Process(delta);
// GD.Print(_voxelGridRegistry.Get<ISlotFace>(Vector3I.Zero).First().GetConnectingFace());
}
IEquipmentComponentRegistry _equipmentComponentRegistry;
IEquipmentComponentRegistry IProvide<IEquipmentComponentRegistry>.Value() => _equipmentComponentRegistry;
}
// [Meta, Id("voxel_grid")]
public sealed partial class EquipmentVoxelGrid : IVoxelGridQuery<LayeredEquipment>
{
private System.Collections.Generic.Dictionary<Vector3I, LayeredEquipment> _data = new();
public void AddEquipment(Vector3I position, Equipment equipment)
{
if (!_data.TryGetValue(position, out var layers))
{
_data[position] = layers = new();
}
layers.Add(equipment);
}
//TODO Use Options instead of nu;lable
public LayeredEquipment GetVoxel(Vector3I position) => _data.TryGetValue(position, out var result) ? result : new();
public IEnumerable<Equipment> GetEquipmentAt(Vector3I position) => GetVoxel(position).GetEquipments();
// public
// public void SetEquipmentAt(Vector3I position, T value)
// {
// _data[position] = value;
// GD.Print(value);
// }
public LayeredEquipment SetVoxel(Vector3I position, LayeredEquipment value) => _data[position] = value;
public bool IsOccupied(Vector3I cell) => _data.ContainsKey(cell);
}
public interface IVoxelGridQuery<T>
{
T GetVoxel(Vector3I cell);
T SetVoxel(Vector3I cell, T value);
bool IsOccupied(Vector3I cell);
}
public class LayeredEquipment
{
public int Count => _equipment.Count;
private readonly HashSet<Equipment> _equipment = new();
public IEnumerable<Equipment> GetEquipments() => _equipment;
public bool Add(Equipment equipment) => _equipment.Add(equipment);
public bool Remove(Equipment equipment) => _equipment.Remove(equipment);
public void AddMany(params Equipment[] equipment)
{
foreach (var item in equipment)
{
Add(item);
}
}
public void RemoveMany(params Equipment[] equipment)
{
foreach (var item in equipment)
{
Remove(item);
}
}
public void IfAny(Action<IEnumerable<Equipment>> action)
{
if (Count > 0)
{
action(GetEquipments());
}
}
}
public sealed class SlotDescriptor
{
public SlotDirection Direction { get; }
public SlotDescriptor(
SlotDirection direction
)
{
Direction = direction;
}
}
public abstract class SlotLogic<TPayload>
{
public SlotDescriptor Descriptor { get; }
protected SlotLogic(SlotDescriptor descriptor)
{
Descriptor = descriptor;
}
public abstract bool CanTransfer(
TPayload payload
);
public abstract bool TryTransfer(
TPayload payload
);
}
public sealed class ItemSlotLogic
: SlotLogic<IBeltItem>
{
public ItemSlotLogic(SlotDescriptor descriptor)
: base(descriptor) { }
public override bool CanTransfer(IBeltItem item) => false;
// item.Count > 0;
public override bool TryTransfer(IBeltItem item)
{
// routing rules
return true;
}
}
[Meta]
public partial class ItemSlotNode
: SlotComponentNode
{
private ItemSlotLogic _logic;
public override void _Ready()
{
base._Ready();
_logic = new ItemSlotLogic(
new SlotDescriptor(Direction)
);
}
public void OnResolved()
{
}
public void Tick(IBeltItem stack)
{
if (_logic.CanTransfer(stack))
_logic.TryTransfer(stack);
}
}
public enum SlotDirection
{
Input,
Output
}

View File

@@ -9,72 +9,9 @@ using System.Collections.Generic;
using System.Linq;
using ChickenGameTest;
public interface ISlotFace : IVoxelNode // INode3D,
{
ISlotFace GetConnectingFace();
}
[Tool]
[Meta(typeof(IAutoNode))]
public partial class SlotFace : Node3D, ISlotFace
{
public Guid Id { get; set; }
public IEnumerable<Vector3I> Shape => [Vector3I.Zero];
[Export] public Vector3I VoxelPosition { get; set; }
[Export] public Direction VoxelRotation { get; set; }
[Export] public bool ShowDebug { get; set; } = false;
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IVoxelGridRegistry GridRegistry => this.DependOn<IVoxelGridRegistry>();
public void OnResolved()
{
GridRegistry.Register(this);
GD.Print("Regestered");
}
public ISlotFace GetConnectingFace()//TODO there could be tecnaly muiple slots shareing a face, and should be acounted for
{
var nodes = GridRegistry.Get<ISlotFace>(VoxelPosition + VoxelRotation.ToVector());//TODO Acoount for rotation to get slot direction
// GD.Print(nodes.Count());
foreach (var item in nodes)
{
if (item.VoxelRotation.Reverse() == VoxelRotation)
{
return item;
}
}
return null;
}
private static Vector3[] _Square = [new(-.5f, .5f, -.5f), new(.5f, .5f, -.5f), new(.5f, -.5f, -.5f), new(-.5f, -.5f, -.5f), new(-.5f, .5f, -.5f)];
public override void _Process(double delta)
{
if (ShowDebug)
{
ShowDebugFace();
}
}
private void ShowDebugFace()
{
var color = Colors.Red;
var pos = ToGlobal(new Vector3(0, 0, -.5f));
if (!Engine.IsEditorHint())
{
color = GetConnectingFace() is null ? Colors.Red : Colors.Green;
}
// var text = $"SlotFace{Name}";
// GD.PrintS(color);
DebugDraw3D.DrawLinePath([.. _Square.Select(ToGlobal)],color);
// DebugDraw3D.DrawText(pos, text, 16);
}
}
public interface IVoxelGridRegistry
{
[Obsolete]
void Register<T>(T voxelNode) where T : IVoxelNode;
void Register<T>(T voxelNode, params Vector3I[] positions);
void UnRegister<T>(T voxelNode) where T : IVoxelNode=> UnRegister(voxelNode.Id);
void UnRegister<T>(T voxelNode, params Vector3I[] positions);
void UnRegister(Guid id);
IEnumerable<T> Get<T>(Vector3I voxelPos);
@@ -111,25 +48,6 @@ public sealed class VoxelRegistry : IVoxelGridRegistry
}
}
public void Register<T>(T voxelNode) where T : IVoxelNode
{
void register(Vector3I pos, T point)
{
if (!_data.TryGetValue(pos, out var entrys))
{
entrys = [];
_data[pos] = entrys;
}
entrys.Add(point);
}
voxelNode.Shape.ToList().ForEach(
item =>
{
register(item + voxelNode.VoxelPosition, voxelNode);//TODO Acount For Rotation
}
);
}
public void Register<T>(T voxelNode, params Vector3I[] positions)
{
void register(Vector3I pos, T point)
@@ -143,8 +61,10 @@ public sealed class VoxelRegistry : IVoxelGridRegistry
}
foreach (var pos in positions)
{
if (positions.Length>1){
GD.Print("hhhhhhhhh ",pos);}
if (positions.Length > 1)
{
GD.Print("hhhhhhhhh ", pos);
}
register(pos, voxelNode);//TODO Acount For Rotation
}
}
@@ -165,13 +85,6 @@ public sealed class VoxelRegistry : IVoxelGridRegistry
}
}
}
public interface IVoxelNode
{
Guid Id { get; }
Vector3I VoxelPosition { get; }
Direction VoxelRotation { get; } //TODO replace with struct/record for static rotation typeing
IEnumerable<Vector3I> Shape { get; }//TOPO make SHape able to account for occpancy/ partial filled voxels.
}
public enum Direction
{

View File

@@ -0,0 +1 @@
uid://b40bs4c3fwcmb