From b9351a28a538e7fa9b27e2c056fbde5bab19c8ae Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Tue, 1 Mar 2022 13:49:01 -0500 Subject: [PATCH] Refactor some planet stuff out of main --- .../Builder/Body/AsteroidBeltBuilder.cs | 3 +- .../Builder/General/PlanetDestroyer.cs | 5 +- NewHorizons/Components/StarController.cs | 2 +- NewHorizons/Components/StarLightController.cs | 24 +- NewHorizons/Handlers/PlanetCreationHandler.cs | 368 ++++++++++++ NewHorizons/Handlers/TitleSceneHandler.cs | 114 ++++ NewHorizons/Main.cs | 531 ++---------------- NewHorizons/Utility/AstroObjectLocator.cs | 6 +- 8 files changed, 543 insertions(+), 510 deletions(-) create mode 100644 NewHorizons/Handlers/PlanetCreationHandler.cs create mode 100644 NewHorizons/Handlers/TitleSceneHandler.cs diff --git a/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs b/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs index 07ec2d62..1ab97506 100644 --- a/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs +++ b/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs @@ -10,6 +10,7 @@ using UnityEngine; using NewHorizons.External.Configs; using Logger = NewHorizons.Utility.Logger; using Random = UnityEngine.Random; +using NewHorizons.Handlers; namespace NewHorizons.Builder.Body { @@ -64,7 +65,7 @@ namespace NewHorizons.Builder.Body var asteroidConfig = new PlanetConfig(config); if (belt.ProcGen != null) asteroidConfig.ProcGen = belt.ProcGen; var asteroid = new NewHorizonsBody(new PlanetConfig(config), mod); - Main.NextPassBodies.Add(asteroid); + PlanetCreationHandler.NextPassBodies.Add(asteroid); } } } diff --git a/NewHorizons/Builder/General/PlanetDestroyer.cs b/NewHorizons/Builder/General/PlanetDestroyer.cs index f4b11c0a..48f5db46 100644 --- a/NewHorizons/Builder/General/PlanetDestroyer.cs +++ b/NewHorizons/Builder/General/PlanetDestroyer.cs @@ -1,4 +1,5 @@ -using NewHorizons.Utility; +using NewHorizons.Components; +using NewHorizons.Utility; using OWML.Utils; using System; using System.Collections.Generic; @@ -143,7 +144,7 @@ namespace NewHorizons.Builder.General else if(ao.GetAstroObjectName() == AstroObject.Name.Sun) { var starController = ao.gameObject.GetComponent(); - Main.Instance.StarLightController.RemoveStar(starController); + StarLightController.RemoveStar(starController); GameObject.Destroy(starController); var audio = ao.GetComponentInChildren(); diff --git a/NewHorizons/Components/StarController.cs b/NewHorizons/Components/StarController.cs index 143b8ca4..a0a0dbb1 100644 --- a/NewHorizons/Components/StarController.cs +++ b/NewHorizons/Components/StarController.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using UnityEngine; -namespace NewHorizons.Utility +namespace NewHorizons.Components { public class StarController : MonoBehaviour { diff --git a/NewHorizons/Components/StarLightController.cs b/NewHorizons/Components/StarLightController.cs index c6943337..fabe441e 100644 --- a/NewHorizons/Components/StarLightController.cs +++ b/NewHorizons/Components/StarLightController.cs @@ -1,4 +1,5 @@ -using System; +using NewHorizons.Utility; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,12 +7,14 @@ using System.Threading.Tasks; using UnityEngine; using Logger = NewHorizons.Utility.Logger; -namespace NewHorizons.Utility +namespace NewHorizons.Components { [RequireComponent(typeof(SunLightController))] [RequireComponent(typeof(SunLightParamUpdater))] public class StarLightController : MonoBehaviour { + public static StarLightController Instance { get; private set; } + private List _stars = new List(); private StarController _activeStar; @@ -20,33 +23,34 @@ namespace NewHorizons.Utility public void Awake() { + Instance = this; _sunLightController = GetComponent(); _sunLightController.enabled = true; _sunLightParamUpdater = GetComponent(); _sunLightParamUpdater._sunLightController = _sunLightController; } - public void AddStar(StarController star) + public static void AddStar(StarController star) { if (star == null) return; Logger.Log($"Adding new star to list: {star.gameObject.name}"); - _stars.Add(star); + Instance._stars.Add(star); } - public void RemoveStar(StarController star) + public static void RemoveStar(StarController star) { Logger.Log($"Removing star from list: {star?.gameObject?.name}"); - if (_stars.Contains(star)) + if (Instance._stars.Contains(star)) { - if (_activeStar != null && _activeStar.Equals(star)) + if (Instance._activeStar != null && Instance._activeStar.Equals(star)) { - _stars.Remove(star); - if(_stars.Count > 0) ChangeActiveStar(_stars[0]); + Instance._stars.Remove(star); + if(Instance._stars.Count > 0) Instance.ChangeActiveStar(Instance._stars[0]); } else { - _stars.Remove(star); + Instance._stars.Remove(star); } } } diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs new file mode 100644 index 00000000..f651f297 --- /dev/null +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -0,0 +1,368 @@ +using NewHorizons.Builder.Atmosphere; +using NewHorizons.Builder.Body; +using NewHorizons.Builder.General; +using NewHorizons.Builder.Orbital; +using NewHorizons.Builder.Props; +using NewHorizons.Builder.Updater; +using NewHorizons.Components; +using NewHorizons.External.VariableSize; +using NewHorizons.Utility; +using NewHorizons.Utility.CommonResources; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Handlers +{ + public static class PlanetCreationHandler + { + public static List NextPassBodies = new List(); + + public static void Init(List bodies) + { + Main.FurthestOrbit = 30000; + + // Set up stars + // Need to manage this when there are multiple stars + var sun = GameObject.Find("Sun_Body"); + var starController = sun.AddComponent(); + starController.Light = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); + starController.AmbientLight = GameObject.Find("Sun_Body/AmbientLight_SUN").GetComponent(); + starController.FaceActiveCamera = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); + starController.CSMTextureCacher = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); + starController.ProxyShadowLight = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); + starController.Intensity = 0.9859f; + starController.SunColor = new Color(1f, 0.8845f, 0.6677f, 1f); + + var starLightGO = GameObject.Instantiate(sun.GetComponentInChildren().gameObject); + foreach (var comp in starLightGO.GetComponents()) + { + if (!(comp is SunLightController) && !(comp is SunLightParamUpdater) && !(comp is Light) && !(comp is Transform)) + { + GameObject.Destroy(comp); + } + } + GameObject.Destroy(starLightGO.GetComponent()); + starLightGO.name = "StarLightController"; + + starLightGO.AddComponent(); + StarLightController.AddStar(starController); + + starLightGO.SetActive(true); + + // Order by stars then planets then moons (not necessary but probably speeds things up, maybe) ALSO only include current star system + var toLoad = bodies + .OrderBy(b => + (b.Config.BuildPriority != -1 ? b.Config.BuildPriority : + (b.Config.FocalPoint != null ? 0 : + (b.Config.Star != null) ? 0 : + (b.Config.Orbit.IsMoon ? 2 : 1) + ))).ToList(); + + var passCount = 0; + while (toLoad.Count != 0) + { + Logger.Log($"Starting body loading pass #{++passCount}"); + var flagNoneLoadedThisPass = true; + foreach (var body in toLoad) + { + if (LoadBody(body)) flagNoneLoadedThisPass = false; + } + if (flagNoneLoadedThisPass) + { + Logger.LogWarning("No objects were loaded this pass"); + // Try again but default to sun + foreach (var body in toLoad) + { + if (LoadBody(body, true)) flagNoneLoadedThisPass = false; + } + } + if (flagNoneLoadedThisPass) + { + // Give up + Logger.Log($"Couldn't finish adding bodies."); + return; + } + + toLoad = NextPassBodies; + NextPassBodies = new List(); + + // Infinite loop failsafe + if (passCount > 10) + { + Logger.Log("Something went wrong"); + break; + } + } + + Logger.Log("Done loading bodies"); + + // I don't know what these do but they look really weird from a distance + Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveDistantProxyClones(), 1); + + if (Main.Instance.CurrentStarSystem != "SolarSystem") PlanetDestroyer.RemoveSolarSystem(); + } + + public static bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false) + { + // I don't remember doing this why is it exceptions what am I doing + GameObject existingPlanet = null; + try + { + existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.Name).gameObject; + } + catch (Exception) + { + if (body?.Config?.Name == null) Logger.LogError($"How is there no name for {body}"); + else existingPlanet = GameObject.Find(body.Config.Name.Replace(" ", "") + "_Body"); + } + + if (existingPlanet != null) + { + try + { + if (body.Config.Destroy) + { + var ao = existingPlanet.GetComponent(); + if (ao != null) Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveBody(ao), 1); + else Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => existingPlanet.SetActive(false), 1); + } + else UpdateBody(body, existingPlanet); + } + catch (Exception e) + { + Logger.LogError($"Couldn't update body {body.Config?.Name}: {e.Message}, {e.StackTrace}"); + return false; + } + } + else + { + try + { + GameObject planetObject = GenerateBody(body, defaultPrimaryToSun); + if (planetObject == null) return false; + planetObject.SetActive(true); + } + catch (Exception e) + { + Logger.LogError($"Couldn't generate body {body.Config?.Name}: {e.Message}, {e.StackTrace}"); + return false; + } + } + return true; + } + + public static GameObject UpdateBody(NewHorizonsBody body, GameObject go) + { + Logger.Log($"Updating existing Object {go.name}"); + + var sector = go.GetComponentInChildren(); + var rb = go.GetAttachedOWRigidbody(); + + if (body.Config.ChildrenToDestroy != null && body.Config.ChildrenToDestroy.Length > 0) + { + foreach (var child in body.Config.ChildrenToDestroy) + { + Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.Find(go.name + "/" + child).SetActive(false), 2); + } + } + + // Do stuff that's shared between generating new planets and updating old ones + go = SharedGenerateBody(body, go, sector, rb); + + // Update a position using CommonResources + // Since orbits are always there just check if they set a semi major axis + if (body.Config.Orbit != null && body.Config.Orbit.SemiMajorAxis != 0f) + { + OrbitUpdater.Update(body, go); + } + + return go; + } + + public static GameObject GenerateBody(NewHorizonsBody body, bool defaultPrimaryToSun = false) + { + AstroObject primaryBody; + if (body.Config.Orbit.PrimaryBody != null) + { + primaryBody = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody); + if (primaryBody == null) + { + if (defaultPrimaryToSun) + { + Logger.Log($"Couldn't find {body.Config.Orbit.PrimaryBody}, defaulting to Sun"); + primaryBody = AstroObjectLocator.GetAstroObject("Sun"); + } + else + { + NextPassBodies.Add(body); + return null; + } + } + } + else + { + primaryBody = null; + } + + Logger.Log($"Begin generation sequence of [{body.Config.Name}]"); + + var go = new GameObject(body.Config.Name.Replace(" ", "").Replace("'", "") + "_Body"); + go.SetActive(false); + + if (body.Config.Base.GroundSize != 0) GeometryBuilder.Make(go, body.Config.Base.GroundSize); + + var atmoSize = body.Config.Atmosphere != null ? body.Config.Atmosphere.Size : 0f; + float sphereOfInfluence = Mathf.Max(Mathf.Max(atmoSize, 50), body.Config.Base.SurfaceSize * 2f); + var overrideSOI = body.Config.Base.SphereOfInfluence; + if (overrideSOI != 0) sphereOfInfluence = overrideSOI; + + var outputTuple = BaseBuilder.Make(go, primaryBody, body.Config); + var ao = (AstroObject)outputTuple.Item1; + var owRigidBody = (OWRigidbody)outputTuple.Item2; + + GravityVolume gv = null; + if (body.Config.Base.SurfaceGravity != 0) + gv = GravityBuilder.Make(go, ao, body.Config); + + if (body.Config.Base.HasReferenceFrame) + RFVolumeBuilder.Make(go, owRigidBody, sphereOfInfluence); + + if (body.Config.Base.HasMapMarker) + MarkerBuilder.Make(go, body.Config.Name, body.Config); + + if (body.Config.Base.HasAmbientLight) + AmbientLightBuilder.Make(go, sphereOfInfluence); + + var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence * 2f); + ao._rootSector = sector; + + VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence, body.Config); + + if (body.Config.HeightMap != null) + HeightMapBuilder.Make(go, body.Config.HeightMap, body.Mod); + + if (body.Config.ProcGen != null) + ProcGenBuilder.Make(go, body.Config.ProcGen); + + if (body.Config.Star != null) StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star)); + + if (body.Config.FocalPoint != null) + FocalPointBuilder.Make(go, body.Config.FocalPoint); + + // Do stuff that's shared between generating new planets and updating old ones + go = SharedGenerateBody(body, go, sector, owRigidBody); + + body.Object = go; + + // Now that we're done move the planet into place + UpdatePosition(go, body, primaryBody); + + // Have to do this after setting position + var initialMotion = InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit); + + // Spawning on other planets is a bit hacky so we do it last + if (body.Config.Spawn != null) + { + Logger.Log("Doing spawn point thing"); + Main.SystemDict[body.Config.StarSystem].SpawnPoint = SpawnPointBuilder.Make(go, body.Config.Spawn, owRigidBody); + } + + if (body.Config.Orbit.ShowOrbitLine && !body.Config.Orbit.IsStatic) OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.IsMoon, body.Config); + + if (!body.Config.Orbit.IsStatic) DetectorBuilder.Make(go, owRigidBody, primaryBody, ao); + + if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) AstroObjectLocator.RegisterCustomAstroObject(ao); + + HeavenlyBodyBuilder.Make(go, body.Config, sphereOfInfluence, gv, initialMotion); + + return go; + } + + private static GameObject SharedGenerateBody(NewHorizonsBody body, GameObject go, Sector sector, OWRigidbody rb) + { + if (body.Config.Ring != null) + RingBuilder.Make(go, body.Config.Ring, body.Mod); + + if (body.Config.AsteroidBelt != null) + AsteroidBeltBuilder.Make(body.Config.Name, body.Config, body.Mod); + + if (body.Config.Base.HasCometTail) + CometTailBuilder.Make(go, body.Config.Base, go.GetComponent().GetPrimaryBody()); + + // Backwards compatability + if (body.Config.Base.LavaSize != 0) + { + var lava = new LavaModule(); + lava.Size = body.Config.Base.LavaSize; + LavaBuilder.Make(go, sector, rb, lava); + } + + if (body.Config.Lava != null) + LavaBuilder.Make(go, sector, rb, body.Config.Lava); + + // Backwards compatability + if (body.Config.Base.WaterSize != 0) + { + var water = new WaterModule(); + water.Size = body.Config.Base.WaterSize; + water.Tint = body.Config.Base.WaterTint; + WaterBuilder.Make(go, sector, rb, water); + } + + if (body.Config.Water != null) + WaterBuilder.Make(go, sector, rb, body.Config.Water); + + if (body.Config.Sand != null) + SandBuilder.Make(go, sector, rb, body.Config.Sand); + + if (body.Config.Atmosphere != null) + { + AirBuilder.Make(go, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasOxygen); + + if (body.Config.Atmosphere.Cloud != null) + { + CloudsBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod); + SunOverrideBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere); + } + + if (body.Config.Atmosphere.HasRain || body.Config.Atmosphere.HasSnow) + EffectsBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasSnow); + + if (body.Config.Atmosphere.FogSize != 0) + FogBuilder.Make(go, sector, body.Config.Atmosphere); + + AtmosphereBuilder.Make(go, body.Config.Atmosphere, body.Config.Base.SurfaceSize); + } + + if (body.Config.Props != null) + PropBuildManager.Make(go, sector, body.Config, body.Mod, body.Mod.ModHelper.Manifest.UniqueName); + + if (body.Config.Signal != null) + SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod); + + if (body.Config.Base.BlackHoleSize != 0 || body.Config.Singularity != null) + SingularityBuilder.Make(go, sector, rb, body.Config); + + if (body.Config.Funnel != null) + FunnelBuilder.Make(go, go.GetComponentInChildren(), rb, body.Config.Funnel); + + return go; + } + + private static void UpdatePosition(GameObject go, NewHorizonsBody body, AstroObject primaryBody) + { + go.transform.parent = Locator.GetRootTransform(); + go.transform.position = CommonResourcesUtilities.GetPosition(body.Config.Orbit) + (primaryBody == null ? Vector3.zero : primaryBody.transform.position); + + if (go.transform.position.magnitude > Main.FurthestOrbit) + { + Main.FurthestOrbit = go.transform.position.magnitude + 30000f; + } + } + } +} diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs new file mode 100644 index 00000000..f5428566 --- /dev/null +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -0,0 +1,114 @@ +using NewHorizons.Builder.Body; +using NewHorizons.External; +using NewHorizons.External.VariableSize; +using NewHorizons.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Handlers +{ + public static class TitleSceneHandler + { + public static void DisplayBodyOnTitleScreen(List bodies) + { + //Try loading one planet why not + //var eligible = BodyDict.Values.ToList().SelectMany(x => x).ToList().Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null) && b.Config.Star == null).ToArray(); + var eligible = bodies.Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null) && b.Config.Star == null).ToArray(); + var eligibleCount = eligible.Count(); + if (eligibleCount == 0) return; + + var selectionCount = Mathf.Min(eligibleCount, 3); + var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount); + + Logger.Log($"Displaying {selectionCount} bodies on the title screen"); + + GameObject body1, body2, body3; + + body1 = LoadTitleScreenBody(eligible[indices[0]]); + body1.transform.localRotation = Quaternion.Euler(15, 0, 0); + if (selectionCount > 1) + { + body1.transform.localScale = Vector3.one * (body1.transform.localScale.x) * 0.3f; + body1.transform.localPosition = new Vector3(0, -15, 0); + body1.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + body2 = LoadTitleScreenBody(eligible[indices[1]]); + body2.transform.localScale = Vector3.one * (body2.transform.localScale.x) * 0.3f; + body2.transform.localPosition = new Vector3(7, 30, 0); + body2.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + } + if (selectionCount > 2) + { + body3 = LoadTitleScreenBody(eligible[indices[2]]); + body3.transform.localScale = Vector3.one * (body3.transform.localScale.x) * 0.3f; + body3.transform.localPosition = new Vector3(-5, 10, 0); + body3.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + } + + GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false); + GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); + + var lightGO = new GameObject("Light"); + lightGO.transform.parent = GameObject.Find("Scene/Background").transform; + lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); + var light = lightGO.AddComponent(); + light.color = new Color(1f, 1f, 1f, 1f); + light.range = 100; + light.intensity = 0.8f; + } + + private static GameObject LoadTitleScreenBody(NewHorizonsBody body) + { + Logger.Log($"Displaying {body.Config.Name} on the title screen"); + GameObject titleScreenGO = new GameObject(body.Config.Name + "_TitleScreen"); + HeightMapModule heightMap = new HeightMapModule(); + var minSize = 15; + var maxSize = 30; + float size = minSize; + if (body.Config.HeightMap != null) + { + size = Mathf.Clamp(body.Config.HeightMap.MaxHeight / 10, minSize, maxSize); + heightMap.TextureMap = body.Config.HeightMap.TextureMap; + heightMap.HeightMap = body.Config.HeightMap.HeightMap; + heightMap.MaxHeight = size; + heightMap.MinHeight = body.Config.HeightMap.MinHeight * size / body.Config.HeightMap.MaxHeight; + } + if (body.Config.Atmosphere != null && body.Config.Atmosphere.Cloud != null) + { + // Hacky but whatever I just want a sphere + size = Mathf.Clamp(body.Config.Atmosphere.Size / 10, minSize, maxSize); + heightMap.MaxHeight = heightMap.MinHeight = size + 1; + heightMap.TextureMap = body.Config.Atmosphere.Cloud; + } + + HeightMapBuilder.Make(titleScreenGO, heightMap, body.Mod); + + GameObject pivot = GameObject.Instantiate(GameObject.Find("Scene/Background/PlanetPivot"), GameObject.Find("Scene/Background").transform); + pivot.GetComponent()._degreesPerSecond = 10f; + foreach (Transform child in pivot.transform) + { + GameObject.Destroy(child.gameObject); + } + pivot.name = "Pivot"; + + if (body.Config.Ring != null) + { + RingModule newRing = new RingModule(); + newRing.InnerRadius = size * 1.2f; + newRing.OuterRadius = size * 2f; + newRing.Texture = body.Config.Ring.Texture; + var ring = RingBuilder.Make(titleScreenGO, newRing, body.Mod); + titleScreenGO.transform.localScale = Vector3.one * 0.8f; + } + + titleScreenGO.transform.parent = pivot.transform; + titleScreenGO.transform.localPosition = Vector3.zero; + + return titleScreenGO; + } + } +} diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 643e7317..55426627 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -40,24 +40,21 @@ namespace NewHorizons public static Dictionary SystemDict = new Dictionary(); public static Dictionary> BodyDict = new Dictionary>(); - public static List NextPassBodies = new List(); public static Dictionary AssetBundles = new Dictionary(); public static List MountedAddons = new List(); public static float FurthestOrbit { get; set; } = 50000f; - public StarLightController StarLightController { get; private set; } - private string _defaultStarSystem = "SolarSystem"; - private string _currentStarSystem = "SolarSystem"; public string CurrentStarSystem { get { return Instance._currentStarSystem; } } - - private bool _isChangingStarSystem = false; - private bool _firstLoad = true; public bool IsWarping { get; private set; } = false; public bool WearingSuit { get; private set; } = false; public static bool HasWarpDrive { get; private set; } = false; + private string _defaultStarSystem = "SolarSystem"; + private string _currentStarSystem = "SolarSystem"; + private bool _isChangingStarSystem = false; + private bool _firstLoad = true; private ShipWarpController _shipWarpController; public override object GetApi() @@ -181,245 +178,51 @@ namespace NewHorizons _isChangingStarSystem = false; - if (scene.name.Equals("TitleScreen")) DisplayBodyOnTitleScreen(); + if (scene.name == "TitleScreen") + { + TitleSceneHandler.DisplayBodyOnTitleScreen(BodyDict.Values.ToList().SelectMany(x => x).ToList()); + } - if (scene.name != "SolarSystem") + if(scene.name == "SolarSystem") + { + HeavenlyBodyBuilder.Reset(); + NewHorizonsData.Load(); + SignalBuilder.Init(); + AstroObjectLocator.RefreshList(); + PlanetCreationHandler.Init(BodyDict[CurrentStarSystem]); + LoadTranslations(ModHelper.Manifest.ModFolderPath + "AssetBundle/", this); + + Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => Locator.GetPlayerBody().gameObject.AddComponent()); + + // Warp drive + StarChartHandler.Init(SystemDict.Values.ToArray()); + HasWarpDrive = StarChartHandler.CanWarp(); + _shipWarpController = GameObject.Find("Ship_Body").AddComponent(); + _shipWarpController.Init(); + if (HasWarpDrive == true) EnableWarpDrive(); + + Logger.Log($"Is the player warping in? {IsWarping}"); + if (IsWarping && _shipWarpController) Instance.ModHelper.Events.Unity.FireInNUpdates(() => _shipWarpController.WarpIn(WearingSuit), 5); + else Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.FindObjectOfType().DebugWarp(SystemDict[_currentStarSystem].SpawnPoint), 5); + IsWarping = false; + + var map = GameObject.FindObjectOfType(); + if (map != null) map._maxPanDistance = FurthestOrbit * 1.5f; + } + else { // Reset back to original solar system after going to main menu. _currentStarSystem = _defaultStarSystem; - return; } - - FurthestOrbit = 30000; - - HeavenlyBodyBuilder.Reset(); - - NewHorizonsData.Load(); - - // By default we dont have it - HasWarpDrive = false; - - // Gotta prepare it anyway - StarChartHandler.Init(SystemDict.Values.ToArray()); - HasWarpDrive = StarChartHandler.CanWarp(); - - _shipWarpController = GameObject.Find("Ship_Body").AddComponent(); - _shipWarpController.Init(); - - if (HasWarpDrive == true) EnableWarpDrive(); - - LoadTranslations(ModHelper.Manifest.ModFolderPath + "AssetBundle/", this); - - Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => AstroObjectLocator.GetAstroObject("MapSatellite").gameObject.AddComponent()); - - // Need to manage this when there are multiple stars - var sun = GameObject.Find("Sun_Body"); - var starController = sun.AddComponent(); - starController.Light = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); - starController.AmbientLight = GameObject.Find("Sun_Body/AmbientLight_SUN").GetComponent(); - starController.FaceActiveCamera = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); - starController.CSMTextureCacher = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); - starController.ProxyShadowLight = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent(); - starController.Intensity = 0.9859f; - starController.SunColor = new Color(1f, 0.8845f, 0.6677f, 1f); - - var starLightGO = GameObject.Instantiate(sun.GetComponentInChildren().gameObject); - foreach(var comp in starLightGO.GetComponents()) - { - if(!(comp is SunLightController) && !(comp is SunLightParamUpdater) && !(comp is Light) && !(comp is Transform)) - { - GameObject.Destroy(comp); - } - } - GameObject.Destroy(starLightGO.GetComponent()); - starLightGO.name = "StarLightController"; - - StarLightController = starLightGO.AddComponent(); - StarLightController.AddStar(starController); - - starLightGO.SetActive(true); - - // TODO: Make this configurable probably - Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => Locator.GetPlayerBody().gameObject.AddComponent()); - - // Some builders need to be reset each time - SignalBuilder.Init(); - - // We do our own AstroObject tracking - AstroObjectLocator.RefreshList(); - foreach (AstroObject ao in GameObject.FindObjectsOfType()) - { - AstroObjectLocator.AddAstroObject(ao); - } - - // Order by stars then planets then moons (not necessary but probably speeds things up, maybe) ALSO only include current star system - var toLoad = BodyDict[_currentStarSystem] - .OrderBy(b => - (b.Config.BuildPriority != -1 ? b.Config.BuildPriority : - (b.Config.FocalPoint != null ? 0 : - (b.Config.Star != null) ? 0 : - (b.Config.Orbit.IsMoon ? 2 : 1) - ))).ToList(); - - var passCount = 0; - while (toLoad.Count != 0) - { - Logger.Log($"Starting body loading pass #{++passCount}"); - var flagNoneLoadedThisPass = true; - foreach (var body in toLoad) - { - if (LoadBody(body)) flagNoneLoadedThisPass = false; - } - if (flagNoneLoadedThisPass) - { - Logger.LogWarning("No objects were loaded this pass"); - // Try again but default to sun - foreach (var body in toLoad) - { - if (LoadBody(body, true)) flagNoneLoadedThisPass = false; - } - } - if (flagNoneLoadedThisPass) - { - // Give up - Logger.Log($"Couldn't finish adding bodies."); - return; - } - - toLoad = NextPassBodies; - NextPassBodies = new List(); - - // Infinite loop failsafe - if (passCount > 10) - { - Logger.Log("Something went wrong"); - break; - } - } - - Logger.Log("Done loading bodies"); - - // I don't know what these do but they look really weird from a distance - Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveDistantProxyClones(), 1); - - if(!_currentStarSystem.Equals("SolarSystem")) PlanetDestroyer.RemoveSolarSystem(); - - var map = GameObject.FindObjectOfType(); - if (map != null) map._maxPanDistance = FurthestOrbit * 1.5f; - - Logger.Log($"Is the player warping in? {IsWarping}"); - if (IsWarping && _shipWarpController) Instance.ModHelper.Events.Unity.FireInNUpdates(() => _shipWarpController.WarpIn(WearingSuit), 5); - else Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.FindObjectOfType().DebugWarp(SystemDict[_currentStarSystem].SpawnPoint), 5); - - IsWarping = false; } public void EnableWarpDrive() { Logger.Log("Setting up warp drive"); - LoadBody(LoadConfig(this, "AssetBundle/WarpDriveConfig.json")); + PlanetCreationHandler.LoadBody(LoadConfig(this, "AssetBundle/WarpDriveConfig.json")); HasWarpDrive = true; } - #region TitleScreen - - public void DisplayBodyOnTitleScreen() - { - //Try loading one planet why not - var eligible = BodyDict.Values.SelectMany(x => x).ToList().Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null) && b.Config.Star == null).ToArray(); - var eligibleCount = eligible.Count(); - if (eligibleCount == 0) return; - - var selectionCount = Mathf.Min(eligibleCount, 3); - var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount); - - Logger.Log($"Displaying {selectionCount} bodies on the title screen"); - - GameObject body1, body2, body3; - - body1 = LoadTitleScreenBody(eligible[indices[0]]); - body1.transform.localRotation = Quaternion.Euler(15, 0, 0); - if (selectionCount > 1) - { - body1.transform.localScale = Vector3.one * (body1.transform.localScale.x) * 0.3f; - body1.transform.localPosition = new Vector3(0, -15, 0); - body1.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - body2 = LoadTitleScreenBody(eligible[indices[1]]); - body2.transform.localScale = Vector3.one * (body2.transform.localScale.x) * 0.3f; - body2.transform.localPosition = new Vector3(7, 30, 0); - body2.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - } - if (selectionCount > 2) - { - body3 = LoadTitleScreenBody(eligible[indices[2]]); - body3.transform.localScale = Vector3.one * (body3.transform.localScale.x) * 0.3f; - body3.transform.localPosition = new Vector3(-5, 10, 0); - body3.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - } - - GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false); - GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); - - var lightGO = new GameObject("Light"); - lightGO.transform.parent = GameObject.Find("Scene/Background").transform; - lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); - var light = lightGO.AddComponent(); - light.color = new Color(1f, 1f, 1f, 1f); - light.range = 100; - light.intensity = 0.8f; - } - - private GameObject LoadTitleScreenBody(NewHorizonsBody body) - { - Logger.Log($"Displaying {body.Config.Name} on the title screen"); - GameObject titleScreenGO = new GameObject(body.Config.Name + "_TitleScreen"); - HeightMapModule heightMap = new HeightMapModule(); - var minSize = 15; - var maxSize = 30; - float size = minSize; - if (body.Config.HeightMap != null) - { - size = Mathf.Clamp(body.Config.HeightMap.MaxHeight / 10, minSize, maxSize); - heightMap.TextureMap = body.Config.HeightMap.TextureMap; - heightMap.HeightMap = body.Config.HeightMap.HeightMap; - heightMap.MaxHeight = size; - heightMap.MinHeight = body.Config.HeightMap.MinHeight * size / body.Config.HeightMap.MaxHeight; - } - if (body.Config.Atmosphere != null && body.Config.Atmosphere.Cloud != null) - { - // Hacky but whatever I just want a sphere - size = Mathf.Clamp(body.Config.Atmosphere.Size / 10, minSize, maxSize); - heightMap.MaxHeight = heightMap.MinHeight = size + 1; - heightMap.TextureMap = body.Config.Atmosphere.Cloud; - } - - HeightMapBuilder.Make(titleScreenGO, heightMap, body.Mod); - - GameObject pivot = GameObject.Instantiate(GameObject.Find("Scene/Background/PlanetPivot"), GameObject.Find("Scene/Background").transform); - pivot.GetComponent()._degreesPerSecond = 10f; - foreach (Transform child in pivot.transform) - { - GameObject.Destroy(child.gameObject); - } - pivot.name = "Pivot"; - - if (body.Config.Ring != null) - { - RingModule newRing = new RingModule(); - newRing.InnerRadius = size * 1.2f; - newRing.OuterRadius = size * 2f; - newRing.Texture = body.Config.Ring.Texture; - var ring = RingBuilder.Make(titleScreenGO, newRing, body.Mod); - titleScreenGO.transform.localScale = Vector3.one * 0.8f; - } - - titleScreenGO.transform.parent = pivot.transform; - titleScreenGO.transform.localPosition = Vector3.zero; - - return titleScreenGO; - } - - #endregion TitleScreen #region Load public void LoadConfigs(IModBehaviour mod) @@ -517,270 +320,8 @@ namespace NewHorizons return body; } - private bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false) - { - // I don't remember doing this why is it exceptions what am I doing - GameObject existingPlanet = null; - try - { - existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.Name).gameObject; - } - catch (Exception) - { - if (body?.Config?.Name == null) Logger.LogError($"How is there no name for {body}"); - else existingPlanet = GameObject.Find(body.Config.Name.Replace(" ", "") + "_Body"); - } - - if (existingPlanet != null) - { - try - { - if (body.Config.Destroy) - { - var ao = existingPlanet.GetComponent(); - if (ao != null) Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveBody(ao), 1); - else Instance.ModHelper.Events.Unity.FireInNUpdates(() => existingPlanet.SetActive(false), 1); - } - else UpdateBody(body, existingPlanet); - } - catch (Exception e) - { - Logger.LogError($"Couldn't update body {body.Config?.Name}: {e.Message}, {e.StackTrace}"); - return false; - } - } - else - { - try - { - GameObject planetObject = GenerateBody(body, defaultPrimaryToSun); - if (planetObject == null) return false; - planetObject.SetActive(true); - } - catch (Exception e) - { - Logger.LogError($"Couldn't generate body {body.Config?.Name}: {e.Message}, {e.StackTrace}"); - return false; - } - } - return true; - } - - public GameObject UpdateBody(NewHorizonsBody body, GameObject go) - { - Logger.Log($"Updating existing Object {go.name}"); - - var sector = go.GetComponentInChildren(); - var rb = go.GetAttachedOWRigidbody(); - - if (body.Config.ChildrenToDestroy != null && body.Config.ChildrenToDestroy.Length > 0) - { - foreach (var child in body.Config.ChildrenToDestroy) - { - Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.Find(go.name + "/" + child).SetActive(false), 2); - } - } - - // Do stuff that's shared between generating new planets and updating old ones - go = SharedGenerateBody(body, go, sector, rb); - - // Update a position using CommonResources - // Since orbits are always there just check if they set a semi major axis - if (body.Config.Orbit != null && body.Config.Orbit.SemiMajorAxis != 0f) - { - OrbitUpdater.Update(body, go); - } - - return go; - } - #endregion Load - #region Body generation - - public GameObject GenerateBody(NewHorizonsBody body, bool defaultPrimaryToSun = false) - { - AstroObject primaryBody; - if (body.Config.Orbit.PrimaryBody != null) - { - primaryBody = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody); - if (primaryBody == null) - { - if (defaultPrimaryToSun) - { - Logger.Log($"Couldn't find {body.Config.Orbit.PrimaryBody}, defaulting to Sun"); - primaryBody = AstroObjectLocator.GetAstroObject("Sun"); - } - else - { - NextPassBodies.Add(body); - return null; - } - } - } - else - { - primaryBody = null; - } - - Logger.Log($"Begin generation sequence of [{body.Config.Name}]"); - - var go = new GameObject(body.Config.Name.Replace(" ", "").Replace("'", "") + "_Body"); - go.SetActive(false); - - if (body.Config.Base.GroundSize != 0) GeometryBuilder.Make(go, body.Config.Base.GroundSize); - - var atmoSize = body.Config.Atmosphere != null ? body.Config.Atmosphere.Size : 0f; - float sphereOfInfluence = Mathf.Max(Mathf.Max(atmoSize, 50), body.Config.Base.SurfaceSize * 2f); - var overrideSOI = body.Config.Base.SphereOfInfluence; - if (overrideSOI != 0) sphereOfInfluence = overrideSOI; - - var outputTuple = BaseBuilder.Make(go, primaryBody, body.Config); - var ao = (AstroObject)outputTuple.Item1; - var owRigidBody = (OWRigidbody)outputTuple.Item2; - - GravityVolume gv = null; - if (body.Config.Base.SurfaceGravity != 0) - gv = GravityBuilder.Make(go, ao, body.Config); - - if (body.Config.Base.HasReferenceFrame) - RFVolumeBuilder.Make(go, owRigidBody, sphereOfInfluence); - - if (body.Config.Base.HasMapMarker) - MarkerBuilder.Make(go, body.Config.Name, body.Config); - - if (body.Config.Base.HasAmbientLight) - AmbientLightBuilder.Make(go, sphereOfInfluence); - - var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence * 2f); - ao.SetValue("_rootSector", sector); - - VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence, body.Config); - - if (body.Config.HeightMap != null) - HeightMapBuilder.Make(go, body.Config.HeightMap, body.Mod); - - if (body.Config.ProcGen != null) - ProcGenBuilder.Make(go, body.Config.ProcGen); - - if (body.Config.Star != null) StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star)); - - if (body.Config.FocalPoint != null) - FocalPointBuilder.Make(go, body.Config.FocalPoint); - - // Do stuff that's shared between generating new planets and updating old ones - go = SharedGenerateBody(body, go, sector, owRigidBody); - - body.Object = go; - - // Now that we're done move the planet into place - UpdatePosition(go, body, primaryBody); - - // Have to do this after setting position - var initialMotion = InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit); - - // Spawning on other planets is a bit hacky so we do it last - if (body.Config.Spawn != null) - { - Logger.Log("Doing spawn point thing"); - SystemDict[body.Config.StarSystem].SpawnPoint = SpawnPointBuilder.Make(go, body.Config.Spawn, owRigidBody); - } - - if (body.Config.Orbit.ShowOrbitLine && !body.Config.Orbit.IsStatic) OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.IsMoon, body.Config); - - if (!body.Config.Orbit.IsStatic) DetectorBuilder.Make(go, owRigidBody, primaryBody, ao); - - if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) AstroObjectLocator.RegisterCustomAstroObject(ao); - - HeavenlyBodyBuilder.Make(go, body.Config, sphereOfInfluence, gv, initialMotion); - - return go; - } - - private GameObject SharedGenerateBody(NewHorizonsBody body, GameObject go, Sector sector, OWRigidbody rb) - { - if (body.Config.Ring != null) - RingBuilder.Make(go, body.Config.Ring, body.Mod); - - if (body.Config.AsteroidBelt != null) - AsteroidBeltBuilder.Make(body.Config.Name, body.Config, body.Mod); - - if (body.Config.Base.HasCometTail) - CometTailBuilder.Make(go, body.Config.Base, go.GetComponent().GetPrimaryBody()); - - // Backwards compatability - if (body.Config.Base.LavaSize != 0) - { - var lava = new LavaModule(); - lava.Size = body.Config.Base.LavaSize; - LavaBuilder.Make(go, sector, rb, lava); - } - - if (body.Config.Lava != null) - LavaBuilder.Make(go, sector, rb, body.Config.Lava); - - // Backwards compatability - if (body.Config.Base.WaterSize != 0) - { - var water = new WaterModule(); - water.Size = body.Config.Base.WaterSize; - water.Tint = body.Config.Base.WaterTint; - WaterBuilder.Make(go, sector, rb, water); - } - - if (body.Config.Water != null) - WaterBuilder.Make(go, sector, rb, body.Config.Water); - - if (body.Config.Sand != null) - SandBuilder.Make(go, sector, rb, body.Config.Sand); - - if (body.Config.Atmosphere != null) - { - AirBuilder.Make(go, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasOxygen); - - if (body.Config.Atmosphere.Cloud != null) - { - CloudsBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod); - SunOverrideBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere); - } - - if (body.Config.Atmosphere.HasRain || body.Config.Atmosphere.HasSnow) - EffectsBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasSnow); - - if (body.Config.Atmosphere.FogSize != 0) - FogBuilder.Make(go, sector, body.Config.Atmosphere); - - AtmosphereBuilder.Make(go, body.Config.Atmosphere, body.Config.Base.SurfaceSize); - } - - if (body.Config.Props != null) - PropBuildManager.Make(go, sector, body.Config, body.Mod, body.Mod.ModHelper.Manifest.UniqueName); - - if (body.Config.Signal != null) - SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod); - - if (body.Config.Base.BlackHoleSize != 0 || body.Config.Singularity != null) - SingularityBuilder.Make(go, sector, rb, body.Config); - - if (body.Config.Funnel != null) - FunnelBuilder.Make(go, go.GetComponentInChildren(), rb, body.Config.Funnel); - - return go; - } - - private void UpdatePosition(GameObject go, NewHorizonsBody body, AstroObject primaryBody) - { - go.transform.parent = Locator.GetRootTransform(); - go.transform.position = CommonResourcesUtilities.GetPosition(body.Config.Orbit) + (primaryBody == null ? Vector3.zero : primaryBody.transform.position); - - if (go.transform.position.magnitude > FurthestOrbit) - { - FurthestOrbit = go.transform.position.magnitude + 30000f; - } - } - - #endregion Body generation - #region Change star system public void ChangeCurrentStarSystem(string newStarSystem, bool warp = false) { diff --git a/NewHorizons/Utility/AstroObjectLocator.cs b/NewHorizons/Utility/AstroObjectLocator.cs index 3a3b6cd4..82daed2a 100644 --- a/NewHorizons/Utility/AstroObjectLocator.cs +++ b/NewHorizons/Utility/AstroObjectLocator.cs @@ -102,7 +102,11 @@ namespace NewHorizons.Utility { _customAstroObjectDictionary = new Dictionary(); _list = new List(); - } + foreach (AstroObject ao in GameObject.FindObjectsOfType()) + { + AddAstroObject(ao); + } + } public static AstroObject[] GetAllAstroObjects() {