Exemple #1
0
        void Place(IMySlimBlock Block)
        {
            if (!Block.IsProjectable())
            {
                return;
            }
            var FirstItem = ((MyCubeBlockDefinition)Block.BlockDefinition).Components[0].Definition.Id;

            if (MyAPIGateway.Session.CreativeMode || ToolCargo.PullAny(OnboardInventoryOwners, FirstItem.SubtypeName, 1))
            {
                var Projector = ((Block.CubeGrid as MyCubeGrid).Projector as IMyProjector);
                Projector.Build(Block, 0, Tool.EntityId, false);
                ToolCargo.RemoveItemsOfType(1, FirstItem);
            }
            else
            {
                UnbuiltBlocks.Add(Block);
                SessionCore.DebugWrite($"{Tool.CustomName}.Place()", $"Tool can't pull the component {FirstItem.SubtypeName}!", IsExcessive: false);
            }
        }
        void Weld(List <IMySlimBlock> Blocks, int ticks = 1)
        {
            var Welder = Tool as IMyShipWelder;

            if (Welder == null)
            {
                return;
            }
            Blocks = Blocks.Where(x => x.IsWeldable() || x.IsProjectable()).ToList();
            if (Blocks.Count == 0)
            {
                return;
            }
            if (DistanceMode)
            {
                Blocks = Blocks.OrderByDescending(x => Vector3D.DistanceSquared(x.GetPosition(), Tool.GetPosition())).ToList();
            }
            float SpeedRatio   = WelderSpeed / (DistanceMode ? 1 : Blocks.Count) * ticks;
            float BoneFixSpeed = WelderBoneRepairSpeed * ticks;
            var   Missing      = Blocks.ReadMissingComponents();
            bool  Pull         = Tool.UseConveyorSystem ? ToolCargo.PullAny(OnboardInventoryOwners, Missing) : false;

            Missing.Clear();
            HashSet <IMySlimBlock> UnbuiltBlocks = new HashSet <IMySlimBlock>();

            foreach (IMySlimBlock Block in Blocks)
            {
                if (Block.CubeGrid.Physics?.Enabled == true)
                {
                    if (Block.CanContinueBuild(ToolCargo) || Block.HasDeformation)
                    {
                        Block.MoveItemsToConstructionStockpile(ToolCargo);
                        Block.IncreaseMountLevel(SpeedRatio, Welder.OwnerId, ToolCargo, BoneFixSpeed, false);
                    }
                    else
                    {
                        UnbuiltBlocks.Add(Block);
                    }
                }
                else
                {
                    try
                    {
                        var FirstItem = ((MyCubeBlockDefinition)Block.BlockDefinition).Components[0].Definition.Id;
                        if (ToolCargo.PullAny(OnboardInventoryOwners, FirstItem.SubtypeName, 1))
                        {
                            try
                            {
                                var Projector = ((Block.CubeGrid as MyCubeGrid).Projector as IMyProjector);
                                Projector.Build(Block, 0, Tool.EntityId, false);
                            }
                            catch (Exception Scrap)
                            {
                                SessionCore.LogError(Tool.CustomName + ".WeldProjectorBlock.Build", Scrap);
                            }
                            ToolCargo.RemoveItemsOfType(1, FirstItem);
                        }
                    }
                    catch (Exception Scrap)
                    {
                        SessionCore.LogError(Tool.CustomName + ".WeldProjectorBlockStart", Scrap);
                    }
                }
                if (DistanceMode)
                {
                    break;
                }
            }
            PrintMissing(UnbuiltBlocks);
        }
        IEnumerator <bool> WeldAndPlaceBlocks(ICollection <IMySlimBlock> RealBlocks, ICollection <IMySlimBlock> ProjectedBlocks)
        {
            if (RealBlocks == null || ProjectedBlocks == null)
            {
                yield return(false);
            }
            if (RealBlocks.Count == 0 && ProjectedBlocks.Count == 0)
            {
                yield return(false);
            }
            if (MyKernel.TermControls.ToolMode == false)
            {
                yield return(false);
            }
            if (!SafeZonesHelper.IsActionAllowed(MyKernel.Block.GetPosition(), MySafeZoneAction.Welding | MySafeZoneAction.Building, MyKernel.Block.EntityId))
            {
                yield return(false);
            }

            bool ShouldContinue = RealBlocks.Count > 0 || ProjectedBlocks.Count > 0;

            //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Entry Point: real blocks: {RealBlocks.Count}, projected blocks: {ProjectedBlocks.Count}, should continue: {ShouldContinue}");

            if (!ShouldContinue)
            {
                yield return(false);
            }

            if (MyKernel.TermControls.DistanceMode && RealBlocks.Count > 0)
            {
                IMySlimBlock FarthestBlock = RealBlocks.OrderBy(x => Vector3D.DistanceSquared(x.CubeGrid.GridIntegerToWorld(x.Position), MyKernel.Block.GetPosition())).Last();
                RealBlocks.Clear();
                RealBlocks.Add(FarthestBlock);
                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Selected block for distance mode");
            }

            float        SpeedRatio   = NominalWorkingFrequency * MyKernel.TermControls.SpeedMultiplier * WeldGrindSpeedMultiplier * (VanillaToolConstants.WelderSpeed / RealBlocks.Count);
            float        BoneFixSpeed = VanillaToolConstants.WelderBoneRepairSpeed * NominalWorkingFrequency;
            IMyProjector Projector    = null;

            if (ProjectedBlocks.Count > 0)
            {
                Projector = ((ProjectedBlocks.First().CubeGrid as MyCubeGrid).Projector as IMyProjector);
            }

            //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Checked for projectors");

            if (!MyAPIGateway.Session.CreativeMode)
            {
                Dictionary <string, int> RequiredComponentNames = new Dictionary <string, int>();

                {
                    Action worker = () =>
                    {
                        foreach (IMySlimBlock Block in RealBlocks)
                        {
                            Block.GetMissingComponents(RequiredComponentNames);
                        }
                    };
                    bool   completed = false;
                    Action callback  = () => completed = true;
                    MyAPIGateway.Parallel.StartBackground(worker, callback);
                    while (!completed)
                    {
                        yield return(true);
                    }
                }

                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Got missing components");

                foreach (IMySlimBlock Block in ProjectedBlocks)
                {
                    var FirstItem = ((MyCubeBlockDefinition)Block.BlockDefinition).Components[0].Definition.Id;
                    if (RequiredComponentNames.ContainsKey(FirstItem.SubtypeName))
                    {
                        RequiredComponentNames[FirstItem.SubtypeName] += 1;
                    }
                    else
                    {
                        RequiredComponentNames.Add(FirstItem.SubtypeName, 1);
                    }
                }

                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Got missing components for projected blocks");

                Dictionary <MyItemType, float> RequiredComponents = new Dictionary <MyItemType, float>();
                var list = RequiredComponentNames.ToList();

                foreach (KeyValuePair <string, int> kvp in list)
                {
                    //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Trying to generate itemtype...");
                    //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"for {kvp.Key}");
                    MyItemType itemtype = new MyItemType("MyObjectBuilder_Component", kvp.Key);
                    //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Generated item value");
                    //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"(item: {itemtype.SubtypeId}, amount: {kvp.Value})");
                    RequiredComponents.Add(itemtype, kvp.Value);
                }

                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Reassembled missing dictionary");

                List <IMyTerminalBlock> InventoryOwners = new List <IMyTerminalBlock>(MyKernel.Inventory.InventoryOwners);
                InventoryOwners.Add(MyKernel.Tool);

                InventoryModule.CalculateMissingItems(RequiredComponents, MyKernel.Inventory.GetAggregateItemsFor(InventoryOwners));

                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Calculated aggregate missing components");

                if (MyKernel.Tool.UseConveyorSystem)
                {
                    Dictionary <MyItemType, float> _RqComponents = new Dictionary <MyItemType, float>(RequiredComponents);
                    foreach (var RequiredComponent in RequiredComponents)
                    {
                        float pulledAmount = MyKernel.Inventory.TryTransferTo(ToolCargo, RequiredComponent.Key, RequiredComponent.Value, InventoryOwners);
                        _RqComponents[RequiredComponent.Key] -= pulledAmount;
                    }
                    RequiredComponents = _RqComponents;
                    //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Pulled missing components");
                }

                MyKernel.ResponderModule.UpdateMissing(RequiredComponents);

                yield return(true);

                int weldedBlocks = 0;
                List <IMySlimBlock> UnweldedBlocks = new List <IMySlimBlock>();
                foreach (IMySlimBlock Block in RealBlocks)
                {
                    if (Block.CanContinueBuild(ToolCargo) || Block.HasDeformation)
                    {
                        if (MyKernel.Session.Settings.AllowAsyncWelding)
                        {
                            if (CanWeldInAsyncMode(Block))
                            {
                                MyAPIGateway.Parallel.StartBackground(() => Weld(Block, SpeedRatio, BoneFixSpeed));
                            }
                            else
                            {
                                Weld(Block, SpeedRatio, BoneFixSpeed);
                            }
                        }
                        else
                        {
                            Weld(Block, SpeedRatio, BoneFixSpeed);
                        }
                        weldedBlocks++;
                        if (!MyKernel.Session.Settings.AllowAsyncWelding && weldedBlocks != RealBlocks.Count - 1)
                        {
                            yield return(true);
                        }
                    }
                    else
                    {
                        UnweldedBlocks.Add(Block);
                    }
                }

                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Welded real blocks");

                if (weldedBlocks > 0)
                {
                    yield return(true);
                }

                int placedBlocks = 0;
                List <IMySlimBlock> NonplacedBlocksByLimit     = new List <IMySlimBlock>();
                List <IMySlimBlock> NonplacedBlocksByResources = new List <IMySlimBlock>();
                List <IMySlimBlock> PlaceableProjectedBlocks   = new List <IMySlimBlock>();

                foreach (IMySlimBlock Block in ProjectedBlocks)
                {
                    MyCubeBlockDefinition blockDef = Block.BlockDefinition as MyCubeBlockDefinition;
                    if (MyKernel.Tool.IsWithinWorldLimits(Projector, blockDef.BlockPairName, blockDef.PCU))
                    {
                        var FirstItem = blockDef.Components[0].Definition.Id;
                        if (ToolCargo.GetItemAmount(FirstItem) >= 1)
                        {
                            PlaceableProjectedBlocks.Add(Block);
                        }
                        else
                        {
                            NonplacedBlocksByResources.Add(Block);
                        }
                    }
                    else
                    {
                        NonplacedBlocksByLimit.Add(Block);
                    }
                }

                foreach (IMySlimBlock Block in PlaceableProjectedBlocks)
                {
                    var FirstItem = ((MyCubeBlockDefinition)Block.BlockDefinition).Components[0].Definition.Id;
                    Projector.Build(Block, MyKernel.Tool.OwnerId, MyKernel.Tool.EntityId, false);
                    ToolCargo.RemoveItemsOfType(1, FirstItem);
                    placedBlocks++;
                    if (placedBlocks != ProjectedBlocks.Count - 1)
                    {
                        yield return(true);
                    }
                }

                if (UnweldedBlocks.Count > 0)
                {
                    StringBuilder UnweldedReport = new StringBuilder();
                    UnweldedReport.AppendLine($"Failed to weld {UnweldedBlocks.Count} blocks:");
                    List <IGrouping <MyObjectBuilderType, IMySlimBlock> > unweldedByType = UnweldedBlocks.GroupBy(x => x.BlockDefinition.Id.TypeId).ToList();
                    foreach (IGrouping <MyObjectBuilderType, IMySlimBlock> grouping in unweldedByType)
                    {
                        UnweldedReport.AppendLine($"{grouping.Key.ToString().Replace("MyObjectBuilder_", "")} ({grouping.Count()})");
                    }

                    if (NonplacedBlocksByLimit.Count > 0 || NonplacedBlocksByResources.Count > 0)
                    {
                        UnweldedReport.AppendLine();
                    }

                    MyKernel.ResponderModule.UpdateStatusReport(UnweldedReport, append: true);
                }

                if (NonplacedBlocksByLimit.Count > 0)
                {
                    StringBuilder NonplacedReport = new StringBuilder();
                    NonplacedReport.AppendLine($"Failed to place {UnweldedBlocks.Count} blocks,");
                    NonplacedReport.AppendLine($"reached the PCU/block limit:");
                    List <IGrouping <MyObjectBuilderType, IMySlimBlock> > unplacedByType = UnweldedBlocks.GroupBy(x => x.BlockDefinition.Id.TypeId).ToList();
                    foreach (IGrouping <MyObjectBuilderType, IMySlimBlock> grouping in unplacedByType)
                    {
                        NonplacedReport.AppendLine($"{grouping.Key.ToString().Replace("MyObjectBuilder_", "")} ({grouping.Count()})");
                    }

                    MyKernel.ResponderModule.UpdateStatusReport(NonplacedReport, append: true);
                }

                if (NonplacedBlocksByResources.Count > 0)
                {
                    StringBuilder NonplacedReport = new StringBuilder();
                    NonplacedReport.AppendLine($"Failed to place {UnweldedBlocks.Count} blocks,");
                    NonplacedReport.AppendLine($"out of resources:");
                    List <IGrouping <MyObjectBuilderType, IMySlimBlock> > unplacedByType = UnweldedBlocks.GroupBy(x => x.BlockDefinition.Id.TypeId).ToList();
                    foreach (IGrouping <MyObjectBuilderType, IMySlimBlock> grouping in unplacedByType)
                    {
                        NonplacedReport.AppendLine($"{grouping.Key.ToString().Replace("MyObjectBuilder_", "")} ({grouping.Count()})");
                    }

                    MyKernel.ResponderModule.UpdateStatusReport(NonplacedReport, append: true);
                }
                //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Placed projected blocks");
            }
            else if (MyAPIGateway.Session.CreativeMode)
            {
                foreach (IMySlimBlock Block in RealBlocks)
                {
                    if (MyKernel.Session.Settings.AllowAsyncWelding)
                    {
                        if (CanWeldInAsyncMode(Block))
                        {
                            MyAPIGateway.Parallel.StartBackground(() => Weld(Block, SpeedRatio, BoneFixSpeed));
                        }
                        else
                        {
                            Weld(Block, SpeedRatio, BoneFixSpeed);
                        }
                    }
                    else
                    {
                        Weld(Block, SpeedRatio, BoneFixSpeed);
                    }
                }

                foreach (IMySlimBlock Block in ProjectedBlocks)
                {
                    Projector.Build(Block, MyKernel.Tool.OwnerId, MyKernel.Tool.EntityId, false);
                }
            }

            //MyKernel.SessionBase.Log.DebugLog.WriteToLog($"WeldAndPlaceBlocks", $"Exit Point");
            yield return(false);
        }
        void Place(ICollection <IMySlimBlock> _Blocks)
        {
            try
            {
                if (_Blocks.Count == 0)
                {
                    return;
                }
                HashSet <IMySlimBlock> Blocks  = new HashSet <IMySlimBlock>(_Blocks);
                HashSet <IMySlimBlock> unbuilt = new HashSet <IMySlimBlock>();

                var Projector = ((Blocks.First().CubeGrid as MyCubeGrid).Projector as IMyProjector);

                if (MyAPIGateway.Session.CreativeMode)
                {
                    foreach (IMySlimBlock Block in Blocks)
                    {
                        Projector.Build(Block, Tool.OwnerId, Tool.EntityId, false);
                    }
                    return;
                }

                Dictionary <string, int> ToPull = new Dictionary <string, int>();
                if (Welder.UseConveyorSystem)
                {
                    foreach (IMySlimBlock Block in Blocks)
                    {
                        var FirstItem = ((MyCubeBlockDefinition)Block.BlockDefinition).Components[0].Definition.Id;
                        if (!ToPull.ContainsKey(FirstItem.SubtypeName))
                        {
                            ToPull.Add(FirstItem.SubtypeName, 1);
                        }
                        else
                        {
                            ToPull[FirstItem.SubtypeName] += 1;
                        }
                    }

                    lock (GridInventoryModule.InventoryLock)
                    {
                        GridInventoryModule.PullIn(Welder, Reduce(ToPull), "Component");
                    }
                }

                foreach (IMySlimBlock Block in Blocks)
                {
                    var FirstItem = ((MyCubeBlockDefinition)Block.BlockDefinition).Components[0].Definition.Id;
                    if (ToolCargo.GetItemAmount(FirstItem) >= 1)
                    {
                        Projector.Build(Block, Tool.OwnerId, Tool.EntityId, false);
                        ToolCargo.RemoveItemsOfType(1, FirstItem);
                    }
                    else
                    {
                        unbuilt.Add(Block);
                    }
                }
                SessionCore.DebugAsync(Tool.CustomName, $"Place failed for {unbuilt.Count} blocks: can't pull first component", WriteOnlyIfDebug: true);
                UnbuiltBlocks.UnionWith(unbuilt);
                ComplainUnbuilt();
            }
            catch (Exception Scrap)
            {
                SessionCore.LogError($"{Tool.CustomName}.Place()", Scrap);
            }
        }