Exemple #1
0
        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);
            }
        }
Exemple #4
0
            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);
            }
        }
Exemple #6
0
            /// <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;
            }
        }
Exemple #9
0
 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);
 }
Exemple #10
0
        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());
            }
        }
Exemple #11
0
        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));
        }
Exemple #12
0
        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;
        }