protected IPlantCell MoveUpOrDown(IFluidCarrier <TFluid> carrier, IPlantPart part)
        {
            var cells = part.Cells;

            var currentTop = carrier.Current.Geometry.TopCenter.Y;

            var destTop = carrier.Destination.Geometry.BottomCenter.Y;

            IPlantCell next;

            if (IsWithinHeight(carrier.Current.Geometry, carrier.Destination.Geometry))
            {
                next = MoveTowardsDestination(carrier, cells);
            }
            else if (currentTop >= destTop)
            {
                next = FindUpOrDown(false, carrier.Current, part);
            }
            else
            {
                next = FindUpOrDown(true, carrier.Current, part);
            }

            return(next);
        }
        protected IPlantCell GetClosestCellTowards(IFluidCarrier <TFluid> carrier, IEnumerable <IPlantCell> neighbors)
        {
            var currentPoint = new Vector2(carrier.Current.Geometry.TopCenter.X, carrier.Current.Geometry.TopCenter.Z);

            float lowestDistance = float.MaxValue;

            IPlantCell closestCell = null;

            foreach (var neighbor in neighbors)
            {
                if (neighbor.Equals(carrier.ClosestTransportCell))
                {
                    return(neighbor);
                }

                var neighboringPoint = new Vector2(neighbor.Geometry.TopCenter.X, neighbor.Geometry.TopCenter.Z);

                float dist = Vector2.Distance(currentPoint, neighboringPoint);

                if (dist < lowestDistance)
                {
                    lowestDistance = dist;
                    closestCell    = neighbor;
                }
            }

            return(closestCell);
        }
        protected bool MoveCarrier(IFluidCarrier <TFluid> carrier, IPlantPart part)
        {
            // Get all the cells in the current plant part
            var cells = part.Cells;

            // The current carrier placement
            var current = carrier.Current;

            // Get the neighbors for the current carrier placement
            var neighbors = GetNeighboringCells(current, cells);

            IPlantCell next;

            // If the carrier is at the destination
            if (carrier.Current.Geometry.TopCenter.Equals(carrier.Destination.Geometry.TopCenter))
            {
                return(true);
            }

            // If the carrier is in a transport cell, it must move up or down
            if (carrier.IsInTransportCell)
            {
                next = MoveUpOrDown(carrier, part);
            }
            // If the carrier is not in a transport cell then it must move towards a transport cell
            // or the destination based on the height of the current placement
            else
            {
                next = GetClosestCellTowards(carrier, neighbors);
            }

            if (next != null)
            {
                carrier.Current = next;
            }

            return(false);
        }
        protected IPlantCell MoveTowardsDestination(IFluidCarrier <TFluid> carrier, IEnumerable <IPlantCell> cells)
        {
            IPlantCell next = null;

            float lowestDistance = float.MaxValue;

            foreach (var c in cells)
            {
                if (c.Equals(carrier.Destination))
                {
                    return(c);
                }

                float dist = Vector3.Distance(carrier.Current.Geometry.TopCenter, c.Geometry.TopCenter);

                if (dist < lowestDistance)
                {
                    next = c;
                }
            }

            return(next);
        }
 public bool TryGet(IPlantCell cell, out IFluidCarrier <TFluid> carrier)
 {
     return(carriers.TryGetValue(cell, out carrier));
 }
 public void Add(IFluidCarrier <TFluid> carrier)
 {
     carriers.Add(carrier.Destination, carrier);
 }