From 1be3bf209f1f63972e1693345145be00c8a5aba0 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 00:54:25 -0500 Subject: [PATCH 01/17] Dream arrival point and dream campfire builders --- .../DreamArrivalPointBuilder.cs | 63 ++++++++++++++ .../EchoesOfTheEye/DreamCampfireBuilder.cs | 73 ++++++++++++++++ NewHorizons/Builder/Props/PropBuildManager.cs | 3 + NewHorizons/External/Modules/PropModule.cs | 10 +++ .../EchoesOfTheEye/DreamArrivalPointInfo.cs | 22 +++++ .../Props/EchoesOfTheEye/DreamCampfireInfo.cs | 18 ++++ NewHorizons/Handlers/DreamHandler.cs | 85 +++++++++++++++++++ .../Handlers/PlanetDestructionHandler.cs | 9 ++ NewHorizons/Main.cs | 3 + .../DreamworldControllerPatches.cs | 35 ++++++++ 10 files changed, 321 insertions(+) create mode 100644 NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs create mode 100644 NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs create mode 100644 NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamArrivalPointInfo.cs create mode 100644 NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCampfireInfo.cs create mode 100644 NewHorizons/Handlers/DreamHandler.cs diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs new file mode 100644 index 00000000..cb828744 --- /dev/null +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs @@ -0,0 +1,63 @@ +using NewHorizons.Components.Props; +using NewHorizons.External.Modules.Props; +using NewHorizons.External.Modules.Props.EchoesOfTheEye; +using NewHorizons.Handlers; +using NewHorizons.Utility; +using NewHorizons.Utility.OWML; +using OWML.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Builder.Props.EchoesOfTheEye +{ + public static class DreamArrivalPointBuilder + { + private static GameObject _prefab; + + internal static void InitPrefab() + { + if (_prefab == null) + { + _prefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/DreamFireHouse_1/Interactibles_DreamFireHouse_1/Prefab_IP_DreamArrivalPoint_Zone1").InstantiateInactive().Rename("Prefab_DreamArrivalPoint").DontDestroyOnLoad(); + if (_prefab == null) + { + NHLogger.LogWarning($"Tried to make a dream arrival point but couldn't. Do you have the DLC installed?"); + return; + } + else + { + _prefab.AddComponent()._destroyOnDLCNotOwned = true; + var dreamArrivalPoint = _prefab.GetComponent(); + dreamArrivalPoint._location = DreamArrivalPoint.Location.Undefined; + dreamArrivalPoint._sector = null; + dreamArrivalPoint._entrywayVolumes = []; + dreamArrivalPoint._raftSpawn = null; + dreamArrivalPoint._connectedDreamCampfire = null; + dreamArrivalPoint._campfire._sector = null; + } + } + } + + public static GameObject Make(GameObject planetGO, Sector sector, DreamArrivalPointInfo info, IModBehaviour mod) + { + InitPrefab(); + + if (_prefab == null || sector == null) return null; + + var arrivalPointObj = DetailBuilder.Make(planetGO, sector, mod, _prefab, new DetailInfo(info)); + + StreamingHandler.SetUpStreaming(arrivalPointObj, sector); + + DreamArrivalPoint arrivalPoint = arrivalPointObj.GetComponent(); + arrivalPoint._sector = arrivalPoint.GetComponentInParent(); + arrivalPoint._location = DreamHandler.GetDreamArrivalLocation(info.id); + Locator.RegisterDreamArrivalPoint(arrivalPoint, arrivalPoint._location); + + return arrivalPointObj; + } + } +} diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs new file mode 100644 index 00000000..5005e310 --- /dev/null +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs @@ -0,0 +1,73 @@ +using NewHorizons.External.Modules.Props; +using NewHorizons.External.Modules.Props.EchoesOfTheEye; +using NewHorizons.Handlers; +using NewHorizons.Utility; +using NewHorizons.Utility.OWML; +using OWML.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Builder.Props.EchoesOfTheEye +{ + public static class DreamCampfireBuilder + { + private static GameObject _prefab; + + internal static void InitPrefab() + { + if (_prefab == null) + { + _prefab = SearchUtilities.Find("RingWorld_Body/Sector_RingInterior/Sector_Zone4/Sector_PrisonDocks/Sector_PrisonInterior/Interactibles_PrisonInterior/Prefab_IP_DreamCampfire").InstantiateInactive().Rename("Prefab_DreamCampfire").DontDestroyOnLoad(); + if (_prefab == null) + { + NHLogger.LogWarning($"Tried to make a dream campfire but couldn't. Do you have the DLC installed?"); + return; + } + else + { + _prefab.AddComponent()._destroyOnDLCNotOwned = true; + var campfire = _prefab.GetComponentInChildren(); + campfire._dreamArrivalLocation = DreamArrivalPoint.Location.Undefined; + campfire._sector = null; + campfire._entrywayVolumes = []; + } + } + } + + public static GameObject Make(GameObject planetGO, Sector sector, DreamCampfireInfo info, IModBehaviour mod) + { + InitPrefab(); + + if (_prefab == null || sector == null) return null; + + var campfireObj = DetailBuilder.Make(planetGO, sector, mod, _prefab, new DetailInfo(info)); + + var campfire = campfireObj.GetComponentInChildren(); + campfire._dreamArrivalLocation = DreamHandler.GetDreamArrivalLocation(info.id); + + Delay.FireInNUpdates(() => { + var streaming = campfireObj.GetComponentInChildren(); + if (streaming != null) + { + var targetArrivalPoint = Locator.GetDreamArrivalPoint(campfire._dreamArrivalLocation); + if (targetArrivalPoint != null) + { + var streamingGroup = targetArrivalPoint.transform.root.GetComponentInChildren(); + if (streamingGroup) + { + streaming._streamingGroup = streamingGroup; + } + } + } + }, 2); + + Locator.RegisterDreamCampfire(campfire, campfire._dreamArrivalLocation); + + return campfireObj; + } + } +} diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index 433b7bc4..8cff2939 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -1,5 +1,6 @@ using NewHorizons.Builder.Body; using NewHorizons.Builder.Props.Audio; +using NewHorizons.Builder.Props.EchoesOfTheEye; using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.Builder.ShipLog; using NewHorizons.External; @@ -101,6 +102,8 @@ namespace NewHorizons.Builder.Props // If a prop has set its parentPath and the parent cannot be found, add it to the next pass and try again later nextPass = new List(); + if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamCampfires, (campfire) => DreamCampfireBuilder.Make(go, sector, campfire, mod), (campfire) => campfire.id); + if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamArrivalPoints, (point) => DreamArrivalPointBuilder.Make(go, sector, point, mod), (point) => point.id); MakeGeneralProps(go, config.Props.gravityCannons, (cannon) => GravityCannonBuilder.Make(go, sector, cannon, mod), (cannon) => cannon.shuttleID); MakeGeneralProps(go, config.Props.shuttles, (shuttle) => ShuttleBuilder.Make(go, sector, mod, shuttle), (shuttle) => shuttle.id); MakeGeneralProps(go, config.Props.details, (detail) => DetailBuilder.Make(go, sector, mod, detail), (detail) => detail.path); diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index b77c2f68..68ff0ee6 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -123,6 +123,16 @@ namespace NewHorizons.External.Modules /// public ShuttleInfo[] shuttles; + /// + /// Add campfires that allow you to enter the dream world/simulation. Must be paired with a dream arrival point, which can be placed on this planet or elsewhere. + /// + public DreamCampfireInfo[] dreamCampfires; + + /// + /// Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere. + /// + public DreamArrivalPointInfo[] dreamArrivalPoints; + [Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public RevealVolumeInfo[] reveal; [Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public AudioVolumeInfo[] audioVolumes; diff --git a/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamArrivalPointInfo.cs b/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamArrivalPointInfo.cs new file mode 100644 index 00000000..148ec55d --- /dev/null +++ b/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamArrivalPointInfo.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External.Modules.Props.EchoesOfTheEye +{ + [JsonObject] + public class DreamArrivalPointInfo : GeneralPropInfo + { + /// + /// Unique ID for this dream-world arrival point + /// + public string id; + /// + /// Whether to generate simulation meshes (the models used in the "tronworld" or "matrix" view) for most objects on the current planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them. + /// + public bool generateSimulationMeshes; + } +} diff --git a/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCampfireInfo.cs b/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCampfireInfo.cs new file mode 100644 index 00000000..4b96d0ff --- /dev/null +++ b/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCampfireInfo.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External.Modules.Props.EchoesOfTheEye +{ + [JsonObject] + public class DreamCampfireInfo : GeneralPropInfo + { + /// + /// Unique ID for this dream-world campfire + /// + public string id; + } +} diff --git a/NewHorizons/Handlers/DreamHandler.cs b/NewHorizons/Handlers/DreamHandler.cs new file mode 100644 index 00000000..7bc8b0bf --- /dev/null +++ b/NewHorizons/Handlers/DreamHandler.cs @@ -0,0 +1,85 @@ +using NewHorizons.Utility; +using NewHorizons.Utility.OWML; +using OWML.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Handlers +{ + public static class DreamHandler + { + public static DreamArrivalPoint.Location GetDreamArrivalLocation(string id) + { + try + { + if (EnumUtils.TryParse(id, out DreamArrivalPoint.Location location)) + { + return location; + } + else + { + NHLogger.LogVerbose($"Registering new dream arrival location [{id}]"); + return EnumUtilities.Create(id); + } + } + catch (Exception e) + { + NHLogger.LogError($"Couldn't load dream arrival location [{id}]:\n{e}"); + return DreamArrivalPoint.Location.Undefined; + } + } + + public static void MigrateDreamWorldController() + { + // Create new DreamWorldController instance since the existing one is disabled + var managerObj = new GameObject("DreamWorldManager"); + managerObj.SetActive(false); + var oldDWC = Locator.GetDreamWorldController(); + var dwc = managerObj.AddComponent(); + + var simRootObj = MigrateCopy(oldDWC._primarySimulationRoot.gameObject, managerObj); + + dwc._primarySimulationRoot = simRootObj.transform; + dwc._simulationRoots = [simRootObj.transform]; + dwc._simulationCamera = simRootObj.FindChild("Camera_Simulation").GetComponent(); + dwc._simulationSphere = simRootObj.FindChild("SimulationSphere").GetComponent(); + + dwc._tempSkyboxColor = oldDWC._tempSkyboxColor; + dwc._sarcophagusController = oldDWC._sarcophagusController; + dwc._prisonerDirector = oldDWC._prisonerDirector; + + // These should correspond to the arrival point's attached body + dwc._dreamBody = null; + dwc._dreamWorldSector = null; + dwc._dreamWorldVolume = null; + + // These should correspond to the campfire's attached body + dwc._planetBody = null; + dwc._ringWorldController = null; + + managerObj.SetActive(true); + + // Run after Start() completes + Delay.FireOnNextUpdate(() => + { + dwc._dreamBody = null; + dwc._dreamWorldSector = null; + dwc._dreamWorldVolume = null; + dwc._planetBody = null; + dwc._ringWorldController = null; + }); + + } + + private static GameObject MigrateCopy(GameObject go, GameObject newParent) + { + var clone = GameObject.Instantiate(go); + clone.transform.SetParent(newParent.transform, false); + return clone; + } + } +} diff --git a/NewHorizons/Handlers/PlanetDestructionHandler.cs b/NewHorizons/Handlers/PlanetDestructionHandler.cs index 7087c6fe..65152541 100644 --- a/NewHorizons/Handlers/PlanetDestructionHandler.cs +++ b/NewHorizons/Handlers/PlanetDestructionHandler.cs @@ -70,6 +70,7 @@ namespace NewHorizons.Handlers if (Main.HasDLC) { StrangerRemoved(); + DreamWorldRemoved(); } // Put it back at the center of the universe after banishing it else there are weird graphical bugs @@ -90,6 +91,11 @@ namespace NewHorizons.Handlers } } + private static void DreamWorldRemoved() + { + DreamHandler.MigrateDreamWorldController(); + } + private static void SunRemoved() { var sun = SearchUtilities.Find("Sun_Body").GetComponent(); @@ -207,6 +213,9 @@ namespace NewHorizons.Handlers case AstroObject.Name.RingWorld: StrangerRemoved(); break; + case AstroObject.Name.DreamWorld: + DreamWorldRemoved(); + break; } // Always delete the children diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index b80cf1e3..3da1061e 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -4,6 +4,7 @@ using NewHorizons.Builder.Body; using NewHorizons.Builder.General; using NewHorizons.Builder.Props; using NewHorizons.Builder.Props.Audio; +using NewHorizons.Builder.Props.EchoesOfTheEye; using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.Components.Fixers; using NewHorizons.Components.Ship; @@ -381,6 +382,8 @@ namespace NewHorizons ProjectionBuilder.InitPrefabs(); CloakBuilder.InitPrefab(); RaftBuilder.InitPrefab(); + DreamCampfireBuilder.InitPrefab(); + DreamArrivalPointBuilder.InitPrefab(); } WarpPadBuilder.InitPrefabs(); diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs index 4119fd0a..84471b9b 100644 --- a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs @@ -26,5 +26,40 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches .Repeat(matcher => matcher.RemoveInstructions(5)) .InstructionEnumeration(); } + + [HarmonyPrefix] + [HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))] + public static void DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint) + { + var dreamWorldAO = Locator.GetAstroObject(AstroObject.Name.DreamWorld); + if (arrivalPoint.GetAttachedOWRigidbody() == dreamWorldAO.GetOWRigidbody()) + { + __instance._dreamBody = dreamWorldAO.GetAttachedOWRigidbody(); + __instance._dreamWorldSector = dreamWorldAO.GetRootSector(); + __instance._dreamWorldVolume = __instance._dreamWorldSector.transform.Find("Volumes_DreamWorld").Find("DreamWorldVolume").GetComponent(); + } + else + { + var arrivalAO = arrivalPoint.GetComponentInParent(); + __instance._dreamBody = arrivalAO.GetAttachedOWRigidbody(); + __instance._dreamWorldSector = arrivalAO.GetRootSector(); + __instance._dreamWorldVolume = arrivalAO._gravityVolume.GetOWTriggerVolume(); + } + + __instance._primarySimulationRoot.GetComponent().SetSector(__instance._dreamWorldSector); + + var ringWorldAO = Locator.GetAstroObject(AstroObject.Name.RingWorld); + if (dreamCampfire.GetAttachedOWRigidbody() == ringWorldAO.GetOWRigidbody()) + { + __instance._planetBody = ringWorldAO.GetAttachedOWRigidbody(); + __instance._ringWorldController = ringWorldAO.GetComponent(); + } + else + { + var departureAO = dreamCampfire.GetComponentInParent(); + __instance._planetBody = departureAO.GetAttachedOWRigidbody(); + __instance._ringWorldController = null; + } + } } } From 6528d2c654f4141fde6aba365a758bfaea5a6c57 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 00:55:29 -0500 Subject: [PATCH 02/17] Build simulation meshes --- .../EchoesOfTheEye/DreamSimulationBuilder.cs | 83 +++++++++++++++++++ NewHorizons/Builder/Props/PropBuildManager.cs | 5 ++ .../Components/Props/DreamSimulationMesh.cs | 76 +++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs create mode 100644 NewHorizons/Components/Props/DreamSimulationMesh.cs diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs new file mode 100644 index 00000000..47623e1b --- /dev/null +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs @@ -0,0 +1,83 @@ +using NewHorizons.Components.Props; +using NewHorizons.Utility; +using NewHorizons.Utility.OuterWilds; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Builder.Props.EchoesOfTheEye +{ + public static class DreamSimulationBuilder + { + private static Material gridMaterial; + private static Material waterMaterial; + + private readonly static string[] EXCLUDED_OBJECT_NAMES = + { + "Prefab_IP_SIM_", + "Props_IP_SIM_", + "Effects_IP_SIM_", + }; + + private readonly static string[] EXCLUDED_SHADER_NAMES = + { + "Fog", + "Simulation Bubble", + "Foliage", + "Flame", + }; + + public static void MakeDreamSimulationMeshes(GameObject go) + { + if (gridMaterial == null) gridMaterial = SearchUtilities.FindResourceOfTypeAndName("Terrain_IP_DreamGrid_mat"); + if (waterMaterial == null) waterMaterial = SearchUtilities.FindResourceOfTypeAndName("Terrain_IP_DreamGrid_mat"); + + foreach (var mr in go.GetComponentsInChildren(true)) + { + if (mr.GetType() != typeof(MeshRenderer)) continue; + var mf = mr.GetComponent(); + if (mf == null) continue; + if (!CheckMeshCreationHeuristic(mr.gameObject, mr.sharedMaterials)) continue; + var simMesh = new GameObject("SimulationMesh").AddComponent(); + simMesh.Init(mr.transform, GetMeshMaterial(go, mr.sharedMaterials)); + } + } + + private static Material GetMeshMaterial(GameObject go, Material[] materials) + { + if (materials.Any(m => m.name.Contains("Ocean_Stencil_mat"))) return waterMaterial; + return gridMaterial; + } + + private static bool CheckMeshCreationHeuristic(GameObject go, Material[] materials) + { + if (go.layer == Layer.DreamSimulation) return false; + var mr = go.GetComponent(); + if (EXCLUDED_SHADER_NAMES.Any(name => materials.Any(mat => mat.shader.name.Contains(name)))) return false; + if (go.transform.parent) + { + foreach (Transform c in go.transform.parent) + { + if (c && c.gameObject.layer == Layer.DreamSimulation) return false; + } + } + if (go.transform.parent.parent) + { + foreach (Transform c in go.transform.parent.parent) + { + if (c && c.gameObject.layer == Layer.DreamSimulation) return false; + } + } + var t = go.transform; + while (t != null) + { + if (EXCLUDED_OBJECT_NAMES.Any(t.name.Contains)) return false; + t = t.parent; + } + return true; + } + } +} diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index 8cff2939..3b5b2e8f 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -181,6 +181,11 @@ namespace NewHorizons.Builder.Props } } } + + if (Main.HasDLC && config.Props.dreamArrivalPoints != null && config.Props.dreamArrivalPoints.Any(p => p.generateSimulationMeshes)) + { + DreamSimulationBuilder.MakeDreamSimulationMeshes(sector ? sector.gameObject : go); + } } private static bool _ignoreParent; diff --git a/NewHorizons/Components/Props/DreamSimulationMesh.cs b/NewHorizons/Components/Props/DreamSimulationMesh.cs new file mode 100644 index 00000000..8283ad51 --- /dev/null +++ b/NewHorizons/Components/Props/DreamSimulationMesh.cs @@ -0,0 +1,76 @@ +using NewHorizons.Utility.OuterWilds; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Remoting; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Components.Props +{ + public class DreamSimulationMesh : MonoBehaviour + { + Transform target; + Material mat; + MeshFilter sourceMeshFilter; + MeshRenderer sourceMeshRenderer; + MeshFilter targetMeshFilter; + MeshRenderer targetMeshRenderer; + StreamingRenderMeshHandle streamingHandle; + + bool initialized; + + public void Init(Transform target, Material mat) + { + this.target = target; + this.mat = mat; + + gameObject.layer = Layer.DreamSimulation; + + sourceMeshFilter = target.GetComponent(); + sourceMeshRenderer = target.GetComponent(); + targetMeshFilter = gameObject.AddComponent(); + targetMeshRenderer = gameObject.AddComponent(); + + transform.SetParent(target.transform, false); + + streamingHandle = target.GetComponent(); + if (streamingHandle != null) + { + streamingHandle.OnMeshLoaded += OnMeshLoaded; + streamingHandle.OnMeshUnloaded += OnMeshUnloaded; + } + + initialized = true; + Sync(); + } + + public void Sync() + { + if (!initialized) return; + targetMeshFilter.sharedMesh = sourceMeshFilter.sharedMesh; + targetMeshRenderer.sharedMaterials = sourceMeshRenderer.sharedMaterials.Select(_ => mat).ToArray(); + targetMeshRenderer.enabled = sourceMeshRenderer.enabled; + } + + void OnDestroy() + { + if (streamingHandle != null) + { + streamingHandle.OnMeshLoaded -= OnMeshLoaded; + streamingHandle.OnMeshUnloaded -= OnMeshUnloaded; + } + } + + void OnMeshLoaded() + { + Sync(); + } + + void OnMeshUnloaded() + { + Sync(); + } + } +} From 637fa401cf800b3c0bb868b831d4f2a298cc1418 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 00:55:40 -0500 Subject: [PATCH 03/17] Disable ambient lights in dream world --- .../Builder/General/AmbientLightBuilder.cs | 3 +++ NewHorizons/Components/AmbientLight.cs | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 NewHorizons/Components/AmbientLight.cs diff --git a/NewHorizons/Builder/General/AmbientLightBuilder.cs b/NewHorizons/Builder/General/AmbientLightBuilder.cs index d177679f..0688850b 100644 --- a/NewHorizons/Builder/General/AmbientLightBuilder.cs +++ b/NewHorizons/Builder/General/AmbientLightBuilder.cs @@ -2,6 +2,7 @@ using UnityEngine; using NewHorizons.Utility; using NewHorizons.External.Modules; using NewHorizons.Utility.Files; +using NewHorizons.Components; namespace NewHorizons.Builder.General { @@ -64,6 +65,8 @@ namespace NewHorizons.Builder.General } } + lightGO.AddComponent(); + return light; } } diff --git a/NewHorizons/Components/AmbientLight.cs b/NewHorizons/Components/AmbientLight.cs new file mode 100644 index 00000000..a86a473e --- /dev/null +++ b/NewHorizons/Components/AmbientLight.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Components +{ + public class AmbientLight : MonoBehaviour + { + Light light; + float cachedIntensity; + + void Awake() + { + light = GetComponent(); + cachedIntensity = light.intensity; + } + + void Update() + { + var targetIntensity = PlayerState.InDreamWorld() ? 0f : cachedIntensity; + light.intensity = Mathf.MoveTowards(light.intensity, targetIntensity, Time.deltaTime * 5f); + } + } +} From 26dbc048641661694a7ce2e904037cf322ae84e5 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 5 Oct 2024 05:56:53 +0000 Subject: [PATCH 04/17] Updated Schemas --- NewHorizons/Schemas/body_schema.json | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index f759f8e2..86532bfb 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -1293,6 +1293,20 @@ "items": { "$ref": "#/definitions/ShuttleInfo" } + }, + "dreamCampfires": { + "type": "array", + "description": "Add campfires that allow you to enter the dream world/simulation. Must be paired with a dream arrival point, which can be placed on this planet or elsewhere.", + "items": { + "$ref": "#/definitions/DreamCampfireInfo" + } + }, + "dreamArrivalPoints": { + "type": "array", + "description": "Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere.", + "items": { + "$ref": "#/definitions/DreamArrivalPointInfo" + } } } }, @@ -3288,6 +3302,84 @@ } } }, + "DreamCampfireInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, + "id": { + "type": "string", + "description": "Unique ID for this dream-world campfire" + } + } + }, + "DreamArrivalPointInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, + "id": { + "type": "string", + "description": "Unique ID for this dream-world arrival point" + }, + "generateSimulationMeshes": { + "type": "boolean", + "description": "Whether to generate simulation meshes (the models used in the \"tronworld\" or \"matrix\" view) for most objects on the current planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them." + } + } + }, "ReferenceFrameModule": { "type": "object", "additionalProperties": false, From fd06497193fa47e6218dc4a45944ab97efd67a6d Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 00:58:28 -0500 Subject: [PATCH 05/17] Document simulation planets should be static --- NewHorizons/External/Modules/PropModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index 68ff0ee6..04662df7 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -129,7 +129,7 @@ namespace NewHorizons.External.Modules public DreamCampfireInfo[] dreamCampfires; /// - /// Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere. + /// Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere. The planet with the arrival point should be statically positioned to avoid issues with the simulation view materials. /// public DreamArrivalPointInfo[] dreamArrivalPoints; From 821cd982ea41325faaceb694b51a50df8124ddb5 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 5 Oct 2024 05:59:44 +0000 Subject: [PATCH 06/17] Updated Schemas --- NewHorizons/Schemas/body_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 86532bfb..e7611277 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -1303,7 +1303,7 @@ }, "dreamArrivalPoints": { "type": "array", - "description": "Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere.", + "description": "Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere. The planet with the arrival point should be statically positioned to avoid issues with the simulation view materials.", "items": { "$ref": "#/definitions/DreamArrivalPointInfo" } From 3317221f5844c04ec76d82e8022f8f6af43bba9a Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 01:29:25 -0500 Subject: [PATCH 07/17] Remove ambient light code --- .../Builder/General/AmbientLightBuilder.cs | 2 -- NewHorizons/Components/AmbientLight.cs | 27 ------------------- 2 files changed, 29 deletions(-) delete mode 100644 NewHorizons/Components/AmbientLight.cs diff --git a/NewHorizons/Builder/General/AmbientLightBuilder.cs b/NewHorizons/Builder/General/AmbientLightBuilder.cs index 0688850b..36d0c0c0 100644 --- a/NewHorizons/Builder/General/AmbientLightBuilder.cs +++ b/NewHorizons/Builder/General/AmbientLightBuilder.cs @@ -65,8 +65,6 @@ namespace NewHorizons.Builder.General } } - lightGO.AddComponent(); - return light; } } diff --git a/NewHorizons/Components/AmbientLight.cs b/NewHorizons/Components/AmbientLight.cs deleted file mode 100644 index a86a473e..00000000 --- a/NewHorizons/Components/AmbientLight.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace NewHorizons.Components -{ - public class AmbientLight : MonoBehaviour - { - Light light; - float cachedIntensity; - - void Awake() - { - light = GetComponent(); - cachedIntensity = light.intensity; - } - - void Update() - { - var targetIntensity = PlayerState.InDreamWorld() ? 0f : cachedIntensity; - light.intensity = Mathf.MoveTowards(light.intensity, targetIntensity, Time.deltaTime * 5f); - } - } -} From 06491ec9bd6da47bd56baef87d11127b42a29521 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 01:40:15 -0500 Subject: [PATCH 08/17] Add comments to dreamworldcontroller patch --- .../EchoesOfTheEyePatches/DreamworldControllerPatches.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs index 84471b9b..6ee7e21f 100644 --- a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs @@ -31,6 +31,7 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches [HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))] public static void DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint) { + // Make the body/sector/volume where the player 'wakes up' in the dream match the body where the arrival point is located if it isn't the vanilla DreamWorld, or reset it if it is var dreamWorldAO = Locator.GetAstroObject(AstroObject.Name.DreamWorld); if (arrivalPoint.GetAttachedOWRigidbody() == dreamWorldAO.GetOWRigidbody()) { @@ -46,8 +47,10 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches __instance._dreamWorldVolume = arrivalAO._gravityVolume.GetOWTriggerVolume(); } + // Make the 'bubble' around the artifact load correctly when the destination body isn't the vanilla DreamWorld __instance._primarySimulationRoot.GetComponent().SetSector(__instance._dreamWorldSector); + // Make the body where the player 'wakes up' out of the dream match the body where the campfire is located if it isn't the Stranger ("RingWorld"), or reset it if it is var ringWorldAO = Locator.GetAstroObject(AstroObject.Name.RingWorld); if (dreamCampfire.GetAttachedOWRigidbody() == ringWorldAO.GetOWRigidbody()) { From 823aa36b566a55b20799932c40bb79fb51b83f47 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 01:40:23 -0500 Subject: [PATCH 09/17] Handle possible null parent parent --- .../Props/EchoesOfTheEye/DreamSimulationBuilder.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs index 47623e1b..e51165f9 100644 --- a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs @@ -63,12 +63,12 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye { if (c && c.gameObject.layer == Layer.DreamSimulation) return false; } - } - if (go.transform.parent.parent) - { - foreach (Transform c in go.transform.parent.parent) + if (go.transform.parent.parent) { - if (c && c.gameObject.layer == Layer.DreamSimulation) return false; + foreach (Transform c in go.transform.parent.parent) + { + if (c && c.gameObject.layer == Layer.DreamSimulation) return false; + } } } var t = go.transform; From 9b8d44a81935e51c0474ef18a71f89149e42b62c Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 09:55:03 -0500 Subject: [PATCH 10/17] Dreamworld dimensions --- .../DreamDimensionBuilder.cs} | 28 ++++++++++- NewHorizons/Builder/Props/PropBuildManager.cs | 5 -- NewHorizons/Components/EOTE/DreamDimension.cs | 48 +++++++++++++++++++ NewHorizons/External/Configs/PlanetConfig.cs | 8 ++++ NewHorizons/External/Modules/DreamModule.cs | 22 +++++++++ NewHorizons/External/NewHorizonBody.cs | 3 ++ NewHorizons/Handlers/PlanetCreationHandler.cs | 6 +++ .../DreamworldControllerPatches.cs | 8 ++++ 8 files changed, 121 insertions(+), 7 deletions(-) rename NewHorizons/Builder/{Props/EchoesOfTheEye/DreamSimulationBuilder.cs => Body/DreamDimensionBuilder.cs} (74%) create mode 100644 NewHorizons/Components/EOTE/DreamDimension.cs create mode 100644 NewHorizons/External/Modules/DreamModule.cs diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs b/NewHorizons/Builder/Body/DreamDimensionBuilder.cs similarity index 74% rename from NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs rename to NewHorizons/Builder/Body/DreamDimensionBuilder.cs index e51165f9..9bd5c69c 100644 --- a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamSimulationBuilder.cs +++ b/NewHorizons/Builder/Body/DreamDimensionBuilder.cs @@ -1,6 +1,10 @@ +using NewHorizons.Components.EOTE; using NewHorizons.Components.Props; +using NewHorizons.External; +using NewHorizons.External.Configs; using NewHorizons.Utility; using NewHorizons.Utility.OuterWilds; +using NewHorizons.Utility.OWML; using System; using System.Collections.Generic; using System.Linq; @@ -8,9 +12,9 @@ using System.Text; using System.Threading.Tasks; using UnityEngine; -namespace NewHorizons.Builder.Props.EchoesOfTheEye +namespace NewHorizons.Builder.Body { - public static class DreamSimulationBuilder + public static class DreamDimensionBuilder { private static Material gridMaterial; private static Material waterMaterial; @@ -30,6 +34,26 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye "Flame", }; + public static void Make(GameObject planetGO, Sector sector, NewHorizonsBody body) + { + var bodyWantsSimMeshes = body.Config.Dream?.generateSimulationMeshes ?? false; + var propsWantSimMeshes = body.Config.Props?.dreamArrivalPoints?.Any(p => p.generateSimulationMeshes) ?? false; + if (bodyWantsSimMeshes || propsWantSimMeshes) + { + MakeDreamSimulationMeshes(sector ? sector.gameObject : planetGO); + } + + if (body.Config?.Dream?.inDreamWorld ?? false) + { + var dreamDimension = planetGO.AddComponent(); + Delay.FireInNUpdates(() => + { + dreamDimension.Initialize(); + }, 4); + } + + } + public static void MakeDreamSimulationMeshes(GameObject go) { if (gridMaterial == null) gridMaterial = SearchUtilities.FindResourceOfTypeAndName("Terrain_IP_DreamGrid_mat"); diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index 3b5b2e8f..8cff2939 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -181,11 +181,6 @@ namespace NewHorizons.Builder.Props } } } - - if (Main.HasDLC && config.Props.dreamArrivalPoints != null && config.Props.dreamArrivalPoints.Any(p => p.generateSimulationMeshes)) - { - DreamSimulationBuilder.MakeDreamSimulationMeshes(sector ? sector.gameObject : go); - } } private static bool _ignoreParent; diff --git a/NewHorizons/Components/EOTE/DreamDimension.cs b/NewHorizons/Components/EOTE/DreamDimension.cs new file mode 100644 index 00000000..00c3389b --- /dev/null +++ b/NewHorizons/Components/EOTE/DreamDimension.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Components.EOTE +{ + public class DreamDimension : MonoBehaviour + { + private bool initialized; + private bool active; + private List toggledObjects = []; + + public void Initialize() + { + foreach (Transform child in transform) + { + if (child.gameObject.name == "FieldDetector") continue; + toggledObjects.Add(child.gameObject); + } + + initialized = true; + UpdateState(); + } + + public void SetActive(bool active) + { + if (this.active != active) + { + this.active = active; + UpdateState(); + } + } + + void UpdateState() + { + foreach (var obj in toggledObjects) obj.SetActive(active); + } + + public void Update() + { + if (!initialized) return; + SetActive(PlayerState.InDreamWorld()); + } + } +} diff --git a/NewHorizons/External/Configs/PlanetConfig.cs b/NewHorizons/External/Configs/PlanetConfig.cs index 28f00318..2e23410b 100644 --- a/NewHorizons/External/Configs/PlanetConfig.cs +++ b/NewHorizons/External/Configs/PlanetConfig.cs @@ -93,6 +93,11 @@ namespace NewHorizons.External.Configs /// public CloakModule Cloak; + /// + /// Make this planet part of the dream world + /// + public DreamModule Dream; + /// /// Make this body into a focal point (barycenter) /// @@ -282,6 +287,9 @@ namespace NewHorizons.External.Configs // Stars and focal points shouldnt be destroyed by stars if (Star != null || FocalPoint != null) Base.invulnerableToSun = true; + + // Disable map marker for dream dimensions + if (Dream != null && Dream.inDreamWorld) MapMarker.enabled = false; } public void Migrate() diff --git a/NewHorizons/External/Modules/DreamModule.cs b/NewHorizons/External/Modules/DreamModule.cs new file mode 100644 index 00000000..1d422689 --- /dev/null +++ b/NewHorizons/External/Modules/DreamModule.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External.Modules +{ + [JsonObject] + public class DreamModule + { + /// + /// Setting this value will make this body a dream world style dimension where its contents are only activated while entering it from a dream campfire. Disables the body's map marker. + /// + public bool inDreamWorld; + /// + /// Whether to generate simulation meshes (the models used in the "tronworld" or "matrix" view) for most objects on this planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them. + /// + public bool generateSimulationMeshes; + } +} diff --git a/NewHorizons/External/NewHorizonBody.cs b/NewHorizons/External/NewHorizonBody.cs index 6779e526..b2ed22fc 100644 --- a/NewHorizons/External/NewHorizonBody.cs +++ b/NewHorizons/External/NewHorizonBody.cs @@ -32,8 +32,11 @@ namespace NewHorizons.External { var detailPaths = Config?.Props?.details?.Select(x => x.path) ?? Array.Empty(); return Config?.Cloak != null + || Config?.Dream != null || Config?.Props?.rafts != null || Config?.Props?.slideShows != null + || Config?.Props?.dreamArrivalPoints != null + || Config?.Props?.dreamCampfires != null || detailPaths.Any(x => x.StartsWith("RingWorld_Body") || x.StartsWith("DreamWorld_Body")); } catch diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index fda247e7..5f5a0587 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -1,3 +1,4 @@ +using Epic.OnlineServices; using NewHorizons.Builder.Atmosphere; using NewHorizons.Builder.Body; using NewHorizons.Builder.General; @@ -724,6 +725,11 @@ namespace NewHorizons.Handlers } } + if (Main.HasDLC) + { + DreamDimensionBuilder.Make(go, sector, body); + } + // Has to go last probably if (willHaveCloak) { diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs index 6ee7e21f..ede68948 100644 --- a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using NewHorizons.Components.EOTE; using System.Collections.Generic; using System.Reflection.Emit; using UnityEngine; @@ -31,6 +32,13 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches [HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))] public static void DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint) { + // If we are arriving in a custom dream dimension, activate it immediately + var dimension = arrivalPoint.GetAttachedOWRigidbody().GetComponent(); + if (dimension != null) + { + dimension.SetActive(true); + } + // Make the body/sector/volume where the player 'wakes up' in the dream match the body where the arrival point is located if it isn't the vanilla DreamWorld, or reset it if it is var dreamWorldAO = Locator.GetAstroObject(AstroObject.Name.DreamWorld); if (arrivalPoint.GetAttachedOWRigidbody() == dreamWorldAO.GetOWRigidbody()) From 982642028750b64c707b1d19c2eec77b02159253 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 5 Oct 2024 14:58:58 +0000 Subject: [PATCH 11/17] Updated Schemas --- NewHorizons/Schemas/body_schema.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 37d707b4..100d8d92 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -65,6 +65,10 @@ "description": "Add a cloaking field to this planet", "$ref": "#/definitions/CloakModule" }, + "Dream": { + "description": "Make this planet part of the dream world", + "$ref": "#/definitions/DreamModule" + }, "FocalPoint": { "description": "Make this body into a focal point (barycenter)", "$ref": "#/definitions/FocalPointModule" @@ -799,6 +803,20 @@ } } }, + "DreamModule": { + "type": "object", + "additionalProperties": false, + "properties": { + "inDreamWorld": { + "type": "boolean", + "description": "Setting this value will make this body a dream world style dimension where its contents are only activated while entering it from a dream campfire. Disables the body's map marker." + }, + "generateSimulationMeshes": { + "type": "boolean", + "description": "Whether to generate simulation meshes (the models used in the \"tronworld\" or \"matrix\" view) for most objects on this planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them." + } + } + }, "FocalPointModule": { "type": "object", "additionalProperties": false, From ae13194d13920b92665f5054da4472c24b87af9f Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 16:09:05 -0500 Subject: [PATCH 12/17] Preserve original dream campfire when recursive dreaming so you get kicked out to the real world properly --- .../DreamworldControllerPatches.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs index ede68948..ded7f3d5 100644 --- a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs @@ -30,7 +30,7 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches [HarmonyPrefix] [HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))] - public static void DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint) + public static bool DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint) { // If we are arriving in a custom dream dimension, activate it immediately var dimension = arrivalPoint.GetAttachedOWRigidbody().GetComponent(); @@ -58,6 +58,14 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches // Make the 'bubble' around the artifact load correctly when the destination body isn't the vanilla DreamWorld __instance._primarySimulationRoot.GetComponent().SetSector(__instance._dreamWorldSector); + // if the player's already in the dream world, we want to wake up at the first campfire we slept at, so don't override those values + if (PlayerState.InDreamWorld()) + { + __instance._dreamArrivalPoint = arrivalPoint; + __instance._enteringDream = true; + return false; + } + // Make the body where the player 'wakes up' out of the dream match the body where the campfire is located if it isn't the Stranger ("RingWorld"), or reset it if it is var ringWorldAO = Locator.GetAstroObject(AstroObject.Name.RingWorld); if (dreamCampfire.GetAttachedOWRigidbody() == ringWorldAO.GetOWRigidbody()) @@ -71,6 +79,8 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches __instance._planetBody = departureAO.GetAttachedOWRigidbody(); __instance._ringWorldController = null; } + + return true; } } } From 05d0dfc185402d84242f9fd1fdaeedfa63483a31 Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sat, 5 Oct 2024 22:47:02 -0500 Subject: [PATCH 13/17] Use EnterDreamWorld/ExitDreamWorld events instead of polling in update --- .../EchoesOfTheEye/DreamCampfireBuilder.cs | 1 + NewHorizons/Components/EOTE/DreamDimension.cs | 22 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs index 5005e310..f0eb6618 100644 --- a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs @@ -49,6 +49,7 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye var campfire = campfireObj.GetComponentInChildren(); campfire._dreamArrivalLocation = DreamHandler.GetDreamArrivalLocation(info.id); + // The streaming groups on DreamCampfires get set on Start() so we wait until after to change it again Delay.FireInNUpdates(() => { var streaming = campfireObj.GetComponentInChildren(); if (streaming != null) diff --git a/NewHorizons/Components/EOTE/DreamDimension.cs b/NewHorizons/Components/EOTE/DreamDimension.cs index 00c3389b..e244dca8 100644 --- a/NewHorizons/Components/EOTE/DreamDimension.cs +++ b/NewHorizons/Components/EOTE/DreamDimension.cs @@ -34,15 +34,31 @@ namespace NewHorizons.Components.EOTE } } + void Awake() + { + GlobalMessenger.AddListener("EnterDreamWorld", OnEnterDreamWorld); + GlobalMessenger.AddListener("ExitDreamWorld", OnExitDreamWorld); + } + + void OnDestroy() + { + GlobalMessenger.RemoveListener("EnterDreamWorld", OnEnterDreamWorld); + GlobalMessenger.RemoveListener("ExitDreamWorld", OnExitDreamWorld); + } + void UpdateState() { foreach (var obj in toggledObjects) obj.SetActive(active); } - public void Update() + void OnEnterDreamWorld() { - if (!initialized) return; - SetActive(PlayerState.InDreamWorld()); + SetActive(true); + } + + void OnExitDreamWorld() + { + SetActive(false); } } } From 3c1abb582eefb37543c21e8a5698a8ce69bfe00e Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 6 Oct 2024 11:30:56 -0400 Subject: [PATCH 14/17] I don't feel like uploading my visual studio --- .../Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs | 2 +- .../Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs | 2 +- NewHorizons/Components/EOTE/DreamDimension.cs | 4 +++- NewHorizons/Handlers/DreamHandler.cs | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs index cb828744..c2a5d261 100644 --- a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamArrivalPointBuilder.cs @@ -34,7 +34,7 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye var dreamArrivalPoint = _prefab.GetComponent(); dreamArrivalPoint._location = DreamArrivalPoint.Location.Undefined; dreamArrivalPoint._sector = null; - dreamArrivalPoint._entrywayVolumes = []; + dreamArrivalPoint._entrywayVolumes = new OWTriggerVolume[0]; dreamArrivalPoint._raftSpawn = null; dreamArrivalPoint._connectedDreamCampfire = null; dreamArrivalPoint._campfire._sector = null; diff --git a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs index f0eb6618..8d05f73e 100644 --- a/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs +++ b/NewHorizons/Builder/Props/EchoesOfTheEye/DreamCampfireBuilder.cs @@ -33,7 +33,7 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye var campfire = _prefab.GetComponentInChildren(); campfire._dreamArrivalLocation = DreamArrivalPoint.Location.Undefined; campfire._sector = null; - campfire._entrywayVolumes = []; + campfire._entrywayVolumes = new OWTriggerVolume[0]; } } } diff --git a/NewHorizons/Components/EOTE/DreamDimension.cs b/NewHorizons/Components/EOTE/DreamDimension.cs index e244dca8..89eec750 100644 --- a/NewHorizons/Components/EOTE/DreamDimension.cs +++ b/NewHorizons/Components/EOTE/DreamDimension.cs @@ -11,10 +11,12 @@ namespace NewHorizons.Components.EOTE { private bool initialized; private bool active; - private List toggledObjects = []; + private List toggledObjects = new(); public void Initialize() { + if (initialized) return; + foreach (Transform child in transform) { if (child.gameObject.name == "FieldDetector") continue; diff --git a/NewHorizons/Handlers/DreamHandler.cs b/NewHorizons/Handlers/DreamHandler.cs index 7bc8b0bf..5a967bdd 100644 --- a/NewHorizons/Handlers/DreamHandler.cs +++ b/NewHorizons/Handlers/DreamHandler.cs @@ -44,7 +44,7 @@ namespace NewHorizons.Handlers var simRootObj = MigrateCopy(oldDWC._primarySimulationRoot.gameObject, managerObj); dwc._primarySimulationRoot = simRootObj.transform; - dwc._simulationRoots = [simRootObj.transform]; + dwc._simulationRoots = new Transform[] { simRootObj.transform }; dwc._simulationCamera = simRootObj.FindChild("Camera_Simulation").GetComponent(); dwc._simulationSphere = simRootObj.FindChild("SimulationSphere").GetComponent(); From afe2bd558a9d8002444a7012b6f0cae95be35fbd Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 6 Oct 2024 12:26:53 -0400 Subject: [PATCH 15/17] Allow NH water to extinguish dreamworld lanterns --- .../Components/EOTE/LanternExtinguisher.cs | 23 +++++++++++++++++++ NewHorizons/External/Modules/DreamModule.cs | 5 ---- NewHorizons/Main.cs | 2 ++ 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 NewHorizons/Components/EOTE/LanternExtinguisher.cs diff --git a/NewHorizons/Components/EOTE/LanternExtinguisher.cs b/NewHorizons/Components/EOTE/LanternExtinguisher.cs new file mode 100644 index 00000000..26d1b2a0 --- /dev/null +++ b/NewHorizons/Components/EOTE/LanternExtinguisher.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Components.EOTE; + +public class LanternExtinguisher : MonoBehaviour +{ + public void Update() + { + if (PlayerState.InDreamWorld() && PlayerState.IsCameraUnderwater()) + { + var heldItem = Locator.GetToolModeSwapper().GetItemCarryTool().GetHeldItem(); + if (heldItem is DreamLanternItem lantern && lantern._lanternController._lit) + { + Locator.GetDreamWorldController().ExitDreamWorld(DreamWakeType.LanternSubmerged); + } + } + } +} diff --git a/NewHorizons/External/Modules/DreamModule.cs b/NewHorizons/External/Modules/DreamModule.cs index 1d422689..c8b7fd2f 100644 --- a/NewHorizons/External/Modules/DreamModule.cs +++ b/NewHorizons/External/Modules/DreamModule.cs @@ -1,9 +1,4 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace NewHorizons.External.Modules { diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 57b6c619..08dd728c 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -6,6 +6,7 @@ using NewHorizons.Builder.Props; using NewHorizons.Builder.Props.Audio; using NewHorizons.Builder.Props.EchoesOfTheEye; using NewHorizons.Builder.Props.TranslatorText; +using NewHorizons.Components.EOTE; using NewHorizons.Components.Fixers; using NewHorizons.Components.Ship; using NewHorizons.Components.SizeControllers; @@ -622,6 +623,7 @@ namespace NewHorizons Locator.GetPlayerBody().gameObject.AddComponent(); Locator.GetPlayerBody().gameObject.AddComponent(); Locator.GetPlayerBody().gameObject.AddComponent(); + if (HasDLC) Locator.GetPlayerBody().gameObject.AddComponent(); PlayerSpawnHandler.OnSystemReady(shouldWarpInFromShip, shouldWarpInFromVessel); From 3e0cd944978e57d35981a3957a3e141a1d13b22d Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 6 Oct 2024 12:45:18 -0400 Subject: [PATCH 16/17] Preload assets when dying in dream --- .../DreamworldControllerPatches.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs index ded7f3d5..209021f7 100644 --- a/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs +++ b/NewHorizons/Patches/EchoesOfTheEyePatches/DreamworldControllerPatches.cs @@ -82,5 +82,42 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches return true; } + + /// + /// Load assets when dying in dreamworld and returning to a custom dream campfire + /// Only really relevant for campfires on stock planets + /// + /// This only gets us like a 1 second headstart on loading so honestly it's barely worth it, + /// could be replaced with keeping the assets loaded the entire time you're in the dreamworld + /// but we should only do that if it becomes relevant I think + /// + /// + /// + [HarmonyPrefix, HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))] + private static void OnEnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire) + { + var planet = dreamCampfire.GetComponentInParent(); + if (planet.GetAstroObjectName() != AstroObject.Name.RingWorld) + { + _dreamEntryLocationStreamingGroup = planet.GetComponentInChildren(); + GlobalMessenger.AddListener("PlayerDeath", OnPlayerDeath); + } + } + + private static StreamingGroup _dreamEntryLocationStreamingGroup; + + private static void OnPlayerDeath(DeathType type) + { + if (PlayerState.InDreamWorld()) + { + if (_dreamEntryLocationStreamingGroup != null) + { + _dreamEntryLocationStreamingGroup.RequestRequiredAssets(0); + _dreamEntryLocationStreamingGroup.RequestGeneralAssets(0); + } + _dreamEntryLocationStreamingGroup = null; + } + GlobalMessenger.RemoveListener("PlayerDeath", OnPlayerDeath); + } } } From c37a4445c60e7c31dd0c0bc1e6dfa14185195e73 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 6 Oct 2024 13:26:31 -0400 Subject: [PATCH 17/17] Remove weird plane --- NewHorizons/Handlers/DreamHandler.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NewHorizons/Handlers/DreamHandler.cs b/NewHorizons/Handlers/DreamHandler.cs index 5a967bdd..d96e6457 100644 --- a/NewHorizons/Handlers/DreamHandler.cs +++ b/NewHorizons/Handlers/DreamHandler.cs @@ -71,6 +71,9 @@ namespace NewHorizons.Handlers dwc._dreamWorldVolume = null; dwc._planetBody = null; dwc._ringWorldController = null; + + // Dreamworld has a giant plane for simulation water, we don't want that in our custom world + dwc._primarySimulationRoot.Find("water_simulation").gameObject.SetActive(false); }); }