using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")] [assembly: AssemblyCompany("DSPNestedMoons")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+b0b99c7e92e155b9e8c3ceb71cd5ca2263c6c778")] [assembly: AssemblyProduct("DSPNestedMoons")] [assembly: AssemblyTitle("DSPNestedMoons")] [assembly: AssemblyVersion("1.0.2.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace DSPNestedMoons { internal sealed class BodyLayout { internal int BodyIndex { get; } internal bool IsGas { get; } internal int ParentIndex { get; set; } internal int Depth { get; set; } internal int OrbitIndex { get; set; } internal int SiblingNumber { get; set; } internal List Children { get; } internal BodyLayout(int bodyIndex, bool isGas) { BodyIndex = bodyIndex; IsGas = isGas; ParentIndex = -1; Children = new List(); } } internal static class NestedMoonLayoutGenerator { private sealed class LayoutRandom { private uint state; internal LayoutRandom(int seed) { state = (uint)(seed ^ -1640531527); if (state == 0) { state = 1831565813u; } } internal double NextDouble() { uint num = state; num ^= num << 13; num ^= num >> 17; return (double)(state = num ^ (num << 5)) / 4294967296.0; } } internal const double BaseMoonChance = 0.6; internal static BodyLayout[] Generate(IReadOnlyList gasFlags, int seed) { LayoutRandom layoutRandom = new LayoutRandom(seed); return Generate(gasFlags, layoutRandom.NextDouble); } internal static BodyLayout[] Generate(IReadOnlyList gasFlags, Func nextDouble) { if (gasFlags == null) { throw new ArgumentNullException("gasFlags"); } if (nextDouble == null) { throw new ArgumentNullException("nextDouble"); } BodyLayout[] array = new BodyLayout[gasFlags.Count]; int cursor = 0; while (cursor < array.Length) { AddChildrenDepthFirst(CreateBody(array, gasFlags, cursor++, -1, 0), array, gasFlags, ref cursor, nextDouble); } for (int i = 0; i < array.Length; i++) { if (array[i].ParentIndex < 0) { AssignSatelliteOrbits(array[i], array); } } return array; } internal static double GetHostChance(int hostDepth) { if (hostDepth < 0) { throw new ArgumentOutOfRangeException("hostDepth"); } return Math.Pow(0.6, hostDepth + 1); } internal static float GetRadiusForDepth(int depth, float originalRadius) { if (depth == 3) { return 160f; } if (depth >= 4) { return 80f; } return originalRadius; } private static BodyLayout CreateBody(BodyLayout[] layouts, IReadOnlyList gasFlags, int bodyIndex, int parentIndex, int depth) { BodyLayout result = (layouts[bodyIndex] = new BodyLayout(bodyIndex, gasFlags[bodyIndex]) { ParentIndex = parentIndex, Depth = depth }); if (parentIndex >= 0) { layouts[parentIndex].Children.Add(bodyIndex); } return result; } private static void AddChildrenDepthFirst(BodyLayout parent, BodyLayout[] layouts, IReadOnlyList gasFlags, ref int cursor, Func nextDouble) { double hostChance = GetHostChance(parent.Depth); while (cursor < layouts.Length && nextDouble() < hostChance) { AddChildrenDepthFirst(CreateBody(layouts, gasFlags, cursor++, parent.BodyIndex, parent.Depth + 1), layouts, gasFlags, ref cursor, nextDouble); } } private static void AssignSatelliteOrbits(BodyLayout host, BodyLayout[] layouts) { int num = 0; for (int i = 0; i < host.Children.Count; i++) { BodyLayout bodyLayout = layouts[host.Children[i]]; int num2 = (bodyLayout.IsGas ? 3 : ((bodyLayout.Children.Count > 0) ? 1 : 0)); bodyLayout.SiblingNumber = i + 1; bodyLayout.OrbitIndex = i + 1 + num + num2; num += num2 * 2; AssignSatelliteOrbits(bodyLayout, layouts); } } } [BepInPlugin("Zincon.DSPNestedMoons", "mooooooon", "1.0.2")] [BepInProcess("DSPGAME.exe")] [BepInDependency("Zincon.DSPAddPlanetMoon2Patch", "3.0.15")] [BepInIncompatibility("dsp.galactic-scale.2")] public sealed class Plugin : BaseUnityPlugin { internal static class DspAddPlanetCompatibility { private static object pluginInstance; private static FieldInfo orderedPoseUpdateField; internal static void Initialize() { Type type = AccessTools.TypeByName("DSPAddPlanet.Plugin"); if (type == null) { throw new TypeLoadException("DSPAddPlanet.Plugin was not found. mooooooon requires Zincon.DSPAddPlanetMoon2Patch 3.0.15 or newer."); } PropertyInfo propertyInfo = AccessTools.Property(type, "Instance"); orderedPoseUpdateField = AccessTools.Field(type, "needsOrderedPoseUpdate"); pluginInstance = propertyInfo?.GetValue(null, null); if (pluginInstance == null || orderedPoseUpdateField == null || orderedPoseUpdateField.FieldType != typeof(bool)) { throw new MissingMemberException("The installed DSPAddPlanet recursive-pose compatibility contract has changed."); } } internal static void RequireOrderedPoseUpdates() { orderedPoseUpdateField.SetValue(pluginInstance, true); } } public const string PluginGuid = "Zincon.DSPNestedMoons"; public const string PluginName = "mooooooon"; public const string PluginVersion = "1.0.2"; public const string DspAddPlanetGuid = "Zincon.DSPAddPlanetMoon2Patch"; public const string DspAddPlanetMinimumVersion = "3.0.15"; private Harmony harmony; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown try { StarGenerationPatch.ValidateTarget(); DspAddPlanetCompatibility.Initialize(); harmony = new Harmony("Zincon.DSPNestedMoons"); harmony.PatchAll(typeof(StarGenerationPatch)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"mooooooon 1.0.2 loaded. Natural recursive moon generation is enabled for new universes."); } catch (Exception arg) { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } harmony = null; ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to enable recursive moon generation:\n{arg}"); } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } harmony = null; } } [HarmonyPatch(typeof(StarGen), "CreateStarPlanets")] internal static class StarGenerationPatch { private readonly struct OrbitAnchor { internal int OrbitIndex { get; } internal float OrbitRadius { get; } internal OrbitAnchor(int orbitIndex, float orbitRadius) { OrbitIndex = orbitIndex; OrbitRadius = orbitRadius; } } private const double StarGravity = 1.3538551990520382E-06; private const double SatelliteGravity = 1.0830842106853677E-08; private const double FourPiSquared = 39.47841760435743; internal static void ValidateTarget() { MethodInfo methodInfo = AccessTools.Method(typeof(StarGen), "CreateStarPlanets", new Type[3] { typeof(GalaxyData), typeof(StarData), typeof(GameDesc) }, (Type[])null); if (methodInfo == null || methodInfo.ReturnType != typeof(void) || !methodInfo.IsStatic) { throw new MissingMethodException("StarGen.CreateStarPlanets(GalaxyData, StarData, GameDesc) has changed."); } } [HarmonyPostfix] [HarmonyPriority(800)] [HarmonyBefore(new string[] { "Zincon.DSPAddPlanetMoon2Patch" })] private static void CreateStarPlanetsPostfix(GalaxyData galaxy, StarData star) { if (galaxy != null && star?.planets != null && star.planets.Length >= 2) { ApplyNaturalLayout(galaxy, star); Plugin.DspAddPlanetCompatibility.RequireOrderedPoseUpdates(); } } private static void ApplyNaturalLayout(GalaxyData galaxy, StarData star) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) PlanetData[] planets = star.planets; bool[] array = new bool[planets.Length]; List list = new List(); for (int i = 0; i < planets.Length; i++) { PlanetData val = planets[i]; if (val == null) { throw new InvalidOperationException($"Star {star.id} contains an empty body slot at index {i}."); } array[i] = (int)val.type == 5; if (val.orbitAroundPlanet == null) { list.Add(new OrbitAnchor(val.orbitIndex, val.orbitRadius)); } } int seed = (star.seed * 397) ^ (star.id * 7919) ^ 0x4D6F6F6E; BodyLayout[] array2 = NestedMoonLayoutGenerator.Generate(array, seed); int num = 0; int num2 = 0; int val2 = 0; for (int j = 0; j < array2.Length; j++) { BodyLayout bodyLayout = array2[j]; PlanetData val3 = planets[j]; val2 = Math.Max(val2, bodyLayout.Depth); if (bodyLayout.ParentIndex < 0) { OrbitAnchor orbitAnchor = ((num < list.Count) ? list[num] : CreateAdditionalRootAnchor(star, num2 + 1)); val3.orbitAroundPlanet = null; val3.orbitAround = 0; val3.orbitIndex = orbitAnchor.OrbitIndex; val3.number = num + 1; val3.orbitRadius = orbitAnchor.OrbitRadius; val3.sunDistance = val3.orbitRadius; val3.orbitalPeriod = CalculateOrbitPeriod(val3.orbitRadius, 1.3538551990520382E-06 * (double)star.mass); num2 = val3.orbitIndex; num++; } else { PlanetData val4 = (val3.orbitAroundPlanet = planets[bodyLayout.ParentIndex]); val3.orbitAround = val4.number; val3.orbitIndex = bodyLayout.OrbitIndex; val3.number = bodyLayout.SiblingNumber; val3.orbitRadius = CalculateSatelliteOrbitRadius(star, val4, val3); val3.sunDistance = GetRootOrbitRadius(val4); val3.orbitalPeriod = CalculateOrbitPeriod(val3.orbitRadius, 1.0830842106853677E-08); } ApplyDepthRadius(galaxy, val3, bodyLayout.Depth); UpdateRuntimeRotations(val3); UpdateLuminosity(val3); val3.singularity = (EPlanetSingularity)(val3.singularity & -33); } for (int k = 0; k < array2.Length; k++) { if (array2[k].Children.Count > 0) { PlanetData obj = planets[k]; obj.singularity = (EPlanetSingularity)(obj.singularity | 0x20); } } Plugin.DspAddPlanetCompatibility.RequireOrderedPoseUpdates(); } private static OrbitAnchor CreateAdditionalRootAnchor(StarData star, int requestedIndex) { int num = Math.Max(1, requestedIndex); float orbitRadius; if (num < StarGen.orbitRadius.Length) { orbitRadius = StarGen.orbitRadius[num] * star.orbitScaler; } else { int num2 = StarGen.orbitRadius.Length - 1; float num3 = StarGen.orbitRadius[num2] - StarGen.orbitRadius[num2 - 1]; orbitRadius = (StarGen.orbitRadius[num2] + num3 * (float)(num - num2)) * star.orbitScaler; } return new OrbitAnchor(num, orbitRadius); } private static float CalculateSatelliteOrbitRadius(StarData star, PlanetData parent, PlanetData satellite) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) DotNet35Random val = new DotNet35Random(satellite.infoSeed); double num = val.NextDouble(); double num2 = val.NextDouble(); float num3 = Mathf.Pow(1.2f, (float)(num * (num2 - 0.5) * 0.5)); return ((1600f * (float)satellite.orbitIndex + 200f) * Mathf.Pow(star.orbitScaler, 0.3f) * Mathf.Lerp(num3, 1f, 0.5f) + parent.realRadius) / 40000f; } private static double CalculateOrbitPeriod(float orbitRadius, double gravity) { double num = orbitRadius; return Math.Sqrt(39.47841760435743 * num * num * num / gravity); } private static float GetRootOrbitRadius(PlanetData body) { PlanetData val = body; while (val.orbitAroundPlanet != null) { val = val.orbitAroundPlanet; } return val.orbitRadius; } private static void ApplyDepthRadius(GalaxyData galaxy, PlanetData body, int depth) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 float radiusForDepth = NestedMoonLayoutGenerator.GetRadiusForDepth(depth, body.radius); if (!(Math.Abs(radiusForDepth - body.radius) < 0.01f)) { body.radius = radiusForDepth; if ((int)body.type != 5) { body.scale = 1f; body.precision = 200; body.segment = 5; } if (body.id >= 0 && body.id < galaxy.astrosData.Length) { galaxy.astrosData[body.id].uRadius = body.realRadius; } } } private static void UpdateRuntimeRotations(PlanetData body) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Quaternion val = Quaternion.AngleAxis(body.orbitLongitude, Vector3.up) * Quaternion.AngleAxis(body.orbitInclination, Vector3.forward); body.runtimeOrbitRotation = ((body.orbitAroundPlanet == null) ? val : (body.orbitAroundPlanet.runtimeOrbitRotation * val)); body.runtimeSystemRotation = body.runtimeOrbitRotation * Quaternion.AngleAxis(body.obliquity, Vector3.forward); } private static void UpdateLuminosity(PlanetData body) { body.luminosity = Mathf.Pow(body.star.lightBalanceRadius / (body.sunDistance + 0.01f), 0.6f); if (body.luminosity > 1f) { body.luminosity = Mathf.Log(body.luminosity) + 1f; body.luminosity = Mathf.Log(body.luminosity) + 1f; body.luminosity = Mathf.Log(body.luminosity) + 1f; } body.luminosity = Mathf.Round(body.luminosity * 100f) / 100f; } } }