private bool BuildTarget(BlockTarget target, ShipyardItem item, IMyCubeBlock tool)
        {
            IMyProjector projector = target.Projector;
            IMySlimBlock block     = target.Block;

            if (projector == null || block == null)
            {
                return(false);
            }

            if (projector.CanBuild(block, false) != BuildCheckResult.OK)
            {
                return(false);
            }

            if (MyAPIGateway.Session.CreativeMode)
            {
                projector.Build(block, 0, tool.EntityId, false);
                return(projector.CanBuild(block, true) != BuildCheckResult.OK);
            }

            //try to remove the first component from inventory
            string name = ((MyCubeBlockDefinition)block.BlockDefinition).Components[0].Definition.Id.SubtypeName;

            if (_tmpInventory.PullAny(item.ConnectedCargo, name, 2))
            {
                _tmpInventory.Clear();
                projector.Build(block, 0, tool.EntityId, false);
                return(projector.CanBuild(block, true) != BuildCheckResult.OK);
            }

            return(false);
        }
Exemple #2
0
 private void Start()
 {
     blockTarget    = this.gameObject.GetComponent <BlockTarget>();
     blockGenerator = this.gameObject.GetComponent <BlockGenerator>();
     blockSlider    = this.gameObject.GetComponent <BlockSlider>();
     resetCheck     = blockGenerator.GenerateBlockSet(true);
     itemDoCount    = itemSuCount = totalHit = totalMiss = 0;
     SoundManager.Instance.PlayBGM(SoundManager.Instance.bgm_Play);
 }
Exemple #3
0
 void OnDoMoveComplete()
 {
     if (m_raycastHit.transform == null) //Nếu khối đã vỡ
     {
         FlyInDirection(m_directFly);    //bay tiếp theo hướng cũ
     }
     else
     {
         if (m_raycastHit.transform.tag == "Wall Bottom") //Nếu đã chạm xuống sàn
         {
             FinishFly();
         }
         else
         {
             if (m_raycastHit.transform.tag == "Block Target")
             {
                 BlockTarget blockTarget = m_raycastHit.transform.GetComponent <BlockTarget>();
                 blockTarget.TakeDamage(m_damage);
             }
             FlyInDirection(Vector3.Reflect(m_directFly, m_raycastHit.normal));
         }
     }
 }
        private bool StepWeld(ShipyardItem shipyardItem)
        {
            var targetsToRemove = new HashSet <BlockTarget>();
            var targetsToRedraw = new HashSet <BlockTarget>();

            //we need to multiply this by MyShipWelder.WELDER_AMOUNT_PER_SECOND / 2, which also evaluates to 1
            float weldAmount = MyAPIGateway.Session.WelderSpeedMultiplier * shipyardItem.Settings.WeldMultiplier;
            float boneAmount = weldAmount * .1f;

            if (shipyardItem.TargetBlocks.Count == 0)
            {
                var sortBlock = Profiler.Start(FullName, nameof(StepWeld), "Sort Targets");
                shipyardItem.TargetBlocks.Clear();
                shipyardItem.ProxDict.Clear();
                //precalculate all the BlockTarget for our target grids to speed things up
                var gridTargets = new Dictionary <long, List <BlockTarget> >();
                foreach (IMyCubeGrid targetGrid in shipyardItem.YardGrids)
                {
                    if (targetGrid.Closed || targetGrid.MarkedForClose)
                    {
                        continue;
                    }

                    var tmpBlocks = new List <IMySlimBlock>();
                    targetGrid.GetBlocks(tmpBlocks);

                    gridTargets.Add(targetGrid.EntityId, new List <BlockTarget>(tmpBlocks.Count));
                    foreach (IMySlimBlock block in tmpBlocks.ToArray())
                    {
                        if (block == null || (block.CubeGrid.Physics != null && block.IsFullIntegrity && !block.HasDeformation))
                        {
                            continue;
                        }

                        var target = new BlockTarget(block, shipyardItem);

                        shipyardItem.TargetBlocks.Add(target);

                        gridTargets[targetGrid.EntityId].Add(target);
                    }

                    //Shouldn't be needed as this is handled by the projector logic in BlockTarget

                    //var proj = targetGrid.Projector();
                    //if (proj != null && !shipyardItem.YardGrids.Contains(proj.CubeGrid))
                    //{
                    //    proj.CubeGrid.GetBlocks(tmpBlocks);
                    //    gridTargets.Add(proj.CubeGrid.EntityId, new List<BlockTarget>());
                    //    foreach (var block in tmpBlocks.ToArray())
                    //    {
                    //        if (block == null || (targetGrid.Physics != null && block.IsFullIntegrity && !block.HasDeformation))
                    //            continue;

                    //        var pos = block.GetPosition();
                    //        if (!shipyardItem.ShipyardBox.Contains(ref pos))
                    //            continue;

                    //        var target = new BlockTarget(block, shipyardItem);

                    //        shipyardItem.TargetBlocks.Add(target);
                    //        gridTargets[block.CubeGrid.EntityId].Add(target);
                    //    }
                    //}
                }
                int count = 0;
                foreach (KeyValuePair <long, List <BlockTarget> > entry in gridTargets)
                {
                    count += entry.Value.Count;
                }

                foreach (IMyCubeBlock tool in shipyardItem.Tools)
                {
                    shipyardItem.ProxDict.Add(tool.EntityId, new List <BlockTarget>());
                    //first sort grids by distance to tool
                    shipyardItem.YardGrids.Sort((a, b) =>
                                                Vector3D.DistanceSquared(a.Center(), tool.GetPosition()).CompareTo(
                                                    Vector3D.DistanceSquared(b.Center(), tool.GetPosition())));

                    foreach (IMyCubeGrid grid in shipyardItem.YardGrids)
                    {
                        //then sort blocks by distance to grid center
                        List <BlockTarget> list = gridTargets[grid.EntityId];
                        switch (shipyardItem.Settings.BuildPattern)
                        {
                        case BuildPatternEnum.FromProjector:
                            list.Sort((a, b) => a.ProjectorDist.CompareTo(b.ProjectorDist));
                            break;

                        case BuildPatternEnum.FromCenter:
                            list.Sort((a, b) => a.CenterDist.CompareTo(b.CenterDist));
                            break;

                        case BuildPatternEnum.FromCorners:
                            list.Sort((a, b) => a.ToolDist[tool.EntityId].CompareTo(b.ToolDist[tool.EntityId]));
                            break;

                        default:
                            throw new Exception("Invalid BuildPatternEnum");
                        }
                        shipyardItem.ProxDict[tool.EntityId].AddRange(list);
                    }
                }
                sortBlock.End();
            }

            //nothing to do
            if (shipyardItem.TargetBlocks.Count == 0)
            {
                Logging.Instance.WriteDebug("TargetBlocks 0");
                return(false);
            }

            //assign blocks to our welders
            foreach (IMyCubeBlock welder in shipyardItem.Tools)
            {
                for (int i = 0; i < shipyardItem.Settings.BeamCount; i++)
                {
                    if (shipyardItem.BlocksToProcess[welder.EntityId][i] != null)
                    {
                        continue;
                    }

                    var         toRemove   = new List <BlockTarget>();
                    BlockTarget nextTarget = null;

                    foreach (BlockTarget target in shipyardItem.ProxDict[welder.EntityId])
                    {
                        bool found = false;
                        //each block can only have one laser assigned
                        foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
                        {
                            if (entry.Value.Contains(target))
                            {
                                found = true;
                                break;
                            }
                        }
                        if (found)
                        {
                            toRemove.Add(target);
                            continue;
                        }

                        if (target.Projector != null)
                        {
                            BuildCheckResult res = target.Projector.CanBuild(target.Block, false);
                            if (res == BuildCheckResult.AlreadyBuilt)
                            {
                                target.UpdateAfterBuild();
                            }
                            else if (res != BuildCheckResult.OK)
                            {
                                continue;
                            }
                            else
                            {
                                bool success = false;
                                Utilities.InvokeBlocking(() => success = BuildTarget(target, shipyardItem, welder));
                                Logging.Instance.WriteDebug(success.ToString());
                                if (!success)
                                {
                                    //toRemove.Add(target);
                                    continue;
                                }
                                target.UpdateAfterBuild();
                            }
                        }
                        if (target.CubeGrid.Physics != null && target.Block.IsFullIntegrity && !target.Block.HasDeformation)
                        {
                            toRemove.Add(target);
                            continue;
                        }
                        nextTarget = target;
                        break;
                    }

                    if (nextTarget != null)
                    {
                        targetsToRedraw.Add(nextTarget);
                        shipyardItem.BlocksToProcess[welder.EntityId][i] = nextTarget;
                    }

                    foreach (BlockTarget removeTarget in toRemove)
                    {
                        shipyardItem.ProxDict[welder.EntityId].Remove(removeTarget);
                        shipyardItem.TargetBlocks.Remove(removeTarget);
                    }
                }
            }

            //update lasers
            foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
            {
                for (int i = 0; i < entry.Value.Length; i++)
                {
                    BlockTarget targetBlock = entry.Value[i];

                    if (targetBlock == null || _stalledTargets.Contains(targetBlock))
                    {
                        continue;
                    }

                    if (targetsToRedraw.Contains(targetBlock))
                    {
                        var toolLine = new Communication.ToolLineStruct
                        {
                            ToolId       = entry.Key,
                            GridId       = targetBlock.CubeGrid.EntityId,
                            BlockPos     = targetBlock.GridPosition,
                            PackedColor  = Color.DarkCyan.PackedValue,
                            Pulse        = false,
                            EmitterIndex = (byte)i
                        };

                        Communication.SendLine(toolLine, shipyardItem.ShipyardBox.Center);
                    }
                }
            }

            if (shipyardItem.BlocksToProcess.All(e => e.Value.All(t => t == null)))
            {
                Logging.Instance.WriteDebug("Null thing?");
                return(false);
            }

            shipyardItem.UpdatePowerUse();
            targetsToRedraw.Clear();

            Utilities.InvokeBlocking(() =>
            {
                foreach (IMyCubeBlock welder in shipyardItem.Tools)
                {
                    var tool = (IMyCollector)welder;
                    MyInventory welderInventory = ((MyEntity)tool).GetInventory();
                    int i = 0;
                    foreach (BlockTarget target in shipyardItem.BlocksToProcess[tool.EntityId])
                    {
                        if (target == null)
                        {
                            continue;
                        }

                        if (target.CubeGrid.Physics == null || target.CubeGrid.Closed || target.CubeGrid.MarkedForClose)
                        {
                            targetsToRemove.Add(target);
                            continue;
                        }

                        if (!MyAPIGateway.Session.CreativeMode)
                        {
                            /*
                             * Welding laser "efficiency" is a float between 0-1 where:
                             *   0.0 =>   0% of component stock used for construction (100% loss)
                             *   1.0 => 100% of component stock used for construction (0% loss)
                             *
                             * Efficiency decay/distance formula is the same as above for grinder
                             */
                            double efficiency = 1 - (target.ToolDist[tool.EntityId] / 200000);
                            if (!shipyardItem.StaticYard)
                            {
                                efficiency /= 2;
                            }
                            if (efficiency < 0.1)
                            {
                                efficiency = 0.1;
                            }
                            //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] distance=[{2:F2}m] efficiency=[{3:F5}]", tool.DisplayNameText, i, Math.Sqrt(target.ToolDist[tool.EntityId]), efficiency));

                            /*
                             * We have to factor in our efficiency ratio before transferring to the block "construction stockpile",
                             * but that math isn't nearly as easy as it was with the grinder.
                             *
                             * For each missing component type, we know how many items are "missing" from the construction model, M
                             *
                             * The simplest approach would be to pull M items from the conveyor system (if enabled), then move
                             * (M*efficiency) items to the "construction stockpile" and vaporize the other (M*(1-efficiency)) items.
                             * However, this approach would leave the construction stockpile incomplete and require several iterations
                             * before M items have actually been copied.
                             *
                             * A better solution is to pull enough "extra" items from the conveyors that the welder has enough to
                             * move M items to the construction stockpile even after losses due to distance inefficiency
                             *
                             * For example, if the target block is missing M=9 items and we are running at 0.9 (90%) efficiency,
                             * ideally that means we should pull 10 units, vaporize 1, and still have 9 for construction. However,
                             * if the conveyor system was only able to supply us with 2 components, we should not continue to blindly
                             * vaporize 1 unit.
                             *
                             * Instead, we have to consult the post-conveyor-pull welder inventory to determine if it has at least
                             * the required number of components.  If it does, we vaporize M*(1-efficiency).  Otherwise we only
                             * vaporize current_count*(1-efficiency) and transfer the rest to the construction stockpile
                             */
                            var missingComponents = new Dictionary <string, int>();
                            target.Block.GetMissingComponents(missingComponents);

                            var wasteComponents = new Dictionary <string, int>();
                            foreach (KeyValuePair <string, int> entry in missingComponents)
                            {
                                var componentId            = new MyDefinitionId(typeof(MyObjectBuilder_Component), entry.Key);
                                int missing                = entry.Value;
                                MyFixedPoint totalRequired = (MyFixedPoint)(missing / efficiency);

                                MyFixedPoint currentStock = welderInventory.GetItemAmount(componentId);

                                //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] Component[{2}] missing[{3:F3}] inefficiency requires[{4:F3}] in_stock[{5:F3}]", tool.DisplayNameText, i, entry.Key, missing, totalRequired, currentStock));
                                if (currentStock < totalRequired && tool.UseConveyorSystem)
                                {
                                    // Welder doesn't have totalRequired, so try to pull the difference from conveyors
                                    welderInventory.PullAny(shipyardItem.ConnectedCargo, entry.Key, (int)Math.Ceiling((double)(totalRequired - currentStock)));
                                    currentStock = welderInventory.GetItemAmount(componentId);
                                    //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] Component[{2}] - after conveyor pull - in_stock[{3:F3}]", tool.DisplayNameText, i, entry.Key, currentStock));
                                }

                                // Now compute the number of components to delete
                                // MoveItemsToConstructionPile() below won't move anything if we have less than 1 unit,
                                // so don't bother "losing" anything due to ineffeciency
                                if (currentStock >= 1)
                                {
                                    // The lesser of (missing, currentStock), times (1 minus) our efficiency fraction
                                    MyFixedPoint toDelete = MyFixedPoint.Min(MyFixedPoint.Floor(currentStock), missing) * (MyFixedPoint)(1 - efficiency);
                                    //Logging.Instance.WriteDebug(String.Format("Welder[{0}]block[{1}] Component[{2}] amount lost due to distance [{3:F3}]", tool.DisplayNameText, i, entry.Key, toDelete));
                                    welderInventory.RemoveItemsOfType((int)toDelete, componentId);
                                }
                            }

                            target.Block.MoveItemsToConstructionStockpile(welderInventory);

                            missingComponents.Clear();
                            target.Block.GetMissingComponents(missingComponents);

                            if (missingComponents.Any() && !target.Block.HasDeformation)
                            {
                                if (_stalledTargets.Add(target))
                                {
                                    targetsToRedraw.Add(target);
                                }
                            }
                            else
                            {
                                if (_stalledTargets.Remove(target))
                                {
                                    targetsToRedraw.Add(target);
                                }
                            }

                            target.Block.IncreaseMountLevel(weldAmount, 0, welderInventory, boneAmount, true);
                            if (target.Block.IsFullIntegrity && !target.Block.HasDeformation)
                            {
                                targetsToRemove.Add(target);
                            }
                        }
                        i++;
                    }
                }
            });

            shipyardItem.MissingComponentsDict.Clear();

            foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
            {
                for (int i = 0; i < entry.Value.Length; i++)
                {
                    BlockTarget target = entry.Value[i];

                    if (target == null)
                    {
                        continue;
                    }

                    if (targetsToRemove.Contains(target))
                    {
                        Communication.ClearLine(entry.Key, i);
                        _stalledTargets.Remove(target);
                        shipyardItem.TargetBlocks.Remove(target);
                        entry.Value[i] = null;
                        continue;
                    }

                    if (_stalledTargets.Contains(target))
                    {
                        var blockComponents = new Dictionary <string, int>();
                        target.Block.GetMissingComponents(blockComponents);

                        foreach (KeyValuePair <string, int> component in blockComponents)
                        {
                            if (shipyardItem.MissingComponentsDict.ContainsKey(component.Key))
                            {
                                shipyardItem.MissingComponentsDict[component.Key] += component.Value;
                            }
                            else
                            {
                                shipyardItem.MissingComponentsDict.Add(component.Key, component.Value);
                            }
                        }

                        var toolLine = new Communication.ToolLineStruct
                        {
                            ToolId       = entry.Key,
                            GridId       = target.CubeGrid.EntityId,
                            BlockPos     = target.GridPosition,
                            PackedColor  = Color.Purple.PackedValue,
                            Pulse        = true,
                            EmitterIndex = (byte)i
                        };

                        if (targetsToRedraw.Contains(target))
                        {
                            Communication.ClearLine(entry.Key, i);
                            Communication.SendLine(toolLine, shipyardItem.ShipyardBox.Center);
                        }
                        continue;
                    }
                }
            }

            return(true);
        }
        private void StepGrind(ShipyardItem shipyardItem)
        {
            var targetsToRedraw = new HashSet <BlockTarget>();
            //we need to multiply this by MyShipGrinderConstants.GRINDER_AMOUNT_PER_SECOND / 2... which evaluates to 1
            float grindAmount = MyAPIGateway.Session.GrinderSpeedMultiplier * shipyardItem.Settings.GrindMultiplier;

            if (shipyardItem.TargetBlocks.Count == 0)
            {
                var targetblock = Profiler.Start(FullName, nameof(StepGrind), "Populate target blocks");
                var blocks      = new List <IMySlimBlock>();
                Logging.Instance.WriteLine(shipyardItem.YardGrids.Count.ToString());
                foreach (IMyCubeGrid yardGrid in shipyardItem.YardGrids.Where(g => g.Physics != null)) //don't process projections
                {
                    var tmpBlocks = new List <IMySlimBlock>();
                    yardGrid.GetBlocks(tmpBlocks);
                    blocks.AddRange(tmpBlocks);
                }

                foreach (IMySlimBlock tmpBlock in blocks)
                {
                    shipyardItem.TargetBlocks.Add(new BlockTarget(tmpBlock, shipyardItem));
                }
                targetblock.End();
            }
            List <BlockTarget> allBlocks = shipyardItem.TargetBlocks.ToList();

            if (allBlocks.Count == 0)
            {
                return;
            }

            if (!shipyardItem.ProxDict.Any())
            {
                //sort blocks by distance to each tool
                foreach (IMyCubeBlock tool in shipyardItem.Tools)
                {
                    var targetSortBlock            = Profiler.Start(FullName, nameof(StepGrind), "Sort Targets");
                    List <BlockTarget> sortTargets = allBlocks.ToList();
                    sortTargets.Sort((a, b) => a.ToolDist[tool.EntityId].CompareTo(b.ToolDist[tool.EntityId]));
                    shipyardItem.ProxDict[tool.EntityId] = sortTargets;
                    targetSortBlock.End();
                }
            }

            var targetFindBlock = Profiler.Start(FullName, nameof(StepGrind), "Find Targets");

            foreach (IMyCubeBlock tool in shipyardItem.Tools)
            {
                if (tool.Closed || tool.MarkedForClose)
                {
                    //this is bad
                    shipyardItem.Disable();
                    return;
                }

                BlockTarget[] blockArray = shipyardItem.BlocksToProcess[tool.EntityId];

                //find the next target for each grinder, if it needs one
                for (int i = 0; i < shipyardItem.Settings.BeamCount; i++)
                {
                    var toRemove = new HashSet <BlockTarget>();
                    if (blockArray[i] != null)
                    {
                        continue;
                    }

                    BlockTarget nextTarget = null;

                    for (int b = 0; b < shipyardItem.ProxDict[tool.EntityId].Count; b++)
                    {
                        nextTarget = shipyardItem.ProxDict[tool.EntityId][b];

                        if (nextTarget.CubeGrid.Closed || nextTarget.CubeGrid.MarkedForClose)
                        {
                            continue;
                        }

                        //one grinder per block, please
                        bool found = false;
                        foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
                        {
                            foreach (BlockTarget target in entry.Value)
                            {
                                if (target == null)
                                {
                                    continue;
                                }

                                if (target == nextTarget)
                                {
                                    found = true;
                                    break;
                                }
                            }
                        }

                        if (found)
                        {
                            toRemove.Add(nextTarget);
                            continue;
                        }

                        targetsToRedraw.Add(nextTarget);
                        break;
                    }

                    foreach (BlockTarget removeTarget in toRemove)
                    {
                        shipyardItem.ProxDict[tool.EntityId].Remove(removeTarget);
                        shipyardItem.TargetBlocks.Remove(removeTarget);
                    }

                    //we found a block to pair with our grinder, add it to the dictionary and carry on with destruction
                    if (nextTarget != null)
                    {
                        shipyardItem.BlocksToProcess[tool.EntityId][i] = nextTarget;
                    }
                }
            }
            targetFindBlock.End();
            shipyardItem.UpdatePowerUse();
            var grindActionBlock = Profiler.Start(FullName, nameof(StepGrind), "Grind action");
            var removeTargets    = new List <BlockTarget>();

            //do the grinding
            Utilities.InvokeBlocking(() =>
            {
                foreach (IMyCubeBlock tool in shipyardItem.Tools)
                {
                    for (int b = 0; b < shipyardItem.BlocksToProcess[tool.EntityId].Length; b++)
                    {
                        BlockTarget target = shipyardItem.BlocksToProcess[tool.EntityId][b];
                        if (target == null)
                        {
                            continue;
                        }

                        if (target.CubeGrid.Closed || target.CubeGrid.MarkedForClose)
                        {
                            Logging.Instance.WriteDebug("Error in grind action: Target closed");
                            removeTargets.Add(target);
                            return;
                        }

                        if (targetsToRedraw.Contains(target))
                        {
                            var toolLine = new Communication.ToolLineStruct
                            {
                                ToolId       = tool.EntityId,
                                GridId       = target.CubeGrid.EntityId,
                                BlockPos     = target.GridPosition,
                                PackedColor  = Color.OrangeRed.PackedValue,
                                Pulse        = false,
                                EmitterIndex = (byte)b
                            };

                            Communication.SendLine(toolLine, shipyardItem.ShipyardBox.Center);
                        }

                        /*
                         * Grinding laser "efficiency" is a float between 0-1 where:
                         *   0.0 =>   0% of components recovered
                         *   1.0 => 100% of components recovered
                         *
                         * Efficiency decays exponentially as distance to the target (length of the "laser") increases
                         *     0m => 1.0000
                         *    10m => 0.9995
                         *    25m => 0.9969
                         *    50m => 0.9875
                         *   100m => 0.9500
                         *   150m => 0.8875
                         *   250m => 0.6875
                         *   400m => 0.2000
                         *    inf => 0.1000
                         * We impose a minimum efficiency of 0.1 (10%), which happens at distances > ~450m
                         */
                        double efficiency = 1 - (target.ToolDist[tool.EntityId] / 200000);
                        if (!shipyardItem.StaticYard)
                        {
                            efficiency /= 2;
                        }
                        if (efficiency < 0.1)
                        {
                            efficiency = 0.1;
                        }
                        //Logging.Instance.WriteDebug(String.Format("Grinder[{0}]block[{1}] distance=[{2:F2}m] efficiency=[{3:F5}]", tool.DisplayNameText, b, Math.Sqrt(target.ToolDist[tool.EntityId]), efficiency));

                        if (!shipyardItem.YardGrids.Contains(target.CubeGrid))
                        {
                            //we missed this grid or its split at some point, so add it to the list and register the split event
                            shipyardItem.YardGrids.Add(target.CubeGrid);
                            ((MyCubeGrid)target.CubeGrid).OnGridSplit += shipyardItem.OnGridSplit;
                        }
                        MyInventory grinderInventory = ((MyEntity)tool).GetInventory();

                        if (!target.Block.IsFullyDismounted)
                        {
                            var decreaseBlock = Profiler.Start(FullName, nameof(StepGrind), "DecreaseMountLevel");
                            target.Block.DecreaseMountLevel(grindAmount, grinderInventory);
                            decreaseBlock.End();

                            var inventoryBlock = Profiler.Start(FullName, nameof(StepGrind), "Grind Inventory");
                            // First move everything into _tmpInventory
                            target.Block.MoveItemsFromConstructionStockpile(_tmpInventory);

                            // Then move items into grinder inventory, factoring in our efficiency ratio
                            foreach (MyPhysicalInventoryItem item in _tmpInventory.GetItems())
                            {
                                //Logging.Instance.WriteDebug(String.Format("Grinder[{0}]block[{1}] Item[{2}] grind_amt[{3:F2}] collect_amt[{4:F2}]", tool.DisplayNameText, b, item.Content.SubtypeName, item.Amount, (double)item.Amount*efficiency));
                                grinderInventory.Add(item, (int)Math.Round((double)item.Amount * efficiency));
                            }

                            // Then clear out everything left in _tmpInventory
                            _tmpInventory.Clear();
                            inventoryBlock.End();
                        }

                        // This isn't an <else> clause because target.Block may have become FullyDismounted above,
                        // in which case we need to run both code blocks
                        if (target.Block.IsFullyDismounted)
                        {
                            var dismountBlock = Profiler.Start(FullName, nameof(StepGrind), "FullyDismounted");
                            var tmpItemList   = new List <MyPhysicalInventoryItem>();
                            var blockEntity   = target.Block.FatBlock as MyEntity;
                            if (blockEntity != null && blockEntity.HasInventory)
                            {
                                var dismountInventory = Profiler.Start(FullName, nameof(StepGrind), "DismountInventory");
                                for (int i = 0; i < blockEntity.InventoryCount; ++i)
                                {
                                    MyInventory blockInventory = blockEntity.GetInventory(i);
                                    if (blockInventory == null)
                                    {
                                        continue;
                                    }

                                    if (blockInventory.Empty())
                                    {
                                        continue;
                                    }

                                    tmpItemList.Clear();
                                    tmpItemList.AddRange(blockInventory.GetItems());

                                    foreach (MyPhysicalInventoryItem item in tmpItemList)
                                    {
                                        //Logging.Instance.WriteDebug(String.Format("Grinder[{0}]block[{1}] Item[{2}] inventory[{3:F2}] collected[{4:F2}]", tool.DisplayNameText, b, item.Content.SubtypeName, item.Amount, (double)item.Amount * efficiency));
                                        blockInventory.Remove(item, item.Amount);
                                        grinderInventory.Add(item, (int)Math.Round((double)item.Amount * efficiency));
                                    }
                                }
                                dismountInventory.End();
                            }
                            target.Block.SpawnConstructionStockpile();
                            target.CubeGrid.RazeBlock(target.GridPosition);
                            removeTargets.Add(target);
                            shipyardItem.TargetBlocks.Remove(target);
                            dismountBlock.End();
                        }
                    }
                }
            });

            foreach (KeyValuePair <long, List <BlockTarget> > entry in shipyardItem.ProxDict)
            {
                foreach (BlockTarget removeBlock in removeTargets)
                {
                    entry.Value.Remove(removeBlock);
                }
            }

            foreach (BlockTarget removeBlock in removeTargets)
            {
                shipyardItem.TargetBlocks.Remove(removeBlock);
            }

            //shipyardItem.ActiveTargets = 0;
            //clear lines for any destroyed blocks and update our target count
            foreach (KeyValuePair <long, BlockTarget[]> entry in shipyardItem.BlocksToProcess)
            {
                for (int i = 0; i < entry.Value.Length; i++)
                {
                    BlockTarget removeBlock = entry.Value[i];

                    if (removeTargets.Contains(removeBlock))
                    {
                        Communication.ClearLine(entry.Key, i);
                        entry.Value[i] = null;
                    }

                    //if (!removeTargets.Contains(removeBlock) && removeBlock != null)
                    //{
                    //    shipyardItem.ActiveTargets++;
                    //}
                }
            }

            grindActionBlock.End();
        }
 public void InitDisplay(BlockTarget t)
 {
     curTarget = t;
     w.text    = t.width + "";
     h.text    = t.height + "";
 }