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