diff --git a/NewHorizons/Builder/Body/SingularityBuilder.cs b/NewHorizons/Builder/Body/SingularityBuilder.cs index 9db42133..a961c9d5 100644 --- a/NewHorizons/Builder/Body/SingularityBuilder.cs +++ b/NewHorizons/Builder/Body/SingularityBuilder.cs @@ -11,6 +11,8 @@ using NewHorizons.Builder.Props; using NewHorizons.Utility.OWML; using NewHorizons.Utility.OuterWilds; using NewHorizons.External.SerializableData; +using NewHorizons.Builder.Volumes; +using System; namespace NewHorizons.Builder.Body { @@ -109,31 +111,52 @@ namespace NewHorizons.Builder.Body { foreach (var pair in _pairsToLink) { - var (blackHoleID, whiteHoleID) = pair; - if (!_singularitiesByID.TryGetValue(blackHoleID, out GameObject blackHole)) + try { - NHLogger.LogWarning($"Black hole [{blackHoleID}] is missing."); - continue; + var (blackHoleID, whiteHoleID) = pair; + if (!_singularitiesByID.TryGetValue(blackHoleID, out GameObject blackHole)) + { + NHLogger.LogWarning($"Black hole [{blackHoleID}] is missing."); + continue; + } + if (!_singularitiesByID.TryGetValue(whiteHoleID, out GameObject whiteHole)) + { + NHLogger.LogWarning($"White hole [{whiteHoleID}] is missing."); + continue; + } + var whiteHoleVolume = whiteHole.GetComponentInChildren(); + var blackHoleVolume = blackHole.GetComponentInChildren(); + if (whiteHoleVolume == null || blackHoleVolume == null) + { + NHLogger.LogWarning($"Singularities [{blackHoleID}] and [{whiteHoleID}] do not have compatible polarities."); + continue; + } + if (blackHoleVolume._whiteHole != null && blackHoleVolume._whiteHole != whiteHoleVolume) + { + NHLogger.LogWarning($"Black hole [{blackHoleID}] has already been linked!"); + continue; + } + NHLogger.LogVerbose($"Pairing singularities [{blackHoleID}], [{whiteHoleID}]"); + blackHoleVolume._whiteHole = whiteHoleVolume; + + // If warping to a vanilla planet, we add a streaming volume to pre-load it + var streamingGroup = whiteHoleVolume.GetAttachedOWRigidbody().GetComponentInChildren(); + if (streamingGroup != null) + { + var sphereCollider = blackHoleVolume.GetComponent(); + // Shouldn't ever be null but doesn't hurt ig + var loadRadius = sphereCollider == null ? 100f : sphereCollider.radius + 50f; + var streamingVolume = VolumeBuilder.Make(blackHoleVolume.GetAttachedOWRigidbody().gameObject, blackHoleVolume.GetComponentInParent(), + new External.Modules.Volumes.VolumeInfos.VolumeInfo() { radius = loadRadius }); + streamingVolume.streamingGroup = streamingGroup; + streamingVolume.transform.parent = blackHoleVolume.transform; + streamingVolume.transform.localPosition = Vector3.zero; + } } - if (!_singularitiesByID.TryGetValue(whiteHoleID, out GameObject whiteHole)) + catch (Exception e) { - NHLogger.LogWarning($"White hole [{whiteHoleID}] is missing."); - continue; + NHLogger.LogError($"Failed to pair singularities {e}"); } - var whiteHoleVolume = whiteHole.GetComponentInChildren(); - var blackHoleVolume = blackHole.GetComponentInChildren(); - if (whiteHoleVolume == null || blackHoleVolume == null) - { - NHLogger.LogWarning($"Singularities [{blackHoleID}] and [{whiteHoleID}] do not have compatible polarities."); - continue; - } - if (blackHoleVolume._whiteHole != null && blackHoleVolume._whiteHole != whiteHoleVolume) - { - NHLogger.LogWarning($"Black hole [{blackHoleID}] has already been linked!"); - continue; - } - NHLogger.LogVerbose($"Pairing singularities [{blackHoleID}], [{whiteHoleID}]"); - blackHoleVolume._whiteHole = whiteHoleVolume; } } @@ -167,7 +190,7 @@ namespace NewHorizons.Builder.Body OWAudioSource oneShotOWAudioSource = null; - var singularityAmbience = Object.Instantiate(_blackHoleAmbience, singularity.transform); + var singularityAmbience = GameObject.Instantiate(_blackHoleAmbience, singularity.transform); singularityAmbience.name = polarity ? "BlackHoleAmbience" : "WhiteHoleAmbience"; singularityAmbience.SetActive(true); singularityAmbience.GetComponent().SetSector(sector); @@ -214,7 +237,7 @@ namespace NewHorizons.Builder.Body } else { - var blackHoleOneShot = Object.Instantiate(_blackHoleEmissionOneShot, singularity.transform); + var blackHoleOneShot = GameObject.Instantiate(_blackHoleEmissionOneShot, singularity.transform); blackHoleOneShot.name = "BlackHoleEmissionOneShot"; blackHoleOneShot.SetActive(true); oneShotOWAudioSource = blackHoleOneShot.GetComponent(); @@ -223,7 +246,7 @@ namespace NewHorizons.Builder.Body oneShotAudioSource.minDistance = horizon; if (sizeController != null) sizeController.oneShotAudioSource = oneShotAudioSource; - var blackHoleVolume = Object.Instantiate(_blackHoleVolume, singularity.transform); + var blackHoleVolume = GameObject.Instantiate(_blackHoleVolume, singularity.transform); blackHoleVolume.name = "BlackHoleVolume"; // Scale vanish effect to black hole size @@ -249,7 +272,7 @@ namespace NewHorizons.Builder.Body { foreach (var renderer in blackHoleVolume.GetComponentsInChildren(true)) { - Object.Destroy(renderer); + GameObject.Destroy(renderer); } }); } @@ -257,7 +280,7 @@ namespace NewHorizons.Builder.Body } else { - GameObject whiteHoleVolumeGO = Object.Instantiate(_whiteHoleVolume); + GameObject whiteHoleVolumeGO = GameObject.Instantiate(_whiteHoleVolume); whiteHoleVolumeGO.transform.parent = singularity.transform; whiteHoleVolumeGO.transform.localPosition = Vector3.zero; whiteHoleVolumeGO.transform.localScale = Vector3.one; diff --git a/NewHorizons/Components/Volumes/BaseVolume.cs b/NewHorizons/Components/Volumes/BaseVolume.cs index f313310c..970c3ad9 100644 --- a/NewHorizons/Components/Volumes/BaseVolume.cs +++ b/NewHorizons/Components/Volumes/BaseVolume.cs @@ -3,22 +3,27 @@ using UnityEngine; namespace NewHorizons.Components.Volumes { [RequireComponent(typeof(OWTriggerVolume))] - public abstract class BaseVolume : MonoBehaviour + public abstract class BaseVolume : SectoredMonoBehaviour { private OWTriggerVolume _triggerVolume; - public virtual void Awake() + public override void Awake() { + base.Awake(); _triggerVolume = this.GetRequiredComponent(); _triggerVolume.OnEntry += OnTriggerVolumeEntry; _triggerVolume.OnExit += OnTriggerVolumeExit; } - public virtual void OnDestroy() + public override void OnDestroy() { - if (_triggerVolume == null) return; - _triggerVolume.OnEntry -= OnTriggerVolumeEntry; - _triggerVolume.OnExit -= OnTriggerVolumeExit; + base.OnDestroy(); + + if (_triggerVolume != null) + { + _triggerVolume.OnEntry -= OnTriggerVolumeEntry; + _triggerVolume.OnExit -= OnTriggerVolumeExit; + } } public abstract void OnTriggerVolumeEntry(GameObject hitObj); diff --git a/NewHorizons/Components/Volumes/StreamingWarpVolume.cs b/NewHorizons/Components/Volumes/StreamingWarpVolume.cs new file mode 100644 index 00000000..25616c48 --- /dev/null +++ b/NewHorizons/Components/Volumes/StreamingWarpVolume.cs @@ -0,0 +1,110 @@ +using UnityEngine; + +namespace NewHorizons.Components.Volumes +{ + /// + /// Currently only relevant for Vanilla planets, which actually have streaming groups + /// + internal class StreamingWarpVolume : BaseVolume + { + public StreamingGroup streamingGroup; + private bool _probeInVolume; + private bool _playerInVolume; + private bool _preloadingRequiredAssets; + private bool _preloadingGeneralAssets; + + private SurveyorProbe _probe; + + public void Start() + { + _probe = Locator.GetProbe(); + base.enabled = false; + } + + public void FixedUpdate() + { + bool probeActive = _probe.IsLaunched() && !_probe.IsAnchored(); + + bool shouldBeLoadingRequiredAssets = _playerInVolume || (_probeInVolume && probeActive); + bool shouldBeLoadingGeneralAssets = _playerInVolume; + + UpdatePreloadingState(shouldBeLoadingRequiredAssets, shouldBeLoadingGeneralAssets); + } + + private void UpdatePreloadingState(bool shouldBeLoadingRequiredAssets, bool shouldBeLoadingGeneralAssets) + { + if (!this._preloadingRequiredAssets && shouldBeLoadingRequiredAssets) + { + this.streamingGroup.RequestRequiredAssets(0); + this._preloadingRequiredAssets = true; + } + else if (this._preloadingRequiredAssets && !shouldBeLoadingRequiredAssets) + { + this.streamingGroup.ReleaseRequiredAssets(); + this._preloadingRequiredAssets = false; + } + if (!this._preloadingGeneralAssets && shouldBeLoadingGeneralAssets) + { + this.streamingGroup.RequestGeneralAssets(0); + this._preloadingGeneralAssets = true; + return; + } + if (this._preloadingGeneralAssets && !shouldBeLoadingGeneralAssets) + { + this.streamingGroup.ReleaseGeneralAssets(); + this._preloadingGeneralAssets = false; + } + } + + public override void OnSectorOccupantsUpdated() + { + if (this._sector.ContainsAnyOccupants(DynamicOccupant.Player | DynamicOccupant.Probe)) + { + if (StreamingManager.isStreamingEnabled && this.streamingGroup != null) + { + base.enabled = true; + return; + } + } + else + { + this.UpdatePreloadingState(false, false); + base.enabled = false; + } + } + + public override void OnTriggerVolumeEntry(GameObject hitObj) + { + OWRigidbody attachedOWRigidbody = hitObj.GetAttachedOWRigidbody(false); + if (attachedOWRigidbody != null) + { + if (attachedOWRigidbody.CompareTag("Player")) + { + this._playerInVolume = true; + return; + } + if (attachedOWRigidbody.CompareTag("Probe")) + { + this._probeInVolume = true; + } + } + } + + public override void OnTriggerVolumeExit(GameObject hitObj) + { + OWRigidbody attachedOWRigidbody = hitObj.GetAttachedOWRigidbody(false); + if (attachedOWRigidbody != null) + { + if (attachedOWRigidbody.CompareTag("Player")) + { + this._playerInVolume = false; + return; + } + if (attachedOWRigidbody.CompareTag("Probe")) + { + this._probeInVolume = false; + } + } + } + } +}