public void ClearLines()
 {
     foreach (var tool in Tools)
     {
         Communication.MessageStruct message = new Communication.MessageStruct()
         {
             toolId      = tool.EntityId,
             gridId      = 0,
             blockPos    = new SerializableVector3I(0, 0, 0),
             packedColor = 0,
             pulse       = false
         };
         Communication.SendLine(message);
     }
 }
Beispiel #2
0
        private static void StepGrind(ShipyardItem shipyardItem)
        {
            var            random           = new Random();
            float          grindAmount      = Server.Instance.Config.GrinderSpeedMultiplier * PluginSettings.Instance.GrindMultiplier;
            HashSet <long> grindersToRemove = new HashSet <long>();
            //shorten this to grid for convenience
            MyCubeGrid  grid       = shipyardItem.Grid;
            List <Task> blockTasks = new List <Task>();

            if (grid?.Physics == null || grid.Closed)
            {
                return;
            }

            if (grid.BlocksCount < 1)
            {
                return;
            }

            //do a raycast to see if the grinder can see the block we're assigning to it
            foreach (IMyCubeBlock listGrinder in shipyardItem.Tools)
            {
                blockTasks.Add(Task.Run(() =>
                {
                    DisconnectHelper localDisconnect = new DisconnectHelper();
                    MySlimBlock nextBlock;
                    if (!shipyardItem.ProcessBlocks.TryGetValue(listGrinder.EntityId, out nextBlock))
                    {
                        var tryCount = 0;

                        //TODO: optimize the try count instead of picking an arbitrary value
                        //what the hell does that mean?
                        while (tryCount < 30)
                        {
                            if (grid.Physics.LinearVelocity != Vector3D.Zero || grid.Physics.AngularVelocity != Vector3D.Zero)
                            {
                                grid.Stop();
                            }

                            //limit the number of tries so we don't get stuck in a loop forever
                            tryCount++;

                            //pick a random block. we don't really care if two grinders hit the same block, so don't check
                            if (grid.BlocksCount > 30)
                            {
                                nextBlock = grid.CubeBlocks.ElementAt(random.Next(0, grid.BlocksCount - 1));
                            }

                            //if we have less than 30 blocks total, just iterate through them, it's faster than going at random
                            else
                            {
                                nextBlock = grid.CubeBlocks.ElementAt(Math.Min(tryCount, grid.BlocksCount - 1));
                            }
                            if (nextBlock == null)
                            {
                                continue;
                            }

                            if (shipyardItem.ProcessBlocks.ContainsValue(nextBlock))
                            {
                                continue;
                            }

                            //this raycast should give us the grid location of the first block it hits
                            //we don't really care if it hits our random block, just grab whatever the grinder sees first
                            Vector3I?blockResult = grid.RayCastBlocks(listGrinder.GetPosition(),
                                                                      grid.GridIntegerToWorld(nextBlock.Position));
                            if (!blockResult.HasValue)
                            {
                                continue;
                            }

                            //TODO: remove this when my PR is merged
                            //check if removing this block will split the grid
                            if (localDisconnect.TryDisconnect(grid.GetCubeBlock(blockResult.Value)))
                            {
                                //UtilityPlugin.Log.Info( "detected split" );
                                continue;
                            }

                            nextBlock = grid.GetCubeBlock(blockResult.Value);

                            break;
                        }

                        //we weren't able to find a suitable block somehow, so skip this grinder for now
                        if (nextBlock == null)
                        {
                            return;
                        }

                        //we found a block to pair with our grinder, add it to the dictionary and carry on with destruction
                        lock (shipyardItem.ProcessBlocks)
                        {
                            shipyardItem.ProcessBlocks.Add(listGrinder.EntityId, nextBlock);
                        }
                    }
                }));
                if (blockTasks.Count >= 2)
                {
                }
            }
            Task.WaitAll(blockTasks.ToArray());
            blockTasks.Clear();
            var tmpItemList = new List <MyPhysicalInventoryItem>();

            foreach (IMyCubeBlock grinderBlock in shipyardItem.Tools)
            {
                var grinder = (IMyShipGrinder)grinderBlock;

                var         grinderInventory = (MyInventory)grinder.GetInventory(0);
                MySlimBlock block;

                if (!shipyardItem.ProcessBlocks.TryGetValue(grinderBlock.EntityId, out block))
                {
                    continue;
                }

                if (block?.CubeGrid?.Physics == null)
                {
                    continue;
                }

                if (disconnect.TryDisconnect(block))
                {
                    //UtilityPlugin.Log.Info( "detected split at grind" );
                    shipyardItem.ProcessBlocks.Remove(grinderBlock.EntityId);
                    continue;
                }

                Wrapper.GameAction(() =>
                {
                    var damageInfo = new MyDamageInformation(false, grindAmount, MyDamageType.Grind,
                                                             grinder.EntityId);
                    if (block.UseDamageSystem)
                    {
                        MyDamageSystem.Static.RaiseBeforeDamageApplied(block, ref damageInfo);
                    }

                    block.DecreaseMountLevel(damageInfo.Amount, grinderInventory);
                    block.MoveItemsFromConstructionStockpile(grinderInventory);
                    if (block.UseDamageSystem)
                    {
                        MyDamageSystem.Static.RaiseAfterDamageApplied(block, damageInfo);
                    }

                    if (block.IsFullyDismounted)
                    {
                        if (block.FatBlock != null && block.FatBlock.HasInventory)
                        {
                            for (var i = 0; i < block.FatBlock.InventoryCount; ++i)
                            {
                                MyInventory blockInventory = block.FatBlock.GetInventory(i);
                                if (blockInventory == null)
                                {
                                    continue;
                                }

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

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

                                foreach (MyPhysicalInventoryItem item in tmpItemList)
                                {
                                    MyInventory.Transfer(blockInventory, grinderInventory, item.ItemId);
                                }
                            }
                        }

                        if (block.UseDamageSystem)
                        {
                            MyDamageSystem.Static.RaiseDestroyed(block, damageInfo);
                        }

                        block.SpawnConstructionStockpile();
                        block.CubeGrid.RazeBlock(block.Min);
                        grindersToRemove.Add(grinderBlock.EntityId);
                    }
                });
                foreach (var tool in shipyardItem.Tools)
                {
                    MySlimBlock targetBlock;
                    Communication.MessageStruct message = new Communication.MessageStruct()
                    {
                        toolId      = tool.EntityId,
                        gridId      = 0,
                        blockPos    = new SerializableVector3I(0, 0, 0),
                        packedColor = 0,
                        pulse       = false
                    };
                    if (!shipyardItem.ProcessBlocks.TryGetValue(tool.EntityId, out targetBlock))
                    {
                        Communication.SendLine(message);
                        continue;
                    }
                    message.gridId      = targetBlock.CubeGrid.EntityId;
                    message.blockPos    = targetBlock.Position;
                    message.packedColor = Color.OrangeRed.PackedValue;
                    Communication.SendLine(message);
                }

                foreach (long removeId in grindersToRemove)
                {
                    shipyardItem.ProcessBlocks.Remove(removeId);
                }
            }
        }
Beispiel #3
0
        private static bool StepWeld(ShipyardItem shipyardItem)
        {
            HashSet <long> stalledWelders    = new HashSet <long>();
            var            missingComponents = new Dictionary <string, int>();
            var            random            = new Random();
            float          weldAmount        = Server.Instance.Config.WelderSpeedMultiplier * PluginSettings.Instance.WeldMultiplier;
            float          boneAmount        = weldAmount * .1f;
            //shorten this to grid for convenience
            MyCubeGrid grid = shipyardItem.Grid;

            if (grid?.Physics == null || grid.Closed)
            {
                return(false);
            }

            var weldBlocks = new HashSet <MySlimBlock>();

            foreach (MySlimBlock block in grid.CubeBlocks.Where(block => !block.IsFullIntegrity || (block.HasDeformation || block.MaxDeformation > 0.0001f)))
            {
                weldBlocks.Add(block);
            }

            //if we have no blocks to weld, return false so we know we're done
            if (weldBlocks.Count == 0)
            {
                if (shipyardItem.GridProjector == null)
                {
                    foreach (var block in shipyardItem.Grid.GetFatBlocks())
                    {
                        MyProjectorBase projector = block as MyProjectorBase;

                        if (projector?.Clipboard.PreviewGrids.Count > 0)
                        {
                            /*
                             * bool canBuild = false;
                             * Wrapper.GameAction( () => canBuild = projector.Clipboard.PreviewGrids[0].CubeBlocks.All(x => projector.CanBuild(x, true) != MyProjectorBase.BuildCheckResult.OK));
                             * if ( !canBuild)
                             *  continue;
                             */
                            shipyardItem.GridProjector = projector;
                            break;
                        }
                    }
                }
            }
            if (weldBlocks.Count < 8 && shipyardItem.GridProjector?.Clipboard.PreviewGrids.Count > 0)
            {
                int neededBlocks = 8 - weldBlocks.Count;
                //shipyardItem.ProcessBlocks.Clear();
                for (int b = 0; b < neededBlocks; b++)
                {
                    var         welder        = shipyardItem.Tools[b];
                    var         projector     = shipyardItem.GridProjector;
                    var         projectedGrid = projector.Clipboard.PreviewGrids[0];
                    MySlimBlock buildBlock    = null;

                    Wrapper.GameAction(() =>
                    {
                        //buildBlock = projectedGrid.CubeBlocks.First( x => projector.CanBuild( x, true ) == MyProjectorBase.BuildCheckResult.OK );
                        foreach (var block in projectedGrid.CubeBlocks)
                        {
                            if (projector.CanBuild(block, true) == MyProjectorBase.BuildCheckResult.OK)
                            {
                                buildBlock = block;
                                break;
                            }
                        }
                        if (buildBlock == null)
                        {
                            return;
                        }
                        var welderInventory = (MyInventory)((IMyShipWelder)welder).GetInventory(0);
                        var components      = buildBlock.BlockDefinition.Components;
                        if (components == null || components.Length == 0)
                        {
                            return;
                        }
                        var componentId = components[0].Definition.Id;
                        MyGridConveyorSystem.ItemPullRequest((IMyConveyorEndpointBlock)welder, welderInventory, welder.OwnerId, componentId, 1);


                        if (welderInventory.ContainItems(1, buildBlock.BlockDefinition.Components[0].Definition.Id))
                        {
                            projector.Build(buildBlock, welder.OwnerId, welder.EntityId);
                        }
                    });

                    /*
                     *  Communication.MessageStruct message = new Communication.MessageStruct()
                     *  {
                     *      toolId=welder.EntityId,
                     *      gridId=buildBlock.CubeGrid.EntityId,
                     *      blockPos=buildBlock.Position,
                     *      packedColor = Color.LightGreen.PackedValue,
                     *      pulse=false
                     *  };
                     *  Communication.SendLine( message );
                     */
                    //if (buildBlock!=null)
                    //weldBlocks.Add( buildBlock );
                }
            }
            if (shipyardItem.GridProjector?.Clipboard.PreviewGrids.Count == 0)
            {
                shipyardItem.GridProjector = null;
                return(false);
            }

            foreach (IMyCubeBlock welder in shipyardItem.Tools)
            {
                if (!shipyardItem.ProcessBlocks.ContainsKey(welder.EntityId))
                {
                    MySlimBlock nextBlock = null;
                    var         tryCount  = 0;

                    while (tryCount < 20)
                    {
                        //limit the number of tries so we don't get stuck in a loop forever
                        tryCount++;

                        //pick a random block. we don't really care if two welders hit the same block, so don't check
                        if (weldBlocks.Count > 1)
                        {
                            nextBlock = weldBlocks.ElementAt(random.Next(0, weldBlocks.Count - 1));
                        }
                        else
                        {
                            nextBlock = weldBlocks.FirstElement();
                        }

                        if (nextBlock == null)
                        {
                            continue;
                        }

                        if (!nextBlock.IsFullIntegrity || (nextBlock.HasDeformation || nextBlock.MaxDeformation > 0.0001f))
                        {
                            break;
                        }
                    }

                    //we weren't able to find a suitable block somehow, so skip this welder for now
                    if (nextBlock == null)
                    {
                        continue;
                    }

                    //we found a block to pair with our welder, add it to the dictionary and carry on with destruction
                    shipyardItem.ProcessBlocks.Add(welder.EntityId, nextBlock);
                }
            }

            if (shipyardItem.ProcessBlocks.Count < 1)
            {
                //No more blocks to weld
                return(false);
            }

            Wrapper.GameAction(() =>
            {
                foreach (IMyCubeBlock welderBlock in shipyardItem.Tools)
                {
                    var welder          = (IMyShipWelder)welderBlock;
                    var welderInventory = (MyInventory)welder.GetInventory(0);
                    MySlimBlock block;

                    shipyardItem.ProcessBlocks.TryGetValue(welderBlock.EntityId, out block);
                    if (block?.CubeGrid?.Physics == null)
                    {
                        continue;
                    }

                    if (!(!block.IsFullIntegrity || (block.HasDeformation || block.MaxDeformation > 0.0001f)))
                    {
                        shipyardItem.ProcessBlocks.Remove(welder.EntityId);
                        continue;
                    }

                    block.GetMissingComponents(missingComponents);

                    foreach (KeyValuePair <string, int> component in missingComponents)
                    {
                        var componentId = new MyDefinitionId(typeof(MyObjectBuilder_Component), component.Key);
                        int amount      = Math.Max(component.Value - (int)welderInventory.GetItemAmount(componentId), 0);
                        if (amount == 0)
                        {
                            continue;
                        }

                        if (welder.UseConveyorSystem)
                        {
                            MyGridConveyorSystem.ItemPullRequest((IMyConveyorEndpointBlock)welder, welderInventory,
                                                                 welder.OwnerId, componentId, component.Value);
                        }
                    }

                    block.MoveItemsToConstructionStockpile((MyInventory)welder.GetInventory(0));
                    block.IncreaseMountLevel(weldAmount, 0, null, boneAmount, true);

                    if (!block.CanContinueBuild((MyInventory)welder.GetInventory(0)) && !block.IsFullIntegrity)
                    {
                        stalledWelders.Add(welder.EntityId);
                    }
                }
            });

            foreach (var tool in shipyardItem.Tools)
            {
                MySlimBlock targetBlock;
                Communication.MessageStruct message = new Communication.MessageStruct()
                {
                    toolId      = tool.EntityId,
                    gridId      = 0,
                    blockPos    = new SerializableVector3I(),
                    packedColor = 0
                };
                if (!shipyardItem.ProcessBlocks.TryGetValue(tool.EntityId, out targetBlock))
                {
                    Communication.SendLine(message);
                    continue;
                }

                message.gridId   = targetBlock.CubeGrid.EntityId;
                message.blockPos = targetBlock.Position;

                if (stalledWelders.Contains(tool.EntityId))
                {
                    message.packedColor = Color.Purple.PackedValue;
                    message.pulse       = true;
                }
                else
                {
                    message.packedColor = Color.DarkCyan.PackedValue;
                    message.pulse       = false;
                }

                Communication.SendLine(message);
            }

            return(true);
        }