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); } }