Add streaming warp volume, make base volume sectored (#787)

## Improvements
- Singularities will now pre-load assets for their destination when the
player/probe is nearby (if the destination is a vanilla planet)
This commit is contained in:
xen-42 2024-02-26 01:40:31 -05:00 committed by GitHub
commit 091f34bdf1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 170 additions and 32 deletions

View File

@ -11,6 +11,8 @@ using NewHorizons.Builder.Props;
using NewHorizons.Utility.OWML; using NewHorizons.Utility.OWML;
using NewHorizons.Utility.OuterWilds; using NewHorizons.Utility.OuterWilds;
using NewHorizons.External.SerializableData; using NewHorizons.External.SerializableData;
using NewHorizons.Builder.Volumes;
using System;
namespace NewHorizons.Builder.Body namespace NewHorizons.Builder.Body
{ {
@ -109,31 +111,52 @@ namespace NewHorizons.Builder.Body
{ {
foreach (var pair in _pairsToLink) foreach (var pair in _pairsToLink)
{ {
var (blackHoleID, whiteHoleID) = pair; try
if (!_singularitiesByID.TryGetValue(blackHoleID, out GameObject blackHole))
{ {
NHLogger.LogWarning($"Black hole [{blackHoleID}] is missing."); var (blackHoleID, whiteHoleID) = pair;
continue; 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<WhiteHoleVolume>();
var blackHoleVolume = blackHole.GetComponentInChildren<BlackHoleVolume>();
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<StreamingGroup>();
if (streamingGroup != null)
{
var sphereCollider = blackHoleVolume.GetComponent<SphereCollider>();
// Shouldn't ever be null but doesn't hurt ig
var loadRadius = sphereCollider == null ? 100f : sphereCollider.radius + 50f;
var streamingVolume = VolumeBuilder.Make<StreamingWarpVolume>(blackHoleVolume.GetAttachedOWRigidbody().gameObject, blackHoleVolume.GetComponentInParent<Sector>(),
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."); NHLogger.LogError($"Failed to pair singularities {e}");
continue;
} }
var whiteHoleVolume = whiteHole.GetComponentInChildren<WhiteHoleVolume>();
var blackHoleVolume = blackHole.GetComponentInChildren<BlackHoleVolume>();
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; OWAudioSource oneShotOWAudioSource = null;
var singularityAmbience = Object.Instantiate(_blackHoleAmbience, singularity.transform); var singularityAmbience = GameObject.Instantiate(_blackHoleAmbience, singularity.transform);
singularityAmbience.name = polarity ? "BlackHoleAmbience" : "WhiteHoleAmbience"; singularityAmbience.name = polarity ? "BlackHoleAmbience" : "WhiteHoleAmbience";
singularityAmbience.SetActive(true); singularityAmbience.SetActive(true);
singularityAmbience.GetComponent<SectorAudioGroup>().SetSector(sector); singularityAmbience.GetComponent<SectorAudioGroup>().SetSector(sector);
@ -214,7 +237,7 @@ namespace NewHorizons.Builder.Body
} }
else else
{ {
var blackHoleOneShot = Object.Instantiate(_blackHoleEmissionOneShot, singularity.transform); var blackHoleOneShot = GameObject.Instantiate(_blackHoleEmissionOneShot, singularity.transform);
blackHoleOneShot.name = "BlackHoleEmissionOneShot"; blackHoleOneShot.name = "BlackHoleEmissionOneShot";
blackHoleOneShot.SetActive(true); blackHoleOneShot.SetActive(true);
oneShotOWAudioSource = blackHoleOneShot.GetComponent<OWAudioSource>(); oneShotOWAudioSource = blackHoleOneShot.GetComponent<OWAudioSource>();
@ -223,7 +246,7 @@ namespace NewHorizons.Builder.Body
oneShotAudioSource.minDistance = horizon; oneShotAudioSource.minDistance = horizon;
if (sizeController != null) sizeController.oneShotAudioSource = oneShotAudioSource; if (sizeController != null) sizeController.oneShotAudioSource = oneShotAudioSource;
var blackHoleVolume = Object.Instantiate(_blackHoleVolume, singularity.transform); var blackHoleVolume = GameObject.Instantiate(_blackHoleVolume, singularity.transform);
blackHoleVolume.name = "BlackHoleVolume"; blackHoleVolume.name = "BlackHoleVolume";
// Scale vanish effect to black hole size // Scale vanish effect to black hole size
@ -249,7 +272,7 @@ namespace NewHorizons.Builder.Body
{ {
foreach (var renderer in blackHoleVolume.GetComponentsInChildren<ParticleSystemRenderer>(true)) foreach (var renderer in blackHoleVolume.GetComponentsInChildren<ParticleSystemRenderer>(true))
{ {
Object.Destroy(renderer); GameObject.Destroy(renderer);
} }
}); });
} }
@ -257,7 +280,7 @@ namespace NewHorizons.Builder.Body
} }
else else
{ {
GameObject whiteHoleVolumeGO = Object.Instantiate(_whiteHoleVolume); GameObject whiteHoleVolumeGO = GameObject.Instantiate(_whiteHoleVolume);
whiteHoleVolumeGO.transform.parent = singularity.transform; whiteHoleVolumeGO.transform.parent = singularity.transform;
whiteHoleVolumeGO.transform.localPosition = Vector3.zero; whiteHoleVolumeGO.transform.localPosition = Vector3.zero;
whiteHoleVolumeGO.transform.localScale = Vector3.one; whiteHoleVolumeGO.transform.localScale = Vector3.one;

View File

@ -3,22 +3,27 @@ using UnityEngine;
namespace NewHorizons.Components.Volumes namespace NewHorizons.Components.Volumes
{ {
[RequireComponent(typeof(OWTriggerVolume))] [RequireComponent(typeof(OWTriggerVolume))]
public abstract class BaseVolume : MonoBehaviour public abstract class BaseVolume : SectoredMonoBehaviour
{ {
private OWTriggerVolume _triggerVolume; private OWTriggerVolume _triggerVolume;
public virtual void Awake() public override void Awake()
{ {
base.Awake();
_triggerVolume = this.GetRequiredComponent<OWTriggerVolume>(); _triggerVolume = this.GetRequiredComponent<OWTriggerVolume>();
_triggerVolume.OnEntry += OnTriggerVolumeEntry; _triggerVolume.OnEntry += OnTriggerVolumeEntry;
_triggerVolume.OnExit += OnTriggerVolumeExit; _triggerVolume.OnExit += OnTriggerVolumeExit;
} }
public virtual void OnDestroy() public override void OnDestroy()
{ {
if (_triggerVolume == null) return; base.OnDestroy();
_triggerVolume.OnEntry -= OnTriggerVolumeEntry;
_triggerVolume.OnExit -= OnTriggerVolumeExit; if (_triggerVolume != null)
{
_triggerVolume.OnEntry -= OnTriggerVolumeEntry;
_triggerVolume.OnExit -= OnTriggerVolumeExit;
}
} }
public abstract void OnTriggerVolumeEntry(GameObject hitObj); public abstract void OnTriggerVolumeEntry(GameObject hitObj);

View File

@ -0,0 +1,110 @@
using UnityEngine;
namespace NewHorizons.Components.Volumes
{
/// <summary>
/// Currently only relevant for Vanilla planets, which actually have streaming groups
/// </summary>
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;
}
}
}
}
}