private void ComputeBlockMap(MyObjectBuilder_CubeGrid primaryGrid, IEnumerable <MyObjectBuilder_CubeGrid> allGrids, BlockSetInfo info) { m_blocks.Clear(); info.BlockCountByType.Clear(); info.ComponentCost.Clear(); info.PowerConsumptionByGroup.Clear(); BoundingBox = new BoundingBox((Vector3I)primaryGrid.CubeBlocks[0].Min, (Vector3I)primaryGrid.CubeBlocks[0].Min); foreach (var grid in allGrids) { foreach (var block in grid.CubeBlocks) { var blockID = block.GetId(); var def = MyDefinitionManager.Static.GetCubeBlockDefinition(blockID); if (grid == primaryGrid) { Vector3I blockMin = block.Min; Vector3I blockMax; BlockTransformations.ComputeBlockMax(block, ref def, out blockMax); BoundingBox = BoundingBox.Include(blockMin); BoundingBox = BoundingBox.Include(blockMax); for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext()) { m_blocks[rangeItr.Current] = block; } } if (def == null) { if (m_erroredDefinitionIds.Add(blockID)) { Logger.Error("Failed to find definition for block {0}", blockID); } continue; } info.BlockCountByType.AddValue(def.Id, 1); foreach (var c in def.Components) { info.ComponentCost.AddValue(c.Definition, c.Count); } var powerUsage = PowerUtilities.MaxPowerConsumption(def); // if it is off, ignore it. if (Math.Abs(powerUsage.Consumption) > 1e-8 && ((block as MyObjectBuilder_FunctionalBlock)?.Enabled ?? true)) { info.PowerConsumptionByGroup.AddValue(powerUsage.ResourceGroup, powerUsage.Consumption); } } } }
private void Process(CommandFeedback feedback, IMyCubeGrid grid) { if (grid.CustomName == null || !grid.CustomName.StartsWithICase("EqProcBuild")) { return; } var ob = grid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid; if (ob == null) { return; } this.Info("Begin processing {0}", grid.CustomName); feedback?.Invoke("Processing {0}", grid.CustomName); try { var dummyDel = new List <MyTuple <MyObjectBuilder_CubeBlock, string> >(); var blockKeep = new List <MyObjectBuilder_CubeBlock>(); var blockMap = new Dictionary <Vector3I, MyObjectBuilder_CubeBlock>(Vector3I.Comparer); foreach (var block in ob.CubeBlocks) { var mount = false; foreach (var name in block.ConfigNames()) { if (!name.StartsWithICase(MountDelegated) && !name.StartsWithICase(ReservedSpaceDelegated)) { continue; } dummyDel.Add(MyTuple.Create(block, name)); mount = true; break; } if (mount) { continue; } var blockMin = (Vector3I)block.Min; Vector3I blockMax; BlockTransformations.ComputeBlockMax(block, out blockMax); for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext()) { blockMap[rangeItr.Current] = block; } blockKeep.Add(block); } this.Info("Found {0} blocks to keep, {1} block mounts to remap", blockKeep.Count, dummyDel.Count); foreach (var pair in dummyDel) { var block = pair.Item1; var useName = pair.Item2; IEnumerable <Base6Directions.Direction> dirs = Base6Directions.EnumDirections; var def = MyDefinitionManager.Static.GetCubeBlockDefinition(pair.Item1); var transform = new MatrixI(block.BlockOrientation); if (def?.MountPoints != null) { var mountDirs = new HashSet <Base6Directions.Direction>(); foreach (var mount in def.MountPoints) { mountDirs.Add(Base6Directions.GetDirection(Vector3I.TransformNormal(mount.Normal, ref transform))); } } var args = useName.Split(' '); var keepArgs = new List <string>(args.Length); foreach (var arg in args) { if (arg.StartsWithICase(PartDummyUtils.ArgumentMountDirection)) { Base6Directions.Direction dir; if (Enum.TryParse(arg.Substring(2), out dir)) { dirs = new[] { transform.GetDirection(Base6Directions.GetOppositeDirection(dir)) } } ; else { this.Error("Failed to parse direction argument \"{0}\"", arg); feedback?.Invoke("Error: Failed to parse direction argument \"{0}\"", arg); } } else { keepArgs.Add(arg); } } useName = string.Join(" ", keepArgs); MyObjectBuilder_CubeBlock outputBlock = null; var outputDir = Base6Directions.Direction.Forward; foreach (var dir in dirs) { MyObjectBuilder_CubeBlock tmp; if (!blockMap.TryGetValue(block.Min + Base6Directions.GetIntVector(dir), out tmp)) { continue; } if (tmp.ConfigNames().Any(x => x.StartsWithICase(MountDelegated))) { continue; } if (outputBlock != null) { this.Error("Multiple directions found for {0}", pair.Item2); feedback?.Invoke("Error: Multiple directions found for {0}", pair.Item2); } outputBlock = tmp; outputDir = dir; } if (outputBlock == null || !ApplyDelegate(ob, block, useName, outputBlock, outputDir)) { this.Error("Failed to find delegated mount point for {0}", pair.Item2); feedback?.Invoke("Error: Failed to find delegated mount point for {0}", pair.Item2); } } ob.CubeBlocks = blockKeep; // Grab related grids! var relatedGrids = new HashSet <IMyCubeGrid> { grid }; var scanRelated = new Queue <IMyCubeGrid>(); var relatedGridController = new Dictionary <IMyCubeGrid, IMyCubeBlock>(); scanRelated.Enqueue(grid); while (scanRelated.Count > 0) { var subGrid = scanRelated.Dequeue(); IMyCubeBlock controllerForThisGrid = null; relatedGridController.TryGetValue(subGrid, out controllerForThisGrid); subGrid.GetBlocks(null, (y) => { var x = y?.FatBlock; if (x == null) { return(false); } var childGrid = (x as IMyMechanicalConnectionBlock)?.TopGrid; if (childGrid != null && relatedGrids.Add(childGrid)) { scanRelated.Enqueue(childGrid); relatedGridController[childGrid] = x.CubeGrid == grid ? x : controllerForThisGrid; } var parentGrid = (x as IMyAttachableTopBlock)?.Base?.CubeGrid; // ReSharper disable once InvertIf if (parentGrid != null && relatedGrids.Add(parentGrid)) { scanRelated.Enqueue(parentGrid); relatedGridController[parentGrid] = x.CubeGrid == grid ? x : controllerForThisGrid; } return(false); }); } relatedGrids.Remove(grid); var removedNoController = relatedGrids.RemoveWhere(x => !relatedGridController.ContainsKey(x)); if (removedNoController > 0) { this.Error("Failed to find the mechanical connection block for all subgrids. {0} will be excluded", removedNoController); feedback?.Invoke("Error: Failed to find the mechanical connection block for all subgrids. {0} will be excluded", removedNoController); } // Need to add reserved space for subgrids so they don't overlap. So compute that. Yay! foreach (var rel in relatedGrids) { IMyCubeBlock root; if (!relatedGridController.TryGetValue(rel, out root)) { this.Error("Unable to find the mechanical connection for grid {0}", rel.CustomName); feedback?.Invoke("Error: Unable to find the mechanical connection for grid {0}", rel.CustomName); continue; } MyObjectBuilder_CubeBlock blockDest; if (blockMap.TryGetValue(root.Min, out blockDest)) { var blockLocal = (MatrixD) new MatrixI(blockDest.BlockOrientation).GetFloatMatrix(); blockLocal.Translation = (Vector3I)blockDest.Min * grid.GridSize; var blockWorld = MatrixD.Multiply(blockLocal, grid.WorldMatrix); var worldAABB = rel.WorldAABB; worldAABB = Utilities.TransformBoundingBox(worldAABB, MatrixD.Invert(blockWorld)); var gridAABB = new BoundingBoxI(Vector3I.Floor(worldAABB.Min / grid.GridSize), Vector3I.Ceiling(worldAABB.Max / grid.GridSize)); var code = $"{PartMetadata.ReservedSpacePrefix} NE:{gridAABB.Min.X}:{gridAABB.Min.Y}:{gridAABB.Min.Z} PE:{gridAABB.Max.X}:{gridAABB.Max.Y}:{gridAABB.Max.Z}"; this.Info("Added reserved space for subgrid {0}: Spec is \"{1}\"", rel.CustomName, code); if (blockDest.Name == null || blockDest.Name.Trim().Length == 0) { blockDest.Name = code; } else { blockDest.Name += PartMetadata.MultiUseSentinel + code; } } else { this.Error("Unable to find the OB for grid block {0} ({1}, {2}, {3}). Is it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z); feedback?.Invoke("Unable to the find OB for grid block {0} ({1}, {2}, {3}). Was it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z); } } var allGrids = new List <MyObjectBuilder_CubeGrid>(relatedGrids.Count + 1) { ob }; allGrids.AddRange(relatedGrids.Select(relGrid => relGrid.GetObjectBuilder(false)).OfType <MyObjectBuilder_CubeGrid>()); // Compose description: TODO I'd love if this actually worked :/ // var storage = new MyPartMetadata(); // storage.InitFromGrids(ob, allGrids); // var data = Convert.ToBase64String(MyAPIGateway.Utilities.SerializeToBinary(storage.GetObjectBuilder())); var defOut = new MyObjectBuilder_PrefabDefinition() { Id = new SerializableDefinitionId(typeof(MyObjectBuilder_PrefabDefinition), grid.CustomName), CubeGrids = allGrids.ToArray() }; var fileName = grid.CustomName + ".sbc"; this.Info("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length); feedback?.Invoke("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length); var mishMash = new MyObjectBuilder_Definitions() { Prefabs = new MyObjectBuilder_PrefabDefinition[] { defOut } }; var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage(fileName, typeof(DesignTools)); var obCode = MyAPIGateway.Utilities.SerializeToXML(mishMash); obCode = obCode.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); writer.Write(Encoding.UTF8.GetBytes(obCode)); writer.Close(); } catch (Exception e) { this.Error("Failed to parse. Error:\n{0}", e.ToString()); } }
public override void Remap(MyObjectBuilder_CubeGrid grid) { var transformCopy = LocalTransform; var minToMin = new Dictionary <Vector3I, Vector3I>(grid.CubeBlocks.Count * 3 / 2); foreach (var x in grid.CubeBlocks) { var orig = (Vector3I)x.Min; var cMin = orig; Vector3I cMax; BlockTransformations.ComputeBlockMax(x, out cMax); x.BlockOrientation.Forward = LocalTransform.GetDirection(x.BlockOrientation.Forward); x.BlockOrientation.Up = LocalTransform.GetDirection(x.BlockOrientation.Up); Vector3I.Transform(ref cMin, ref transformCopy, out cMin); Vector3I.Transform(ref cMax, ref transformCopy, out cMax); minToMin[orig] = x.Min = Vector3I.Min(cMin, cMax); var proj = x as MyObjectBuilder_ProjectorBase; // Don't have to update the rotation; it is bound to the world matrix of the projector. if (proj != null) { Vector3I.TransformNormal(ref proj.ProjectionOffset, ref transformCopy, out proj.ProjectionOffset); } } if (grid.BlockGroups != null) { foreach (var g in grid.BlockGroups) { for (var i = 0; i < g.Blocks.Count; i++) { Vector3I tmpOut; if (minToMin.TryGetValue(g.Blocks[i], out tmpOut)) { g.Blocks[i] = tmpOut; } else { g.Blocks[i] = Vector3I.MaxValue; // sorta discards it? } } } } if (grid.ConveyorLines != null) { foreach (var l in grid.ConveyorLines) { l.StartDirection = LocalTransform.GetDirection(l.StartDirection); l.StartPosition = Vector3I.Transform(l.StartPosition, ref transformCopy); l.EndDirection = LocalTransform.GetDirection(l.EndDirection); l.EndPosition = Vector3I.Transform(l.EndPosition, ref transformCopy); if (l.Sections == null) { continue; } for (var s = 0; s < l.Sections.Count; s++) { l.Sections[s] = new SerializableLineSectionInformation() { Direction = LocalTransform.GetDirection(l.Sections[s].Direction), Length = l.Sections[s].Length } } ; } } }