namespace FoodFactory.Equipment; using Godot; using System.Collections.Generic; using System.Linq; using Chickensoft.AutoInject; using Chickensoft.Introspection; using FoodFactory.Voxel; using FoodFactory.Math; using FoodFactory.Conveyors; using FoodFactory.Items; [Meta(typeof(IAutoNode))] public partial class Balancer : Node3D, IProvide, IProvide { public override void _Notification(int what) => this.Notify(what); private BeltPortHost _insertLogic = default!; public IBeltPortHost Value() => _insertLogic; IVoxelGridRegistry IProvide.Value() => GridRegistry; public IVoxelGridRegistry GridRegistry => FoodFactory.GridRegistry; [Dependency] public IFoodFactoryApi FoodFactory => this.DependOn(); private List _outPuts = new(); public GridTransform3D VoxelTransform { get => GridTransform3D.FromGodot(GlobalTransform); set => GlobalTransform = value.ToGodot(); } public void OnResolved() { _insertLogic = new BeltPortHost(); _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.Access.HasFlag(PortAccess.In), () => new DelegateInsertBeltItemLogic(CanAccept, CanInsert)); _insertLogic.Bind(port => port is BeltPort beltPort && beltPort.Access.HasFlag(PortAccess.Out), () => new DelegateInsertBeltItemLogic((_, _) => true, (_, _) => true)); this.Provide(); _outPuts = [.. OutputPorts]; } private bool CanAccept(IBeltPort port, IBeltItem item) { foreach (var portOther in OutputPorts) { if (portOther.GetPortFacing(GridRegistry).Map(f => f.CanAccept(item, LaneSpan.One, 0)).Or(false)) { return true; } } return false; } private IEnumerable OutputPorts => _insertLogic.GetPorts().OfType().Where(i => i.Access.HasFlag(PortAccess.Out)); private bool CanInsert(IBeltPort port, IBeltItem item) { for (var i = 0; i < _outPuts.Count; i++) { var facing = _outPuts[i].GetPortFacing(GridRegistry); if (facing.HasValue(out var face) && face.CanAccept(item, LaneSpan.One, 0) && face.TryInsert(item, LaneSpan.One, 0)) { var c = _outPuts[i]; _outPuts.RemoveAt(i); _outPuts.Add(c); return true; } } return false; } }