diff --git a/QSB/Animation/Player/Thrusters/RemoteThrusterFlameController.cs b/QSB/Animation/Player/Thrusters/RemoteThrusterFlameController.cs index 17d37e24..999e3914 100644 --- a/QSB/Animation/Player/Thrusters/RemoteThrusterFlameController.cs +++ b/QSB/Animation/Player/Thrusters/RemoteThrusterFlameController.cs @@ -25,7 +25,8 @@ internal class RemoteThrusterFlameController : MonoBehaviour private Vector3 _thrusterFilter; private float _baseLightRadius; private float _currentScale; - + private RemotePlayerFluidDetector _fluidDetector; + private bool _underwater; private bool _initialized; private PlayerInfo _attachedPlayer; @@ -43,6 +44,19 @@ internal class RemoteThrusterFlameController : MonoBehaviour _light.enabled = false; _light.shadows = LightShadows.Soft; _initialized = true; + _underwater = false; + _fluidDetector = player.FluidDetector; + _fluidDetector.OnEnterFluidType += OnEnterExitFluidType; + _fluidDetector.OnExitFluidType += OnEnterExitFluidType; + } + + private void OnDestroy() + { + if (_fluidDetector != null) + { + _fluidDetector.OnEnterFluidType -= OnEnterExitFluidType; + _fluidDetector.OnExitFluidType -= OnEnterExitFluidType; + } } private void Update() @@ -52,7 +66,10 @@ internal class RemoteThrusterFlameController : MonoBehaviour return; } - var num = _scaleByThrust.Evaluate(GetThrustFraction()); + var num = _underwater + ? 0f + : _scaleByThrust.Evaluate(GetThrustFraction()); + if (_belowMaxThrustScalar < 1f) { num *= _belowMaxThrustScalar; @@ -65,7 +82,7 @@ internal class RemoteThrusterFlameController : MonoBehaviour _scaleSpring.ResetVelocity(); } - if (_currentScale <= 0.001f) + if (_underwater && _currentScale <= 0.001f) { _currentScale = 0f; _scaleSpring.ResetVelocity(); @@ -73,10 +90,15 @@ internal class RemoteThrusterFlameController : MonoBehaviour transform.localScale = Vector3.one * _currentScale; _light.range = _baseLightRadius * _currentScale; - _thrusterRenderer.enabled = _currentScale > 0f; + _thrusterRenderer.enabled = _currentScale > 0f && _attachedPlayer.Visible; _light.enabled = _currentScale > 0f; } + private void OnEnterExitFluidType(FluidVolume.Type type) + { + this._underwater = this._fluidDetector.InFluidType(FluidVolume.Type.WATER); + } + private float GetThrustFraction() => Vector3.Dot(_attachedPlayer.JetpackAcceleration.AccelerationVariableSyncer.Value, _thrusterFilter); private void OnRenderObject() diff --git a/QSB/Animation/Player/Thrusters/RemoteThrusterParticlesBehaviour.cs b/QSB/Animation/Player/Thrusters/RemoteThrusterParticlesBehaviour.cs new file mode 100644 index 00000000..b28c9f66 --- /dev/null +++ b/QSB/Animation/Player/Thrusters/RemoteThrusterParticlesBehaviour.cs @@ -0,0 +1,75 @@ +using QSB.Player; +using QSB.Utility; +using UnityEngine; + +namespace QSB.Animation.Player.Thrusters; + +internal class RemoteThrusterParticlesBehaviour : MonoBehaviour +{ + [SerializeField] + private Thruster _thruster; + + [SerializeField] + private bool _underwaterParticles; + + private bool _initialized; + private PlayerInfo _attachedPlayer; + private RemotePlayerFluidDetector _fluidDetector; + private ParticleSystem _thrustingParticles; + private Vector3 _thrusterFilter; + private bool _underwater; + + public void Init(PlayerInfo player) + { + _attachedPlayer = player; + _fluidDetector = player.FluidDetector; + _thrustingParticles = gameObject.GetComponent(); + _thrustingParticles.GetComponent().Init(player); + _thrusterFilter = OWUtilities.GetShipThrusterFilter(_thruster); + _underwater = false; + _thrustingParticles.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); + + _fluidDetector.OnEnterFluidType += OnEnterExitFluidType; + _fluidDetector.OnExitFluidType += OnEnterExitFluidType; + + _initialized = true; + } + + private void OnDestroy() + { + _initialized = false; + if (_fluidDetector != null) + { + _fluidDetector.OnEnterFluidType -= OnEnterExitFluidType; + _fluidDetector.OnExitFluidType -= OnEnterExitFluidType; + } + } + + private void Update() + { + if (!_initialized) + { + return; + } + + if (((_underwater != _underwaterParticles) + ? 0f + : Vector3.Dot(_attachedPlayer.JetpackAcceleration.AccelerationVariableSyncer.Value, _thrusterFilter)) > 1f) + { + if (!_thrustingParticles.isPlaying) + { + _thrustingParticles.Play(); + return; + } + } + else if (_thrustingParticles.isPlaying) + { + _thrustingParticles.Stop(); + } + } + + private void OnEnterExitFluidType(FluidVolume.Type type) + { + _underwater = _fluidDetector.InFluidType(FluidVolume.Type.WATER); + } +} diff --git a/QSB/Animation/Player/Thrusters/RemoteThrusterWashController.cs b/QSB/Animation/Player/Thrusters/RemoteThrusterWashController.cs index 8aa8e68c..ffa1dd60 100644 --- a/QSB/Animation/Player/Thrusters/RemoteThrusterWashController.cs +++ b/QSB/Animation/Player/Thrusters/RemoteThrusterWashController.cs @@ -60,7 +60,7 @@ internal class RemoteThrusterWashController : MonoBehaviour emissionThrusterScale = (!aboveSurface) ? 0f : (emissionThrusterScale * _emissionDistanceScale.Evaluate(hitInfo.distance)); - if (emissionThrusterScale > 0f) + if (emissionThrusterScale > 0f && _attachedPlayer.Visible) { var position = hitInfo.point + (hitInfo.normal * 0.25f); var rotation = Quaternion.LookRotation(hitInfo.normal); diff --git a/QSB/Animation/Player/Thrusters/ThrusterManager.cs b/QSB/Animation/Player/Thrusters/ThrusterManager.cs index 927b0d0b..e0bc0b3d 100644 --- a/QSB/Animation/Player/Thrusters/ThrusterManager.cs +++ b/QSB/Animation/Player/Thrusters/ThrusterManager.cs @@ -9,11 +9,12 @@ internal static class ThrusterManager { var newVfx = player.Body.transform.Find("REMOTE_PlayerVFX").gameObject; - CreateThrusterWashController(newVfx.transform.Find("ThrusterWash").gameObject, player); - CreateThrusterFlameController(newVfx, player); + InitWashController(newVfx.transform.Find("ThrusterWash").gameObject, player); + InitFlameControllers(newVfx, player); + InitParticleControllers(newVfx, player); } - private static void CreateThrusterFlameController(GameObject root, PlayerInfo player) + private static void InitFlameControllers(GameObject root, PlayerInfo player) { var existingControllers = root.GetComponentsInChildren(true); foreach (var controller in existingControllers) @@ -22,7 +23,16 @@ internal static class ThrusterManager } } - private static void CreateThrusterWashController(GameObject root, PlayerInfo player) + private static void InitParticleControllers(GameObject root, PlayerInfo player) + { + var existingBehaviours = root.GetComponentsInChildren(true); + foreach (var item in existingBehaviours) + { + item.Init(player); + } + } + + private static void InitWashController(GameObject root, PlayerInfo player) { var newObj = root.GetComponent(); newObj.Init(player); diff --git a/QSB/AssetBundles/network b/QSB/AssetBundles/network index 533c2bcd..768a9170 100644 Binary files a/QSB/AssetBundles/network and b/QSB/AssetBundles/network differ diff --git a/QSB/AssetBundles/network-big b/QSB/AssetBundles/network-big index d6af37e3..cd394664 100644 Binary files a/QSB/AssetBundles/network-big and b/QSB/AssetBundles/network-big differ diff --git a/QSB/DeathSync/RespawnOnDeath.cs b/QSB/DeathSync/RespawnOnDeath.cs index 4d5a2f6f..c990d24d 100644 --- a/QSB/DeathSync/RespawnOnDeath.cs +++ b/QSB/DeathSync/RespawnOnDeath.cs @@ -87,6 +87,8 @@ public class RespawnOnDeath : MonoBehaviour _playerResources._isSuffocating = false; _playerResources.DebugRefillResources(); + // death by oxygen turns this off, so we gotta enable it again + Delay.RunNextFrame(() => _playerResources.enabled = true); _spaceSuit.RemoveSuit(true); foreach (var pickupVolume in _suitPickupVolumes) diff --git a/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs b/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs index ac4941fd..c510a730 100644 --- a/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs +++ b/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs @@ -33,7 +33,7 @@ internal abstract class RotatingElementsVariableSyncer : BaseVaria protected abstract Transform[] RotatingElements { get; } - protected override bool CheckChanged() + protected override bool HasChanged() { var rotatingElements = RotatingElements; Value ??= new Quaternion[rotatingElements.Length]; diff --git a/QSB/Menus/MenuManager.cs b/QSB/Menus/MenuManager.cs index 05d375b2..19e097d6 100644 --- a/QSB/Menus/MenuManager.cs +++ b/QSB/Menus/MenuManager.cs @@ -42,7 +42,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart private const string DisconnectString = "DISCONNECT"; private const string StopHostingString = "STOP HOSTING"; - private const string UpdateChangelog = $"QSB Version 0.19.0\r\nThis update syncs Echoes of the Eye content! A bit rough around the edges, but things will be polished up in later updates. Enjoy!"; + private const string UpdateChangelog = $"QSB Version 0.20.0\r\nThis updates brings better ship syncing (including destruction), more things around the village being synced, and general bug fixes."; private Action PopupClose; @@ -70,6 +70,23 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart QSBCore.Helper.Storage.Save(QSBCore.Storage, "storage.json"); QSBCore.MenuApi.RegisterStartupPopup(UpdateChangelog); } + + if (QSBCore.DebugSettings.AutoStart) + { + // auto host/connect + Delay.RunWhen(PlayerData.IsLoaded, () => + { + if (DebugLog.ProcessInstanceId == 0) + { + Host(false); + } + else + { + QSBCore.DefaultServerIP = "localhost"; + Connect(); + } + }); + } } private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isUniverse) diff --git a/QSB/Player/JoinLeaveSingularity.cs b/QSB/Player/JoinLeaveSingularity.cs index 42c117a4..6098108c 100644 --- a/QSB/Player/JoinLeaveSingularity.cs +++ b/QSB/Player/JoinLeaveSingularity.cs @@ -40,10 +40,8 @@ public static class JoinLeaveSingularity } var go = new GameObject($"player {player} JoinLeaveSingularity"); - var ct = CancellationTokenSource.CreateLinkedTokenSource( - go.GetCancellationTokenOnDestroy(), - player.TransformSync.GetCancellationTokenOnDestroy() - ).Token; + // yes, it throws sometimes, but i cant destroy when the transform sync destroy or else the black hole doesn't happen + var ct = go.GetCancellationTokenOnDestroy(); UniTask.Create(async () => { DebugLog.DebugWrite($"{go.name}: WARP TASK"); diff --git a/QSB/Player/Patches/VolumePatches.cs b/QSB/Player/Patches/VolumePatches.cs new file mode 100644 index 00000000..f39e0c64 --- /dev/null +++ b/QSB/Player/Patches/VolumePatches.cs @@ -0,0 +1,43 @@ +using HarmonyLib; +using QSB.Patches; +using UnityEngine; + +namespace QSB.Player.Patches; + +internal class VolumePatches : QSBPatch +{ + public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect; + + [HarmonyPostfix] + [HarmonyPatch(typeof(FluidVolume), nameof(FluidVolume.OnEffectVolumeEnter))] + public static void OnEffectVolumeEnter(FluidVolume __instance, GameObject hitObj) + { + var comp = hitObj.GetComponent(); + if (comp != null) + { + comp.AddVolume(__instance); + } + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(FluidVolume), nameof(FluidVolume.OnEffectVolumeExit))] + public static void OnEffectVolumeExit(FluidVolume __instance, GameObject hitObj) + { + var comp = hitObj.GetComponent(); + if (comp != null) + { + comp.RemoveVolume(__instance); + } + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(RingRiverFluidVolume), nameof(RingRiverFluidVolume.OnEffectVolumeEnter))] + public static void OnEffectVolumeEnter(RingRiverFluidVolume __instance, GameObject hitObj) + { + var comp = hitObj.GetComponent(); + if (comp != null) + { + comp.AddVolume(__instance); + } + } +} diff --git a/QSB/Player/PlayerInfo.cs b/QSB/Player/PlayerInfo.cs index 75e26485..7362f604 100644 --- a/QSB/Player/PlayerInfo.cs +++ b/QSB/Player/PlayerInfo.cs @@ -69,13 +69,12 @@ public partial class PlayerInfo SignalscopeEquipped = default; TranslatorEquipped = default; ProbeActive = default; - ProbeLauncherEquipped = default; } public void UpdateObjectsFromStates() { - FlashLight.UpdateState(FlashlightActive); + FlashLight.UpdateState(FlashlightActive && Visible); Translator.ChangeEquipState(TranslatorEquipped); ProbeLauncherTool.ChangeEquipState(LocalProbeLauncherEquipped); Signalscope.ChangeEquipState(SignalscopeEquipped); @@ -138,6 +137,14 @@ public partial class PlayerInfo } _ditheringAnimator.SetVisible(visible, seconds); + if (!visible) + { + FlashLight.UpdateState(false); + } + else + { + FlashLight.UpdateState(FlashlightActive); + } } public override string ToString() => $"{PlayerId}:{GetType().Name} ({Name})"; diff --git a/QSB/Player/PlayerInfoParts/Animation.cs b/QSB/Player/PlayerInfoParts/Animation.cs index 9779aede..30c43023 100644 --- a/QSB/Player/PlayerInfoParts/Animation.cs +++ b/QSB/Player/PlayerInfoParts/Animation.cs @@ -11,4 +11,5 @@ public partial class PlayerInfo public JetpackAccelerationSync JetpackAcceleration { get; set; } internal QSBDitheringAnimator _ditheringAnimator; public DreamWorldSpawnAnimator DreamWorldSpawnAnimator { get; set; } + public RemotePlayerFluidDetector FluidDetector { get; set; } } diff --git a/QSB/Player/RemotePlayerFluidDetector.cs b/QSB/Player/RemotePlayerFluidDetector.cs new file mode 100644 index 00000000..50def10e --- /dev/null +++ b/QSB/Player/RemotePlayerFluidDetector.cs @@ -0,0 +1,196 @@ +using QSB.Utility; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace QSB.Player; + +public class RemotePlayerFluidDetector : PriorityDetector +{ + private SplashEffect[] _splashEffects; + + [SerializeField] + private Transform _splashSpawnRoot; + + private FluidTypeData[] _fluidDataByType; + + protected RemotePlayerVelocity _velocity; + + public event SpawnSplashEvent OnSpawnSplashEvent; + public event FluidTypeEvent OnEnterFluidType; + public event FluidTypeEvent OnExitFluidType; + public event FluidEvent OnEnterFluid; + public event FluidEvent OnExitFluid; + + public delegate void SpawnSplashEvent(FluidVolume splashFluid); + public delegate void FluidTypeEvent(FluidVolume.Type fluidType); + public delegate void FluidEvent(FluidVolume volume); + + public override void Awake() + { + base.Awake(); + + _velocity = gameObject.GetComponentInParent(); + _fluidDataByType = new FluidTypeData[9]; + _splashSpawnRoot = _velocity.transform; + + _splashEffects = new SplashEffect[4] + { + new SplashEffect() + { + fluidType = FluidVolume.Type.WATER, + minImpactSpeed = 15, + triggerEvent = SplashEffect.TriggerEvent.OnEntry, + splashPrefab = Resources.Load("prefabs/particles/Prefab_OceanEntry_Player"), + ignoreSphereAligment = false + }, + new SplashEffect() + { + fluidType = FluidVolume.Type.CLOUD, + minImpactSpeed = 15, + triggerEvent = SplashEffect.TriggerEvent.OnEntry, + splashPrefab = Resources.Load("prefabs/particles/Prefab_CloudEntry_Player"), + ignoreSphereAligment = false + }, + new SplashEffect() + { + fluidType = FluidVolume.Type.CLOUD, + minImpactSpeed = 15, + triggerEvent = SplashEffect.TriggerEvent.OnExit, + splashPrefab = Resources.Load("prefabs/particles/Prefab_CloudExit_Player"), + ignoreSphereAligment = true + }, + new SplashEffect() + { + fluidType = FluidVolume.Type.SAND, + minImpactSpeed = 15, + triggerEvent = SplashEffect.TriggerEvent.OnEntryOrExit, + splashPrefab = Resources.Load("prefabs/particles/Prefab_HEA_Player_SandSplash"), + ignoreSphereAligment = false + } + }; + } + + public bool InFluidType(FluidVolume.Type fluidType) + { + return _fluidDataByType[(int)fluidType].count > 0; + } + + public override void AddVolume(EffectVolume eVol) + { + var fluidVolume = eVol as FluidVolume; + if (fluidVolume != null && (!fluidVolume.IsInheritible())) + { + base.AddVolume(eVol); + } + } + + public override void RemoveVolume(EffectVolume eVol) + { + var fluidVolume = eVol as FluidVolume; + if (fluidVolume != null && (!fluidVolume.IsInheritible())) + { + base.RemoveVolume(eVol); + } + } + + public override void OnVolumeActivated(PriorityVolume volume) + { + var fluidVolume = volume as FluidVolume; + var fluidType = fluidVolume.GetFluidType(); + var fluidDataByType = _fluidDataByType; + var type = fluidType; + fluidDataByType[(int)type].count = fluidDataByType[(int)type].count + 1; + OnEnterFluid?.Invoke(fluidVolume); + + if (_fluidDataByType[(int)fluidType].count == 1) + { + OnEnterFluidType_Internal(fluidVolume); + OnEnterFluidType?.Invoke(fluidType); + } + } + + public override void OnVolumeDeactivated(PriorityVolume volume) + { + var fluidVolume = volume as FluidVolume; + var fluidType = fluidVolume.GetFluidType(); + var fluidDataByType = _fluidDataByType; + var type = fluidType; + fluidDataByType[(int)type].count = fluidDataByType[(int)type].count - 1; + OnExitFluid?.Invoke(fluidVolume); + + if (_fluidDataByType[(int)fluidType].count == 0) + { + OnExitFluidType_Internal(fluidVolume); + OnExitFluidType?.Invoke(fluidType); + } + } + + protected virtual void OnEnterFluidType_Internal(FluidVolume fluid) + { + SpawnSplash(fluid, SplashEffect.TriggerEvent.OnEntry); + if (fluid is SphereOceanFluidVolume) + { + var component = GetComponent(); + var magnitude = (_velocity.Velocity - fluid._attachedBody.GetVelocity()).magnitude; + if (component != null && magnitude >= component.minSplashSpeed) + { + component.Splash(); + } + } + } + + protected virtual void OnExitFluidType_Internal(FluidVolume fluid) + { + SpawnSplash(fluid, SplashEffect.TriggerEvent.OnExit); + } + + private void SpawnSplash(FluidVolume fluid, SplashEffect.TriggerEvent triggerEvent) + { + if (CompareName(Name.Player) && PlayerState.IsRidingRaft(false) && fluid.GetFluidType() == FluidVolume.Type.WATER) + { + return; + } + + if (fluid.GetFluidType() == FluidVolume.Type.CLOUD && InFluidType(FluidVolume.Type.WATER)) + { + return; + } + + var impactVelocity = _velocity.Velocity - fluid._attachedBody.GetVelocity(); + var magnitude = impactVelocity.magnitude; + var num = -1; + for (var i = 0; i < _splashEffects.Length; i++) + { + if (_splashEffects[i].fluidType == fluid.GetFluidType() && magnitude > _splashEffects[i].minImpactSpeed && (triggerEvent & _splashEffects[i].triggerEvent) > (SplashEffect.TriggerEvent)0 && (num == -1 || _splashEffects[i].minImpactSpeed > _splashEffects[num].minImpactSpeed)) + { + num = i; + } + } + + if (num > -1) + { + var splashPrefab = _splashEffects[num].splashPrefab; + var toDirection = (_splashEffects[num].ignoreSphereAligment ? (-impactVelocity) : fluid.GetSplashAlignment(_splashSpawnRoot.position, impactVelocity)); + var rotation = Quaternion.FromToRotation(_splashSpawnRoot.up, toDirection) * _splashSpawnRoot.rotation; + var gameObject = Instantiate(splashPrefab, _splashSpawnRoot.position, rotation); + if (gameObject.GetComponent() != null) + { + Debug.LogError("SPLASHES SHOULD NO LONGER HAVE RIGIDBODIES!!!", gameObject); + gameObject.GetComponent().MakeKinematic(); + } + + gameObject.transform.parent = fluid.transform; + fluid.RegisterSplashTransform(gameObject.transform); + var component = gameObject.GetComponent(); + if (component != null) + { + component.PlaySplash(); + } + + OnSpawnSplashEvent?.Invoke(fluid); + } + } +} diff --git a/QSB/PlayerBodySetup/Remote/RemotePlayerCreation.cs b/QSB/PlayerBodySetup/Remote/RemotePlayerCreation.cs index 6c238a82..8c224524 100644 --- a/QSB/PlayerBodySetup/Remote/RemotePlayerCreation.cs +++ b/QSB/PlayerBodySetup/Remote/RemotePlayerCreation.cs @@ -43,6 +43,7 @@ public static class RemotePlayerCreation // Variable naming convention is broken here to reflect OW unity project (with REMOTE_ prefixed) for readability var REMOTE_Player_Body = Object.Instantiate(GetPrefab()); + var REMOTE_PlayerDetector = REMOTE_Player_Body.transform.Find("REMOTE_PlayerDetector"); var REMOTE_PlayerCamera = REMOTE_Player_Body.transform.Find("REMOTE_PlayerCamera").gameObject; var REMOTE_RoastingSystem = REMOTE_Player_Body.transform.Find("REMOTE_RoastingSystem").gameObject; var REMOTE_Stick_Root = REMOTE_RoastingSystem.transform.Find("REMOTE_Stick_Root").gameObject; @@ -56,6 +57,7 @@ public static class RemotePlayerCreation player.Body = REMOTE_Player_Body; player.ThrusterLightTracker = player.Body.GetComponentInChildren(); + player.FluidDetector = REMOTE_PlayerDetector.GetComponent(); player.AnimationSync.InitRemote(REMOTE_Traveller_HEA_Player_v2.transform); diff --git a/QSB/QSBCore.cs b/QSB/QSBCore.cs index 4f330e97..b822ac61 100644 --- a/QSB/QSBCore.cs +++ b/QSB/QSBCore.cs @@ -104,6 +104,13 @@ public class QSBCore : ModBehaviour ); } + if (DebugSettings.AutoStart) + { + DebugSettings.UseKcpTransport = true; + DebugSettings.SkipTitleScreen = true; + DebugSettings.DebugMode = true; + } + RegisterAddons(); InitAssemblies(); diff --git a/QSB/ShipSync/ShipThrusterVariableSyncer.cs b/QSB/ShipSync/ShipThrusterVariableSyncer.cs index 585c8ddd..79053946 100644 --- a/QSB/ShipSync/ShipThrusterVariableSyncer.cs +++ b/QSB/ShipSync/ShipThrusterVariableSyncer.cs @@ -24,7 +24,7 @@ public class ShipThrusterVariableSyncer : NetworkBehaviour return; } - if (AccelerationSyncer.HasChanged) + if (AccelerationSyncer.public_HasChanged()) { if (AccelerationSyncer.Value == Vector3.zero) { @@ -47,6 +47,11 @@ public class ShipThrusterVariableSyncer : NetworkBehaviour } } - private void GetFromShip() => AccelerationSyncer.Value = _thrusterModel.GetLocalAcceleration(); + private void GetFromShip() + { + if (_thrusterModel) + { + AccelerationSyncer.Value = _thrusterModel.GetLocalAcceleration(); + } + } } - \ No newline at end of file diff --git a/QSB/ShipSync/TransformSync/ShipLegTransformSync.cs b/QSB/ShipSync/TransformSync/ShipLegTransformSync.cs index 36222680..3efd0912 100644 --- a/QSB/ShipSync/TransformSync/ShipLegTransformSync.cs +++ b/QSB/ShipSync/TransformSync/ShipLegTransformSync.cs @@ -15,10 +15,7 @@ internal class ShipLegTransformSync : SectoredRigidbodySync, ILinkedNetworkBehav => AttachedTransform && base.CheckValid(); - protected override bool CheckReady() - => _qsbModule != null - && _qsbModule.AttachedObject.isDetached - && base.CheckReady(); + protected override bool CheckReady() => base.CheckReady() && _qsbModule.AttachedObject.isDetached; protected override bool UseInterpolation => true; diff --git a/QSB/ShipSync/TransformSync/ShipModuleTransformSync.cs b/QSB/ShipSync/TransformSync/ShipModuleTransformSync.cs index d49ed51f..1f655cd7 100644 --- a/QSB/ShipSync/TransformSync/ShipModuleTransformSync.cs +++ b/QSB/ShipSync/TransformSync/ShipModuleTransformSync.cs @@ -15,10 +15,7 @@ internal class ShipModuleTransformSync : SectoredRigidbodySync, ILinkedNetworkBe => AttachedTransform && base.CheckValid(); - protected override bool CheckReady() - => _qsbModule != null - && _qsbModule.AttachedObject.isDetached - && base.CheckReady(); + protected override bool CheckReady() => base.CheckReady() && _qsbModule.AttachedObject.isDetached; protected override bool UseInterpolation => true; diff --git a/QSB/Syncs/QSBNetworkTransform.cs b/QSB/Syncs/QSBNetworkTransform.cs index ddf72bbf..655ebe5e 100644 --- a/QSB/Syncs/QSBNetworkTransform.cs +++ b/QSB/Syncs/QSBNetworkTransform.cs @@ -14,7 +14,7 @@ public class QSBNetworkTransform : QSBNetworkBehaviour private Vector3 _prevPosition; private Quaternion _prevRotation; - protected override bool CheckChanged() => + protected override bool HasChanged() => Vector3.Distance(transform.position, _prevPosition) > PositionChangeThreshold || Quaternion.Angle(transform.rotation, _prevRotation) > RotationChangeThreshold; diff --git a/QSB/Syncs/QSBNetworkTransformChild.cs b/QSB/Syncs/QSBNetworkTransformChild.cs index fd829934..b96fc084 100644 --- a/QSB/Syncs/QSBNetworkTransformChild.cs +++ b/QSB/Syncs/QSBNetworkTransformChild.cs @@ -16,7 +16,7 @@ public class QSBNetworkTransformChild : QSBNetworkBehaviour private Vector3 _prevPosition; private Quaternion _prevRotation; - protected override bool CheckChanged() => + protected override bool HasChanged() => Vector3.Distance(Target.localPosition, _prevPosition) > PositionChangeThreshold || Quaternion.Angle(Target.localRotation, _prevRotation) > RotationChangeThreshold; diff --git a/QSB/Syncs/Sectored/Rigidbodies/SectoredRigidbodySync.cs b/QSB/Syncs/Sectored/Rigidbodies/SectoredRigidbodySync.cs index bfd7ff1f..e41f85c7 100644 --- a/QSB/Syncs/Sectored/Rigidbodies/SectoredRigidbodySync.cs +++ b/QSB/Syncs/Sectored/Rigidbodies/SectoredRigidbodySync.cs @@ -36,8 +36,8 @@ public abstract class SectoredRigidbodySync : BaseSectoredSync ReferenceRigidbody = ReferenceTransform ? ReferenceTransform.GetAttachedOWRigidbody() : null; } - protected override bool CheckChanged() => - base.CheckChanged() || + protected override bool HasChanged() => + base.HasChanged() || Vector3.Distance(Velocity, _prevVelocity) > VelocityChangeThreshold || Vector3.Distance(AngularVelocity, _prevAngularVelocity) > AngularVelocityChangeThreshold; diff --git a/QSB/Syncs/SyncBase.cs b/QSB/Syncs/SyncBase.cs index be35998e..1ab3a6a1 100644 --- a/QSB/Syncs/SyncBase.cs +++ b/QSB/Syncs/SyncBase.cs @@ -198,7 +198,7 @@ public abstract class SyncBase : QSBNetworkTransform /// /// call the base method FIRST /// - protected override bool CheckChanged() + protected override bool HasChanged() { GetFromAttached(); if (UseInterpolation) @@ -207,7 +207,7 @@ public abstract class SyncBase : QSBNetworkTransform SmoothRotation = transform.rotation; } - return base.CheckChanged(); + return base.HasChanged(); } /// diff --git a/QSB/Syncs/Unsectored/Rigidbodies/UnsectoredRigidbodySync.cs b/QSB/Syncs/Unsectored/Rigidbodies/UnsectoredRigidbodySync.cs index ece3d92b..99b5cc91 100644 --- a/QSB/Syncs/Unsectored/Rigidbodies/UnsectoredRigidbodySync.cs +++ b/QSB/Syncs/Unsectored/Rigidbodies/UnsectoredRigidbodySync.cs @@ -36,8 +36,8 @@ public abstract class UnsectoredRigidbodySync : BaseUnsectoredSync ReferenceRigidbody = ReferenceTransform ? ReferenceTransform.GetAttachedOWRigidbody() : null; } - protected override bool CheckChanged() => - base.CheckChanged() || + protected override bool HasChanged() => + base.HasChanged() || Vector3.Distance(Velocity, _prevVelocity) > VelocityChangeThreshold || Vector3.Distance(AngularVelocity, _prevAngularVelocity) > AngularVelocityChangeThreshold; diff --git a/QSB/TimeSync/Patches/TimePatches.cs b/QSB/TimeSync/Patches/TimePatches.cs index cb9f9c77..2763ac99 100644 --- a/QSB/TimeSync/Patches/TimePatches.cs +++ b/QSB/TimeSync/Patches/TimePatches.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using QSB.Inputs; using QSB.Patches; using QSB.Utility; @@ -17,6 +18,16 @@ internal class TimePatches : QSBPatch return false; } + [HarmonyPostfix] + [HarmonyPatch(typeof(PlayerCameraEffectController), nameof(PlayerCameraEffectController.WakeUp))] + public static void PlayerCameraEffectController_WakeUp(PlayerCameraEffectController __instance) + { + // prevent funny thing when you pause while waking up + QSBInputManager.Instance.SetInputsEnabled(false); + Delay.RunWhen(() => !__instance._isOpeningEyes, () => QSBInputManager.Instance.SetInputsEnabled(true)); + } + + [HarmonyPrefix] [HarmonyPatch(typeof(OWTime), nameof(OWTime.Pause))] public static bool StopPausing(OWTime.PauseType pauseType) diff --git a/QSB/Tools/FlashlightTool/Messages/PlayerFlashlightMessage.cs b/QSB/Tools/FlashlightTool/Messages/PlayerFlashlightMessage.cs index d1e71738..eef7825f 100644 --- a/QSB/Tools/FlashlightTool/Messages/PlayerFlashlightMessage.cs +++ b/QSB/Tools/FlashlightTool/Messages/PlayerFlashlightMessage.cs @@ -26,7 +26,7 @@ public class PlayerFlashlightMessage : QSBMessage { var player = QSBPlayerManager.GetPlayer(From); player.FlashlightActive = Data; - player.FlashLight?.UpdateState(Data); + player.FlashLight?.UpdateState(Data && player.Visible); } public override void OnReceiveLocal() => diff --git a/QSB/Tools/QSBTool.cs b/QSB/Tools/QSBTool.cs index 908252ac..d3633673 100644 --- a/QSB/Tools/QSBTool.cs +++ b/QSB/Tools/QSBTool.cs @@ -48,7 +48,7 @@ public class QSBTool : PlayerTool public virtual void OnEnable() { - if (!Player.FlyingShip) + if (!Player?.FlyingShip ?? false) { ToolGameObject?.SetActive(true); } diff --git a/QSB/Utility/DebugActions.cs b/QSB/Utility/DebugActions.cs index f26a9a23..33320c04 100644 --- a/QSB/Utility/DebugActions.cs +++ b/QSB/Utility/DebugActions.cs @@ -46,19 +46,6 @@ public class DebugActions : MonoBehaviour, IAddComponentOnStart return; } - /* - * 1 - Warp to first non local player - * 2 - Enter dream world - * 3 - Destroy probe - * 4 - Damage ship electricals - * 5 - Trigger supernova - * 6 - Set MET_SOLANUM - * 7 - Warp to vessel - * 8 - Place warp core into vessel - * 9 - Load eye scene - * 0 - Respawn some player - */ - if (Keyboard.current[Key.Numpad1].wasPressedThisFrame) { var otherPlayers = QSBPlayerManager.PlayerList.Where(x => !x.IsLocalPlayer).ToList(); diff --git a/QSB/Utility/DebugLog.cs b/QSB/Utility/DebugLog.cs index 9655c4f0..ec3cff3a 100644 --- a/QSB/Utility/DebugLog.cs +++ b/QSB/Utility/DebugLog.cs @@ -6,14 +6,14 @@ namespace QSB.Utility; public static class DebugLog { - private static readonly int _processInstanceId = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName) + public static readonly int ProcessInstanceId = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName) .IndexOf(x => x.Id == Process.GetCurrentProcess().Id); public static void ToConsole(string message, MessageType type = MessageType.Message) { if (QSBCore.DebugSettings.InstanceIdInLogs) { - message = $"[{_processInstanceId}] " + message; + message = $"[{ProcessInstanceId}] " + message; } QSBCore.Helper.Console.WriteLine(message, type, GetCallingType(new StackTrace())); diff --git a/QSB/Utility/DebugSettings.cs b/QSB/Utility/DebugSettings.cs index d9d70b48..e7216fa6 100644 --- a/QSB/Utility/DebugSettings.cs +++ b/QSB/Utility/DebugSettings.cs @@ -20,6 +20,12 @@ public class DebugSettings [JsonProperty("avoidTimeSync")] public bool AvoidTimeSync; + [JsonProperty("autoStart")] + public bool AutoStart; + + [JsonProperty("skipTitleScreen")] + public bool SkipTitleScreen; + [JsonProperty("debugMode")] public bool DebugMode; @@ -43,10 +49,6 @@ public class DebugSettings private bool _drawGhostAI; public bool DrawGhostAI => DebugMode && _drawGhostAI; - [JsonProperty("skipTitleScreen")] - private bool _skipTitleScreen; - public bool SkipTitleScreen => DebugMode && _skipTitleScreen; - [JsonProperty("greySkybox")] private bool _greySkybox; public bool GreySkybox => DebugMode && _greySkybox; diff --git a/QSB/Utility/LinkedWorldObject/Extensions.cs b/QSB/Utility/LinkedWorldObject/Extensions.cs index bbf76e93..97b0b69d 100644 --- a/QSB/Utility/LinkedWorldObject/Extensions.cs +++ b/QSB/Utility/LinkedWorldObject/Extensions.cs @@ -22,8 +22,6 @@ public static class Extensions /// public static void SpawnLinked(this ILinkedWorldObject worldObject, GameObject prefab, bool spawnWithServerAuthority) { - DebugLog.DebugWrite($"SpawnLinked {prefab.name}"); - var go = Object.Instantiate(prefab); var networkBehaviour = go.GetComponent(); diff --git a/QSB/Utility/QSBNetworkBehaviour.cs b/QSB/Utility/QSBNetworkBehaviour.cs index 28a118a1..534fda1c 100644 --- a/QSB/Utility/QSBNetworkBehaviour.cs +++ b/QSB/Utility/QSBNetworkBehaviour.cs @@ -20,12 +20,10 @@ public abstract class QSBNetworkBehaviour : NetworkBehaviour public override void OnStopClient() => RequestInitialStatesMessage.SendInitialState -= SendInitialState; - public bool HasChanged { get; private set; } - /// /// checked before serializing /// - protected abstract bool CheckChanged(); + protected abstract bool HasChanged(); protected abstract void Serialize(NetworkWriter writer); @@ -56,8 +54,7 @@ public abstract class QSBNetworkBehaviour : NetworkBehaviour { _lastSendTime = NetworkTime.localTime; - HasChanged = CheckChanged(); - if (!HasChanged) + if (!HasChanged()) { return; } diff --git a/QSB/Utility/VariableSync/BaseVariableSyncer.cs b/QSB/Utility/VariableSync/BaseVariableSyncer.cs index e25cddf1..4e800482 100644 --- a/QSB/Utility/VariableSync/BaseVariableSyncer.cs +++ b/QSB/Utility/VariableSync/BaseVariableSyncer.cs @@ -12,7 +12,8 @@ public abstract class BaseVariableSyncer : QSBNetworkBehaviour [NonSerialized] public T Value; - protected override bool CheckChanged() => !EqualityComparer.Default.Equals(PrevValue, Value); + public bool Bruh() => HasChanged(); + protected override bool HasChanged() => !EqualityComparer.Default.Equals(PrevValue, Value); protected override void UpdatePrevData() => PrevValue = Value; protected override void Serialize(NetworkWriter writer) => writer.Write(Value); protected override void Deserialize(NetworkReader reader) => Value = reader.Read(); diff --git a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs index a46b130e..88471499 100644 --- a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs +++ b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs @@ -4,4 +4,8 @@ namespace QSB.Utility.VariableSync; public class Vector3VariableSyncer : BaseVariableSyncer { + /// + /// hack for ShipThrusterVariableSyncer + /// + public bool public_HasChanged() => HasChanged(); } \ No newline at end of file diff --git a/QSB/debugsettings.template.json b/QSB/debugsettings.template.json index 2029d7b4..4afa7425 100644 --- a/QSB/debugsettings.template.json +++ b/QSB/debugsettings.template.json @@ -4,12 +4,13 @@ "instanceIdInLogs": false, "hookDebugLogs": false, "avoidTimeSync": false, + "autoStart": false, + "skipTitleScreen": false, "debugMode": false, "drawGui": false, "drawLines": false, "drawLabels": false, "drawQuantumVisibilityObjects": false, "drawGhostAI": false, - "skipTitleScreen": false, "greySkybox": false } \ No newline at end of file diff --git a/QSB/manifest.json b/QSB/manifest.json index b9991496..b4ea8e71 100644 --- a/QSB/manifest.json +++ b/QSB/manifest.json @@ -7,7 +7,7 @@ "body": "- Disable *all* other mods. (Can heavily affect performance)\n- Make sure you are not running any other network-intensive applications." }, "uniqueName": "Raicuparta.QuantumSpaceBuddies", - "version": "0.19.0", + "version": "0.20.0", "owmlVersion": "2.3.3", "dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ], "pathsToPreserve": [ "debugsettings.json", "storage.json" ] diff --git a/README.md b/README.md index 9178c6e5..a050f3b0 100644 --- a/README.md +++ b/README.md @@ -132,14 +132,15 @@ The template for this file is this : "instanceIdInLogs": false, "hookDebugLogs": false, "avoidTimeSync": false, + "autoStart": false, + "skipTitleScreen": false, "debugMode": false, "drawGui": false, "drawLines": false, "drawLabels": false, "drawQuantumVisibilityObjects": false, - "skipTitleScreen": false, - "greySkybox": false, - "drawGhostAI": false + "drawGhostAI": false, + "greySkybox": false } ``` @@ -148,14 +149,15 @@ The template for this file is this : - instanceIdInLogs - Appends the game instance id to every log message sent. - hookDebugLogs - Print Unity logs and warnings. - avoidTimeSync - Disables the syncing of time. +- autoStart - Host/connect automatically for faster testing. +- skipTitleScreen - Auto-skips the splash screen. - debugMode - Enables debug mode. If this is set to `false`, none of the following settings do anything. - drawGui - Draws a GUI at the top of the screen that gives information on many things. - drawLines - Draws gizmo-esque lines around things. Indicates reference sectors/transforms, triggers, etc. LAGGY. - drawLabels - Draws GUI labels attached to some objects. LAGGY. - drawQuantumVisibilityObjects - Indicates visibility objects with an orange shape. -- skipTitleScreen - Auto-skips the splash screen. -- greySkybox - Turns the skybox grey. Useful in the Eye, where it's pretty dark. - drawGhostAI - Draws debug lines and labels just for the ghosts. +- greySkybox - Turns the skybox grey. Useful in the Eye, where it's pretty dark. **Warning : Mod development can lead to unexpected errors in your computer system.** - **When editing the networking code, mistakes can lead to QSB overwhelming your network connection with excess packets**.