Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SimpleOrbit v0.2.15
SimpleOrbit.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using SimpleOrbit.Core; using SimpleOrbit.Features; using SimpleOrbit.Space; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; using UnityEngine.Experimental.Rendering; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SimpleOrbit { internal enum FallMode { Rescue, Kill } internal enum MaskSpot { ButtonPanel, WhereYouOpened } internal enum SpaceStyle { Procedural, Classic } internal enum MoonColorSource { Auto, Table, Planet } internal enum SkyPaletteChoice { Auto, RedPurple, TealBlue, GoldOrange, Green, Pink, DeepSparse, IcyBlue, Violet, Ember, Aurora, EmberBelt, GoldenGiant, EmeraldVeil, CrimsonRift, DeepLagoon, Borealis, GlacierHalo, RoseNebula, VoidDiamond, AmethystStorm } internal static class ModConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> YieldToOriginals; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> SyncWithModdedPlayers; internal static ConfigEntry<bool> DoorInOrbit; internal static ConfigEntry<bool> UseShipDoorButtons; internal static ConfigEntry<string> ToggleKey; internal static ConfigEntry<bool> HideFromOthers; internal static ConfigEntry<MaskSpot> OthersSeeYouAt; internal static ConfigEntry<bool> BlockDropsOutside; internal static ConfigEntry<bool> AllowWhileRouting; internal static ConfigEntry<bool> CloseOnTeleport; internal static ConfigEntry<FallMode> FallBehaviour; internal static ConfigEntry<float> FallLimit; internal static ConfigEntry<float> MaxDistance; internal static ConfigEntry<bool> LadderInOrbit; internal static ConfigEntry<bool> ShowShipExterior; internal static ConfigEntry<string> ExteriorParts; internal static ConfigEntry<bool> StarSky; internal static ConfigEntry<float> SkyRotationSpeed; internal static ConfigEntry<bool> RotateSceneSky; internal static ConfigEntry<float> StarSphereScale; internal static ConfigEntry<bool> PlanetOrbit; internal static ConfigEntry<float> OrbitPeriod; internal static ConfigEntry<float> OrbitTilt; internal static ConfigEntry<float> PlanetSpin; internal static ConfigEntry<float> EaseInSeconds; internal static ConfigEntry<SpaceStyle> Style; internal static ConfigEntry<bool> NoFogInOrbit; internal static ConfigEntry<SkyPaletteChoice> SkyPalette; internal static ConfigEntry<float> SkyBrightness; internal static ConfigEntry<float> StarDensity; internal static ConfigEntry<float> NebulaStrength; internal static ConfigEntry<float> NebulaAmount; internal static ConfigEntry<int> SkyResolution; internal static ConfigEntry<int> CachedMoons; internal static ConfigEntry<bool> HugeMoon; internal static ConfigEntry<float> MoonSize; internal static ConfigEntry<float> MoonTopEdge; internal static ConfigEntry<float> MoonDrift; internal static ConfigEntry<float> MoonBrightness; internal static ConfigEntry<MoonColorSource> MoonColors; internal static ConfigEntry<float> MoonAtmosphere; internal static ConfigEntry<int> MoonResolution; internal static ConfigEntry<bool> HighDetailMoon; internal static ConfigEntry<bool> DiskCache; internal static ConfigEntry<int> DiskCacheMB; internal static ConfigEntry<bool> PrebakeMoons; internal static ConfigEntry<bool> MoonLightOnShip; internal static ConfigEntry<float> MoonLightStrength; internal static ConfigEntry<bool> ForceStaticAmbient; internal static ConfigEntry<bool> HullTopLight; internal static ConfigEntry<float> HullTopLightStrength; internal static ConfigEntry<bool> MoonPlacementVariance; internal static ConfigEntry<float> MoonPlacementAzimuthRange; internal static ConfigEntry<float> MoonPlacementHeightRange; internal static ConfigEntry<float> MoonPlacementSizeRange; internal static ConfigEntry<float> MoonPlacementDriftRange; internal static ConfigEntry<bool> OrbitalMotion; internal static ConfigEntry<float> OrbitalSpeed; internal static ConfigEntry<float> OrbitalSwing; internal static ConfigEntry<float> OrbitalSpin; internal static ConfigEntry<bool> SpaceLooks; internal static ConfigEntry<bool> RingedPlanets; internal static ConfigEntry<bool> AsteroidBelts; internal static ConfigEntry<bool> PlanetStaysInView; internal static ConfigEntry<bool> MovingSun; internal static ConfigEntry<float> SunCycleMinutes; internal static ConfigEntry<float> SunSize; internal static ConfigEntry<float> SunBrightness; internal static ConfigEntry<float> MoonNightSide; internal static ConfigEntry<float> SunMaxPhase; internal static ConfigEntry<bool> EclipsedSun; internal static ConfigEntry<bool> RoutingRumble; internal static ConfigEntry<float> RumbleVolume; internal static ConfigEntry<bool> RumbleShipMotorLayer; internal static ConfigEntry<bool> RumbleCameraShake; internal static ConfigEntry<bool> TransitionFade; internal static ConfigEntry<float> FadeSeconds; internal static void Init(ConfigFile cfg) { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Expected O, but got Unknown //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Expected O, but got Unknown //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Expected O, but got Unknown //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Expected O, but got Unknown //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Expected O, but got Unknown //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Expected O, but got Unknown //IL_04b3: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Expected O, but got Unknown //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Expected O, but got Unknown //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Expected O, but got Unknown //IL_0557: Unknown result type (might be due to invalid IL or missing references) //IL_0561: Expected O, but got Unknown //IL_05aa: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Expected O, but got Unknown //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Expected O, but got Unknown //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0624: Expected O, but got Unknown //IL_0652: Unknown result type (might be due to invalid IL or missing references) //IL_065c: Expected O, but got Unknown //IL_06a5: Unknown result type (might be due to invalid IL or missing references) //IL_06af: Expected O, but got Unknown //IL_06e4: Unknown result type (might be due to invalid IL or missing references) //IL_06ee: Expected O, but got Unknown //IL_074f: Unknown result type (might be due to invalid IL or missing references) //IL_0759: Expected O, but got Unknown //IL_07bd: Unknown result type (might be due to invalid IL or missing references) //IL_07c7: Expected O, but got Unknown //IL_082b: Unknown result type (might be due to invalid IL or missing references) //IL_0835: Expected O, but got Unknown //IL_087e: Unknown result type (might be due to invalid IL or missing references) //IL_0888: Expected O, but got Unknown //IL_08b6: Unknown result type (might be due to invalid IL or missing references) //IL_08c0: Expected O, but got Unknown //IL_08ee: Unknown result type (might be due to invalid IL or missing references) //IL_08f8: Expected O, but got Unknown //IL_0926: Unknown result type (might be due to invalid IL or missing references) //IL_0930: Expected O, but got Unknown //IL_0979: Unknown result type (might be due to invalid IL or missing references) //IL_0983: Expected O, but got Unknown //IL_09b1: Unknown result type (might be due to invalid IL or missing references) //IL_09bb: Expected O, but got Unknown //IL_09e9: Unknown result type (might be due to invalid IL or missing references) //IL_09f3: Expected O, but got Unknown //IL_0aa8: Unknown result type (might be due to invalid IL or missing references) //IL_0ab2: Expected O, but got Unknown //IL_0ae0: Unknown result type (might be due to invalid IL or missing references) //IL_0aea: Expected O, but got Unknown //IL_0b18: Unknown result type (might be due to invalid IL or missing references) //IL_0b22: Expected O, but got Unknown //IL_0b50: Unknown result type (might be due to invalid IL or missing references) //IL_0b5a: Expected O, but got Unknown //IL_0b88: Unknown result type (might be due to invalid IL or missing references) //IL_0b92: Expected O, but got Unknown //IL_0bf6: Unknown result type (might be due to invalid IL or missing references) //IL_0c00: Expected O, but got Unknown //IL_0c7f: Unknown result type (might be due to invalid IL or missing references) //IL_0c89: Expected O, but got Unknown Enabled = cfg.Bind<bool>("1. General", "Enabled", true, "Master switch."); YieldToOriginals = cfg.Bind<bool>("1. General", "YieldToOriginals", true, "If Celestial Tint or ShipWindows are still installed, switch off the SimpleOrbit features they overlap with instead of fighting them."); DebugLogging = cfg.Bind<bool>("1. General", "DebugLogging", false, "Extra log lines."); SyncWithModdedPlayers = cfg.Bind<bool>("1. General", "SyncWithModdedPlayers", true, "Players who also have SimpleOrbit see the real thing: the shared orbit door opens/closes for them and they see your real position and movement while vanilla players still see you standing inside (needs the HOST to have SimpleOrbit; with a vanilla host everything stays local, as before). The moon placement and turning always match between SimpleOrbit players; with a SimpleOrbit host its space-look settings are used by everyone. Uses the game connection's own named messages, which vanilla players never receive."); DoorInOrbit = cfg.Bind<bool>("2. Door", "DoorInOrbit", true, "Let the ship door open in orbit. Only on YOUR screen: nobody else's door moves and no door message is sent."); UseShipDoorButtons = cfg.Bind<bool>("2. Door", "UseShipDoorButtons", true, "In orbit, the ship's own open/close buttons work the local door (the vanilla button press is swallowed, so it never reaches the network)."); ToggleKey = cfg.Bind<string>("2. Door", "DoorToggleKey", "O", "Key that toggles the orbit door, in orbit only (Unity Input System key name, e.g. O, F7, Backslash). None = ship buttons only. Ignored while typing in chat, in the terminal or in a menu."); HideFromOthers = cfg.Bind<bool>("2. Door", "HideFromOthers", true, "From the moment you open the orbit door until it is shut again and you are back inside, everyone else is told you are standing still inside the ship (where: OthersSeeYouAt). Position, look direction, walk/jump/climb animations are all held, using the normal vanilla messages only. Leave on."); OthersSeeYouAt = cfg.Bind<MaskSpot>("2. Door", "OthersSeeYouAt", MaskSpot.ButtonPanel, "With HideFromOthers: where the others see you while the orbit door is open. ButtonPanel = standing on the floor in front of the door button panel, facing it. WhereYouOpened = the spot you were standing on when you opened the door (if that is too close to the doorway: the last spot you stood well inside)."); BlockDropsOutside = cfg.Bind<bool>("2. Door", "BlockDropsOutside", true, "Stop dropping/placing items while outside in orbit (others would see the item appear in space)."); AllowWhileRouting = cfg.Bind<bool>("2. Door", "AllowWhileRouting", true, "Allow staying outside while the ship flies to another moon. Off = you are put back inside when routing starts."); CloseOnTeleport = cfg.Bind<bool>("2. Door", "CloseOnTeleport", true, "Close the local door when you get teleported (ship teleporter etc.)."); FallBehaviour = cfg.Bind<FallMode>("2. Door", "FallBehaviour", FallMode.Rescue, "What happens if you fall off the ship or float too far: Rescue = put back inside, no damage. Kill = normal vanilla death (you stay dead until the next round ends - not recommended)."); FallLimit = cfg.Bind<float>("2. Door", "FallLimit", 8f, new ConfigDescription("Metres below the ship floor that count as falling off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 200f), Array.Empty<object>())); MaxDistance = cfg.Bind<float>("2. Door", "MaxDistance", 60f, new ConfigDescription("Metres from the ship you may wander before being put back inside.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 500f), Array.Empty<object>())); LadderInOrbit = cfg.Bind<bool>("2. Door", "LadderInOrbit", true, "While the orbit door is open, the ship's outside ladder can be climbed (up to the roof). Your screen only; others keep seeing you at the closed door."); ShowShipExterior = cfg.Bind<bool>("3. Exterior", "ShowShipExterior", true, "While the door is open in orbit, show the ship's outside parts (catwalk, thrusters, machinery, lights post) if the game has them hidden. Local copies, no scripts, no network objects."); ExteriorParts = cfg.Bind<string>("3. Exterior", "ExteriorParts", "OutsideShipRoom,ShipLightsPost,ThrusterBackLeft,ThrusterBackRight,ThrusterFrontLeft,ThrusterFrontRight,SideMachineryLeft,SideMachineryRight,ShipSupportBeams,ShipSupportBeams.001,MeterBoxDevice.001", "Names of the ship objects to show in orbit, comma separated."); StarSky = cfg.Bind<bool>("4. Sky", "StarSky", true, "Show the game's own star sphere around you in orbit (the one used in the fired cutscene)."); SkyRotationSpeed = cfg.Bind<float>("4. Sky", "SkyRotationSpeed", 0.6f, new ConfigDescription("Degrees per second the stars turn. Negative turns the other way, 0 = still.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-10f, 10f), Array.Empty<object>())); RotateSceneSky = cfg.Bind<bool>("4. Sky", "RotateSceneSky", true, "Also turn the ship scene's own HDRI / physically based sky in orbit (restored before landing)."); StarSphereScale = cfg.Bind<float>("4. Sky", "StarSphereScale", 0f, new ConfigDescription("0 = automatic (sphere is made big enough to sit behind the planet and sun). Otherwise a fixed scale multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); PlanetOrbit = cfg.Bind<bool>("5. Planet", "PlanetOrbit", true, "Make the moon/planet slowly orbit the ship (passes overhead)."); OrbitPeriod = cfg.Bind<float>("5. Planet", "OrbitPeriodSeconds", 600f, new ConfigDescription("Seconds for one full orbit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 7200f), Array.Empty<object>())); OrbitTilt = cfg.Bind<float>("5. Planet", "OrbitTiltDegrees", 25f, new ConfigDescription("Tilt of the orbit. 0 = goes straight over the top of the ship.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 85f), Array.Empty<object>())); PlanetSpin = cfg.Bind<float>("5. Planet", "PlanetSpinDegreesPerSecond", 1f, new ConfigDescription("How fast the planet turns on its own axis.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-30f, 30f), Array.Empty<object>())); EaseInSeconds = cfg.Bind<float>("5. Planet", "EaseInSeconds", 6f, new ConfigDescription("Orbit and sky motion speed up gently over this many seconds after arriving in orbit, so nothing jumps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); Style = cfg.Bind<SpaceStyle>("6. Space", "SpaceStyle", SpaceStyle.Procedural, "Procedural = 0.2.0 look: a generated star + nebula sky that is different for every moon, and the huge bright moon below the ship (drawn as part of the sky, so it is always behind everything). Classic = the 0.1.1 look (vanilla star sphere + vanilla planet orbiting overhead, sections 4 and 5)."); NoFogInOrbit = cfg.Bind<bool>("6. Space", "NoFogInOrbit", true, "Switch off HDRP fog / volumetric fog / local fog volumes on YOUR screen while in orbit, so space is clean and crisp. Put back exactly as it was before landing."); SkyPalette = cfg.Bind<SkyPaletteChoice>("6. Space", "SkyPalette", SkyPaletteChoice.Auto, "Auto = each moon gets its own nebula colours and layout (vanilla moons hand-picked, modded moons picked from the moon's name, always the same for the same moon). Or force one palette everywhere."); SkyBrightness = cfg.Bind<float>("6. Space", "SkyBrightness", 1f, new ConfigDescription("Brightness of stars and nebulae.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 8f), Array.Empty<object>())); StarDensity = cfg.Bind<float>("6. Space", "StarDensity", 1f, new ConfigDescription("Multiplier on the number of stars.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>())); NebulaStrength = cfg.Bind<float>("6. Space", "NebulaStrength", 1f, new ConfigDescription("Multiplier on nebula cloud brightness. 0 = stars only.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); NebulaAmount = cfg.Bind<float>("6. Space", "NebulaAmount", 0.45f, new ConfigDescription("0.2.12: how much of the swirly nebula clouds to show, on every moon. 1 = the full 0.2.11 nebula; lower = fewer and thinner clouds, dimmer and less saturated (more black space between them); 0 = none (stars, galaxy band and belts stay). Your own screen only.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SkyResolution = cfg.Bind<int>("6. Space", "SkyResolution", 1024, new ConfigDescription("Size of each face of the generated sky cubemap. 1024 = crisp, 512 = lighter on old laptops (about 4x less memory).", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[4] { 256, 512, 1024, 2048 }), Array.Empty<object>())); CachedMoons = cfg.Bind<int>("6. Space", "CachedMoons", 2, new ConfigDescription("How many moons' generated textures are kept in memory (about 60 MB per moon at 1024). The current and the next moon are always kept.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 12), Array.Empty<object>())); HugeMoon = cfg.Bind<bool>("7. Moon", "HugeMoon", true, "Procedural style only: the current moon is huge, bright and right below the ship, slowly drifting past. Off = the vanilla planet does the 0.1.1 overhead orbit instead (section 5). Needs PlanetOrbit=true."); MoonSize = cfg.Bind<float>("7. Moon", "MoonSizeDegrees", 48f, new ConfigDescription("Angular radius of the moon in degrees (how much of the view it fills).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 80f), Array.Empty<object>())); MoonTopEdge = cfg.Bind<float>("7. Moon", "MoonHorizonDegrees", -3f, new ConfigDescription("Where the moon's top edge sits. 0.2.7: always kept in the door view - the top edge ends up between +1 and +10 degrees above eye level, this value + 9 (so -3 = about +6).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-30f, 15f), Array.Empty<object>())); MoonDrift = cfg.Bind<float>("7. Moon", "MoonDriftDegreesPerSecond", 0.08f, new ConfigDescription("How fast the moon turns under the ship (the surface below drifts left/right). Negative = other way.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>())); MoonBrightness = cfg.Bind<float>("7. Moon", "MoonBrightness", 1f, new ConfigDescription("How bright/luminous the moon is.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 8f), Array.Empty<object>())); MoonColors = cfg.Bind<MoonColorSource>("7. Moon", "MoonColorSource", MoonColorSource.Auto, "Auto = hand-picked surface colours for vanilla moons, colours read from the moon's own planet model for modded moons. Table = hand-picked/name-based only. Planet = always read from the planet model (vanilla moons share a few planet models, so they look more alike)."); MoonAtmosphere = cfg.Bind<float>("7. Moon", "MoonAtmosphere", 0.5f, new ConfigDescription("Thin glowing rim of atmosphere along the moon's edge, tinted per moon. 0 = none. This is not fog: nothing between you and the moon is hazed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); MoonResolution = cfg.Bind<int>("7. Moon", "MoonResolution", 1024, new ConfigDescription("Size of each face of the generated moon surface cubemap (detail up close). 512 = lighter.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[4] { 256, 512, 1024, 2048 }), Array.Empty<object>())); HighDetailMoon = cfg.Bind<bool>("7. Moon", "HighDetailMoon", true, "0.2.9: bake the moon at 2048 per face (at least) and store it compressed (BC1) with mipmaps, so a moon that fills half the screen stays sharp; uses less video memory than 0.2.8's 1024 uncompressed. Baked once per moon on worker threads (a few seconds while you fly), no per-frame cost. Turns itself down to MoonResolution on weak machines (under 6 GB RAM, 4 CPU cores or 2 GB video memory). Off = MoonResolution as set."); DiskCache = cfg.Bind<bool>("7. Moon", "BakeCacheOnDisk", true, "0.2.10: keep every finished sky + moon bake on disk (BepInEx/cache/SimpleOrbit in this profile, about 15 MB per moon), so a moon you have seen before (or a pre-baked one) shows at once. Old bakes are ignored automatically when settings or SimpleOrbit's generator change."); DiskCacheMB = cfg.Bind<int>("7. Moon", "BakeCacheMaxMB", 512, new ConfigDescription("0.2.10: size limit of the bake cache folder; the least recently used bakes are deleted beyond it.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 8192), Array.Empty<object>())); PrebakeMoons = cfg.Bind<bool>("7. Moon", "PrebakeMoons", true, "0.2.10: while you idle in orbit, bake the other moons to the disk cache one by one on a single low-priority background thread, so routing anywhere later shows the full look at once."); MoonLightOnShip = cfg.Bind<bool>("7. Moon", "MoonLightOnShip", true, "While you are outside on the hull, softly light the ship from below in the moon's colour (moonlight bouncing up). Off while you are inside, so it never changes the lighting in the ship room."); MoonLightStrength = cfg.Bind<float>("7. Moon", "MoonLightStrength", 0.35f, new ConfigDescription("Strength of that moonlight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); ForceStaticAmbient = cfg.Bind<bool>("7. Moon", "ForceStaticAmbient", false, "If the ship room looks brighter than vanilla in orbit (the sky can feed HDRP's ambient light when the ship scene uses Dynamic ambient), turn this on: ambient then comes from the scene's baked sky instead of the moon/space sky."); HullTopLight = cfg.Bind<bool>("7. Moon", "HullTopLight", true, "While you are outside, a soft shadowless light from above (starlight) so the roof, ladder and railings read clearly; the moonlight only comes from below. Strongest when you are up on the ladder/roof, gentle on the catwalk. Off while you are inside."); HullTopLightStrength = cfg.Bind<float>("7. Moon", "HullTopLightStrength", 0.3f, new ConfigDescription("Strength of that light from above (same scale as MoonLightStrength).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); MoonPlacementVariance = cfg.Bind<bool>("7. Moon", "MoonPlacementVariance", true, "Every time you arrive in orbit (after take-off or a route) the moon sits somewhere a little different: around the ship, higher/lower, a bit bigger/smaller, drifting another way, turned differently, and the stars turned too. Its colours stay the same. Off = always the fixed spot from the settings above."); MoonPlacementAzimuthRange = cfg.Bind<float>("7. Moon", "MoonPlacementAzimuthRange", 60f, new ConfigDescription("How far (degrees, either side) the moon may swing around the ship away from straight out of the door. Each arrival picks the left, middle or right third of that range (never the same third twice in a row). 0.2.7: capped at 34 so the moon always fills part of the door view (the orbital swing adds up to 12 more).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 75f), Array.Empty<object>())); MoonPlacementHeightRange = cfg.Bind<float>("7. Moon", "MoonPlacementHeightRange", 7f, new ConfigDescription("How much (degrees, up or down) the moon's top edge may move from MoonHorizonDegrees. Mostly lower than higher, so it never hides behind the hull.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); MoonPlacementSizeRange = cfg.Bind<float>("7. Moon", "MoonPlacementSizeRange", 0.2f, new ConfigDescription("How much the moon's size may vary from MoonSizeDegrees (0.2 = 20% smaller to 20% bigger).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())); MoonPlacementDriftRange = cfg.Bind<float>("7. Moon", "MoonPlacementDriftRange", 0.5f, new ConfigDescription("How much the drift speed may vary (0.5 = half to one and a half times MoonDriftDegreesPerSecond); the direction is picked at random too.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>())); OrbitalMotion = cfg.Bind<bool>("9. Orbit", "OrbitalMotion", true, "The moon is no longer locked to the ship: it slowly swings across the view on a gentle arc (back and forth, so it never leaves the door view) and its surface turns on its own axis against the stars, so it reads as the ship orbiting it. Same for every player with SimpleOrbit (driven by the shared network clock). Off = the 0.2.4 fixed moon."); OrbitalSpeed = cfg.Bind<float>("9. Orbit", "OrbitalSpeed", 1f, new ConfigDescription("Speed multiplier for that motion. 1 = one full left-right-left swing every 5 minutes and the surface turns ~9 degrees a minute; 2 = twice as fast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>())); OrbitalSwing = cfg.Bind<float>("9. Orbit", "OrbitalSwingDegrees", 12f, new ConfigDescription("How far (degrees, either side of its arrival spot) the moon swings around the ship. It also rises/sinks a little (a quarter of this) along the arc. 0 = no swing, only the surface turn.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 25f), Array.Empty<object>())); OrbitalSpin = cfg.Bind<float>("9. Orbit", "OrbitalSpinDegreesPerSecond", 0.15f, new ConfigDescription("How fast the moon turns on its own (slightly tilted) axis, before OrbitalSpeed. Turns the same way the stars do, but the surface moves at a different rate, which is what makes the parallax.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SpaceLooks = cfg.Bind<bool>("6. Space", "SpaceLooks", true, "With SkyPalette = Auto: every moon gets one of 10 hand-tuned space looks (nebula colours, a galaxy band, star density/brightness, a distant ringed planet or an asteroid belt), so different moons feel different. Always clear, no fog. Off = the 0.2.5 palettes."); RingedPlanets = cfg.Bind<bool>("6. Space", "RingedPlanets", true, "Show the distant ringed planet in the looks that have one (GoldenGiant, DeepLagoon)."); AsteroidBelts = cfg.Bind<bool>("6. Space", "AsteroidBelts", true, "Show the asteroid belt in the looks that have one (EmberBelt, RoseNebula): a band of rocks and faint dust a little above the horizon all the way round."); PlanetStaysInView = cfg.Bind<bool>("6. Space", "PlanetStaysInView", true, "The ringed planet hangs in the door view (beside the moon, above the horizon) and the stars slowly wheel around it. Off = it turns with the stars like everything else, so it is only in the door view part of the time."); MovingSun = cfg.Bind<bool>("10. Sun", "MovingSun", true, "A sun that really lights the moon, so its phase changes over time: 0.2.11: lit from above, swinging out to either side up to SunMaxPhaseDegrees (set that to 180 for the 0.2.7 cycle through crescent and dark; the unlit side stays faintly visible, see MoonNightSide). Driven by the shared network clock, so everyone with SimpleOrbit sees the same. Off = the 0.2.5 evenly self-lit moon."); SunCycleMinutes = cfg.Bind<float>("10. Sun", "SunCycleMinutes", 20f, new ConfigDescription("Minutes for one full cycle of the moon's phases (full -> half -> crescent -> dark -> crescent -> half -> full).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 120f), Array.Empty<object>())); SunSize = cfg.Bind<float>("10. Sun", "SunSizeDegrees", 1.6f, new ConfigDescription("Apparent diameter of the sun disk in degrees (the real Sun from Earth is 0.53).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>())); SunBrightness = cfg.Bind<float>("10. Sun", "SunBrightness", 1f, new ConfigDescription("Brightness of the sun disk and its glow (not of the moonlight).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 4f), Array.Empty<object>())); MoonNightSide = cfg.Bind<float>("10. Sun", "MoonNightSide", 0.15f, new ConfigDescription("How bright the unlit side of the moon still is with MovingSun / EclipsedSun (0 = black, 1 = as bright as the lit side, i.e. no phases).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SunMaxPhase = cfg.Bind<float>("10. Sun", "SunMaxPhaseDegrees", 60f, new ConfigDescription("0.2.11: how far the moving sun swings away from behind the ship (0 = always full, 90 = half lit, 180 = the 0.2.7-0.2.10 cycle through crescent and dark). The moon is so close that a crescent turns the whole side facing you dark with a bright ring round the edge (the dark 'bullseye'), so by default the sun stays on your side: lit from above, swinging to either side up to this angle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 180f), Array.Empty<object>())); EclipsedSun = cfg.Bind<bool>("10. Sun", "EclipsedSun", true, "When the moon you are orbiting has Eclipsed weather, the sun sits right behind the moon's edge (the part of the edge nearest the door view, above eye level) as a dark disc with a glowing corona ring; the moon is lit from behind, so it shows as a dark silhouette with a glowing rim. Needs HugeMoon."); RoutingRumble = cfg.Bind<bool>("8. Travel", "RoutingRumble", true, "When the ship flies to another moon, play a deep engine rumble that builds, holds and fades (your screen/speakers only)."); RumbleVolume = cfg.Bind<float>("8. Travel", "RumbleVolume", 0.8f, new ConfigDescription("Rumble loudness.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), Array.Empty<object>())); RumbleShipMotorLayer = cfg.Bind<bool>("8. Travel", "RumbleShipMotorLayer", true, "Layer the ship's own motor sound (pitched down) into the rumble."); RumbleCameraShake = cfg.Bind<bool>("8. Travel", "RumbleCameraShake", true, "Gentle camera shakes while travelling (the game's own small shake). Vanilla v81 has no screen-shake setting, so this is the switch."); TransitionFade = cfg.Bind<bool>("8. Travel", "TransitionFade", true, "When routing, the old moon sinks away and the sky dims, then the new moon's sky fades in and the new moon rises on arrival. Off = instant switch."); FadeSeconds = cfg.Bind<float>("8. Travel", "FadeSeconds", 2.5f, new ConfigDescription("Length of each fade.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>())); } internal static int EffectiveMoonResolution(out string why) { int value = MoonResolution.Value; why = "MoonResolution"; if (!HighDetailMoon.Value || value >= 2048) { return value; } int systemMemorySize = SystemInfo.systemMemorySize; int graphicsMemorySize = SystemInfo.graphicsMemorySize; int processorCount = Environment.ProcessorCount; if ((systemMemorySize > 0 && systemMemorySize < 6000) || processorCount < 4 || (graphicsMemorySize > 0 && graphicsMemorySize < 2000)) { why = $"HighDetailMoon held back on this machine ({systemMemorySize} MB RAM, {graphicsMemorySize} MB VRAM, {processorCount} cores)"; return value; } why = "HighDetailMoon"; return 2048; } } [BepInPlugin("local.simpleorbit", "SimpleOrbit", "0.2.15")] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("local.simpleorbit"); public static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static bool CelestialTintPresent { get; private set; } internal static bool ShipWindowsPresent { get; private set; } internal static bool CelestialTintEditPresent { get; private set; } internal static bool DoorAllowed { get { if (ModConfig.DoorInOrbit.Value) { if (ModConfig.YieldToOriginals.Value) { return !CelestialTintPresent; } return true; } return false; } } private static bool SkyNotYielded { get { if (ModConfig.YieldToOriginals.Value) { if (!CelestialTintPresent) { return !ShipWindowsPresent; } return false; } return true; } } private static bool PlanetNotYielded { get { if (ModConfig.YieldToOriginals.Value) { return !CelestialTintPresent; } return true; } } private static bool Procedural => LookSync.Style == SpaceStyle.Procedural; internal static bool ProceduralSky { get { if (Procedural && ModConfig.StarSky.Value) { return SkyNotYielded; } return false; } } internal static bool ProceduralMoon { get { if (Procedural && ModConfig.HugeMoon.Value && ModConfig.PlanetOrbit.Value && SkyNotYielded) { return PlanetNotYielded; } return false; } } internal static bool SkyAllowed { get { if (ModConfig.StarSky.Value && SkyNotYielded && !ProceduralSky) { return !ProceduralMoon; } return false; } } internal static bool PlanetAllowed { get { if (ModConfig.PlanetOrbit.Value && PlanetNotYielded) { return !ProceduralMoon; } return false; } } internal static bool FogOffAllowed => ModConfig.NoFogInOrbit.Value; internal static bool RumbleAllowed { get { if (ModConfig.RoutingRumble.Value) { if (ModConfig.YieldToOriginals.Value) { return !CelestialTintEditPresent; } return true; } return false; } } internal static bool ExteriorAllowed { get { if (ModConfig.ShowShipExterior.Value) { if (ModConfig.YieldToOriginals.Value) { return !CelestialTintPresent; } return true; } return false; } } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; ModConfig.Init(((BaseUnityPlugin)this).Config); if (!ModConfig.Enabled.Value) { Logger.LogInfo((object)"SimpleOrbit v0.2.15 is switched off in its config."); return; } CelestialTintPresent = Chainloader.PluginInfos.ContainsKey("CelestialTint"); ShipWindowsPresent = Chainloader.PluginInfos.ContainsKey("TestAccount666.ShipWindows"); CelestialTintEditPresent = Chainloader.PluginInfos.ContainsKey("Piggy.CelestialTintEdit"); if (CelestialTintPresent || ShipWindowsPresent || CelestialTintEditPresent) { Logger.LogWarning((object)("Found " + (CelestialTintPresent ? "Celestial Tint " : "") + (CelestialTintEditPresent ? "Celestial Tint Edit " : "") + (ShipWindowsPresent ? "ShipWindows " : "") + "- SimpleOrbit replaces them. " + (ModConfig.YieldToOriginals.Value ? "Overlapping SimpleOrbit features are switched off until you remove them." : "YieldToOriginals is off, so both will run (expect fights)."))); } ((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs e) { object obj; if (e == null) { obj = null; } else { ConfigEntryBase changedSetting = e.ChangedSetting; obj = ((changedSetting != null) ? changedSetting.Definition.Section : null); } if (obj == null) { obj = ""; } string text = (string)obj; object obj2; if (e == null) { obj2 = null; } else { ConfigEntryBase changedSetting2 = e.ChangedSetting; obj2 = ((changedSetting2 != null) ? changedSetting2.Definition.Key : null); } if (obj2 == null) { obj2 = ""; } string text2 = (string)obj2; if (text2 == "SyncWithModdedPlayers" && !ModConfig.SyncWithModdedPlayers.Value) { LookCache.Invalidate(); } if (text.StartsWith("4.") || text.StartsWith("5.") || text.StartsWith("6.") || text.StartsWith("7.") || text.StartsWith("9.") || text.StartsWith("10.")) { OrbitNet.HostLookChanged(); } if (!text.StartsWith("9.") && !text.StartsWith("10.") && !(text2 == "PlanetStaysInView") && !text2.StartsWith("MoonPlacement") && (text.StartsWith("4.") || text.StartsWith("5.") || text.StartsWith("6.") || text.StartsWith("7."))) { LookCache.Invalidate(); } }; LookCache.InitDisk(); ((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs e) { object obj; if (e == null) { obj = null; } else { ConfigEntryBase changedSetting = e.ChangedSetting; obj = ((changedSetting != null) ? changedSetting.Definition.Key : null); } if (obj == null) { obj = ""; } string text = (string)obj; if (text == "BakeCacheOnDisk" || text == "BakeCacheMaxMB") { LookCache.InitDisk(); } }; _harmony.PatchAll(); Logger.LogInfo((object)"SimpleOrbit v0.2.15 loaded (client-side only, no new network messages)."); Logger.LogInfo((object)string.Format("Space: style={0} sky={1} moon={2} noFog={3} rumble={4}", ModConfig.Style.Value, ProceduralSky ? "procedural" : (SkyAllowed ? "classic" : "off"), ProceduralMoon ? "huge" : (PlanetAllowed ? "classic orbit" : "off"), FogOffAllowed, RumbleAllowed)); Logger.LogInfo((object)string.Format("Looks: {0} (palette {1}), ringed planets {2} (stay in view {3}), asteroid belts {4}; moving sun {5} ({6:0.#} min/turn), eclipsed sun {7}", ModConfig.SpaceLooks.Value ? "10 hand-tuned looks" : "0.2.5 palettes", ModConfig.SkyPalette.Value, ModConfig.RingedPlanets.Value, ModConfig.PlanetStaysInView.Value, ModConfig.AsteroidBelts.Value, ModConfig.MovingSun.Value, ModConfig.SunCycleMinutes.Value, ModConfig.EclipsedSun.Value)); Logger.LogInfo((object)string.Format("Orbital motion: {0}, speed x{1:0.##}, swing ±{2:0.#}°, spin {3:0.###}°/s", ModConfig.OrbitalMotion.Value ? "on" : "off", ModConfig.OrbitalSpeed.Value, ModConfig.OrbitalSwing.Value, ModConfig.OrbitalSpin.Value)); Logger.LogInfo((object)string.Format("Orbit door: {0}, ship buttons={1}, key={2}, debug={3}", DoorAllowed ? "on" : (ModConfig.DoorInOrbit.Value ? "OFF (Celestial Tint is installed and YieldToOriginals is on)" : "off (DoorInOrbit=false)"), ModConfig.UseShipDoorButtons.Value, ModConfig.ToggleKey.Value, ModConfig.DebugLogging.Value)); } internal static void Debug(string msg) { if (ModConfig.DebugLogging.Value) { Logger.LogInfo((object)msg); } } } public static class PluginInfo { public const string Guid = "local.simpleorbit"; public const string Name = "SimpleOrbit"; public const string Version = "0.2.15"; } } namespace SimpleOrbit.Space { internal static class BakeStore { internal const string BakeVersion = "sob-0.2.13-1"; private const uint Magic = 843206483u; internal static string Dir; internal static long MaxBytes = 536870912L; private static readonly object Lock = new object(); private static readonly HashSet<string> NotInKey = new HashSet<string> { "Key", "WaterMask", "MaskRes", "HasFeature", "FeatureX", "FeatureY", "FeatureZ", "MoonLight", "AirTint", "Source", "Blurb" }; internal static bool Enabled => !string.IsNullOrEmpty(Dir); internal static string KeyOf(LookInfo info) { StringBuilder stringBuilder = new StringBuilder(2048); stringBuilder.Append("sob-0.2.13-1").Append('|'); Append(stringBuilder, info, 0); using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(stringBuilder.ToString())); StringBuilder stringBuilder2 = new StringBuilder(24); for (int i = 0; i < 10; i++) { stringBuilder2.Append(array[i].ToString("x2")); } return stringBuilder2.ToString(); } private static void Append(StringBuilder sb, object o, int depth) { if (o == null) { sb.Append("null;"); return; } Type type = o.GetType(); if (type.IsPrimitive || type.IsEnum || o is string || o is decimal) { sb.Append(Convert.ToString(o, CultureInfo.InvariantCulture)).Append(';'); return; } if (o is float num) { sb.Append(num.ToString("R", CultureInfo.InvariantCulture)).Append(';'); return; } if (depth > 4) { sb.Append("deep;"); return; } if (o is Array array) { sb.Append('['); foreach (object item in array) { Append(sb, item, depth + 1); } sb.Append(']'); return; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Array.Sort(fields, (FieldInfo a, FieldInfo b) => string.CompareOrdinal(a.Name, b.Name)); sb.Append('{'); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { if (!NotInKey.Contains(fieldInfo.Name)) { sb.Append(fieldInfo.Name).Append('='); Append(sb, fieldInfo.GetValue(o), depth + 1); } } sb.Append('}'); } internal static string PathOf(LookInfo info) { if (!Enabled) { return null; } StringBuilder stringBuilder = new StringBuilder(); string text = Palettes.CleanName(info.MoonName); foreach (char c in text) { stringBuilder.Append(char.IsLetterOrDigit(c) ? c : '_'); } if (stringBuilder.Length > 32) { stringBuilder.Length = 32; } return Path.Combine(Dir, $"{stringBuilder}-{KeyOf(info)}.sobake"); } internal static bool TryLoad(string path, LookInfo info, out byte[][] sky, out byte[][][] moonBc, out byte[][] moonRgba, out string why) { sky = null; moonBc = null; moonRgba = null; why = "miss"; if (path == null) { why = "disk cache off"; return false; } try { if (!File.Exists(path)) { return false; } using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 65536)) { using BinaryReader binaryReader = new BinaryReader(fileStream); if (binaryReader.ReadUInt32() != 843206483 || binaryReader.ReadString() != "sob-0.2.13-1") { throw new InvalidDataException("old format"); } int num = binaryReader.ReadInt32(); int num2 = binaryReader.ReadInt32(); int num3 = binaryReader.ReadInt32(); bool hasFeature = binaryReader.ReadBoolean(); float featureX = binaryReader.ReadSingle(); float featureY = binaryReader.ReadSingle(); float featureZ = binaryReader.ReadSingle(); if (num != info.SkyRes || (info.WantMoon && num2 != info.MoonRes)) { throw new InvalidDataException("size mismatch"); } if (info.WantMoon && num3 != (info.Compress ? 1 : 2)) { throw new InvalidDataException("format mismatch"); } using GZipStream s = new GZipStream(fileStream, CompressionMode.Decompress); sky = new byte[6][]; for (int i = 0; i < 6; i++) { sky[i] = ReadExact(s, num * num * 4); } switch (num3) { case 1: { int num4 = Bc1.MipCount(num2); moonBc = new byte[6][][]; for (int k = 0; k < 6; k++) { moonBc[k] = new byte[num4][]; int num5 = num2; for (int l = 0; l < num4; l++) { int num6 = Math.Max(1, (num5 + 3) / 4); moonBc[k][l] = ReadExact(s, num6 * num6 * 8); num5 = Math.Max(1, num5 >> 1); } } break; } case 2: { moonRgba = new byte[6][]; for (int j = 0; j < 6; j++) { moonRgba[j] = ReadExact(s, num2 * num2 * 4); } break; } } info.HasFeature = hasFeature; info.FeatureX = featureX; info.FeatureY = featureY; info.FeatureZ = featureZ; } try { File.SetLastWriteTimeUtc(path, DateTime.UtcNow); } catch (Exception) { } why = "hit"; return true; } catch (Exception ex2) { sky = null; moonBc = null; moonRgba = null; why = "unreadable (" + ex2.GetType().Name + ": " + ex2.Message + "), baking again"; try { File.Delete(path); } catch (Exception) { } return false; } } private static byte[] ReadExact(Stream s, int n) { byte[] array = new byte[n]; int num; for (int i = 0; i < n; i += num) { num = s.Read(array, i, n - i); if (num <= 0) { throw new EndOfStreamException(); } } return array; } internal static long Save(string path, LookInfo info, byte[][] sky, byte[][][] moonBc, byte[][] moonRgba) { if (path == null || sky == null) { return 0L; } lock (Lock) { Directory.CreateDirectory(Path.GetDirectoryName(path)); string text = path + "." + Guid.NewGuid().ToString("N").Substring(0, 8) + ".tmp"; try { using (FileStream fileStream = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.None, 65536)) { using (BinaryWriter binaryWriter = new BinaryWriter(fileStream, Encoding.UTF8, leaveOpen: true)) { binaryWriter.Write(843206483u); binaryWriter.Write("sob-0.2.13-1"); binaryWriter.Write(info.SkyRes); binaryWriter.Write(info.MoonRes); binaryWriter.Write((moonBc != null) ? 1 : ((moonRgba != null) ? 2 : 0)); binaryWriter.Write(info.HasFeature); binaryWriter.Write(info.FeatureX); binaryWriter.Write(info.FeatureY); binaryWriter.Write(info.FeatureZ); } using GZipStream gZipStream = new GZipStream(fileStream, CompressionLevel.Fastest); foreach (byte[] array in sky) { gZipStream.Write(array, 0, array.Length); } if (moonBc != null) { foreach (byte[][] array2 in moonBc) { byte[][] array3 = array2; foreach (byte[] array4 in array3) { gZipStream.Write(array4, 0, array4.Length); } } } else if (moonRgba != null) { foreach (byte[] array5 in moonRgba) { gZipStream.Write(array5, 0, array5.Length); } } } if (File.Exists(path)) { File.Delete(path); } File.Move(text, path); } finally { try { if (File.Exists(text)) { File.Delete(text); } } catch (Exception) { } } Prune(path); return new FileInfo(path).Length; } } internal static int DropOldVersions(out long bytes) { bytes = 0L; int num = 0; if (!Enabled) { return 0; } lock (Lock) { try { FileInfo[] files = new DirectoryInfo(Dir).GetFiles("*.sobake"); foreach (FileInfo fileInfo in files) { string text = null; try { using FileStream input = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 256); using BinaryReader binaryReader = new BinaryReader(input); if (binaryReader.ReadUInt32() == 843206483) { text = binaryReader.ReadString(); } } catch (Exception) { } if (!(text == "sob-0.2.13-1")) { try { long length = fileInfo.Length; fileInfo.Delete(); bytes += length; num++; } catch (Exception) { } } } } catch (Exception) { } } return num; } internal static bool Has(LookInfo info) { string text = PathOf(info); if (text != null) { return File.Exists(text); } return false; } private static void Prune(string keep) { try { List<FileInfo> list = new List<FileInfo>(new DirectoryInfo(Path.GetDirectoryName(keep)).GetFiles("*.sobake")); long num = 0L; foreach (FileInfo item in list) { num += item.Length; } list.Sort((FileInfo a, FileInfo b) => a.LastWriteTimeUtc.CompareTo(b.LastWriteTimeUtc)); foreach (FileInfo item2 in list) { if (num > MaxBytes) { if (!string.Equals(item2.FullName, Path.GetFullPath(keep), StringComparison.OrdinalIgnoreCase)) { num -= item2.Length; item2.Delete(); } continue; } break; } FileInfo[] files = new DirectoryInfo(Path.GetDirectoryName(keep)).GetFiles("*.tmp"); foreach (FileInfo fileInfo in files) { if (fileInfo.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1.0)) { fileInfo.Delete(); } } } catch (Exception) { } } } internal static class Bc1 { private static readonly float[] ToLin = BuildToLin(); private static readonly byte[] ToSrgb = BuildToSrgb(); private const int SrgbLutSize = 4096; private static float[] BuildToLin() { float[] array = new float[256]; for (int i = 0; i < 256; i++) { array[i] = Noise.SrgbToLinear((float)i / 255f); } return array; } private static byte[] BuildToSrgb() { byte[] array = new byte[4097]; for (int i = 0; i <= 4096; i++) { array[i] = Noise.ToSrgbByte((float)i / 4096f); } return array; } internal static int MipCount(int n) { int num = 1; while (n > 1) { n >>= 1; num++; } return num; } internal static byte[][][] Chain(byte[][] faces, int n, int threads) { byte[][][] array = new byte[6][][]; ParallelOptions po = new ParallelOptions { MaxDegreeOfParallelism = Math.Max(1, threads) }; for (int i = 0; i < 6; i++) { array[i] = ChainFace(faces[i], n, po); faces[i] = null; } return array; } internal static byte[][] ChainFace(byte[] face, int n, ParallelOptions po) { int num = MipCount(n); byte[][] array = new byte[num][]; byte[] array2 = face; int num2 = n; for (int i = 0; i < num; i++) { array[i] = Encode(array2, num2, po); if (i + 1 < num) { array2 = Down(array2, num2, po); num2 = Math.Max(1, num2 >> 1); } } return array; } internal static byte[] BlendFace(byte[] preview, int pr, byte[] full, int n, float t, ParallelOptions po) { byte[] dst = new byte[n * n * 4]; int ti = (int)(Math.Max(0f, Math.Min(1f, t)) * 256f + 0.5f); float k = (float)pr / (float)n; Parallel.For(0, n, po, delegate(int y) { float num = ((float)y + 0.5f) * k - 0.5f; int num2 = Math.Max(0, Math.Min(pr - 1, (int)Math.Floor(num))); int num3 = Math.Min(pr - 1, num2 + 1); float num4 = Math.Max(0f, Math.Min(1f, num - (float)num2)); for (int i = 0; i < n; i++) { float num5 = ((float)i + 0.5f) * k - 0.5f; int num6 = Math.Max(0, Math.Min(pr - 1, (int)Math.Floor(num5))); int num7 = Math.Min(pr - 1, num6 + 1); float num8 = Math.Max(0f, Math.Min(1f, num5 - (float)num6)); int num9 = (y * n + i) * 4; int num10 = (num2 * pr + num6) * 4; int num11 = (num2 * pr + num7) * 4; int num12 = (num3 * pr + num6) * 4; int num13 = (num3 * pr + num7) * 4; for (int j = 0; j < 3; j++) { float num14 = (float)(int)preview[num10 + j] + (float)(preview[num11 + j] - preview[num10 + j]) * num8; float num15 = (float)(int)preview[num12 + j] + (float)(preview[num13 + j] - preview[num12 + j]) * num8; int num16 = (int)(num14 + (num15 - num14) * num4 + 0.5f); dst[num9 + j] = (byte)(num16 + ((full[num9 + j] - num16) * ti >> 8)); } dst[num9 + 3] = byte.MaxValue; } }); return dst; } private static byte[] Down(byte[] src, int w, ParallelOptions po) { int h = Math.Max(1, w >> 1); byte[] dst = new byte[h * h * 4]; Parallel.For(0, h, po, delegate(int y) { for (int i = 0; i < h; i++) { int num = (y * h + i) * 4; for (int j = 0; j < 3; j++) { int num2 = (2 * y * w + 2 * i) * 4 + j; float num3 = ToLin[src[num2]] + ToLin[src[num2 + 4]] + ToLin[src[num2 + w * 4]] + ToLin[src[num2 + w * 4 + 4]]; dst[num + j] = ToSrgb[(int)(num3 * 0.25f * 4096f + 0.5f)]; } dst[num + 3] = byte.MaxValue; } }); return dst; } internal static byte[] Encode(byte[] rgba, int w, ParallelOptions po) { int bw = Math.Max(1, (w + 3) / 4); byte[] dst = new byte[bw * bw * 8]; Parallel.For(0, bw, po, delegate(int by) { int[] array = new int[48]; for (int i = 0; i < bw; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { int num = Math.Min(w - 1, i * 4 + k); int num2 = Math.Min(w - 1, by * 4 + j); int num3 = (num2 * w + num) * 4; int num4 = (j * 4 + k) * 3; array[num4] = rgba[num3]; array[num4 + 1] = rgba[num3 + 1]; array[num4 + 2] = rgba[num3 + 2]; } } EncodeBlock(array, dst, (by * bw + i) * 8); } }); return dst; } private static void EncodeBlock(int[] p, byte[] dst, int o) { int num = 255; int num2 = 255; int num3 = 255; int num4 = 0; int num5 = 0; int num6 = 0; float num7 = 0f; float num8 = 0f; float num9 = 0f; for (int i = 0; i < 48; i += 3) { int num10 = p[i]; int num11 = p[i + 1]; int num12 = p[i + 2]; if (num10 < num) { num = num10; } if (num10 > num4) { num4 = num10; } if (num11 < num2) { num2 = num11; } if (num11 > num5) { num5 = num11; } if (num12 < num3) { num3 = num12; } if (num12 > num6) { num6 = num12; } num7 += (float)num10; num8 += (float)num11; num9 += (float)num12; } num7 /= 16f; num8 /= 16f; num9 /= 16f; float num13 = 0f; float num14 = 0f; for (int j = 0; j < 48; j += 3) { float num15 = (float)p[j] - num7; num13 += num15 * ((float)p[j + 1] - num8); num14 += num15 * ((float)p[j + 2] - num9); } float num16 = num4; float num17 = num; float num18 = num5; float num19 = num2; float num20 = num6; float num21 = num3; if (num13 < 0f) { num18 = num2; num19 = num5; } if (num14 < 0f) { num20 = num3; num21 = num6; } float num22 = (num16 - num17) / 16f; float num23 = (num18 - num19) / 16f; float num24 = (num20 - num21) / 16f; num16 -= num22; num17 += num22; num18 -= num23; num19 += num23; num20 -= num24; num21 += num24; int num25 = Pack(num16, num18, num20); int num26 = Pack(num17, num19, num21); if (num25 < num26) { int num27 = num25; num25 = num26; num26 = num27; } uint num28 = 0u; if (num25 != num26) { Unpack(num25, out var r, out var g, out var b); Unpack(num26, out var r2, out var g2, out var b2); int[] array = new int[4] { r, r2, (2 * r + r2) / 3, (r + 2 * r2) / 3 }; int[] array2 = new int[4] { g, g2, (2 * g + g2) / 3, (g + 2 * g2) / 3 }; int[] array3 = new int[4] { b, b2, (2 * b + b2) / 3, (b + 2 * b2) / 3 }; for (int num29 = 15; num29 >= 0; num29--) { int num30 = p[num29 * 3]; int num31 = p[num29 * 3 + 1]; int num32 = p[num29 * 3 + 2]; int num33 = 0; int num34 = int.MaxValue; for (int k = 0; k < 4; k++) { int num35 = num30 - array[k]; int num36 = num31 - array2[k]; int num37 = num32 - array3[k]; int num38 = 3 * num35 * num35 + 4 * num36 * num36 + 2 * num37 * num37; if (num38 < num34) { num34 = num38; num33 = k; } } num28 = (num28 << 2) | (uint)num33; } } dst[o] = (byte)num25; dst[o + 1] = (byte)(num25 >> 8); dst[o + 2] = (byte)num26; dst[o + 3] = (byte)(num26 >> 8); dst[o + 4] = (byte)num28; dst[o + 5] = (byte)(num28 >> 8); dst[o + 6] = (byte)(num28 >> 16); dst[o + 7] = (byte)(num28 >> 24); } private static int Pack(float r, float g, float b) { int num = Math.Max(0, Math.Min(31, (int)(r * 31f / 255f + 0.5f))); int num2 = Math.Max(0, Math.Min(63, (int)(g * 63f / 255f + 0.5f))); int num3 = Math.Max(0, Math.Min(31, (int)(b * 31f / 255f + 0.5f))); return (num << 11) | (num2 << 5) | num3; } private static void Unpack(int c, out int r, out int g, out int b) { int num = (c >> 11) & 0x1F; int num2 = (c >> 5) & 0x3F; int num3 = c & 0x1F; r = (num << 3) | (num >> 2); g = (num2 << 2) | (num2 >> 4); b = (num3 << 3) | (num3 >> 2); } internal static byte[] Decode(byte[] bc, int w) { int num = Math.Max(1, (w + 3) / 4); byte[] array = new byte[w * w * 4]; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { int num2 = (i * num + j) * 8; int num3 = bc[num2] | (bc[num2 + 1] << 8); int num4 = bc[num2 + 2] | (bc[num2 + 3] << 8); uint num5 = (uint)(bc[num2 + 4] | (bc[num2 + 5] << 8) | (bc[num2 + 6] << 16) | (bc[num2 + 7] << 24)); Unpack(num3, out var r, out var g, out var b); Unpack(num4, out var r2, out var g2, out var b2); int[] array2; int[] array3; int[] array4; if (num3 > num4) { array2 = new int[4] { r, r2, (2 * r + r2) / 3, (r + 2 * r2) / 3 }; array3 = new int[4] { g, g2, (2 * g + g2) / 3, (g + 2 * g2) / 3 }; array4 = new int[4] { b, b2, (2 * b + b2) / 3, (b + 2 * b2) / 3 }; } else { array2 = new int[4] { r, r2, (r + r2) / 2, 0 }; array3 = new int[4] { g, g2, (g + g2) / 2, 0 }; array4 = new int[4] { b, b2, (b + b2) / 2, 0 }; } for (int k = 0; k < 16; k++) { int num6 = j * 4 + (k & 3); int num7 = i * 4 + (k >> 2); if (num6 < w && num7 < w) { int num8 = (int)((num5 >> 2 * k) & 3); int num9 = (num7 * w + num6) * 4; array[num9] = (byte)array2[num8]; array[num9 + 1] = (byte)array3[num8]; array[num9 + 2] = (byte)array4[num8]; array[num9 + 3] = byte.MaxValue; } } } } return array; } } internal static class MoonGen { private struct CraterLayer { public float M00; public float M01; public float M02; public float M10; public float M11; public float M12; public float M20; public float M21; public float M22; public float Scale; public float Presence; public float Depth; public int Seed; } private struct BigCrater { public float X; public float Y; public float Z; public float R; } private struct Ctx { public MoonPalette P; public CraterLayer[] Layers; public BigCrater[] Big; public int SL; public int SD; public int SR; public int SA; public int SI; public int SDn; public int SM; public int SC; public int SV; public int SV2; public int SF; public int SK; public int SS; public int SN; public int SW; public float O1; public float O2; public float O3; public float Sea; public int SMs; public int SSt; public int SDs; public float Wx; public float Wy; public float Wz; public float E1x; public float E1y; public float E1z; public float E2x; public float E2y; public float E2z; } private const int S = 4; [ThreadStatic] internal static bool Background; internal static volatile bool Hold; private const int MaskRes = 64; private const int FLg = 0; private const int FMd = 1; private const int FRg = 2; private const int FCn = 3; private const int FRv = 4; private const int FRv2 = 5; private const int FFo = 6; private const int FCl = 7; private const int FAc = 8; private const int FIc = 9; private const int FDw = 10; private const int FSc = 11; private const int FInd = 12; private const int FMs = 13; private const int FSt = 14; private const int FDs = 15; private const int FCount = 16; private static void Yield() { while (Background && Hold) { Thread.Sleep(25); } } internal static byte[][] Generate(LookInfo info, int threads) { int n = info.MoonRes; MoonPalette p = info.Moon; Rng rng = new Rng(info.Seed ^ 0xA11CE); float[] array = new float[7] { 3.2f, 6f, 11f, 21f, 40f, 80f, 150f }; float[] array2 = new float[7] { 0.45f, 0.55f, 0.6f, 0.65f, 0.7f, 0.7f, 0.65f }; float[] array3 = new float[7] { 0.22f, 0.16f, 0.11f, 0.07f, 0.045f, 0.025f, 0.014f }; CraterLayer[] layers = new CraterLayer[array.Length]; for (int i = 0; i < layers.Length; i++) { RandomRotation(ref rng, out var l); l.Scale = array[i]; float num = p.Craters; if (p.Water > 0f || p.Forest > 0f) { num *= ((i < 3) ? 0.5f : 0.35f); } l.Presence = Math.Min(0.95f, array2[i] * (0.35f + 0.65f * Math.Min(1.4f, num))); l.Depth = array3[i] * num; l.Seed = rng.Int(1000000); layers[i] = l; } int sL = rng.Int(100000); int sD = rng.Int(100000); int sR = rng.Int(100000); int sA = rng.Int(100000); int sI = rng.Int(100000); int sG = rng.Int(100000); int sDn = rng.Int(100000); int sM = rng.Int(100000); int sC = rng.Int(100000); int sV = rng.Int(100000); int sV2 = rng.Int(100000); int sF = rng.Int(100000); int sK = rng.Int(100000); int sS = rng.Int(100000); int sN = rng.Int(100000); int sW = rng.Int(100000); int sT = rng.Int(100000); float o1 = rng.Range(-40f, 40f); float o2 = rng.Range(-40f, 40f); float o3 = rng.Range(-40f, 40f); rng.UnitVector(out var dax, out var day, out var daz); rng.UnitVector(out var sax, out var say, out var saz); rng.UnitVector(out var lx, out var ly, out var lz); Rng rng2 = new Rng(info.Seed ^ 0xD0577); rng2.UnitVector(out var wdx, out var wdy, out var wdz); Perp(wdx, wdy, wdz, out var e1x, out var e1y, out var e1z, out var e2x, out var e2y, out var e2z); rng2.UnitVector(out var dbx, out var dby, out var dbz); int sMs = rng2.Int(100000); int sSt = rng2.Int(100000); int sDs = rng2.Int(100000); int sMo = rng2.Int(100000); BigCrater[] big = new BigCrater[Math.Max(0, p.BigCraters)]; for (int j = 0; j < big.Length; j++) { rng.UnitVector(out var x, out var y, out var z); y = 0.35f * y; float num2 = 1f / (float)Math.Sqrt(x * x + y * y + z * z); big[j] = new BigCrater { X = x * num2, Y = y * num2, Z = z * num2, R = p.BigCraterSize * ((j == 0) ? 1f : rng.Range(0.3f, 0.55f)) }; } Ctx ctx = new Ctx { P = p, Layers = layers, Big = big, SL = sL, SD = sD, SR = sR, SA = sA, SI = sI, SDn = sDn, SM = sM, SC = sC, SV = sV, SV2 = sV2, SF = sF, SK = sK, SS = sS, SN = sN, SW = sW, O1 = o1, O2 = o2, O3 = o3, SMs = sMs, SSt = sSt, SDs = sDs, Wx = wdx, Wy = wdy, Wz = wdz, E1x = e1x, E1y = e1y, E1z = e1z, E2x = e2x, E2y = e2y, E2z = e2z }; float sea = -10f; if (p.Water > 0f) { Rng rng3 = new Rng(info.Seed ^ 0x5EA); float[] array4 = new float[4000]; for (int k = 0; k < 4000; k++) { rng3.UnitVector(out var x2, out var y2, out var z2); array4[k] = LandCoarse(ref ctx, x2, y2, z2); } Array.Sort(array4); sea = array4[Math.Min(3999, (int)(Math.Min(0.95f, p.Water) * 4000f))]; } ctx.Sea = sea; int w = n + 2; int cw = (w - 1) / 4 + 2; float[] height = new float[w * w]; float[] land = new float[w * w]; float[] fine = new float[w * w]; float[][] coarse = new float[16][]; for (int m = 0; m < 16; m++) { coarse[m] = new float[cw * cw]; } byte[][] array5 = new byte[6][]; byte[][] array6 = new byte[6][]; ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Math.Max(1, threads) }; float texelAngle = 2f / (float)n; float cavK = 2.2f * (float)n / 512f; float detail = Math.Max(0f, p.Detail); float microK = 512f / (float)n; for (int num3 = 0; num3 < 6; num3++) { int face = num3; Parallel.For(0, cw, parallelOptions, delegate(int cy) { float v = 2f * ((float)(cy * 4 - 1) + 0.5f) / (float)n - 1f; for (int num6 = 0; num6 < cw; num6++) { float u = 2f * ((float)(num6 * 4 - 1) + 0.5f) / (float)n - 1f; CubeMath.Dir(face, u, v, out var x3, out var y3, out var z3); int i2 = cy * cw + num6; CoarseFields(ref ctx, x3, y3, z3, coarse, i2); } }); Parallel.For(0, w, parallelOptions, delegate(int gy) { Yield(); float v = 2f * ((float)(gy - 1) + 0.5f) / (float)n - 1f; int num6 = gy / 4; float fy = (float)(gy - num6 * 4) / 4f; for (int num7 = 0; num7 < w; num7++) { float u = 2f * ((float)(num7 - 1) + 0.5f) / (float)n - 1f; int num8 = num7 / 4; float fx = (float)(num7 - num8 * 4) / 4f; CubeMath.Dir(face, u, v, out var x3, out var y3, out var z3); float num9 = Bilerp(coarse[0], cw, num8, num6, fx, fy); float num10 = Bilerp(coarse[1], cw, num8, num6, fx, fy); float num11 = Noise.Fbm(x3 * 16f + o2, y3 * 16f + o1, z3 * 16f + o3, 3, sD); float num12 = Noise.Perlin(x3 * 310f, y3 * 310f, z3 * 310f, sG); float num13 = 0.62f * num9 + 0.3f * num10 + 0.07f * num11; float num14 = 0.5f * num9 + 0.25f * num10 + 0.12f * num11 + 0.02f * detail * num12 * microK; if (p.Ridges > 0f) { float num15 = Bilerp(coarse[2], cw, num8, num6, fx, fy); num14 += 0.32f * p.Ridges * (num15 - 0.35f); } if (p.Canyons > 0f) { float v2 = Bilerp(coarse[3], cw, num8, num6, fx, fy); num14 -= 0.22f * p.Canyons * Noise.SmoothStep(0.72f, 0.93f, v2); } if (p.Dunes > 0f) { float num16 = DuneWave(x3, y3, z3, dax, day, daz, Bilerp(coarse[10], cw, num8, num6, fx, fy), num11); if (p.DuneTurn > 0f) { num16 += (DuneWave(x3, y3, z3, dbx, dby, dbz, Bilerp(coarse[10], cw, num8, num6, fx, fy) * 0.7f, num11) - num16) * DuneSel(Bilerp(coarse[15], cw, num8, num6, fx, fy), p.DuneTurn); } num14 += 0.022f * p.Dunes * (num16 - 0.5f) * 2f * DuneField(num10); } if (p.Mesas > 0f) { float v3 = Bilerp(coarse[13], cw, num8, num6, fx, fy) + 0.06f * num11; float num17 = Noise.SmoothStep(-0.05f, 0.25f, num10); float num18 = Noise.SmoothStep(0.14f, 0.17f, v3); float num19 = Noise.SmoothStep(0.03f, 0.15f, v3) * (1f - num18); num14 += p.Mesas * num17 * (0.08f * num18 + 0.03f * num19); } if (p.Scars > 0f) { float v4 = Bilerp(coarse[11], cw, num8, num6, fx, fy) + BigRimBoost(big, x3, y3, z3); float num20 = Noise.SmoothStep(0.4f, 0.5f, v4) * p.Scars; if (num20 > 0f) { float num21 = (x3 * sax + y3 * say + z3 * saz) * 140f; num14 -= num20 * 0.05f * (num21 - (float)Math.Floor(num21)); } } num14 += Craters(layers, x3, y3, z3); num14 += BigCraters(big, x3, y3, z3, out var _); int num22 = gy * w + num7; if (num13 < sea) { num14 = Math.Max(num14, 0.15f * num14); } height[num22] = num14; land[num22] = num13; fine[num22] = num11; } }); byte[] bytes = new byte[n * n * 4]; int[] mk = new int[4096]; int mStep = Math.Max(1, n / 64); Parallel.For(0, n, parallelOptions, delegate(int py) { Yield(); float num6 = 2f * ((float)py + 0.5f) / (float)n - 1f; int num7 = py + 1; int num8 = num7 / 4; float fy = (float)(num7 - num8 * 4) / 4f; for (int num9 = 0; num9 < n; num9++) { float num10 = 2f * ((float)num9 + 0.5f) / (float)n - 1f; int num11 = num9 + 1; int num12 = num11 / 4; float fx = (float)(num11 - num12 * 4) / 4f; CubeMath.Dir(face, num10, num6, out var x3, out var y3, out var z3); int num13 = num7 * w + num11; float num14 = height[num13]; float num15 = land[num13]; float num16 = num14 - 0.25f * (height[num13 - 1] + height[num13 + 1] + height[num13 - w] + height[num13 + w]); float num17 = 0.5f * (height[num13 + 1] - height[num13 - 1]); float num18 = 0.5f * (height[num13 + w] - height[num13 - w]); CubeMath.Dir(face, num10 + texelAngle * 0.5f, num6, out var x4, out var y4, out var z4); CubeMath.Dir(face, num10, num6 + texelAngle * 0.5f, out var x5, out var y5, out var z5); float num19 = x4 - x3; float num20 = y4 - y3; float num21 = z4 - z3; float num22 = x5 - x3; float num23 = y5 - y3; float num24 = z5 - z3; float num25 = 1f / Math.Max(1E-09f, (float)Math.Sqrt(num19 * num19 + num20 * num20 + num21 * num21)); float num26 = 1f / Math.Max(1E-09f, (float)Math.Sqrt(num22 * num22 + num23 * num23 + num24 * num24)); float num27 = x3 * lx + y3 * ly + z3 * lz; float num28 = lx - x3 * num27; float num29 = ly - y3 * num27; float num30 = lz - z3 * num27; float num31 = (num28 * num19 + num29 * num20 + num30 * num21) * num25; float num32 = (num28 * num22 + num29 * num23 + num30 * num24) * num26; float num33 = (0f - (num17 * num31 + num18 * num32)) / texelAngle * 0.035f; float num34 = 1f + Math.Max(-0.45f, Math.Min(0.45f, num16 * cavK + num33)); float num35 = Bilerp(coarse[0], cw, num12, num8, fx, fy); float num36 = Bilerp(coarse[1], cw, num12, num8, fx, fy); float num37 = Math.Abs(y3); float num38 = Noise.Perlin(x3 * 310f, y3 * 310f, z3 * 310f, sG); float num39 = Noise.Clamp01(0.52f + 0.85f * num14 + 0.22f * num35 + 0.12f * num36); Rgb rgb = ((num39 < 0.5f) ? Rgb.Lerp(p.Dark, p.Mid, num39 * 2f) : Rgb.Lerp(p.Mid, p.Light, (num39 - 0.5f) * 2f)); if (p.Maria > 0f) { rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Dark, p.Mid, 0.3f), Noise.SmoothStep(0.1f, 0.55f, 0f - num35) * p.Maria * 0.55f); } if (p.AccentAmount > 0f) { float v = Bilerp(coarse[8], cw, num12, num8, fx, fy); rgb = Rgb.Lerp(rgb, p.Accent, Noise.SmoothStep(0.22f, 0.62f, v) * p.AccentAmount); } if (p.Mottle > 0f) { float v2 = 0.6f * Noise.Perlin(x3 * 38f + o1, y3 * 38f + o2, z3 * 38f + o3, sMo) + 0.4f * fine[num13]; rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Accent, p.Mid, 0.25f), p.Mottle * 0.3f * Noise.SmoothStep(0.05f, 0.45f, v2)); rgb *= 1f + p.Mottle * 0.1f * Noise.Perlin(x3 * 11f + o3, y3 * 11f + o1, z3 * 11f + o2, sMo + 1); } if (p.Dunes > 0f) { float num40 = DuneWave(x3, y3, z3, dax, day, daz, Bilerp(coarse[10], cw, num12, num8, fx, fy), fine[num13]); if (p.DuneTurn > 0f) { num40 += (DuneWave(x3, y3, z3, dbx, dby, dbz, Bilerp(coarse[10], cw, num12, num8, fx, fy) * 0.7f, fine[num13]) - num40) * DuneSel(Bilerp(coarse[15], cw, num12, num8, fx, fy), p.DuneTurn); } float num41 = DuneField(num36) * p.Dunes; rgb *= 1f + (0.12f + 0.1f * Math.Min(1f, p.DuneTurn)) * num41 * (num40 - 0.5f); rgb = Rgb.Lerp(rgb, p.Light, 0.16f * num41 * num40 * num40); } if (p.Canyons > 0f) { float v3 = Bilerp(coarse[3], cw, num12, num8, fx, fy); float num42 = Noise.SmoothStep(0.7f, 0.93f, v3) * p.Canyons; float num43 = Noise.SmoothStep(0.62f, 0.8f, v3) * (1f - Noise.SmoothStep(0.86f, 0.97f, v3)); rgb = Rgb.Lerp(rgb, p.Dark * 0.8f, 0.55f * num43 * p.Canyons); rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Dark, p.Accent, 0.35f), 0.45f * num42); } if (p.Mesas > 0f) { float num44 = Bilerp(coarse[13], cw, num12, num8, fx, fy) + 0.06f * fine[num13]; float num45 = Noise.SmoothStep(-0.05f, 0.25f, num36) * p.Mesas; float num46 = Noise.SmoothStep(0.14f, 0.17f, num44); float num47 = Noise.SmoothStep(0.03f, 0.15f, num44) * (1f - num46); float num48 = 0.5f + 0.5f * (float)Math.Sin(num44 * 180f + 1.5f * fine[num13]); rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Dark, p.Accent, 0.5f) * (0.75f + 0.4f * num48), 0.5f * num45 * num47); rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Mid, p.Light, 0.55f), 0.3f * num45 * num46); rgb = Rgb.Lerp(rgb, p.Light, 0.35f * num45 * Bump(num44, 0.165f, 0.012f)); } if (p.Streaks > 0f) { float num49 = x3 * wdx + y3 * wdy + z3 * wdz; float num50 = x3 * e1x + y3 * e1y + z3 * e1z; float num51 = x3 * e2x + y3 * e2y + z3 * e2z; float num52 = Noise.Perlin(num49 * 7f + o2, num50 * 95f + o3, num51 * 95f + o1, sMo + 2); float num53 = Bilerp(coarse[14], cw, num12, num8, fx, fy) + 0.45f * num52; rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Light, p.Mid, 0.2f), 0.3f * p.Streaks * Noise.SmoothStep(0.12f, 0.45f, num53)); rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Dark, p.Accent, 0.5f), 0.24f * p.Streaks * Noise.SmoothStep(0.15f, 0.45f, 0f - num53)); } if (p.Scars > 0f) { float v4 = Bilerp(coarse[11], cw, num12, num8, fx, fy) + BigRimBoost(big, x3, y3, z3); float num54 = Noise.SmoothStep(0.4f, 0.5f, v4) * p.Scars; if (num54 > 0f) { float num55 = (x3 * sax + y3 * say + z3 * saz) * 140f; float num56 = num55 - (float)Math.Floor(num55); Rgb b = Rgb.Lerp(p.Accent, p.Light, 0.35f + 0.45f * num56); rgb = Rgb.Lerp(rgb, b, 0.7f * num54); } } if (big.Length != 0) { BigCraters(big, x3, y3, z3, out var bd); if (bd < 1.8f) { float num57 = 1f - Noise.SmoothStep(0.7f, 0.82f, bd); float num58 = Noise.SmoothStep(0.72f, 0.86f, bd) * (1f - Noise.SmoothStep(0.97f, 1.05f, bd)); float num59 = (float)Math.Exp((0f - (bd - 0.99f) / 0.035f) * ((bd - 0.99f) / 0.035f)); float num60 = Noise.SmoothStep(1.04f, 1.12f, bd) * (1f - Noise.SmoothStep(1.2f, 1.8f, bd)); float num61 = 0.5f + 0.5f * (float)Math.Sin(bd * 45f + 2f * fine[num13]); rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Mid, p.Dark, 0.45f), 0.8f * num57); rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Dark, p.Accent, 0.25f) * (0.8f + 0.3f * num61), 0.85f * num58); rgb = Rgb.Lerp(rgb, p.Dark * 0.75f, 0.7f * num59); rgb = Rgb.Lerp(rgb, p.Light, 0.4f * num60 * (0.6f + 0.4f * fine[num13])); } } if (p.Industry > 0f) { float num62 = Bilerp(coarse[12], cw, num12, num8, fx, fy); float num63 = 0.45f - 0.35f * Math.Min(1f, p.Industry); float num64 = Noise.SmoothStep(num63 - 0.04f, num63 + 0.04f, num62 + 0.1f * fine[num13]) * Math.Min(1f, 0.5f + p.Industry); if (num64 > 0f && num15 >= sea) { float num65 = (float)n / 64f; float num66 = (num10 + 1f) * num65; float num67 = (num6 + 1f) * num65; int num68 = (int)num66; int num69 = (int)num67; float num70 = num66 - (float)num68; float num71 = num67 - (float)num69; float num72 = Noise.Hash01(num68, num69, face, sN); bool flag = num70 < 0.07f || num71 < 0.07f; int num73 = (int)(num70 * 3f); int num74 = (int)(num71 * 2f); float num75 = Noise.Hash01(num68 * 3 + num73, num69 * 2 + num74, face + 7, sN); float num76 = num70 * 3f - (float)num73; float num77 = num71 * 2f - (float)num74; bool flag2 = num76 < 0.1f || num77 < 0.1f; Rgb rgb2 = ((num72 < 0.25f) ? Rgb.Lerp(rgb, new Rgb(0.36f, 0.35f, 0.33f), 0.5f) : ((num75 < 0.4f) ? new Rgb(0.22f, 0.22f, 0.23f) : ((!(num75 < 0.92f)) ? Rgb.Lerp(new Rgb(0.45f, 0.4f, 0.35f), p.Accent, 0.45f) : new Rgb(0.55f, 0.54f, 0.51f)))); if (flag2 && num72 >= 0.25f) { rgb2 = new Rgb(0.3f, 0.3f, 0.29f); } rgb = Rgb.Lerp(rgb, flag ? new Rgb(0.26f, 0.26f, 0.26f) : rgb2, num64 * (flag ? 0.7f : 0.8f)); num34 *= 1f - 0.15f * num64 * (flag2 ? 1f : 0f); } } bool flag3 = num15 < sea; float num78 = num15 - sea; float num79 = -0.55f + 0.25f * p.Mud - (num36 + 0.25f * fine[num13]); if (!flag3 && p.Water > 0f && num78 < 0.3f && num79 > 0f) { flag3 = true; num15 = sea - 0.01f - 0.6f * num79; num78 = num15 - sea; } if (p.Forest > 0f && !flag3) { float num80 = Noise.Perlin(x3 * 260f + o1, y3 * 260f, z3 * 260f, sT + 5); Rgb b2 = Rgb.Lerp(p.ForestLight, Rgb.Lerp(p.Mid, p.Accent, p.Mud * 0.5f), 0.4f) * (0.78f + 0.25f * num80); rgb = Rgb.Lerp(rgb, b2, 0.85f * Math.Min(1f, p.Forest + 0.2f) * (1f - 0.5f * Noise.SmoothStep(0.5f, 0.9f, num78))); float num81 = Bilerp(coarse[6], cw, num12, num8, fx, fy); float num82 = 0.3f - 0.85f * Math.Min(1f, p.Forest); float num83 = Noise.Perlin(x3 * 200f, y3 * 200f, z3 * 200f, sT + 11); float num84 = Noise.SmoothStep(num82 - 0.04f, num82 + 0.04f, num81 + 0.25f * fine[num13] + 0.06f * num83); num84 *= 1f - Noise.SmoothStep(0.6f, 0.9f, num78 + 0.15f * ((p.Ridges > 0f) ? Bilerp(coarse[2], cw, num12, num8, fx, fy) : 0f)); num84 *= 1f - Noise.SmoothStep(0.7f, 0.85f, num37); if (num84 > 0f) { float num85 = Noise.Perlin(x3 * 140f + o3, y3 * 140f + o1, z3 * 140f + o2, sT); float num86 = Noise.Perlin(x3 * 420f, y3 * 420f, z3 * 420f, sT + 7); float num87 = Noise.Clamp01(0.5f + 0.55f * num85 + 0.35f * num86 * detail + 0.25f * num81); Rgb rgb3 = Rgb.Lerp(p.ForestDark, p.ForestLight, num87); float num88 = Bilerp(coarse[8], cw, num12, num8, fx, fy); rgb3 = new Rgb(rgb3.R * (1f + 0.25f * num88), rgb3.G, rgb3.B * (1f - 0.2f * num88)); if (p.Polar >= 0.6f) { rgb3 = Rgb.Lerp(rgb3, p.Snow, 0.35f * Noise.Clamp01(0.5f + num86)); } rgb = Rgb.Lerp(rgb, rgb3, num84); num34 *= 1f - 0.12f * num84 * (1f - num87); } } float num89 = 0f; if (flag3) { float v5 = sea - num15; Rgb rgb4 = Rgb.Lerp(p.WaterShallow, p.WaterDeep, Noise.SmoothStep(0f, 0.12f, v5)); rgb4 *= 1f + 0.04f * num38; rgb = rgb4; num34 = 1f + 0.25f * (num34 - 1f); num89 = 1f; } else if (p.Water > 0f && num78 < 0.03f) { float num90 = 1f - num78 / 0.03f; rgb = Rgb.Lerp(rgb, Rgb.Lerp(p.Accent, p.Mid, 0.4f) * 0.85f, 0.5f * num90); } if (p.Rivers > 0f && !flag3) { float value = Bilerp(coarse[4], cw, num12, num8, fx, fy); float value2 = Bilerp(coarse[5], cw, num12, num8, fx, fy); float num91 = 1f - Noise.SmoothStep(0.1f, 0.38f, num78); float num92 = (0.01f + 0.012f * (1f - Noise.SmoothStep(0f, 0.15f, num78))) * (0.6f + 0.6f * p.Rivers); float val = 1f - Noise.SmoothStep(num92 * 0.5f, num92, Math.Abs(value)); float num93 = 1f - Noise.SmoothStep(num92 * 0.25f, num92 * 0.55f, Math.Abs(value2)); float num94 = Math.Max(val, num93 * 0.85f) * num91 * Math.Min(1f, p.Rivers * 1.3f); if (num94 > 0f) { rgb = Rgb.Lerp(rgb, p.WaterShallow, num94); num34 = 1f + (1f - 0.7f * num94) * (num34 - 1f); num89 = Math.Max(num89, num94); } } if (p.Mud > 0f && !flag3) { float num95 = 1f - Noise.SmoothStep(0f, 0.1f, num78); float num96 = num95 * Noise.SmoothStep(-0.1f, 0.3f, fine[num13] + 0.3f * num36) * p.Mud; rgb = Rgb.Lerp(rgb, p.Accent * 0.8f, 0.65f * num96); } if (p.Ice > 0f) { float v6 = Bilerp(coarse[9], cw, num12, num8, fx, fy); float num97 = Noise.SmoothStep(0.25f, 0.55f, v6) * p.Ice; if (num14 < -0.05f) { num97 += 0.25f * p.Ice; } rgb = Rgb.Lerp(rgb, new Rgb(0.86f, 0.93f, 1f), Math.Min(1f, num97) * 0.7f); } if (p.Polar > 0f) { float num98 = Bilerp(coarse[9], cw, num12, num8, fx, fy); float num99 = 1f - 0.32f * Math.Min(1f, p.Polar); float num100 = Noise.SmoothStep(num99 - 0.03f, num99 + 0.04f, num37 + 0.06f * num98 + 0.03f * fine[num13]); float num101 = ((p.Polar < 0.5f) ? 0f : (Noise.SmoothStep(0.25f, 0.42f, num14 + 0.1f * fine[num13]) * 0.8f * p.Polar)); float t = Math.Max(num100, flag3 ? 0f : num101); rgb = Rgb.Lerp(rgb, p.Snow, t); if (flag3 && num100 > 0.5f) { num89 *= 0.3f; } } if (p.Latitude > 0f) { rgb *= 1f + p.Latitude * 0.14f * (num37 - 0.45f); } if (p.Clouds > 0f) { float num102 = Bilerp(coarse[7], cw, num12, num8, fx, fy); float num103 = Noise.SmoothStep(0.1f, 0.5f, num102 + 0.08f * fine[num13]) * Math.Min(1f, p.Clouds) * 0.8f; rgb = Rgb.Lerp(rgb * num34, p.CloudTint, num103); num34 = 1f; num89 *= 1f - num103; } float num104 = 1f + detail * (0.05f * num38 + 0.035f * Noise.Perlin(x3 * 120f, y3 * 120f, z3 * 120f, sG + 3)); rgb *= num34 * num104; int num105 = (py * n + num9) * 4; bytes[num105] = ToByte(rgb.R); bytes[num105 + 1] = ToByte(rgb.G); bytes[num105 + 2] = ToByte(rgb.B); bytes[num105 + 3] = byte.MaxValue; if (num89 > 0f) { int num106 = Math.Min(63, py / mStep) * 64 + Math.Min(63, num9 / mStep); Interlocked.Add(ref mk[num106], (int)(num89 * 255f)); } } }); if (n >= 1024) { Sharpen(bytes, n, 0.45f, parallelOptions); } array5[num3] = bytes; byte[] array7 = new byte[4096]; float num4 = (float)mStep * (float)mStep; for (int num5 = 0; num5 < array7.Length; num5++) { array7[num5] = (byte)Math.Min(255, (int)((float)mk[num5] / num4 + 0.5f)); } array6[num3] = array7; } info.HasFeature = big.Length != 0; if (big.Length != 0) { info.FeatureX = big[0].X; info.FeatureY = big[0].Y; info.FeatureZ = big[0].Z; } info.WaterMask = ((p.Water > 0f || p.Rivers > 0f) ? array6 : null); info.MaskRes = 64; return array5; } private static float LandCoarse(ref Ctx c, float x, float y, float z) { float num = Noise.Fbm(x * 1.3f + c.O1, y * 1.3f + c.O2, z * 1.3f + c.O3, 5, c.SL); float num2 = Noise.Fbm(x * 4.5f + c.O3, y * 4.5f + c.O1, z * 4.5f + c.O2, 4, c.SM); return 0.62f * num + 0.3f * num2; } private static void CoarseFields(ref Ctx c, float x, float y, float z, float[][] o, int i) { MoonPalette p = c.P; o[0][i] = Noise.Fbm(x * 1.3f + c.O1, y * 1.3f + c.O2, z * 1.3f + c.O3, 5, c.SL); o[1][i] = Noise.Fbm(x * 4.5f + c.O3, y * 4.5f + c.O1, z * 4.5f + c.O2, 4, c.SM); if (p.Ridges > 0f || p.Forest > 0f) { o[2][i] = Noise.Ridged(x * 3.2f + c.O2, y * 3.2f + c.O3, z * 3.2f + c.O1, 4, c.SR); } if (p.Canyons > 0f) { float num = Noise.Perlin(x * 2f, y * 2f, z * 2f, c.SW) * 0.25f; float num2 = Noise.Perlin(x * 2f + 5f, y * 2f, z * 2f, c.SW) * 0.25f; o[3][i] = Noise.Ridged(x * 2.6f + num + c.O1, y * 2.6f + num2 + c.O3, z * 2.6f + c.O2, 4, c.SC); } if (p.Rivers > 0f) { float num3 = Noise.Perlin(x * 3f, y * 3f, z * 3f, c.SW + 1) * 0.35f; float num4 = Noise.Perlin(x * 3f + 7f, y * 3f, z * 3f, c.SW + 1) * 0.35f; o[4][i] = Noise.Fbm(x * 3.6f + num3, y * 3.6f + num4, z * 3.6f, 4, c.SV); o[5][i] = Noise.Fbm(x * 9f + num4, y * 9f + num3, z * 9f, 3, c.SV2); } if (p.Forest > 0f) { o[6][i] = Noise.Fbm(x * 5.5f + c.O2, y * 5.5f + c.O3, z * 5.5f + c.O1, 5, c.SF); } if (p.Clouds > 0f) { float num5 = Noise.Fbm(x * 2.5f, y * 2.5f, z * 2.5f, 2, c.SK + 1) * 0.6f; o[7][i] = Noise.Fbm(x * 3.2f + num5, y * 9f, z * 3.2f - num5, 5, c.SK); } if (p.AccentAmount > 0f || p.Forest > 0f) { o[8][i] = Noise.Fbm(x * 3.5f + c.O3, y * 3.5f + c.O1, z * 3.5f + c.O2, 4, c.SA); } if (p.Ice > 0f || p.Polar > 0f) { o[9][i] = Noise.Fbm(x * 5.5f + c.O1, y * 5.5f + c.O3, z * 5.5f + c.O2, 4, c.SI); } if (p.Dunes > 0f) { o[10][i] = 16f * Noise.Fbm(x * 3f, y * 3f, z * 3f, 3, c.SDn); } if (p.Scars > 0f) { o[11][i] = Noise.Fbm(x * 5f + c.O1, y * 5f + c.O2, z * 5f + c.O3, 3, c.SS); } if (p.Mesas > 0f) { o[13][i] = Noise.Fbm(x * 4.2f + c.O2, y * 4.2f + c.O1, z * 4.2f + c.O3, 4, c.SMs); } if (p.Streaks > 0f) { float num6 = x * c.Wx + y * c.Wy + z * c.Wz; float num7 = x * c.E1x + y * c.E1y + z * c.E1z; float num8 = x * c.E2x + y * c.E2y + z * c.E2z; o[14][i] = Noise.Fbm(num6 * 2.2f + c.O1, num7 * 20f + c.O2, num8 * 20f + c.O3, 3, c.SSt); } if (p.DuneTurn > 0f) { o[15][i] = Noise.Fbm(x * 2.4f + c.O3, y * 2.4f + c.O2, z * 2.4f + c.O1, 3, c.SDs); } if (p.Industry > 0f) { o[12][i] = Noise.Fbm(x * 2.8f + c.O2, y * 2.8f + c.O1, z * 2.8f + c.O3, 3, c.SN); } } private static float DuneWave(float x, float y, float z, float dax, float day, float daz, float warp, float fine) { float num = (x * dax + y * day + z * daz) * 150f + warp + 3.5f * fine; float num2 = 0.5f + 0.5f * (float)Math.Sin(num); return num2 * num2 * (3f - 2f * num2); } private static void Sharpen(byte[] px, int n, float amount, ParallelOptions po) { byte[] src = (byte[])px.Clone(); Parallel.For(0, n, po, delegate(int y) { int yy = Math.Max(0, y - 1); int yy2 = Math.Min(n - 1, y + 1); for (int i = 0; i < n; i++) { int xx = Math.Max(0, i - 1); int xx2 = Math.Min(n - 1, i + 1); int c; for (c = 0; c < 3; c++) { float num = (float)(Cc(xx, yy) + 2 * Cc(i, yy) + Cc(xx2, yy) + 2 * Cc(xx, y) + 4 * Cc(i, y) + 2 * Cc(xx2, y) + Cc(xx, yy2) + 2 * Cc(i, yy2) + Cc(xx2, yy2)) / 16f; float num2 = Cc(i, y); float num3 = num2 + amount * (num2 - num); px[(y * n + i) * 4 + c] = (byte)((!(num3 <= 0f)) ? ((num3 >= 255f) ? byte.MaxValue : ((byte)(num3 + 0.5f))) : 0); } } }); int Cc(int xx, int yy) { return src[(yy * n + xx) * 4 + P_2.c]; } } private static float DuneSel(float ds, float turn) { return Math.Min(1f, turn) * Noise.SmoothStep(-0.12f, 0.12f, ds); } private static float Bump(float v, float c, float w) { float num = (v - c) / w; if (!(num * num >= 1f)) { return (1f - num * num) * (1f - num * num); } return 0f; } private static void Perp(float x, float y, float z, out float ax, out float ay, out float az, out float bx, out float by, out float bz) { float num = ((Math.Abs(x) < 0.9f) ? 1f : 0f); float num2 = 1f - num; float num3 = 0f; ax = y * num3 - z * num2; ay = z * num - x * num3; az = x * num2 - y * num; float num4 = 1f / (float)Math.Sqrt(ax * ax + ay * ay + az * az); ax *= num4; ay *= num4; az *= num4; bx = y * az - z * ay; by = z * ax - x * az; bz = x * ay - y * ax; } private static float DuneField(float md) { return 0.25f + 0.75f * Noise.SmoothStep(-0.15f, 0.35f, md); } private static float Bilerp(float[] g, int cw, int cx, int cy, float fx, float fy) { int num = cy * cw + cx; float num2 = g[num] + (g[num + 1] - g[num]) * fx; float num3 = g[num + cw] + (g[num + cw + 1] - g[num + cw]) * fx; return num2 + (num3 - num2) * fy; } private static byte ToByte(float s) { if (!(s <= 0f)) { if (!(s >= 1f)) { return (byte)(s * 255f + 0.5f); } return byte.MaxValue; } return 0; } private static float BigCraters(BigCrater[] big, float x, float y, float z, out float bd) { bd = 99f; float num = 0f; for (int i = 0; i < big.Length; i++) { float val = x * big[i].X + y * big[i].Y + z * big[i].Z; float num2 = (float)Math.Acos(Math.Max(-1f, Math.Min(1f, val))); float num3 = num2 / big[i].R; if (num3 < bd) { bd = num3; } if (!(num3 > 2f)) { float num4 = -0.16f; float num5; if (num3 < 0.74f) { num5 = num4; } else if (num3 < 1f) { float num6 = Noise.SmoothStep(0.74f, 1f, num3); num5 = num4 + 0.27f * num6; } else { num5 = 0.11f * (float)Math.Exp((0f - (num3 - 1f)) * 4f); } num += num5 * (big[i].R / 0.32f); } } return num; } private static float BigRimBoost(BigCrater[] big, float x, float y, float z) { if (big.Length == 0) { return 0f; } BigCraters(big, x, y, z, out var bd); if (!(bd < 0.75f)) { return 0.35f * (float)Math.Exp((0f - (bd - 1.3f)) * (bd - 1.3f) / 0.06f); } return 0f; } private static float Craters(CraterLayer[] layers, float x, float y, float z) { float num = 0f; for (int i = 0; i < layers.Length; i++) { ref CraterLayer reference = ref layers[i]; if (reference.Depth <= 0f) { continue; } float num2 = (reference.M00 * x + reference.M01 * y + reference.M02 * z) * reference.Scale; float num3 = (reference.M10 * x + reference.M11 * y + reference.M12 * z) * reference.Scale; float num4 = (reference.M20 * x + reference.M21 * y + reference.M22 * z) * reference.Scale; int num5 = ((num2 >= 0f) ? ((int)num2) : ((int)num2 - 1)); int num6 = ((num3 >= 0f) ? ((int)num3) : ((int)num3 - 1)); int num7 = ((num4 >= 0f) ? ((int)num4) : ((int)num4 - 1)); if (!(Noise.Hash01(num5, num6, num7, reference.Seed) > reference.Presence)) { float num8 = (float)num5 + 0.3f + 0.4f * Noise.Hash01(num5, num6, num7, reference.Seed + 1); float num9 = (float)num6 + 0.3f + 0.4f * Noise.Hash01(num5, num6, num7, reference.Seed + 2); float num10 = (float)num7 + 0.3f + 0.4f * Noise.Hash01(num5, num6, num7, reference.Seed + 3); float num11 = Noise.Hash01(num5, num6, num7, reference.Seed + 4); float num12 = 0.08f + 0.12f * num11 * num11; float num13 = num2 - num8; float num14 = num3 - num9; float num15 = num4 - num10; float num16 = (float)Math.Sqrt(num13 * num13 + num14 * num14 + num15 * num15) / num12; if (!(num16 > 1.45f)) { float num17 = num12 / 0.2f; float num18 = ((num16 < 1f) ? (Math.Max(num16 * num16 - 1f, -0.75f) * reference.Depth * num17) : 0f); float num19 = (num16 - 1f) / 0.22f; float num20 = 0.22f * reference.Depth * num17 * (float)Math.Exp((0f - num19) * num19); num += num18 + num20; } } } return num; } private static void RandomRotation(ref Rng rng, out CraterLayer l) { float num = rng.Float(); float num2 = rng.Range(0f, MathF.PI * 2f); float num3 = rng.Range(0f, MathF.PI * 2f); float num4 = (float)Math.Sqrt(1f - num); float num5 = (float)Math.Sqrt(num); float num6 = num4 * (float)Math.Sin(num2); float num7 = num4 * (float)Math.Cos(num2); float num8 = num5 * (float)Math.Sin(num3); float num9 = num5 * (float)Math.Cos(num3); l = new CraterLayer { M00 = 1f - 2f * (num7 * num7 + num8 * num8), M01 = 2f * (num6 * num7 - num8 * num9), M02 = 2f * (num6 * num8 + num7 * num9), M10 = 2f * (num6 * num7 + num8 * num9), M11 = 1f - 2f * (num6 * num6 + num8 * num8), M12 = 2f * (num7 * num8 - num6 * num9), M20 = 2f * (num6 * num8 - num7 * num9), M21 = 2f * (num7 * num8 + num6 * num9), M22 = 1f - 2f * (num6 * num6 + num7 * num7) }; } } internal static class Noise { private const int SrgbLutSize = 8192; private static readonly byte[] SrgbLut = BuildSrgbLut(); internal static int Hash(int x, int y, int z, int seed) { uint num = (uint)(x * 374761393 + y * 668265263 + z * 1274126177 + seed * 1442695041); num = (num ^ (num >> 13)) * 1274126177; num ^= num >> 16; num *= 2246822507u; return (int)(num ^ (num >> 13)); } internal static float Hash01(int x, int y, int z, int seed) { return (float)(Hash(x, y, z, seed) & 0xFFFFFF) / 16777216f; } private static int FastFloor(float v) { if (!(v >= 0f)) { return (int)v - 1; } return (int)v; } private static float Grad(int h, float x, float y, float z) { return (h & 0xF) switch { 0 => x + y, 1 => 0f - x + y, 2 => x - y, 3 => 0f - x - y, 4 => x + z, 5 => 0f - x + z, 6 => x - z, 7 => 0f - x - z, 8 => y + z, 9 => 0f - y + z, 10 => y - z, 11 => 0f - y - z, 12 => x + y, 13 => 0f - x + y, 14 => 0f - y + z, _ => 0f - y - z, }; } private static float Fade(float t) { return t * t * t * (t * (t * 6f - 15f) + 10f); } internal static float Perlin(float x, float y, float z, int seed) { int num = FastFloor(x); int num2 = FastFloor(y); int num3 = FastFloor(z); float num4 = x - (float)num; float num5 = y - (float)num2; float num6 = z - (float)num3; float num7 = Fade(num4); float num8 = Fade(num5); float num9 = Fade(num6); float num10 = Grad(Hash(num, num2, num3, seed), num4, num5, num6); float num11 = Grad(Hash(num + 1, num2, num3, seed), num4 - 1f, num5, num6); float num12 = Grad(Hash(num, num2 + 1, num3, seed), num4, num5 - 1f, num6); float num13 = Grad(Hash(num + 1, num2 + 1, num3, seed), num4 - 1f, num5 - 1f, num6); float num14 = Grad(Hash(num, num2, num3 + 1, seed), num4, num5, num6 - 1f); float num15 = Grad(Hash(num + 1, num2, num3 + 1, seed), num4 - 1f, num5, num6 - 1f); float num16 = Grad(Hash(num, num2 + 1, num3 + 1, seed), num4, num5 - 1f, num6 - 1f); float num17 = Grad(Hash(num + 1, num2 + 1, num3 + 1, seed), num4 - 1f, num5 - 1f, num6 - 1f); float num18 = num10 + num7 * (num11 - num10); float num19 = num12 + num7 * (num13 - num12); float num20 = num14 + num7 * (num15 - num14); float num21 = num16 + num7 * (num17 - num16); float num22 = num18 + num8 * (num19 - num18); float num23 = num20 + num8 * (num21 - num20); return (num22 + num9 * (num23 - num22)) * 0.95f; } internal static float Fbm(float x, float y, float z, int octaves, int seed, float lacunarity = 2.03f, float gain = 0.5f) { float num = 0f; float num2 = 0.5f; float num3 = 0f; for (int i = 0; i < octaves; i++) { num += num2 * Perlin(x, y, z, seed + i * 131); num3 += num2; x *= lacunarity; y *= lacunarity; z *= lacunarity; num2 *= gain; } return num / num3 * 1.6f; } internal static float Ridged(float x, float y, float z, int octaves, int seed) { float num = 0f; float num2 = 0.5f; float nu