public void UpdateMapping() { LastCockpit = MyGrid.MainCockpit as MyCockpit; var orientation = LastCockpit?.Orientation ?? MyCube.Orientation; var fwdReverse = Base6Directions.GetOppositeDirection(orientation.Forward); var upReverse = Base6Directions.GetOppositeDirection(orientation.Up); var leftReverse = Base6Directions.GetOppositeDirection(orientation.Left); RealSideStates[(Session.ShieldSides)orientation.Forward] = new Session.ShieldInfo { Side = Session.ShieldSides.Forward, Redirected = IsSideShunted(Session.ShieldSides.Forward) }; RealSideStates[(Session.ShieldSides)fwdReverse] = new Session.ShieldInfo { Side = Session.ShieldSides.Backward, Redirected = IsSideShunted(Session.ShieldSides.Backward) }; RealSideStates[(Session.ShieldSides)orientation.Up] = new Session.ShieldInfo { Side = Session.ShieldSides.Up, Redirected = IsSideShunted(Session.ShieldSides.Up) }; RealSideStates[(Session.ShieldSides)upReverse] = new Session.ShieldInfo { Side = Session.ShieldSides.Down, Redirected = IsSideShunted(Session.ShieldSides.Down) }; RealSideStates[(Session.ShieldSides)orientation.Left] = new Session.ShieldInfo { Side = Session.ShieldSides.Left, Redirected = IsSideShunted(Session.ShieldSides.Left) }; RealSideStates[(Session.ShieldSides)leftReverse] = new Session.ShieldInfo { Side = Session.ShieldSides.Right, Redirected = IsSideShunted(Session.ShieldSides.Right) }; }
public void UpdateMapping() { LastCockpit = MyGrid.MainCockpit as MyCockpit; var orientation = LastCockpit?.Orientation ?? MyCube.Orientation; var fwdReverse = Base6Directions.GetOppositeDirection(orientation.Forward); var upReverse = Base6Directions.GetOppositeDirection(orientation.Up); var leftReverse = Base6Directions.GetOppositeDirection(orientation.Left); RealSideStates[(Session.ShieldSides)orientation.Forward] = new Session.ShieldInfo { Side = Session.ShieldSides.Forward, Redirected = IsSideShunted(Session.ShieldSides.Forward) }; RealSideStates[(Session.ShieldSides)fwdReverse] = new Session.ShieldInfo { Side = Session.ShieldSides.Backward, Redirected = IsSideShunted(Session.ShieldSides.Backward) }; RealSideStates[(Session.ShieldSides)orientation.Up] = new Session.ShieldInfo { Side = Session.ShieldSides.Up, Redirected = IsSideShunted(Session.ShieldSides.Up) }; RealSideStates[(Session.ShieldSides)upReverse] = new Session.ShieldInfo { Side = Session.ShieldSides.Down, Redirected = IsSideShunted(Session.ShieldSides.Down) }; RealSideStates[(Session.ShieldSides)orientation.Left] = new Session.ShieldInfo { Side = Session.ShieldSides.Left, Redirected = IsSideShunted(Session.ShieldSides.Left) }; RealSideStates[(Session.ShieldSides)leftReverse] = new Session.ShieldInfo { Side = Session.ShieldSides.Right, Redirected = IsSideShunted(Session.ShieldSides.Right) }; //foreach (var pair in RealSideStates) Log.CleanLine($"RealSide:{pair.Key} - UserSide:{pair.Value.Side} - Redirected:{pair.Value.Redirected}"); }
public void GetTransforms(PartMountPointBlock other, HashSet <MatrixI> cache) { var dirSelf = Base6Directions.GetOppositeDirection(MountDirection6); var dirOther = other.MountDirection6; if (other.BiasDirection6.HasValue && BiasDirection6.HasValue) { // Simple case. Only one possible transform. var tmp = new MatrixI(); // Mount directions need to be aligned tmp.SetDirection(dirOther, dirSelf); // Bias directions must be aligned var biasSelf = BiasDirection6.Value; var biasOther = other.BiasDirection6.Value; tmp.SetDirection(biasOther, biasSelf); // Final alignment tmp.SetDirection(Base6Directions.GetCross(dirOther, biasOther), Base6Directions.GetCross(dirSelf, biasSelf)); // Check secondary alignment when present. If it fails just return. These will never work. if (other.SecondBiasDirection6.HasValue && SecondBiasDirection6.HasValue && tmp.GetDirection(other.SecondBiasDirection6.Value) != SecondBiasDirection6.Value) { return; } tmp.Translation = AnchorLocation - Vector3I.TransformNormal(other.MountLocation, ref tmp); cache.Add(tmp); return; } // Complicated case. 4 possibilities // Perp. axis using +2 // Base direction for axis (first entry) using ~1 var dirSelfI = ((int)dirSelf & ~1) + 2; var dirOtherI = ((int)dirOther & ~1) + 2; for (var i = 0; i < 4; i++) { var tmp = new MatrixI(); tmp.SetDirection(dirOther, dirSelf); // Align one of the 4 perp. vectors with another perp vector var biasSelf = Base6Directions.EnumDirections[dirSelfI % 6]; var biasOther = Base6Directions.EnumDirections[(dirOtherI + i) % 6]; tmp.SetDirection(biasOther, biasSelf); // Complete the matrix tmp.SetDirection(Base6Directions.GetCross(dirOther, biasOther), Base6Directions.GetCross(dirSelf, biasSelf)); tmp.Translation = AnchorLocation - Vector3I.TransformNormal(other.MountLocation, ref tmp); cache.Add(tmp); } }
public void SetThrust(Vector3D deltaV, bool align) { Base6Directions.Direction direction = Base6Directions.GetClosestDirection(deltaV); Base6Directions.Direction oppositeDirection = Base6Directions.GetOppositeDirection(direction); //Program.Echo($"\nDirection: {direction.ToString()}"); //Program.Echo($"\nOpposite: {oppositeDirection.ToString()}"); float maxThrust = MaxThrusters[direction]; //double decayFactor = 0.8; //if (align && direction != Base6Directions.Direction.Forward || direction != Base6Directions.Direction.Backward) // decayFactor = 0.25; //double acceleration = MathHelper.Clamp(maxThrust / Remote.CalculateShipMass().TotalMass, 0.1, Math.Pow(deltaV.Length(), decayFactor)); //Drone.LogToLcd($"{direction.ToString()} {acceleration.ToString()}m/s/s"); double acceleration = 0; var freq = this.Program.Runtime.TimeSinceLastRun.TotalMilliseconds / 1000; if (direction == Base6Directions.Direction.Left || direction == Base6Directions.Direction.Right) { acceleration = XPID.CorrectError(deltaV.Length(), freq); } else if (direction == Base6Directions.Direction.Up || direction == Base6Directions.Direction.Down) { acceleration = YPID.CorrectError(deltaV.Length(), freq); } else if (direction == Base6Directions.Direction.Forward || direction == Base6Directions.Direction.Backward) { acceleration = ZPID.CorrectError(deltaV.Length(), freq); } double force = Remote.CalculateShipMass().TotalMass *acceleration; foreach (IMyThrust thruster in Thrusters[direction]) { thruster.Enabled = true; thruster.ThrustOverride = (float)force; } foreach (IMyThrust thruster in Thrusters[oppositeDirection]) { thruster.ThrustOverride = 0f; thruster.Enabled = false; } }
// Used for replacing a block in every grid that spawns; must be only server side private void OnEntityAdded(MyEntity ent) { try { var grid = ent as MyCubeGrid; if (grid == null) { return; } replaceBlocks.Clear(); var blocks = grid.GetBlocks(); var gridModAPI = (IMyCubeGrid)ent; foreach (IMySlimBlock b in blocks) { if (b.BlockDefinition.Id == OLD_LIGHT_DEFID) { replaceBlocks.Add(b); } } foreach (var b in replaceBlocks) { var obj = b.GetObjectBuilder(false); obj.SubtypeName = NEW_LIGHT_SUBID; obj.BlockOrientation = new MyBlockOrientation(Base6Directions.GetOppositeDirection(obj.BlockOrientation.Up), obj.BlockOrientation.Forward); // initial block rotation is different, needs correcting gridModAPI.RemoveBlock(b, false); gridModAPI.AddBlock(obj, false); } replaceBlocks.Clear(); } catch (Exception e) { MyLog.Default.WriteLine(e); MyAPIGateway.Utilities.ShowNotification($"[ Error in {GetType().FullName}: {e.Message} ]", 10000, MyFontEnum.Red); } }
/// <summary> /// Solves the required thrusts to go in targetDirection at max speed. This takes gravity into account. /// </summary> /// <param name="g">Gravity and unknown forces</param> /// <param name="targetDirection">The target direction to go in</param> /// <param name="maxPercentageThrustToUse">The maximum amount of thrust devoted to going in the target direction.</param> /// <returns></returns> public ThrusterGroup SolveMaxThrust(Vector3D minus_g, Vector3D targetDirection, double maxPercentageThrustToUse = 1) { //parent_program.Echo("Starting"); Base6Directions.Direction actual2Di; Base6Directions.Direction actual3Di; double t2c; double t3c; double Lambda; ThrusterGroup t1; ThrusterGroup t2; ThrusterGroup t3; if (maxPercentageThrustToUse > 1) { maxPercentageThrustToUse = 1; } else if (maxPercentageThrustToUse < 0) { maxPercentageThrustToUse = 0; } foreach (var entry in thrusterGroups) { //parent_program.Echo("Loading " + entry.Key.ToString()); t1 = entry.Value; if (t1.LocalThrustDirection == Base6Directions.Direction.Up || t1.LocalThrustDirection == Base6Directions.Direction.Down) { t2 = thrusterGroups[Base6Directions.Direction.Left]; t3 = thrusterGroups[Base6Directions.Direction.Forward]; } else if (t1.LocalThrustDirection == Base6Directions.Direction.Left || t1.LocalThrustDirection == Base6Directions.Direction.Right) { t2 = thrusterGroups[Base6Directions.Direction.Up]; t3 = thrusterGroups[Base6Directions.Direction.Forward]; } else if (t1.LocalThrustDirection == Base6Directions.Direction.Forward || t1.LocalThrustDirection == Base6Directions.Direction.Backward) { t2 = thrusterGroups[Base6Directions.Direction.Up]; t3 = thrusterGroups[Base6Directions.Direction.Left]; } else { parent_program.shipIOHandler.Error( "Encountered unusual thruster direction.\nIf you've gotten this error in particular,\nplease report it to the script owner, Spug."); t2 = thrusterGroups[Base6Directions.Direction.Up]; t3 = thrusterGroups[Base6Directions.Direction.Left]; } //var mat = new double[,] { //{ t2.WorldThrustDirection.X, t3.WorldThrustDirection.X, -targetDirection.X }, //{ t2.WorldThrustDirection.Y, t3.WorldThrustDirection.Y, -targetDirection.Y }, //{ t2.WorldThrustDirection.Z, t3.WorldThrustDirection.Z, -targetDirection.Z }, //}; t1.matrixM[0, 0] = t2.WorldThrustDirection.X; t1.matrixM[0, 1] = t3.WorldThrustDirection.X; t1.matrixM[0, 2] = -targetDirection.X; t1.matrixM[1, 0] = t2.WorldThrustDirection.Y; t1.matrixM[1, 1] = t3.WorldThrustDirection.Y; t1.matrixM[1, 2] = -targetDirection.Y; t1.matrixM[2, 0] = t2.WorldThrustDirection.Z; t1.matrixM[2, 1] = t3.WorldThrustDirection.Z; t1.matrixM[2, 2] = -targetDirection.Z; t1.ANS[0] = -t1.MaxThrust * t1.WorldThrustDirection.X * maxPercentageThrustToUse - minus_g.X; t1.ANS[1] = -t1.MaxThrust * t1.WorldThrustDirection.Y * maxPercentageThrustToUse - minus_g.Y; t1.ANS[2] = -t1.MaxThrust * t1.WorldThrustDirection.Z * maxPercentageThrustToUse - minus_g.Z; PID.ComputeCoefficients(t1.matrixM, t1.ANS); t2c = t1.ANS[0]; t3c = t1.ANS[1]; Lambda = t1.ANS[2]; actual2Di = t2.LocalThrustDirection; actual3Di = t3.LocalThrustDirection; if (t2c < 0) { actual2Di = Base6Directions.GetOppositeDirection(t2.LocalThrustDirection); t2c *= -1; } if (t3c < 0) { actual3Di = Base6Directions.GetOppositeDirection(t3.LocalThrustDirection); t3c *= -1; } //// Publish the results t1.finalThrustForces.X = t1.MaxThrust * maxPercentageThrustToUse; t1.finalThrustForces.Y = t2c; t1.finalThrustForces.Z = t3c; t1.lambdaResult = Lambda; t1.finalThrusterGroups[0] = t1; t1.finalThrusterGroups[1] = thrusterGroups[actual2Di]; t1.finalThrusterGroups[2] = thrusterGroups[actual3Di]; t1.finalThrusterGroups[3] = thrusterGroups[Base6Directions.GetOppositeDirection(t1.LocalThrustDirection)]; t1.finalThrusterGroups[4] = thrusterGroups[Base6Directions.GetOppositeDirection(t2.LocalThrustDirection)]; t1.finalThrusterGroups[5] = thrusterGroups[Base6Directions.GetOppositeDirection(t3.LocalThrustDirection)]; //parent_program.Echo("Completed " + entry.Key.ToString()); } ThrusterGroup bestCandidate = null; double bestCandidateLambda = -999999999; foreach (var entry in thrusterGroups) { if (entry.Value.lambdaResult > bestCandidateLambda) { if (entry.Value.finalThrustForces.Y <= entry.Value.finalThrusterGroups[1].MaxThrust + 1 && entry.Value.finalThrustForces.Z <= entry.Value.finalThrusterGroups[2].MaxThrust + 1) { bestCandidate = entry.Value; bestCandidateLambda = entry.Value.lambdaResult; } } } //parent_program.Echo("Finished"); //parent_program.Echo("Best: " + bestCandidate.LocalThrustDirection.ToString()); return(bestCandidate); }
public CruiseControl(IMyShipController controller, List <IMyThrust> allThrusters) { this.controller = controller; //screen = (controller as IMyTextSurfaceProvider).GetSurface(0); //screen.ContentType = ContentType.TEXT_AND_IMAGE; electricThrusters = new Dictionary <Base6Directions.Direction, List <IMyThrust> >() { { Base6Directions.Direction.Forward, new List <IMyThrust>() }, { Base6Directions.Direction.Backward, new List <IMyThrust>() }, { Base6Directions.Direction.Up, new List <IMyThrust>() }, { Base6Directions.Direction.Down, new List <IMyThrust>() }, }; hydrogenThrusters = new Dictionary <Base6Directions.Direction, List <IMyThrust> >() { { Base6Directions.Direction.Forward, new List <IMyThrust>() }, { Base6Directions.Direction.Backward, new List <IMyThrust>() }, { Base6Directions.Direction.Up, new List <IMyThrust>() }, { Base6Directions.Direction.Down, new List <IMyThrust>() }, }; var forward = controller.Orientation.Forward; var back = Base6Directions.GetOppositeDirection(forward); var up = controller.Orientation.Up; var down = Base6Directions.GetOppositeDirection(up); //For automatic thruster selection. var maxThrust = new Dictionary <Base6Directions.Direction, float>() { { Base6Directions.Direction.Forward, 0f }, { Base6Directions.Direction.Backward, 0f }, { Base6Directions.Direction.Up, 0f }, { Base6Directions.Direction.Down, 0f } }; //These are all inverted to make the Dictuionary reflect which way they push, not which way they point. foreach (var item in allThrusters) { if (item.Orientation.Forward == forward) { if (item.BlockDefinition.SubtypeId.Contains("Hydrogen")) { hydrogenThrusters[Base6Directions.Direction.Backward].Add(item); } else { electricThrusters[Base6Directions.Direction.Backward].Add(item); } maxThrust[Base6Directions.Direction.Backward] += item.MaxThrust; } else if (item.Orientation.Forward == back) { if (item.BlockDefinition.SubtypeId.Contains("Hydrogen")) { hydrogenThrusters[Base6Directions.Direction.Forward].Add(item); } else { electricThrusters[Base6Directions.Direction.Forward].Add(item); } maxThrust[Base6Directions.Direction.Forward] += item.MaxThrust; } if (item.Orientation.Forward == up) { if (item.BlockDefinition.SubtypeId.Contains("Hydrogen")) { hydrogenThrusters[Base6Directions.Direction.Down].Add(item); } else { electricThrusters[Base6Directions.Direction.Down].Add(item); } maxThrust[Base6Directions.Direction.Down] += item.MaxThrust; } else if (item.Orientation.Forward == down) { if (item.BlockDefinition.SubtypeId.Contains("Hydrogen")) { hydrogenThrusters[Base6Directions.Direction.Up].Add(item); } else { electricThrusters[Base6Directions.Direction.Up].Add(item); } maxThrust[Base6Directions.Direction.Up] += item.MaxThrust; } } Forward = maxThrust.Aggregate((left, right) => left.Value > right.Value ? left : right).Key; autoForward = Forward; }
public void Init(MyObjectBuilder_CubeBlock block, string piece, IEnumerable <string> args) { Piece = piece; MountDirection6 = Base6Directions.GetOppositeDirection(Base6Directions.GetCross(block.BlockOrientation.Up, block.BlockOrientation.Forward)); AnchorLocation = block.Min; AdjacencyRule = AdjacencyRule.Any; BiasDirection6 = null; SecondBiasDirection6 = null; var blockOrientation = new MatrixI(block.BlockOrientation); foreach (var arg in args) { if (arg.StartsWithICase(PartDummyUtils.ArgumentMountDirection)) { Base6Directions.Direction tmpMountDirection; if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentMountDirection.Length), out tmpMountDirection)) { MountDirection6 = blockOrientation.GetDirection(tmpMountDirection); } else { Logging.Error("Failed to parse mount point direction argument \"{0}\"", arg); } } else if (arg.StartsWithICase(PartDummyUtils.ArgumentBiasDirection)) { Base6Directions.Direction tmpBiasDirection; if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentBiasDirection.Length), out tmpBiasDirection)) { BiasDirection6 = blockOrientation.GetDirection(tmpBiasDirection); } else { Logging.Error("Failed to parse bias direction argument \"{0}\"", arg); } } else if (arg.StartsWithICase(PartDummyUtils.ArgumentSecondBiasDirection)) { Base6Directions.Direction tmpBiasDirection; if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentSecondBiasDirection.Length), out tmpBiasDirection)) { SecondBiasDirection6 = blockOrientation.GetDirection(tmpBiasDirection); } else { Logging.Error("Failed to parse second bias direction argument \"{0}\"", arg); } } else if (arg.StartsWithICase(PartDummyUtils.ArgumentAnchorPoint)) { Vector3I anchor; if (PartDummyUtils.TryParseVector(arg.Substring(PartDummyUtils.ArgumentAnchorPoint.Length), out anchor)) { AnchorLocation = block.Min + anchor; continue; } Logging.Error("Failed to parse anchor location argument \"{0}\"", arg); } else if (arg.StartsWithICase(PartDummyUtils.ArgumentAdjacencyRule)) // Adjacency Rule { AdjacencyRule rule; if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentAdjacencyRule.Length), out rule)) { AdjacencyRule = rule; } else { Logging.Error("Failed to parse adjacency rule argument \"{0}\"", arg); } } else { Logging.Error("Failed to parse mount point argument \"{0}\"", arg); } } // ReSharper disable once InvertIf if (SecondBiasDirection6.HasValue && !BiasDirection6.HasValue) { BiasDirection6 = SecondBiasDirection6; SecondBiasDirection6 = null; } }
private bool ApplyDelegate(MyObjectBuilder_CubeGrid grid, MyObjectBuilder_CubeBlock source, string srcName, MyObjectBuilder_CubeBlock dest, Base6Directions.Direction destDir) { if (srcName.StartsWithICase(MountDelegated)) { var lTransOrig = new MatrixI(source.BlockOrientation); var lTrans = new MatrixI(dest.BlockOrientation); MatrixI iTrans; MatrixI.Invert(ref lTrans, out iTrans); var arguments = PartDummyUtils.ConfigArguments(srcName.Substring(MountDelegated.Length).Trim()).Select( (arg) => { if (arg.StartsWithICase(PartDummyUtils.ArgumentBiasDirection)) { Base6Directions.Direction dir; if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentBiasDirection.Length), out dir)) { return(PartDummyUtils.ArgumentBiasDirection + iTrans.GetDirection(lTransOrig.GetDirection(dir))); } else { this.Error("Failed to parse bias argument \"{0}\"", arg); } } else if (arg.StartsWithICase(PartDummyUtils.ArgumentSecondBiasDirection)) { Base6Directions.Direction dir; if (Enum.TryParse(arg.Substring(PartDummyUtils.ArgumentSecondBiasDirection.Length), out dir)) { return(PartDummyUtils.ArgumentSecondBiasDirection + iTrans.GetDirection(lTransOrig.GetDirection(dir))); } else { this.Error("Failed to parse second bias argument \"{0}\"", arg); } } return(arg); }).ToList(); arguments.Add(PartDummyUtils.ArgumentMountDirection + iTrans.GetDirection(Base6Directions.GetOppositeDirection(destDir))); var anchorPoint = source.Min + Base6Directions.GetIntVector(destDir); var del = anchorPoint - dest.Min; if (del != Vector3I.Zero) { arguments.Add(PartDummyUtils.ArgumentAnchorPoint + del.X + ":" + del.Y + ":" + del.Z); } var outName = PartMetadata.MountPrefix + " " + string.Join(" ", arguments); if (string.IsNullOrWhiteSpace(dest.Name)) { dest.Name = outName; } else { dest.Name = dest.Name + PartMetadata.MultiUseSentinel + outName; } return(true); } if (srcName.StartsWithICase(ReservedSpaceDelegated)) { var baseName = srcName.Substring(ReservedSpaceDelegated.Length).Trim(); var args = baseName.Split(' ').Select(x => x.Trim()).Where(x => x.Length > 0).ToArray(); var box = PartDummyUtils.ParseReservedSpace(MyDefinitionManager.Static.GetCubeSize(grid.GridSizeEnum), source, args, this.Error); var del = source.Min - (Vector3I)dest.Min; box.Box.Max += del; box.Box.Min += del; var boxLocalFloat = Utilities.TransformBoundingBox(box.Box, Matrix.Invert(new MatrixI(dest.BlockOrientation).GetFloatMatrix())); var boxLocal = new BoundingBoxI(Vector3I.Floor(boxLocalFloat.Min), Vector3I.Ceiling(boxLocalFloat.Max)); var outName = $"{PartMetadata.ReservedSpacePrefix} NE:{boxLocal.Min.X}:{boxLocal.Min.Y}:{boxLocal.Min.Z} PE:{boxLocal.Max.X}:{boxLocal.Max.Y}:{boxLocal.Max.Z}"; if (box.IsShared) { outName += " shared"; } if (box.IsOptional) { outName += " optional"; } if (string.IsNullOrWhiteSpace(dest.Name)) { dest.Name = outName; } else { dest.Name = dest.Name + PartMetadata.MultiUseSentinel + outName; } return(true); } return(false); }
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 static Vector3I CalculateOffset(IMyCubeBlock pad1, IMyCubeBlock pad2) { Vector3 pad1local = pad1.Position; // ConstraintPositionInGridSpace(pad1) / pad1.CubeGrid.GridSize; Vector3 pad2local = -pad2.Position; // -ConstraintPositionInGridSpace(pad2) / pad2.CubeGrid.GridSize; // I dunno why it works but it seems to do in the tests I made xD pad1local += Base6Directions.GetVector(pad1.Orientation.TransformDirection(Base6Directions.GetOppositeDirection(WeldPad.DirForward))); //pad2local += Base6Directions.GetVector(pad2.Orientation.TransformDirection(Base6Directions.GetOppositeDirection(WeldPad.DIR_FORWARD))); Base6Directions.Direction direction = pad1.Orientation.TransformDirection(WeldPad.DirRight); MatrixI matrix = MatrixI.CreateRotation( newB: pad1.Orientation.TransformDirection(WeldPad.DirForward), oldB: Base6Directions.GetFlippedDirection(pad2.Orientation.TransformDirection(WeldPad.DirForward)), oldA: pad2.CubeGrid.WorldMatrix.GetClosestDirection(pad1.CubeGrid.WorldMatrix.GetDirectionVector(direction)), newA: direction); Vector3 offset; Vector3.Transform(ref pad2local, ref matrix, out offset); return(Vector3I.Round(pad1local + offset)); }
public Program() { tmpLst = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyCockpit>(tmpLst, (b) => (b.IsSameConstructAs(Me) && b.CustomName.Contains(COCKPIT_NAME))); if (tmpLst.Count > 0) { myCockpit = tmpLst[0] as IMyCockpit; lcd = myCockpit.GetSurface(4); } else { Echo("No Main Cockpit"); } hovers = new List <IMyThrust>(); GridTerminalSystem.GetBlocksOfType <IMyThrust>(hovers, (b) => (b.IsSameConstructAs(Me) && (b.Orientation.Forward == Base6Directions.GetOppositeDirection(myCockpit.Orientation.Up)))); minHoversHeight = hovers[0].GetMinimum <float>("Hover_MinHeight"); maxHoversHeight = hovers[0].GetMaximum <float>("Hover_MinHeight"); lcd.WriteText("..."); if (!bool.TryParse(Storage, out show)) { show = true; } Runtime.UpdateFrequency = UpdateFrequency.Update10; }