diff --git a/QSB/Animation/NPC/CharacterAnimManager.cs b/QSB/Animation/NPC/CharacterAnimManager.cs index 0d4f0ebc..8590b37e 100644 --- a/QSB/Animation/NPC/CharacterAnimManager.cs +++ b/QSB/Animation/NPC/CharacterAnimManager.cs @@ -16,10 +16,6 @@ namespace QSB.Animation.NPC QSBWorldSync.Init(); QSBWorldSync.Init(); QSBWorldSync.Init(); - - //MOVE : this is the wrong place to put this... move it to Conversations? - QSBWorldSync.OldDialogueTrees.Clear(); - QSBWorldSync.OldDialogueTrees.AddRange(QSBWorldSync.GetUnityObjects()); } } } diff --git a/QSB/Animation/NPC/Patches/CharacterAnimationPatches.cs b/QSB/Animation/NPC/Patches/CharacterAnimationPatches.cs index 1c9f6caa..442b3e8d 100644 --- a/QSB/Animation/NPC/Patches/CharacterAnimationPatches.cs +++ b/QSB/Animation/NPC/Patches/CharacterAnimationPatches.cs @@ -6,7 +6,7 @@ using QSB.ConversationSync; using QSB.Messaging; using QSB.Patches; using QSB.Player; -using QSB.Player.Messages; +using QSB.TriggerSync.WorldObjects; using QSB.Utility; using QSB.WorldSync; using System.Linq; @@ -26,12 +26,18 @@ namespace QSB.Animation.NPC.Patches { if (!WorldObjectManager.AllObjectsReady || ConversationManager.Instance == null) { - return false; + return true; } var playerId = ConversationManager.Instance.GetPlayerTalkingToTree(__instance._dialogueTree); var player = QSBPlayerManager.GetPlayer(playerId); - var qsbObj = __instance.GetWorldObject(); // OPTIMIZE : maybe cache this somewhere... or assess how slow this is + + if (__instance.playerTrackingZone == null) + { + return true; + } + + var qsbObj = __instance.playerTrackingZone.GetWorldObject(); // OPTIMIZE : maybe cache this somewhere... or assess how slow this is PlayerInfo playerToUse = null; if (__instance._inConversation) @@ -48,9 +54,9 @@ namespace QSB.Animation.NPC.Patches : player; } } - else if (!__instance.lookOnlyWhenTalking && qsbObj.GetPlayersInHeadZone().Count != 0) // IDEA : maybe this would be more fun if characters looked between players at random times? :P + else if (!__instance.lookOnlyWhenTalking && qsbObj.Occupants.Count != 0) // IDEA : maybe this would be more fun if characters looked between players at random times? :P { - playerToUse = QSBPlayerManager.GetClosestPlayerToWorldPoint(qsbObj.GetPlayersInHeadZone(), __instance.transform.position); + playerToUse = QSBPlayerManager.GetClosestPlayerToWorldPoint(qsbObj.Occupants, __instance.transform.position); } else if (QSBPlayerManager.PlayerList.Count != 0) { @@ -65,16 +71,16 @@ namespace QSB.Animation.NPC.Patches if (__instance.lookOnlyWhenTalking) { if (!__instance._inConversation - || qsbObj.GetPlayersInHeadZone().Count == 0 - || !qsbObj.GetPlayersInHeadZone().Contains(playerToUse)) + || qsbObj.Occupants.Count == 0 + || !qsbObj.Occupants.Contains(playerToUse)) { targetWeight *= 0; } } else { - if (qsbObj.GetPlayersInHeadZone().Count == 0 - || !qsbObj.GetPlayersInHeadZone().Contains(playerToUse)) + if (qsbObj.Occupants.Count == 0 + || !qsbObj.Occupants.Contains(playerToUse)) { targetWeight *= 0; } @@ -88,32 +94,6 @@ namespace QSB.Animation.NPC.Patches } - [HarmonyPrefix] - [HarmonyPatch(typeof(CharacterAnimController), nameof(CharacterAnimController.OnZoneExit))] - public static bool HeadZoneExit(CharacterAnimController __instance, GameObject input) - { - if (input.CompareTag("PlayerDetector")) - { - var qsbObj = __instance.GetWorldObject(); - new EnterLeaveMessage(EnterLeaveType.ExitNonNomaiHeadZone, qsbObj.ObjectId).Send(); - } - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(CharacterAnimController), nameof(CharacterAnimController.OnZoneEntry))] - public static bool HeadZoneEntry(CharacterAnimController __instance, GameObject input) - { - if (input.CompareTag("PlayerDetector")) - { - var qsbObj = __instance.GetWorldObject(); - new EnterLeaveMessage(EnterLeaveType.EnterNonNomaiHeadZone, qsbObj.ObjectId).Send(); - } - - return false; - } - [HarmonyPrefix] [HarmonyPatch(typeof(FacePlayerWhenTalking), nameof(FacePlayerWhenTalking.OnStartConversation))] public static bool OnStartConversation(FacePlayerWhenTalking __instance) diff --git a/QSB/Animation/NPC/Patches/SolanumPatches.cs b/QSB/Animation/NPC/Patches/SolanumPatches.cs index 08f43fa4..f1150a2f 100644 --- a/QSB/Animation/NPC/Patches/SolanumPatches.cs +++ b/QSB/Animation/NPC/Patches/SolanumPatches.cs @@ -1,9 +1,7 @@ using HarmonyLib; using QSB.Animation.NPC.WorldObjects; -using QSB.Messaging; using QSB.Patches; using QSB.Player; -using QSB.Player.Messages; using QSB.WorldSync; using System.Linq; using UnityEngine; @@ -26,7 +24,7 @@ namespace QSB.Animation.NPC.Patches } var qsbObj = __instance.GetWorldObject(); - var playersInHeadZone = qsbObj.GetPlayersInHeadZone(); + var playersInHeadZone = qsbObj.Trigger.Occupants; var targetCamera = playersInHeadZone == null || playersInHeadZone.Count == 0 ? __instance._playerCameraTransform @@ -41,38 +39,12 @@ namespace QSB.Animation.NPC.Patches return false; } - [HarmonyPrefix] - [HarmonyPatch(typeof(NomaiConversationManager), nameof(NomaiConversationManager.OnEnterWatchVolume))] - public static bool EnterWatchZone(NomaiConversationManager __instance, GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - var qsbObj = __instance._solanumAnimController.GetWorldObject(); - new EnterLeaveMessage(EnterLeaveType.EnterNomaiHeadZone, qsbObj.ObjectId).Send(); - } - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(NomaiConversationManager), nameof(NomaiConversationManager.OnExitWatchVolume))] - public static bool ExitWatchZone(NomaiConversationManager __instance, GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - var qsbObj = __instance._solanumAnimController.GetWorldObject(); - new EnterLeaveMessage(EnterLeaveType.ExitNomaiHeadZone, qsbObj.ObjectId).Send(); - } - - return false; - } - [HarmonyPrefix] [HarmonyPatch(typeof(NomaiConversationManager), nameof(NomaiConversationManager.Update))] public static bool ReplacementUpdate(NomaiConversationManager __instance) { var qsbObj = __instance._solanumAnimController.GetWorldObject(); - __instance._playerInWatchVolume = qsbObj.GetPlayersInHeadZone().Any(); + __instance._playerInWatchVolume = qsbObj.Trigger.Occupants.Any(); if (!__instance._initialized) { diff --git a/QSB/Animation/NPC/WorldObjects/QSBCharacterAnimController.cs b/QSB/Animation/NPC/WorldObjects/QSBCharacterAnimController.cs index 9144e966..940b9918 100644 --- a/QSB/Animation/NPC/WorldObjects/QSBCharacterAnimController.cs +++ b/QSB/Animation/NPC/WorldObjects/QSBCharacterAnimController.cs @@ -1,35 +1,7 @@ -using QSB.Player; -using System.Collections.Generic; - -namespace QSB.Animation.NPC.WorldObjects +namespace QSB.Animation.NPC.WorldObjects { internal class QSBCharacterAnimController : NpcAnimController { - private readonly List _playersInHeadZone = new(); - - public List GetPlayersInHeadZone() - => _playersInHeadZone; - - public void AddPlayerToHeadZone(PlayerInfo player) - { - if (_playersInHeadZone.Contains(player)) - { - return; - } - - _playersInHeadZone.Add(player); - } - - public void RemovePlayerFromHeadZone(PlayerInfo player) - { - if (!_playersInHeadZone.Contains(player)) - { - return; - } - - _playersInHeadZone.Remove(player); - } - public override CharacterDialogueTree GetDialogueTree() => AttachedObject._dialogueTree; diff --git a/QSB/Animation/NPC/WorldObjects/QSBSolanumAnimController.cs b/QSB/Animation/NPC/WorldObjects/QSBSolanumAnimController.cs index e940c8c9..7e1c78c3 100644 --- a/QSB/Animation/NPC/WorldObjects/QSBSolanumAnimController.cs +++ b/QSB/Animation/NPC/WorldObjects/QSBSolanumAnimController.cs @@ -1,34 +1,12 @@ -using QSB.Player; +using QSB.TriggerSync.WorldObjects; using QSB.WorldSync; -using System.Collections.Generic; +using System.Linq; namespace QSB.Animation.NPC.WorldObjects { internal class QSBSolanumAnimController : WorldObject { - private readonly List _playersInHeadZone = new(); - - public List GetPlayersInHeadZone() - => _playersInHeadZone; - - public void AddPlayerToHeadZone(PlayerInfo player) - { - if (_playersInHeadZone.Contains(player)) - { - return; - } - - _playersInHeadZone.Add(player); - } - - public void RemovePlayerFromHeadZone(PlayerInfo player) - { - if (!_playersInHeadZone.Contains(player)) - { - return; - } - - _playersInHeadZone.Remove(player); - } + private QSBSolanumTrigger _trigger; + public QSBSolanumTrigger Trigger => _trigger ??= QSBWorldSync.GetWorldObjects().Single(); } } diff --git a/QSB/Animation/Player/AnimationType.cs b/QSB/Animation/Player/AnimationType.cs index 7ab25897..e151f08d 100644 --- a/QSB/Animation/Player/AnimationType.cs +++ b/QSB/Animation/Player/AnimationType.cs @@ -2,12 +2,12 @@ { public enum AnimationType { - Chert = 0, - Esker = 1, - Feldspar = 2, - Gabbro = 3, - PlayerSuited = 4, - PlayerUnsuited = 5, - Riebeck = 6 + Chert, + Esker, + Feldspar, + Gabbro, + PlayerSuited, + PlayerUnsuited, + Riebeck } } \ No newline at end of file diff --git a/QSB/Audio/QSBPlayerAudioController.cs b/QSB/Audio/QSBPlayerAudioController.cs index 964ad84a..e708edfb 100644 --- a/QSB/Audio/QSBPlayerAudioController.cs +++ b/QSB/Audio/QSBPlayerAudioController.cs @@ -45,6 +45,7 @@ namespace QSB.Audio bool randomize) { var go = new GameObject(name); + go.SetActive(false); go.transform.parent = parent; go.transform.localPosition = Vector3.zero; go.transform.localScale = Vector3.one; @@ -66,6 +67,8 @@ namespace QSB.Audio owAudioSource._track = track; owAudioSource._randomizePlayheadOnAwake = randomize; + go.SetActive(true); + return owAudioSource; } } diff --git a/QSB/ClientServerStateSync/ClientState.cs b/QSB/ClientServerStateSync/ClientState.cs index 2b0f3b4d..0cad0d24 100644 --- a/QSB/ClientServerStateSync/ClientState.cs +++ b/QSB/ClientServerStateSync/ClientState.cs @@ -7,7 +7,6 @@ AliveInSolarSystem, DeadInSolarSystem, AliveInEye, - WaitingForOthersToDie, WaitingForOthersToBeReady, WatchingLongCredits, WatchingShortCredits diff --git a/QSB/ConversationSync/ConversationType.cs b/QSB/ConversationSync/ConversationType.cs index 7c67563d..3e8658f3 100644 --- a/QSB/ConversationSync/ConversationType.cs +++ b/QSB/ConversationSync/ConversationType.cs @@ -2,9 +2,9 @@ { public enum ConversationType { - Character = 0, - Player = 1, - CloseCharacter = 2, - ClosePlayer = 3 + Character, + Player, + CloseCharacter, + ClosePlayer } } \ No newline at end of file diff --git a/QSB/ConversationSync/Messages/DialogueConditionMessage.cs b/QSB/ConversationSync/Messages/DialogueConditionMessage.cs index b9371f44..a83cf3bb 100644 --- a/QSB/ConversationSync/Messages/DialogueConditionMessage.cs +++ b/QSB/ConversationSync/Messages/DialogueConditionMessage.cs @@ -1,5 +1,4 @@ using QSB.Messaging; -using QSB.Player.TransformSync; using QSB.WorldSync; using QuantumUNET.Transport; @@ -7,16 +6,6 @@ namespace QSB.ConversationSync.Messages { public class DialogueConditionMessage : QSBMessage { - static DialogueConditionMessage() => GlobalMessenger.AddListener(OWEvents.DialogueConditionChanged, Handler); - - private static void Handler(string name, bool state) - { - if (PlayerTransformSync.LocalInstance) - { - new DialogueConditionMessage(name, state).Send(); - } - } - private string ConditionName; private bool ConditionState; @@ -47,7 +36,32 @@ namespace QSB.ConversationSync.Messages QSBWorldSync.SetDialogueCondition(ConditionName, ConditionState); } - DialogueConditionManager.SharedInstance.SetConditionState(ConditionName, ConditionState); + var sharedInstance = DialogueConditionManager.SharedInstance; + + var flag = true; + if (sharedInstance.ConditionExists(ConditionName)) + { + if (sharedInstance._dictConditions[ConditionName] == ConditionState) + { + flag = false; + } + + sharedInstance._dictConditions[ConditionName] = ConditionState; + } + else + { + sharedInstance.AddCondition(ConditionName, ConditionState); + } + + if (flag) + { + GlobalMessenger.FireEvent("DialogueConditionChanged", ConditionName, ConditionState); + } + + if (ConditionName == "LAUNCH_CODES_GIVEN") + { + PlayerData.LearnLaunchCodes(); + } } public override void OnReceiveLocal() diff --git a/QSB/ConversationSync/Messages/PersistentConditionMessage.cs b/QSB/ConversationSync/Messages/PersistentConditionMessage.cs new file mode 100644 index 00000000..b676a108 --- /dev/null +++ b/QSB/ConversationSync/Messages/PersistentConditionMessage.cs @@ -0,0 +1,73 @@ +using QSB.Messaging; +using QSB.Utility; +using QSB.WorldSync; +using QuantumUNET.Transport; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QSB.ConversationSync.Messages +{ + internal class PersistentConditionMessage : QSBMessage + { + private string _conditionName; + private bool _conditionState; + + public PersistentConditionMessage(string condition, bool state) + { + _conditionName = condition; + _conditionState = state; + } + + public override void Serialize(QNetworkWriter writer) + { + base.Serialize(writer); + writer.Write(_conditionName); + writer.Write(_conditionState); + } + + public override void Deserialize(QNetworkReader reader) + { + base.Deserialize(reader); + _conditionName = reader.ReadString(); + _conditionState = reader.ReadBoolean(); + } + + public override void OnReceiveRemote() + { + if (QSBCore.IsHost) + { + QSBWorldSync.SetPersistentCondition(_conditionName, _conditionState); + } + + var gameSave = PlayerData._currentGameSave; + if (gameSave.dictConditions.ContainsKey(_conditionName)) + { + gameSave.dictConditions[_conditionName] = _conditionState; + } + else + { + gameSave.dictConditions.Add(_conditionName, _conditionState); + } + + if (_conditionName + is not "LAUNCH_CODES_GIVEN" + and not "PLAYER_ENTERED_TIMELOOPCORE" + and not "PROBE_ENTERED_TIMELOOPCORE" + and not "PLAYER_ENTERED_TIMELOOPCORE_MULTIPLE") + { + PlayerData.SaveCurrentGame(); + } + } + + public override void OnReceiveLocal() + { + if (QSBCore.IsHost) + { + QSBWorldSync.SetPersistentCondition(_conditionName, _conditionState); + } + } + } +} diff --git a/QSB/ConversationSync/Patches/ConversationPatches.cs b/QSB/ConversationSync/Patches/ConversationPatches.cs index 59f889e9..718e0b43 100644 --- a/QSB/ConversationSync/Patches/ConversationPatches.cs +++ b/QSB/ConversationSync/Patches/ConversationPatches.cs @@ -7,6 +7,7 @@ using QSB.Patches; using QSB.Player; using QSB.Utility; using QSB.WorldSync; +using System.Linq; namespace QSB.ConversationSync.Patches { @@ -15,6 +16,23 @@ namespace QSB.ConversationSync.Patches { public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect; + public static readonly string[] PersistentConditionsToSync = + { + "MET_SOLANUM", + "MET_PRISONER", + "TALKED_TO_GABBRO", + "GABBRO_MERGE_TRIGGERED", + "KNOWS_MEDITATION" + }; + + [HarmonyPrefix] + [HarmonyPatch(typeof(DialogueConditionManager), nameof(DialogueConditionManager.SetConditionState))] + public static bool SetConditionState(string conditionName, bool conditionState) + { + new DialogueConditionMessage(conditionName, conditionState).Send(); + return true; + } + [HarmonyPrefix] [HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.StartConversation))] public static void CharacterDialogueTree_StartConversation(CharacterDialogueTree __instance) @@ -144,5 +162,15 @@ namespace QSB.ConversationSync.Patches __result = true; return false; } + + [HarmonyPostfix] + [HarmonyPatch(typeof(GameSave), nameof(GameSave.SetPersistentCondition))] + public static void SetPersistentCondition(string condition, bool state) + { + if (PersistentConditionsToSync.Contains(condition)) + { + new PersistentConditionMessage(condition, state).Send(); + } + } } } \ No newline at end of file diff --git a/QSB/ElevatorSync/WorldObjects/QSBElevator.cs b/QSB/ElevatorSync/WorldObjects/QSBElevator.cs index 70e1d904..3f99e161 100644 --- a/QSB/ElevatorSync/WorldObjects/QSBElevator.cs +++ b/QSB/ElevatorSync/WorldObjects/QSBElevator.cs @@ -28,7 +28,9 @@ namespace QSB.ElevatorSync.WorldObjects _owAudioSourceOneShot = AttachedObject._owAudioSourceOneShot; _owAudioSourceLP = AttachedObject._owAudioSourceLP; - var boxShape = AttachedObject.gameObject.AddComponent(); + // BUG : This won't work for the log lift! need to make a different trigger for that + + var boxShape = AttachedObject.gameObject.GetAddComponent(); boxShape.center = new Vector3(0, 1.75f, 0.25f); boxShape.size = new Vector3(3, 3.5f, 3); @@ -74,5 +76,16 @@ namespace QSB.ElevatorSync.WorldObjects _owAudioSourceLP.FadeIn(0.5f); _interactVolume.DisableInteraction(); } + + public override void DisplayLines() + { + var boxShape = (BoxShape)_elevatorTrigger._shape; + Popcron.Gizmos.Cube( + ShapeUtil.Box.CalcWorldSpaceCenter(boxShape), + boxShape.transform.rotation, + ShapeUtil.Box.CalcWorldSpaceSize(boxShape), + _elevatorTrigger.IsTrackingObject(Locator.GetPlayerDetector()) ? Color.green : Color.white + ); + } } } \ No newline at end of file diff --git a/QSB/EyeOfTheUniverse/CosmicInflation/InflationManager.cs b/QSB/EyeOfTheUniverse/CosmicInflation/InflationManager.cs deleted file mode 100644 index fb259a67..00000000 --- a/QSB/EyeOfTheUniverse/CosmicInflation/InflationManager.cs +++ /dev/null @@ -1,127 +0,0 @@ -using QSB.Messaging; -using QSB.Player; -using QSB.Player.Messages; -using QSB.Utility; -using QSB.WorldSync; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace QSB.EyeOfTheUniverse.CosmicInflation -{ - internal class InflationManager : WorldObjectManager - { - public static InflationManager Instance { get; private set; } - - private readonly List _playersInFog = new(); - private CosmicInflationController _controller; - - public override WorldObjectType WorldObjectType => WorldObjectType.Eye; - - public override void Awake() - { - base.Awake(); - Instance = this; - - QSBPlayerManager.OnRemovePlayer += OnPlayerLeave; - } - - private void OnPlayerLeave(uint id) - { - _playersInFog.Remove(QSBPlayerManager.GetPlayer(id)); - - // wait 1 frame for player to be removed - QSBCore.UnityEvents.FireOnNextUpdate(() => - { - if (QSBCore.IsInMultiplayer && _playersInFog.Count == QSBPlayerManager.PlayerList.Count) - { - StartCollapse(); - } - }); - } - - protected override void RebuildWorldObjects(OWScene scene) - { - _playersInFog.Clear(); - - if (_controller != null) - { - _controller._smokeSphereTrigger.OnEntry -= OnEntry; - } - - _controller = QSBWorldSync.GetUnityObjects().First(); - _controller._smokeSphereTrigger.OnEntry -= _controller.OnEnterFogSphere; - - _controller._smokeSphereTrigger.OnEntry += OnEntry; - } - - private void OnEntry(GameObject hitObj) - { - if (hitObj.CompareTag("PlayerCameraDetector") && _controller._state == CosmicInflationController.State.ReadyToCollapse) - { - _controller._smokeSphereTrigger.SetTriggerActivation(false); - _controller._probeDestroyTrigger.SetTriggerActivation(false); - new EnterLeaveMessage(EnterLeaveType.EnterCosmicFog).Send(); - - DebugLog.DebugWrite("disable input, wait for other players to enter"); - - var repelVolume = (WhiteHoleFluidVolume)_controller._repelVolume; - repelVolume._flowSpeed = -repelVolume._flowSpeed; - repelVolume._massiveFlowSpeed = -repelVolume._massiveFlowSpeed; - repelVolume.SetVolumeActivation(true); - QSBPlayerManager.HideAllPlayers(); - - ReticleController.Hide(); - Locator.GetFlashlight().TurnOff(false); - Locator.GetPromptManager().SetPromptsVisible(false); - OWInput.ChangeInputMode(InputMode.None); - } - } - - public void Enter(PlayerInfo player) - { - _playersInFog.Add(player); - - if (player != QSBPlayerManager.LocalPlayer) - { - DebugLog.DebugWrite($"fade out player {player.PlayerId}"); - player.DitheringAnimator.SetVisible(false, 3); - } - - if (_playersInFog.Count == QSBPlayerManager.PlayerList.Count) - { - StartCollapse(); - } - } - - private void StartCollapse() - { - DebugLog.DebugWrite("fade in everyone, fog sphere collapse"); - - var repelVolume = (WhiteHoleFluidVolume)_controller._repelVolume; - repelVolume.SetVolumeActivation(false); - QSBPlayerManager.ShowAllPlayers(); - - _controller._state = CosmicInflationController.State.Collapsing; - _controller._stateChangeTime = Time.time; - _controller._collapseStartPos = _controller._possibilitySphereRoot.localPosition; - _controller._smokeSphereTrigger.SetTriggerActivation(false); - _controller._inflationLight.FadeTo(1f, 1f); - _controller._possibilitySphereController.OnCollapse(); - if (_controller._campsiteController.GetUseAltPostCollapseSocket()) - { - _controller._playerPostCollapseSocket = _controller._altPlayerPostCollapseSocket; - _controller._altTravelerToHidePostCollapse.SetActive(false); - } - - Locator.GetPlayerBody().SetPosition(_controller._playerPostCollapseSocket.position); - Locator.GetPlayerBody().SetRotation(_controller._playerPostCollapseSocket.rotation); - Locator.GetPlayerBody().SetVelocity(-_controller._playerPostCollapseSocket.forward); - Locator.GetPlayerTransform().GetRequiredComponent().LockOn(_controller._possibilitySphereRoot, 2f); - foreach (var particles in _controller._smokeSphereParticles) - { - particles.Stop(); - } - } - } -} diff --git a/QSB/EyeOfTheUniverse/CosmicInflation/Patches/InflationPatches.cs b/QSB/EyeOfTheUniverse/CosmicInflation/Patches/InflationPatches.cs deleted file mode 100644 index 1d561d09..00000000 --- a/QSB/EyeOfTheUniverse/CosmicInflation/Patches/InflationPatches.cs +++ /dev/null @@ -1,9 +0,0 @@ -using QSB.Patches; - -namespace QSB.EyeOfTheUniverse.CosmicInflation.Patches -{ - internal class InflationPatches : QSBPatch - { - public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect; - } -} diff --git a/QSB/EyeOfTheUniverse/EyeStateSync/Messages/FlickerMessage.cs b/QSB/EyeOfTheUniverse/EyeStateSync/Messages/FlickerMessage.cs index 8fe4543c..f3b4abe1 100644 --- a/QSB/EyeOfTheUniverse/EyeStateSync/Messages/FlickerMessage.cs +++ b/QSB/EyeOfTheUniverse/EyeStateSync/Messages/FlickerMessage.cs @@ -1,6 +1,5 @@ using QSB.Messaging; using QSB.Player.TransformSync; -using QSB.Utility; using QSB.WorldSync; using QuantumUNET.Transport; using System; @@ -10,10 +9,18 @@ namespace QSB.EyeOfTheUniverse.EyeStateSync.Messages { internal class FlickerMessage : QSBMessage { + public static bool IgnoreNextMessage; + static FlickerMessage() => GlobalMessenger.AddListener(OWEvents.FlickerOffAndOn, Handler); private static void Handler(float offDuration, float onDuration) { + if (IgnoreNextMessage) + { + IgnoreNextMessage = false; + return; + } + if (PlayerTransformSync.LocalInstance) { new FlickerMessage(offDuration, onDuration).Send(); diff --git a/QSB/EyeOfTheUniverse/InstrumentSync/Messages/GatherInstrumentMessage.cs b/QSB/EyeOfTheUniverse/InstrumentSync/Messages/GatherInstrumentMessage.cs index aff15c49..dcf3f352 100644 --- a/QSB/EyeOfTheUniverse/InstrumentSync/Messages/GatherInstrumentMessage.cs +++ b/QSB/EyeOfTheUniverse/InstrumentSync/Messages/GatherInstrumentMessage.cs @@ -5,6 +5,6 @@ namespace QSB.EyeOfTheUniverse.InstrumentSync.Messages { internal class GatherInstrumentMessage : QSBWorldObjectMessage { - public override void OnReceiveRemote() => WorldObject.AttachedObject.Gather(); + public override void OnReceiveRemote() => WorldObject.Gather(); } } diff --git a/QSB/EyeOfTheUniverse/InstrumentSync/WorldObjects/QSBQuantumInstrument.cs b/QSB/EyeOfTheUniverse/InstrumentSync/WorldObjects/QSBQuantumInstrument.cs index 3cd3e380..cfa76555 100644 --- a/QSB/EyeOfTheUniverse/InstrumentSync/WorldObjects/QSBQuantumInstrument.cs +++ b/QSB/EyeOfTheUniverse/InstrumentSync/WorldObjects/QSBQuantumInstrument.cs @@ -1,8 +1,21 @@ -using QSB.WorldSync; +using QSB.Player; +using QSB.WorldSync; +using System.Linq; namespace QSB.EyeOfTheUniverse.InstrumentSync.WorldObjects { internal class QSBQuantumInstrument : WorldObject { + public void Gather() + { + AttachedObject.Gather(); + + var maskZoneController = QSBWorldSync.GetUnityObjects().First(); + if (maskZoneController._maskInstrument == AttachedObject) + { + // remote gathering solanum mask - make all players visible + QSBPlayerManager.ShowAllPlayers(); + } + } } } diff --git a/QSB/EyeOfTheUniverse/MaskSync/MaskManager.cs b/QSB/EyeOfTheUniverse/MaskSync/MaskManager.cs new file mode 100644 index 00000000..d9bf5628 --- /dev/null +++ b/QSB/EyeOfTheUniverse/MaskSync/MaskManager.cs @@ -0,0 +1,46 @@ +using QSB.EyeOfTheUniverse.EyeStateSync.Messages; +using QSB.Messaging; +using QSB.Player; +using QSB.Utility; +using QSB.WorldSync; +using System.Linq; +using UnityEngine; + +namespace QSB.EyeOfTheUniverse.MaskSync +{ + internal class MaskManager : MonoBehaviour + { + private static bool _flickering; + private static float _flickerOutTime; + + public void Awake() => QSBSceneManager.OnSceneLoaded += OnSceneLoaded; + + private static void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool inUniverse) + { + _flickering = false; + _flickerOutTime = 0f; + } + + public static void FlickerOutShuttle() + { + FlickerMessage.IgnoreNextMessage = true; + GlobalMessenger.FireEvent(OWEvents.FlickerOffAndOn, 0.5f, 0.5f); + _flickerOutTime = Time.time + 0.5f; + _flickering = true; + + // hide all players in shuttle + QSBPlayerManager.PlayerList.Where(x => x.IsInEyeShuttle).ForEach(x => x.DitheringAnimator.SetVisibleImmediate(false)); + } + + private void Update() + { + if (_flickering && Time.time > _flickerOutTime) + { + var controller = QSBWorldSync.GetUnityObjects().First(); + controller._shuttleObject.SetActive(false); + _flickering = false; + _flickerOutTime = 0f; + } + } + } +} diff --git a/QSB/EyeOfTheUniverse/MaskSync/Patches/MaskPatches.cs b/QSB/EyeOfTheUniverse/MaskSync/Patches/MaskPatches.cs new file mode 100644 index 00000000..c2cb8843 --- /dev/null +++ b/QSB/EyeOfTheUniverse/MaskSync/Patches/MaskPatches.cs @@ -0,0 +1,25 @@ +using HarmonyLib; +using QSB.Patches; + +namespace QSB.EyeOfTheUniverse.MaskSync.Patches +{ + internal class MaskPatches : QSBPatch + { + public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect; + + [HarmonyPrefix] + [HarmonyPatch(typeof(EyeShuttleController), nameof(EyeShuttleController.OnLaunchSlotActivated))] + public static bool DontLaunch(EyeShuttleController __instance) + { + if (__instance._isPlayerInside) + { + return true; + } + + MaskManager.FlickerOutShuttle(); + __instance.enabled = false; + + return false; + } + } +} diff --git a/QSB/EyeOfTheUniverse/VesselSync/VesselManager.cs b/QSB/EyeOfTheUniverse/VesselSync/VesselManager.cs deleted file mode 100644 index df1313cc..00000000 --- a/QSB/EyeOfTheUniverse/VesselSync/VesselManager.cs +++ /dev/null @@ -1,80 +0,0 @@ -using QSB.Messaging; -using QSB.Player; -using QSB.Player.Messages; -using QSB.WorldSync; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace QSB.EyeOfTheUniverse.VesselSync -{ - internal class VesselManager : WorldObjectManager - { - public static VesselManager Instance { get; private set; } - - private readonly List _playersInCage = new(); - private VesselWarpController _warpController; - - public override WorldObjectType WorldObjectType => WorldObjectType.Both; - - public override void Awake() - { - base.Awake(); - Instance = this; - } - - protected override void RebuildWorldObjects(OWScene scene) - { - _playersInCage.Clear(); - - if (_warpController != null) - { - _warpController._cageTrigger.OnEntry -= OnEntry; - _warpController._cageTrigger.OnExit -= OnExit; - } - - _warpController = QSBWorldSync.GetUnityObjects().First(); - _warpController._cageTrigger.OnExit -= _warpController.OnExitCageTrigger; - - _warpController._cageTrigger.OnEntry += OnEntry; - _warpController._cageTrigger.OnExit += OnExit; - } - - private static void OnEntry(GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - new EnterLeaveMessage(EnterLeaveType.EnterVesselCage).Send(); - } - } - - private static void OnExit(GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - new EnterLeaveMessage(EnterLeaveType.ExitVesselCage).Send(); - } - } - - public void Enter(PlayerInfo player) - { - _playersInCage.Add(player); - } - - public void Exit(PlayerInfo player) - { - _playersInCage.Remove(player); - - if (_playersInCage.Count == 0 && _warpController._hasPower) - { - var obj = _warpController; - obj._cageClosed = true; - obj._cageAnimator.TranslateToLocalPosition(new Vector3(0f, -8.1f, 0f), 5f); - obj._cageAnimator.RotateToLocalEulerAngles(new Vector3(0f, 180f, 0f), 5f); - obj._cageAnimator.OnTranslationComplete -= obj.OnCageAnimationComplete; - obj._cageAnimator.OnTranslationComplete += obj.OnCageAnimationComplete; - obj._cageLoopingAudio.FadeIn(1f); - } - } - } -} diff --git a/QSB/Instruments/QSBCamera/CameraMode.cs b/QSB/Instruments/QSBCamera/CameraMode.cs index 49229d27..71cb586d 100644 --- a/QSB/Instruments/QSBCamera/CameraMode.cs +++ b/QSB/Instruments/QSBCamera/CameraMode.cs @@ -2,7 +2,7 @@ { public enum CameraMode { - FirstPerson = 0, - ThirdPerson = 1 + FirstPerson, + ThirdPerson } } \ No newline at end of file diff --git a/QSB/ItemSync/WorldObjects/Items/QSBOWItem.cs b/QSB/ItemSync/WorldObjects/Items/QSBOWItem.cs index 1a27ad04..3e57f9a5 100644 --- a/QSB/ItemSync/WorldObjects/Items/QSBOWItem.cs +++ b/QSB/ItemSync/WorldObjects/Items/QSBOWItem.cs @@ -56,9 +56,9 @@ namespace QSB.ItemSync.WorldObjects.Items public override void OnRemoval() => QSBPlayerManager.OnRemovePlayer -= OnPlayerLeave; - private void OnPlayerLeave(uint player) + private void OnPlayerLeave(PlayerInfo player) { - if (HoldingPlayer != player) + if (HoldingPlayer != player.PlayerId) { return; } diff --git a/QSB/Menus/MenuManager.cs b/QSB/Menus/MenuManager.cs index 05d1512d..bcef3789 100644 --- a/QSB/Menus/MenuManager.cs +++ b/QSB/Menus/MenuManager.cs @@ -5,6 +5,7 @@ using QSB.SaveSync.Messages; using QSB.Utility; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; @@ -151,6 +152,7 @@ namespace QSB.Menus { IPPopup = MenuApi.MakeInputFieldPopup("IP Address", "IP Address", "Connect", "Cancel"); IPPopup.OnPopupConfirm += Connect; + IPPopup.OnPopupValidate += Validate; InfoPopup = MenuApi.MakeInfoPopup("", ""); InfoPopup.OnDeactivateMenu += OnCloseInfoPopup; @@ -222,15 +224,11 @@ namespace QSB.Menus CreateCommonPopups(); ClientButton = MenuApi.TitleScreen_MakeMenuOpenButton("CONNECT TO MULTIPLAYER", _ClientButtonIndex, IPPopup); - var loadEye = MenuApi.TitleScreen_MakeSceneLoadButton("debug load eye", _ClientButtonIndex + 1, SubmitActionLoadScene.LoadableScenes.EYE); - _loadingText = ClientButton.transform.GetChild(0).GetChild(1).GetComponent(); ResumeGameButton = GameObject.Find("MainMenuLayoutGroup/Button-ResumeGame"); NewGameButton = GameObject.Find("MainMenuLayoutGroup/Button-NewGame"); - SetButtonActive(loadEye, QSBCore.DebugMode); - if (QSBCore.IsInMultiplayer) { SetButtonActive(ClientButton, false); @@ -310,13 +308,16 @@ namespace QSB.Menus DisconnectPopup._labelText.text = popupText; } + private bool Validate() + { + var inputText = ((PopupInputMenu)IPPopup).GetInputText(); + var regex = new Regex(@"\A(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\z"); + return inputText == "localhost" || regex.Match(inputText).Success; + } + private void Connect() { - var address = string.Concat(((PopupInputMenu)IPPopup).GetInputText().Where(c => !char.IsWhiteSpace(c))); - if (address.Length == 0) - { - address = QSBCore.DefaultServerIP; - } + var address = ((PopupInputMenu)IPPopup).GetInputText(); QSBNetworkManager.Instance.networkAddress = address; QSBNetworkManager.Instance.StartClient(); diff --git a/QSB/Messaging/OWEvents.cs b/QSB/Messaging/OWEvents.cs index f398be38..db03aa85 100644 --- a/QSB/Messaging/OWEvents.cs +++ b/QSB/Messaging/OWEvents.cs @@ -19,7 +19,6 @@ public const string EquipTranslator = nameof(EquipTranslator); public const string UnequipTranslator = nameof(UnequipTranslator); public const string WakeUp = nameof(WakeUp); - public const string DialogueConditionChanged = nameof(DialogueConditionChanged); public const string PlayerEnterQuantumMoon = nameof(PlayerEnterQuantumMoon); public const string PlayerExitQuantumMoon = nameof(PlayerExitQuantumMoon); public const string EnterRoastingMode = nameof(EnterRoastingMode); diff --git a/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs b/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs index 3e737119..8dd902ec 100644 --- a/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs +++ b/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs @@ -59,12 +59,14 @@ namespace QSB.OrbSync.TransformSync _attachedBody = AttachedObject.GetAttachedOWRigidbody(); SetReferenceTransform(_attachedBody.GetOrigParent()); + /* if (_attachedBody.GetOrigParent() == Locator.GetRootTransform()) { DebugLog.DebugWrite($"{LogName} with AttachedObject {AttachedObject.name} had it's original parent as SolarSystemRoot - Disabling..."); enabled = false; return; } + */ if (QSBCore.IsHost) { diff --git a/QSB/Patches/QSBPatchTypes.cs b/QSB/Patches/QSBPatchTypes.cs index dc2ad86f..f428af74 100644 --- a/QSB/Patches/QSBPatchTypes.cs +++ b/QSB/Patches/QSBPatchTypes.cs @@ -2,9 +2,9 @@ { public enum QSBPatchTypes { - OnClientConnect = 0, - OnNonServerClientConnect = 1, - OnServerClientConnect = 2, - RespawnTime = 3 + OnClientConnect, + OnNonServerClientConnect, + OnServerClientConnect, + RespawnTime } } \ No newline at end of file diff --git a/QSB/Player/EnterLeaveType.cs b/QSB/Player/EnterLeaveType.cs index 672dc875..f3d47a36 100644 --- a/QSB/Player/EnterLeaveType.cs +++ b/QSB/Player/EnterLeaveType.cs @@ -2,20 +2,11 @@ { public enum EnterLeaveType { - EnterMoon = 0, - ExitMoon = 1, - EnterShrine = 2, - ExitShrine = 3, - EnterPlatform = 4, - ExitPlatform = 5, - EnterNonNomaiHeadZone = 6, - ExitNonNomaiHeadZone = 7, - EnterShip = 8, - ExitShip = 9, - EnterNomaiHeadZone = 10, - ExitNomaiHeadZone = 11, - EnterVesselCage = 12, - ExitVesselCage = 13, - EnterCosmicFog = 14, + EnterMoon, + ExitMoon, + EnterPlatform, + ExitPlatform, + EnterShip, + ExitShip, } } diff --git a/QSB/Player/GamePlatform.cs b/QSB/Player/GamePlatform.cs index 6aedb3f1..0b3c8f52 100644 --- a/QSB/Player/GamePlatform.cs +++ b/QSB/Player/GamePlatform.cs @@ -2,7 +2,6 @@ { public enum GamePlatform { - None, Steam, Epic } diff --git a/QSB/Player/Messages/EnterLeaveMessage.cs b/QSB/Player/Messages/EnterLeaveMessage.cs index 3c133d99..954d7602 100644 --- a/QSB/Player/Messages/EnterLeaveMessage.cs +++ b/QSB/Player/Messages/EnterLeaveMessage.cs @@ -1,7 +1,4 @@ using OWML.Common; -using QSB.Animation.NPC.WorldObjects; -using QSB.EyeOfTheUniverse.CosmicInflation; -using QSB.EyeOfTheUniverse.VesselSync; using QSB.Messaging; using QSB.Player.TransformSync; using QSB.PoolSync; @@ -65,12 +62,6 @@ namespace QSB.Player.Messages case EnterLeaveType.ExitMoon: player.IsInMoon = false; break; - case EnterLeaveType.EnterShrine: - player.IsInShrine = true; - break; - case EnterLeaveType.ExitShrine: - player.IsInShrine = false; - break; case EnterLeaveType.EnterPlatform: CustomNomaiRemoteCameraPlatform.CustomPlatformList[ObjectId] .OnRemotePlayerEnter(From); @@ -79,33 +70,12 @@ namespace QSB.Player.Messages CustomNomaiRemoteCameraPlatform.CustomPlatformList[ObjectId] .OnRemotePlayerExit(From); break; - case EnterLeaveType.EnterNonNomaiHeadZone: - ObjectId.GetWorldObject().AddPlayerToHeadZone(player); - break; - case EnterLeaveType.ExitNonNomaiHeadZone: - ObjectId.GetWorldObject().RemovePlayerFromHeadZone(player); - break; - case EnterLeaveType.EnterNomaiHeadZone: - ObjectId.GetWorldObject().AddPlayerToHeadZone(player); - break; - case EnterLeaveType.ExitNomaiHeadZone: - ObjectId.GetWorldObject().RemovePlayerFromHeadZone(player); - break; case EnterLeaveType.EnterShip: ShipManager.Instance.AddPlayerToShip(player); break; case EnterLeaveType.ExitShip: ShipManager.Instance.RemovePlayerFromShip(player); break; - case EnterLeaveType.EnterVesselCage: - VesselManager.Instance.Enter(player); - break; - case EnterLeaveType.ExitVesselCage: - VesselManager.Instance.Exit(player); - break; - case EnterLeaveType.EnterCosmicFog: - InflationManager.Instance.Enter(player); - break; default: DebugLog.ToConsole($"Warning - Unknown EnterLeaveType : {Value}", MessageType.Warning); break; diff --git a/QSB/Player/Messages/RequestStateResyncMessage.cs b/QSB/Player/Messages/RequestStateResyncMessage.cs index 8c927f12..be5a53f2 100644 --- a/QSB/Player/Messages/RequestStateResyncMessage.cs +++ b/QSB/Player/Messages/RequestStateResyncMessage.cs @@ -16,6 +16,8 @@ using QSB.Tools.TranslatorTool.TranslationSync.Messages; using QSB.Tools.TranslatorTool.TranslationSync.WorldObjects; using QSB.TornadoSync.Messages; using QSB.TornadoSync.WorldObjects; +using QSB.TriggerSync.Messages; +using QSB.TriggerSync.WorldObjects; using QSB.Utility; using QSB.WorldSync; using System.Linq; @@ -126,6 +128,9 @@ namespace QSB.Player.Messages QSBWorldSync.GetWorldObjects().ForEach(tornado => tornado.SendMessage(new TornadoFormStateMessage(tornado.FormState) { To = From })); + + QSBWorldSync.GetWorldObjects().ForEach(trigger + => trigger.SendMessage(new TriggerResyncMessage(trigger.Occupants) { To = From })); } /// diff --git a/QSB/Player/PlayerInfo.cs b/QSB/Player/PlayerInfo.cs index 35701ac0..b6492ba8 100644 --- a/QSB/Player/PlayerInfo.cs +++ b/QSB/Player/PlayerInfo.cs @@ -39,6 +39,7 @@ namespace QSB.Player public bool IsReady { get; set; } public bool IsInMoon { get; set; } public bool IsInShrine { get; set; } + public bool IsInEyeShuttle { get; set; } public IQSBQuantumObject EntangledObject { get; set; } public QSBPlayerAudioController AudioController { get; set; } public DitheringAnimator DitheringAnimator { get; set; } @@ -97,7 +98,7 @@ namespace QSB.Player // Tools public GameObject ProbeBody { get; set; } public QSBProbe Probe { get; set; } - public QSBFlashlight FlashLight => CameraBody?.GetComponentInChildren(); + public QSBFlashlight FlashLight => CameraBody == null ? null : CameraBody.GetComponentInChildren(); public QSBTool Signalscope => GetToolByType(ToolType.Signalscope); public QSBTool Translator => GetToolByType(ToolType.Translator); public QSBProbeLauncherTool ProbeLauncher => (QSBProbeLauncherTool)GetToolByType(ToolType.ProbeLauncher); diff --git a/QSB/Player/QSBPlayerManager.cs b/QSB/Player/QSBPlayerManager.cs index 8d7229a8..e1704c1d 100644 --- a/QSB/Player/QSBPlayerManager.cs +++ b/QSB/Player/QSBPlayerManager.cs @@ -32,11 +32,11 @@ namespace QSB.Player /// /// called right after player is added /// - public static Action OnAddPlayer; + public static Action OnAddPlayer; /// /// called right before player is removed /// - public static Action OnRemovePlayer; + public static Action OnRemovePlayer; public static readonly List PlayerList = new(); diff --git a/QSB/Player/TransformSync/PlayerTransformSync.cs b/QSB/Player/TransformSync/PlayerTransformSync.cs index 77c4c105..1dcef988 100644 --- a/QSB/Player/TransformSync/PlayerTransformSync.cs +++ b/QSB/Player/TransformSync/PlayerTransformSync.cs @@ -50,7 +50,7 @@ namespace QSB.Player.TransformSync var player = new PlayerInfo(this); QSBPlayerManager.PlayerList.SafeAdd(player); base.Start(); - QSBPlayerManager.OnAddPlayer?.Invoke(Player.PlayerId); + QSBPlayerManager.OnAddPlayer?.Invoke(Player); DebugLog.DebugWrite($"Create Player : id<{Player.PlayerId}>", MessageType.Info); } @@ -87,7 +87,7 @@ namespace QSB.Player.TransformSync protected override void OnDestroy() { // TODO : Maybe move this to a leave event...? Would ensure everything could finish up before removing the player - QSBPlayerManager.OnRemovePlayer?.Invoke(Player.PlayerId); + QSBPlayerManager.OnRemovePlayer?.Invoke(Player); base.OnDestroy(); Player.HudMarker?.Remove(); QSBPlayerManager.PlayerList.Remove(Player); @@ -169,6 +169,12 @@ namespace QSB.Player.TransformSync REMOTE_Player_Body.AddComponent().Init(Player); REMOTE_Player_Body.AddComponent().PlayerName = Player.Name; Player.DitheringAnimator = REMOTE_Player_Body.AddComponent(); + // get inactive renderers too + QSBCore.UnityEvents.FireOnNextUpdate(() => + Player.DitheringAnimator._renderers = Player.DitheringAnimator + .GetComponentsInChildren(true) + .Select(x => x.gameObject.GetAddComponent()) + .ToArray()); Player.AudioController = PlayerAudioManager.InitRemote(REMOTE_Player_Body.transform); /* diff --git a/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs b/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs index f7cd1b1a..0a9534cb 100644 --- a/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs +++ b/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs @@ -673,14 +673,13 @@ namespace QSB.PoolSync public bool IsPlatformActive() => _platformActive; - public void OnRemovePlayer(uint id) + public void OnRemovePlayer(PlayerInfo player) { - if (id == QSBPlayerManager.LocalPlayerId) + if (player == QSBPlayerManager.LocalPlayer) { return; } - var player = QSBPlayerManager.GetPlayer(id); if (!_playerToHologram.Any(x => x.Key == player)) { return; @@ -689,7 +688,7 @@ namespace QSB.PoolSync var hologram = _playerToHologram.First(x => x.Key == player).Value; if (hologram.activeSelf) { - OnRemotePlayerExit(id); + OnRemotePlayerExit(player.PlayerId); } _playerToHologram.Remove(player); diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj index a11b5377..e461422c 100644 --- a/QSB/QSB.csproj +++ b/QSB/QSB.csproj @@ -63,10 +63,10 @@ copy /y "$(OwmlDir)\OWML.Abstractions.dll" "$(UnityAssetsDir)" - + - - + + diff --git a/QSB/QSBCore.cs b/QSB/QSBCore.cs index 9a3bdfbc..9eb0ba44 100644 --- a/QSB/QSBCore.cs +++ b/QSB/QSBCore.cs @@ -2,6 +2,7 @@ using OWML.ModHelper; using OWML.ModHelper.Input; using QSB.EyeOfTheUniverse.GalaxyMap; +using QSB.EyeOfTheUniverse.MaskSync; using QSB.Inputs; using QSB.Menus; using QSB.Patches; @@ -109,6 +110,7 @@ namespace QSB gameObject.AddComponent(); gameObject.AddComponent(); gameObject.AddComponent(); + gameObject.AddComponent(); // WorldObject managers foreach (var type in typeof(WorldObjectManager).GetDerivedTypes()) diff --git a/QSB/QSBNetworkManager.cs b/QSB/QSBNetworkManager.cs index 94a0f886..13e98317 100644 --- a/QSB/QSBNetworkManager.cs +++ b/QSB/QSBNetworkManager.cs @@ -174,6 +174,7 @@ namespace QSB if (QSBSceneManager.IsInUniverse) { WorldObjectManager.Rebuild(QSBSceneManager.CurrentScene); + QSBWorldSync.Init(); } var specificType = QNetworkServer.active ? QSBPatchTypes.OnServerClientConnect : QSBPatchTypes.OnNonServerClientConnect; @@ -205,9 +206,7 @@ namespace QSB QSBPlayerManager.PlayerList.ForEach(player => player.HudMarker?.Remove()); RemoveWorldObjects(); - QSBWorldSync.DialogueConditions.Clear(); - QSBWorldSync.OldDialogueTrees.Clear(); - QSBWorldSync.ShipLogFacts.Clear(); + QSBWorldSync.Reset(); if (WakeUpSync.LocalInstance != null) { @@ -236,10 +235,10 @@ namespace QSB DebugLog.DebugWrite("OnServerDisconnect", MessageType.Info); // revert authority from ship - if (ShipTransformSync.LocalInstance) + if (ShipTransformSync.LocalInstance != null) { var identity = ShipTransformSync.LocalInstance.NetIdentity; - if (identity.ClientAuthorityOwner == conn) + if (identity != null && identity.ClientAuthorityOwner == conn) { identity.SetAuthority(QSBPlayerManager.LocalPlayerId); } @@ -248,6 +247,12 @@ namespace QSB // stop dragging for the orbs this player was dragging foreach (var qsbOrb in QSBWorldSync.GetWorldObjects()) { + if (qsbOrb.TransformSync == null) + { + DebugLog.ToConsole($"{qsbOrb.LogName} TransformSync == null??????????", MessageType.Warning); + continue; + } + if (!qsbOrb.TransformSync.enabled) { continue; diff --git a/QSB/QSBSceneManager.cs b/QSB/QSBSceneManager.cs index d7aaf45a..76ba5876 100644 --- a/QSB/QSBSceneManager.cs +++ b/QSB/QSBSceneManager.cs @@ -28,6 +28,8 @@ namespace QSB { // So objects have time to be deleted, made, whatever QSBCore.UnityEvents.FireOnNextUpdate(() => WorldObjectManager.Rebuild(newScene)); + + QSBWorldSync.Init(); } OnSceneLoaded?.SafeInvoke(oldScene, newScene, universe); diff --git a/QSB/QuantumSync/Messages/MoveSkeletonMessage.cs b/QSB/QuantumSync/Messages/MoveSkeletonMessage.cs new file mode 100644 index 00000000..9ee597f5 --- /dev/null +++ b/QSB/QuantumSync/Messages/MoveSkeletonMessage.cs @@ -0,0 +1,27 @@ +using QSB.Messaging; +using QSB.QuantumSync.WorldObjects; +using QuantumUNET.Transport; + +namespace QSB.QuantumSync.Messages +{ + internal class MoveSkeletonMessage : QSBWorldObjectMessage + { + private int _index; + + public MoveSkeletonMessage(int index) => _index = index; + + public override void Serialize(QNetworkWriter writer) + { + base.Serialize(writer); + writer.Write(_index); + } + + public override void Deserialize(QNetworkReader reader) + { + base.Deserialize(reader); + _index = reader.ReadInt32(); + } + + public override void OnReceiveRemote() => WorldObject.MoveSkeleton(_index); + } +} diff --git a/QSB/QuantumSync/Messages/SetIsQuantumMessage.cs b/QSB/QuantumSync/Messages/SetIsQuantumMessage.cs new file mode 100644 index 00000000..416bf13a --- /dev/null +++ b/QSB/QuantumSync/Messages/SetIsQuantumMessage.cs @@ -0,0 +1,12 @@ +using QSB.Messaging; +using QSB.QuantumSync.WorldObjects; + +namespace QSB.QuantumSync.Messages +{ + public class SetIsQuantumMessage : QSBBoolWorldObjectMessage + { + public SetIsQuantumMessage(bool isQuantum) => Value = isQuantum; + + public override void OnReceiveRemote() => WorldObject.SetIsQuantum(Value); + } +} diff --git a/QSB/QuantumSync/Patches/QuantumPatches.cs b/QSB/QuantumSync/Patches/QuantumPatches.cs index f1b99f60..020e4cfd 100644 --- a/QSB/QuantumSync/Patches/QuantumPatches.cs +++ b/QSB/QuantumSync/Patches/QuantumPatches.cs @@ -3,7 +3,6 @@ using OWML.Common; using QSB.Messaging; using QSB.Patches; using QSB.Player; -using QSB.Player.Messages; using QSB.QuantumSync.Messages; using QSB.QuantumSync.WorldObjects; using QSB.Utility; @@ -28,6 +27,16 @@ namespace QSB.QuantumSync.Patches return false; } + [HarmonyPostfix] + [HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.SetIsQuantum))] + public static void QuantumObject_SetIsQuantum(QuantumObject __instance) + { + if (WorldObjectManager.AllObjectsReady) + { + __instance.GetWorldObject().SendMessage(new SetIsQuantumMessage(__instance.IsQuantum())); + } + } + [HarmonyPrefix] [HarmonyPatch(typeof(SocketedQuantumObject), nameof(SocketedQuantumObject.ChangeQuantumState))] public static bool SocketedQuantumObject_ChangeQuantumState( @@ -354,48 +363,6 @@ namespace QSB.QuantumSync.Patches return isInControl; } - [HarmonyPrefix] - [HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.OnEntry))] - public static bool QuantumShrine_OnEntry( - QuantumShrine __instance, - GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - __instance._isPlayerInside = true; - __instance._fading = true; - __instance._exteriorLightController.FadeTo(0f, 1f); - new EnterLeaveMessage(EnterLeaveType.EnterShrine).Send(); - } - else if (hitObj.CompareTag("ProbeDetector")) - { - __instance._isProbeInside = true; - } - - return false; - } - - [HarmonyPrefix] - [HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.OnExit))] - public static bool QuantumShrine_OnExit( - QuantumShrine __instance, - GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - __instance._isPlayerInside = false; - __instance._fading = true; - __instance._exteriorLightController.FadeTo(1f, 1f); - new EnterLeaveMessage(EnterLeaveType.ExitShrine).Send(); - } - else if (hitObj.CompareTag("ProbeDetector")) - { - __instance._isProbeInside = false; - } - - return false; - } - [HarmonyPrefix] [HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.CheckPlayerFogProximity))] public static bool QuantumMoon_CheckPlayerFogProximity(QuantumMoon __instance) @@ -462,5 +429,50 @@ namespace QSB.QuantumSync.Patches __instance._shipLandingCamFogBubble.SetFogAlpha(fogAlpha); return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(QuantumSkeletonTower), nameof(QuantumSkeletonTower.ChangeQuantumState))] + public static bool QuantumSkeletonTower_ChangeQuantumState(QuantumSkeletonTower __instance, ref bool __result) + { + if (!WorldObjectManager.AllObjectsReady) + { + return true; + } + + var qsbQuantumSkeletonTower = __instance.GetWorldObject(); + if (qsbQuantumSkeletonTower.ControllingPlayer != QSBPlayerManager.LocalPlayerId) + { + return false; + } + + if (__instance._waitForPlayerToLookAtTower) + { + __result = false; + return false; + } + + if (__instance._index < __instance._towerSkeletons.Length) + { + for (var i = 0; i < __instance._pointingSkeletons.Length; i++) + { + if (__instance._pointingSkeletons[i].gameObject.activeInHierarchy && + (!__instance._pointingSkeletons[i].IsVisible() || !__instance._pointingSkeletons[i].IsIlluminated())) + { + __instance._pointingSkeletons[i].gameObject.SetActive(false); + + __instance._towerSkeletons[__instance._index].SetActive(true); + __instance._index++; + __instance._waitForPlayerToLookAtTower = true; + qsbQuantumSkeletonTower.SendMessage(new MoveSkeletonMessage(i)); + __result = true; + return false; + } + } + } + + __result = false; + return false; + } + } } diff --git a/QSB/QuantumSync/QuantumManager.cs b/QSB/QuantumSync/QuantumManager.cs index 30501ae4..3430f8db 100644 --- a/QSB/QuantumSync/QuantumManager.cs +++ b/QSB/QuantumSync/QuantumManager.cs @@ -40,13 +40,14 @@ namespace QSB.QuantumSync QSBWorldSync.Init(); QSBWorldSync.Init(); QSBWorldSync.Init(); + QSBWorldSync.Init(); if (scene == OWScene.SolarSystem) { Shrine = QSBWorldSync.GetUnityObjects().First(); } } - public void PlayerLeave(uint playerId) + public void PlayerLeave(PlayerInfo player) { if (!QSBCore.IsHost) { @@ -55,7 +56,7 @@ namespace QSB.QuantumSync foreach (var obj in QSBWorldSync.GetWorldObjects()) { - if (obj.ControllingPlayer == playerId) + if (obj.ControllingPlayer == player.PlayerId) { obj.SendMessage(new QuantumAuthorityMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : 0u)); } @@ -64,7 +65,7 @@ namespace QSB.QuantumSync public void OnRenderObject() { - if (!QSBCore.ShowLinesInDebug || !AllObjectsReady) + if (!QSBCore.ShowLinesInDebug) { return; } @@ -73,25 +74,6 @@ namespace QSB.QuantumSync { Popcron.Gizmos.Sphere(Shrine.transform.position, 10f, Color.magenta); } - - foreach (var quantumObject in QSBWorldSync.GetWorldObjects()) - { - if (quantumObject.ControllingPlayer == 0) - { - if (quantumObject.IsEnabled) - { - Popcron.Gizmos.Line(quantumObject.ReturnObject().transform.position, - QSBPlayerManager.LocalPlayer.Body.transform.position, - Color.magenta * 0.25f); - } - - continue; - } - - Popcron.Gizmos.Line(quantumObject.ReturnObject().transform.position, - QSBPlayerManager.GetPlayer(quantumObject.ControllingPlayer).Body.transform.position, - Color.magenta); - } } public static Tuple> IsVisibleUsingCameraFrustum(ShapeVisibilityTracker tracker, bool ignoreLocalCamera) diff --git a/QSB/QuantumSync/WorldObjects/IQSBQuantumObject.cs b/QSB/QuantumSync/WorldObjects/IQSBQuantumObject.cs index b30b92fe..bba09ddb 100644 --- a/QSB/QuantumSync/WorldObjects/IQSBQuantumObject.cs +++ b/QSB/QuantumSync/WorldObjects/IQSBQuantumObject.cs @@ -6,9 +6,10 @@ namespace QSB.QuantumSync.WorldObjects public interface IQSBQuantumObject : IWorldObject { uint ControllingPlayer { get; set; } - bool IsEnabled { get; set; } + bool IsEnabled { get; } - List GetVisibilityTrackers(); List GetAttachedShapes(); + + void SetIsQuantum(bool isQuantum); } } diff --git a/QSB/QuantumSync/WorldObjects/QSBEyeProxyQuantumMoon.cs b/QSB/QuantumSync/WorldObjects/QSBEyeProxyQuantumMoon.cs index fecffb94..2fd4a9ee 100644 --- a/QSB/QuantumSync/WorldObjects/QSBEyeProxyQuantumMoon.cs +++ b/QSB/QuantumSync/WorldObjects/QSBEyeProxyQuantumMoon.cs @@ -1,15 +1,7 @@ -using QSB.Player; -using System.Linq; - -namespace QSB.QuantumSync.WorldObjects +namespace QSB.QuantumSync.WorldObjects { internal class QSBEyeProxyQuantumMoon : QSBQuantumObject { - public override void Init() - { - // smallest player id is the host - ControllingPlayer = QSBPlayerManager.PlayerList.Min(x => x.PlayerId); - base.Init(); - } + protected override bool HostControls => true; } } diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumMoon.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumMoon.cs index 48b84b76..9a7fc71a 100644 --- a/QSB/QuantumSync/WorldObjects/QSBQuantumMoon.cs +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumMoon.cs @@ -1,15 +1,7 @@ -using QSB.Player; -using System.Linq; - -namespace QSB.QuantumSync.WorldObjects +namespace QSB.QuantumSync.WorldObjects { internal class QSBQuantumMoon : QSBQuantumObject { - public override void Init() - { - // smallest player id is the host - ControllingPlayer = QSBPlayerManager.PlayerList.Min(x => x.PlayerId); - base.Init(); - } + protected override bool HostControls => true; } } diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs index a1826a0b..3e3bf99d 100644 --- a/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs @@ -7,17 +7,28 @@ using QSB.WorldSync; using System.Collections.Generic; using System.Linq; using UnityEngine; +using Object = UnityEngine.Object; namespace QSB.QuantumSync.WorldObjects { internal abstract class QSBQuantumObject : WorldObject, IQSBQuantumObject where T : QuantumObject { + /// + /// whether the controlling player is always the host
+ /// also means this object is considered always enabled + ///
+ protected virtual bool HostControls => false; public uint ControllingPlayer { get; set; } - public bool IsEnabled { get; set; } + public bool IsEnabled { get; private set; } public override void OnRemoval() { + if (HostControls) + { + return; + } + foreach (var shape in GetAttachedShapes()) { shape.OnShapeActivated -= OnEnable; @@ -25,38 +36,31 @@ namespace QSB.QuantumSync.WorldObjects } } - public override bool ShouldDisplayLabel() => ControllingPlayer != 0; - public override void Init() { - var debugBundle = QSBCore.DebugAssetBundle; - var sphere = debugBundle.LoadAsset("Assets/Prefabs/Sphere.prefab"); - var cube = debugBundle.LoadAsset("Assets/Prefabs/Cube.prefab"); - var capsule = debugBundle.LoadAsset("Assets/Prefabs/Capsule.prefab"); - - if (cube == null) + if (QSBCore.ShowQuantumVisibilityObjects) { - DebugLog.DebugWrite($"CUBE IS NULL"); - } + var debugBundle = QSBCore.DebugAssetBundle; + var sphere = debugBundle.LoadAsset("Assets/Prefabs/Sphere.prefab"); + var cube = debugBundle.LoadAsset("Assets/Prefabs/Cube.prefab"); + var capsule = debugBundle.LoadAsset("Assets/Prefabs/Capsule.prefab"); - if (sphere == null) - { - DebugLog.DebugWrite($"SPHERE IS NULL"); - } - - if (capsule == null) - { - DebugLog.DebugWrite($"CAPSULE IS NULL"); - } - - foreach (var shape in GetAttachedShapes()) - { - if (shape == null) + if (cube == null) { - break; + DebugLog.DebugWrite($"CUBE IS NULL"); } - if (QSBCore.ShowQuantumVisibilityObjects) + if (sphere == null) + { + DebugLog.DebugWrite($"SPHERE IS NULL"); + } + + if (capsule == null) + { + DebugLog.DebugWrite($"CAPSULE IS NULL"); + } + + foreach (var shape in GetAttachedShapes()) { if (shape is BoxShape boxShape) { @@ -92,20 +96,28 @@ namespace QSB.QuantumSync.WorldObjects private void LateInit() { FinishDelayedReady(); - foreach (var shape in GetAttachedShapes()) + + if (HostControls) { - shape.OnShapeActivated += OnEnable; - shape.OnShapeDeactivated += OnDisable; + // smallest player id is the host + ControllingPlayer = QSBPlayerManager.PlayerList.Min(x => x.PlayerId); + IsEnabled = true; + return; } var attachedShapes = GetAttachedShapes(); - if (attachedShapes.Count == 0) { IsEnabled = false; return; } + foreach (var shape in attachedShapes) + { + shape.OnShapeActivated += OnEnable; + shape.OnShapeDeactivated += OnDisable; + } + if (attachedShapes.All(x => x.enabled && x.gameObject.activeInHierarchy && x.active)) { IsEnabled = true; @@ -117,11 +129,6 @@ namespace QSB.QuantumSync.WorldObjects } } - public List GetVisibilityTrackers() - => AttachedObject?._visibilityTrackers == null - ? new() - : AttachedObject._visibilityTrackers.Select(x => (ShapeVisibilityTracker)x).ToList(); - public List GetAttachedShapes() { if (AttachedObject == null) @@ -150,13 +157,16 @@ namespace QSB.QuantumSync.WorldObjects continue; } - var shapes = tracker._shapes; - totalShapes.AddRange(shapes); + // if the tracker is not active, this won't have been set, so just do it ourselves + tracker._shapes ??= tracker.GetComponents(); + totalShapes.AddRange(tracker._shapes.Where(x => x != null)); } return totalShapes; } + public void SetIsQuantum(bool isQuantum) => AttachedObject._isQuantum = isQuantum; + private void OnEnable(Shape s) { if (IsEnabled) @@ -209,5 +219,57 @@ namespace QSB.QuantumSync.WorldObjects // send event to other players that we're releasing authority ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(0u)); }); + + public override void DisplayLines() + { + if (AttachedObject == null) + { + return; + } + + var localPlayer = QSBPlayerManager.LocalPlayer; + + if (localPlayer == null) + { + return; + } + + var body = localPlayer.Body; + + if (body == null) + { + return; + } + + if (ControllingPlayer == 0) + { + if (IsEnabled) + { + Popcron.Gizmos.Line(AttachedObject.transform.position, + body.transform.position, + Color.magenta * 0.25f); + } + + return; + } + + var player = QSBPlayerManager.GetPlayer(ControllingPlayer); + + if (player == null) + { + return; + } + + var playerBody = player.Body; + + if (playerBody == null) + { + return; + } + + Popcron.Gizmos.Line(AttachedObject.transform.position, + playerBody.transform.position, + Color.magenta); + } } } diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumSkeletonTower.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumSkeletonTower.cs new file mode 100644 index 00000000..859be9d2 --- /dev/null +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumSkeletonTower.cs @@ -0,0 +1,18 @@ +namespace QSB.QuantumSync.WorldObjects +{ + internal class QSBQuantumSkeletonTower : QSBQuantumObject + { + public override string ReturnLabel() => $"{base.ReturnLabel()}\n" + + $"{AttachedObject._index} {AttachedObject._waitForPlayerToLookAtTower}\n" + + $"{AttachedObject._waitForFlicker} {AttachedObject._flickering}"; + + public void MoveSkeleton(int index) + { + AttachedObject._pointingSkeletons[index].gameObject.SetActive(false); + + AttachedObject._towerSkeletons[AttachedObject._index].SetActive(true); + AttachedObject._index++; + AttachedObject._waitForPlayerToLookAtTower = true; + } + } +} diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumSocket.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumSocket.cs index 23e7d857..eb8a4c19 100644 --- a/QSB/QuantumSync/WorldObjects/QSBQuantumSocket.cs +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumSocket.cs @@ -4,5 +4,6 @@ namespace QSB.QuantumSync.WorldObjects { internal class QSBQuantumSocket : WorldObject { + public override bool ShouldDisplayDebug() => false; } } diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumState.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumState.cs index c05ae8ac..287ce9e2 100644 --- a/QSB/QuantumSync/WorldObjects/QSBQuantumState.cs +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumState.cs @@ -11,5 +11,7 @@ namespace QSB.QuantumSync.WorldObjects IsMeantToBeEnabled = visible; AttachedObject.SetVisible(visible); } + + public override bool ShouldDisplayDebug() => false; } } diff --git a/QSB/SaveSync/Messages/GameStateMessage.cs b/QSB/SaveSync/Messages/GameStateMessage.cs index d0a49ea8..825e851c 100644 --- a/QSB/SaveSync/Messages/GameStateMessage.cs +++ b/QSB/SaveSync/Messages/GameStateMessage.cs @@ -31,6 +31,7 @@ namespace QSB.SaveSync.Messages KnownSignals = gameSave.knownSignals; } + public override void Serialize(QNetworkWriter writer) { base.Serialize(writer); @@ -46,10 +47,10 @@ namespace QSB.SaveSync.Messages } writer.Write(KnownSignals.Count); - foreach (var (key, value) in KnownSignals) + foreach (var (name, discovered) in KnownSignals) { - writer.Write(key); - writer.Write(value); + writer.Write(name); + writer.Write(discovered); } } diff --git a/QSB/SaveSync/Messages/RequestGameStateMessage.cs b/QSB/SaveSync/Messages/RequestGameStateMessage.cs index 479065e1..e8427a1f 100644 --- a/QSB/SaveSync/Messages/RequestGameStateMessage.cs +++ b/QSB/SaveSync/Messages/RequestGameStateMessage.cs @@ -1,4 +1,7 @@ -using QSB.Messaging; +using QSB.ConversationSync.Messages; +using QSB.ConversationSync.Patches; +using QSB.Messaging; +using System.Linq; namespace QSB.SaveSync.Messages { @@ -9,6 +12,24 @@ namespace QSB.SaveSync.Messages { public RequestGameStateMessage() => To = 0; - public override void OnReceiveRemote() => new GameStateMessage(From).Send(); + public override void OnReceiveRemote() + { + new GameStateMessage(From).Send(); + + var gameSave = StandaloneProfileManager.SharedInstance.currentProfileGameSave; + + var factSaves = gameSave.shipLogFactSaves; + foreach (var item in factSaves) + { + new ShipLogFactSaveMessage(item.Value).Send(); + } + + var dictConditions = gameSave.dictConditions; + var dictConditionsToSend = dictConditions.Where(x => ConversationPatches.PersistentConditionsToSync.Contains(x.Key)); + foreach (var item in dictConditionsToSend) + { + new PersistentConditionMessage(item.Key, item.Value).Send(); + } + } } } diff --git a/QSB/SaveSync/Messages/ShipLogFactSaveMessage.cs b/QSB/SaveSync/Messages/ShipLogFactSaveMessage.cs new file mode 100644 index 00000000..eb0c23dd --- /dev/null +++ b/QSB/SaveSync/Messages/ShipLogFactSaveMessage.cs @@ -0,0 +1,54 @@ +using QSB.Messaging; +using QuantumUNET.Transport; + +namespace QSB.SaveSync.Messages +{ + internal class ShipLogFactSaveMessage : QSBMessage + { + private string _id; + private int _revealOrder; + private bool _read; + private bool _newlyRevealed; + + public ShipLogFactSaveMessage(ShipLogFactSave save) + { + _id = save.id; + _revealOrder = save.revealOrder; + _read = save.read; + _newlyRevealed = save.newlyRevealed; + } + + public override void Serialize(QNetworkWriter writer) + { + base.Serialize(writer); + writer.Write(_id); + writer.Write(_revealOrder); + writer.Write(_read); + writer.Write(_newlyRevealed); + } + + public override void Deserialize(QNetworkReader reader) + { + base.Deserialize(reader); + _id = reader.ReadString(); + _revealOrder = reader.ReadInt32(); + _read = reader.ReadBoolean(); + _newlyRevealed = reader.ReadBoolean(); + } + + public override void OnReceiveRemote() + { + var save = PlayerData.GetShipLogFactSave(_id); + + if (save == null) + { + save = new ShipLogFactSave(_id); + PlayerData.AddShipLogFactSave(save); + } + + save.revealOrder = _revealOrder; + save.read = _read; + save.newlyRevealed = _newlyRevealed; + } + } +} diff --git a/QSB/ShipSync/ComponentType.cs b/QSB/ShipSync/ComponentType.cs deleted file mode 100644 index f0f7bf30..00000000 --- a/QSB/ShipSync/ComponentType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace QSB.ShipSync -{ - public enum ComponentType - { - None = 0, - Hull = 1, - Component = 2, - SatelliteNode = 3 - } -} diff --git a/QSB/ShipSync/Patches/ShipPatches.cs b/QSB/ShipSync/Patches/ShipPatches.cs index 14ca4f47..82b59962 100644 --- a/QSB/ShipSync/Patches/ShipPatches.cs +++ b/QSB/ShipSync/Patches/ShipPatches.cs @@ -8,7 +8,6 @@ using QSB.ShipSync.TransformSync; using QSB.ShipSync.WorldObjects; using QSB.Utility; using QSB.WorldSync; -using System; using UnityEngine; namespace QSB.ShipSync.Patches @@ -60,7 +59,7 @@ namespace QSB.ShipSync.Patches [HarmonyReversePatch] [HarmonyPatch(typeof(SingleInteractionVolume), nameof(SingleInteractionVolume.UpdateInteractVolume))] - public static void SingleInteractionVolume_UpdateInteractVolume_Stub(object instance) => throw new NotImplementedException(); + public static void SingleInteractionVolume_UpdateInteractVolume_Stub(object instance) { } [HarmonyPrefix] [HarmonyPatch(typeof(InteractZone), nameof(InteractZone.UpdateInteractVolume))] @@ -96,7 +95,7 @@ namespace QSB.ShipSync.Patches [HarmonyReversePatch] [HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.OnEnterShip))] - public static void ShipComponent_OnEnterShip_Stub(object instance) => throw new NotImplementedException(); + public static void ShipComponent_OnEnterShip_Stub(object instance) { } [HarmonyPrefix] [HarmonyPatch(typeof(ShipElectricalComponent), nameof(ShipElectricalComponent.OnEnterShip))] @@ -109,7 +108,7 @@ namespace QSB.ShipSync.Patches [HarmonyReversePatch] [HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.OnExitShip))] - public static void ShipComponent_OnExitShip_Stub(object instance) => throw new NotImplementedException(); + public static void ShipComponent_OnExitShip_Stub(object instance) { } [HarmonyPrefix] [HarmonyPatch(typeof(ShipElectricalComponent), nameof(ShipElectricalComponent.OnExitShip))] diff --git a/QSB/Syncs/Sectored/BaseSectoredSync.cs b/QSB/Syncs/Sectored/BaseSectoredSync.cs index 1b8e4e06..7a675a59 100644 --- a/QSB/Syncs/Sectored/BaseSectoredSync.cs +++ b/QSB/Syncs/Sectored/BaseSectoredSync.cs @@ -1,5 +1,4 @@ using OWML.Common; -using QSB.Player; using QSB.SectorSync; using QSB.SectorSync.WorldObjects; using QSB.Utility; @@ -127,6 +126,13 @@ namespace QSB.Syncs.Sectored { if (IsPlayerObject) { + if (Player == null) + { + // happens once right when you start hosting + writer.Write(-1); + return; + } + if (!Player.IsReady) { writer.Write(-1); diff --git a/QSB/Syncs/SyncBase.cs b/QSB/Syncs/SyncBase.cs index 701a3e76..3b645f86 100644 --- a/QSB/Syncs/SyncBase.cs +++ b/QSB/Syncs/SyncBase.cs @@ -57,7 +57,7 @@ namespace QSB.Syncs public T AttachedObject { get; set; } public Transform ReferenceTransform { get; set; } - public string LogName => $"{(IsPlayerObject ? Player.PlayerId : "")}.{NetId.Value}:{GetType().Name}"; + public string LogName => (IsPlayerObject ? $"{Player.PlayerId}." : string.Empty) + $"{NetId.Value}:{GetType().Name}"; protected virtual float DistanceLeeway { get; } = 5f; private float _previousDistance; protected const float SmoothTime = 0.1f; @@ -157,12 +157,20 @@ namespace QSB.Syncs return; } - if (ReferenceTransform != null && ReferenceTransform.position == Vector3.zero) + if (!AttachedObject.gameObject.activeInHierarchy && !IgnoreDisabledAttachedObject) { - DebugLog.ToConsole($"Warning - {LogName}'s ReferenceTransform is at (0,0,0). ReferenceTransform:{ReferenceTransform.name}, AttachedObject:{AttachedObject.name}", MessageType.Warning); + base.Update(); + return; + } + else + { + if (ReferenceTransform != null && ReferenceTransform.position == Vector3.zero && ReferenceTransform != Locator.GetRootTransform()) + { + DebugLog.ToConsole($"Warning - {LogName}'s ReferenceTransform is at (0,0,0). ReferenceTransform:{ReferenceTransform.name}, AttachedObject:{AttachedObject.name}", MessageType.Warning); + } } - if (!AttachedObject.gameObject.activeInHierarchy && !IgnoreDisabledAttachedObject) + if (ReferenceTransform == Locator.GetRootTransform()) { base.Update(); return; diff --git a/QSB/TimeSync/FastForwardReason.cs b/QSB/TimeSync/FastForwardReason.cs index a9a813ad..2d80cfcc 100644 --- a/QSB/TimeSync/FastForwardReason.cs +++ b/QSB/TimeSync/FastForwardReason.cs @@ -2,7 +2,6 @@ { public enum FastForwardReason { - None, TooFarBehind } } diff --git a/QSB/TimeSync/PauseReason.cs b/QSB/TimeSync/PauseReason.cs index 06e52ef0..d184a2d6 100644 --- a/QSB/TimeSync/PauseReason.cs +++ b/QSB/TimeSync/PauseReason.cs @@ -2,7 +2,6 @@ { public enum PauseReason { - None, TooFarAhead, ServerNotStarted, WaitingForAllPlayersToDie, diff --git a/QSB/TimeSync/TimeSyncType.cs b/QSB/TimeSync/TimeSyncType.cs index 41fdfb88..e1ed69fe 100644 --- a/QSB/TimeSync/TimeSyncType.cs +++ b/QSB/TimeSync/TimeSyncType.cs @@ -2,8 +2,8 @@ { public enum TimeSyncType { - None = 0, - Pausing = 1, - Fastforwarding = 2 + None, + Pausing, + FastForwarding } } \ No newline at end of file diff --git a/QSB/TimeSync/TimeSyncUI.cs b/QSB/TimeSync/TimeSyncUI.cs index d2ef1833..fbe3ae95 100644 --- a/QSB/TimeSync/TimeSyncUI.cs +++ b/QSB/TimeSync/TimeSyncUI.cs @@ -90,7 +90,7 @@ namespace QSB.TimeSync var text = ""; switch (_currentType) { - case TimeSyncType.Fastforwarding: + case TimeSyncType.FastForwarding: switch ((FastForwardReason)_currentReason) { case FastForwardReason.TooFarBehind: diff --git a/QSB/TimeSync/WakeUpSync.cs b/QSB/TimeSync/WakeUpSync.cs index 31b27ff9..96106408 100644 --- a/QSB/TimeSync/WakeUpSync.cs +++ b/QSB/TimeSync/WakeUpSync.cs @@ -192,7 +192,7 @@ namespace QSB.TimeSync OWTime.SetMaxDeltaTime(0.033333335f); OWTime.SetFixedTimestep(0.033333335f); TimeSyncUI.TargetTime = _serverTime; - TimeSyncUI.Start(TimeSyncType.Fastforwarding, FastForwardReason.TooFarBehind); + TimeSyncUI.Start(TimeSyncType.FastForwarding, FastForwardReason.TooFarBehind); } private void StartPausing(PauseReason reason) diff --git a/QSB/Tools/ProbeTool/ProbeEvent.cs b/QSB/Tools/ProbeTool/ProbeEvent.cs index 9ba4833b..bd627eb1 100644 --- a/QSB/Tools/ProbeTool/ProbeEvent.cs +++ b/QSB/Tools/ProbeTool/ProbeEvent.cs @@ -2,11 +2,11 @@ { public enum ProbeEvent { - Invalid = 0, - Launch = 1, - Anchor = 2, - Unanchor = 3, - Retrieve = 4, - Destroy = 5 + Invalid, + Launch, + Anchor, + Unanchor, + Retrieve, + Destroy } } \ No newline at end of file diff --git a/QSB/Tools/ToolType.cs b/QSB/Tools/ToolType.cs index 1b2c711e..a1e2a7ef 100644 --- a/QSB/Tools/ToolType.cs +++ b/QSB/Tools/ToolType.cs @@ -2,8 +2,8 @@ { public enum ToolType { - Signalscope = 0, - ProbeLauncher = 1, - Translator = 2 + Signalscope, + ProbeLauncher, + Translator } } \ No newline at end of file diff --git a/QSB/TriggerSync/Messages/TriggerMessage.cs b/QSB/TriggerSync/Messages/TriggerMessage.cs new file mode 100644 index 00000000..4f63d4d1 --- /dev/null +++ b/QSB/TriggerSync/Messages/TriggerMessage.cs @@ -0,0 +1,26 @@ +using QSB.Messaging; +using QSB.Player; +using QSB.TriggerSync.WorldObjects; + +namespace QSB.TriggerSync.Messages +{ + public class TriggerMessage : QSBBoolWorldObjectMessage + { + public TriggerMessage(bool entered) => Value = entered; + + public override void OnReceiveLocal() => OnReceiveRemote(); + + public override void OnReceiveRemote() + { + var player = QSBPlayerManager.GetPlayer(From); + if (Value) + { + WorldObject.Enter(player); + } + else + { + WorldObject.Exit(player); + } + } + } +} diff --git a/QSB/TriggerSync/Messages/TriggerResyncMessage.cs b/QSB/TriggerSync/Messages/TriggerResyncMessage.cs new file mode 100644 index 00000000..742fd6eb --- /dev/null +++ b/QSB/TriggerSync/Messages/TriggerResyncMessage.cs @@ -0,0 +1,52 @@ +using QSB.Messaging; +using QSB.Player; +using QSB.TriggerSync.WorldObjects; +using QSB.Utility; +using QuantumUNET.Transport; +using System.Collections.Generic; +using System.Linq; + +namespace QSB.TriggerSync.Messages +{ + /// + /// always sent by host + /// + public class TriggerResyncMessage : QSBWorldObjectMessage + { + private uint[] _playerIds; + + public TriggerResyncMessage(IEnumerable occupants) => + _playerIds = occupants.Select(x => x.PlayerId).ToArray(); + + public override void Serialize(QNetworkWriter writer) + { + base.Serialize(writer); + writer.Write(_playerIds.Length); + _playerIds.ForEach(writer.Write); + } + + public override void Deserialize(QNetworkReader reader) + { + base.Deserialize(reader); + _playerIds = new uint[reader.ReadInt32()]; + for (var i = 0; i < _playerIds.Length; i++) + { + _playerIds[i] = reader.ReadUInt32(); + } + } + + public override void OnReceiveRemote() + { + var serverOccupants = _playerIds.Select(QSBPlayerManager.GetPlayer).ToList(); + foreach (var added in serverOccupants.Except(WorldObject.Occupants)) + { + WorldObject.Enter(added); + } + + foreach (var removed in WorldObject.Occupants.Except(serverOccupants)) + { + WorldObject.Exit(removed); + } + } + } +} diff --git a/QSB/TriggerSync/TriggerManager.cs b/QSB/TriggerSync/TriggerManager.cs new file mode 100644 index 00000000..ec6bc137 --- /dev/null +++ b/QSB/TriggerSync/TriggerManager.cs @@ -0,0 +1,20 @@ +using QSB.TriggerSync.WorldObjects; +using QSB.WorldSync; + +namespace QSB.TriggerSync +{ + public class TriggerManager : WorldObjectManager + { + public override WorldObjectType WorldObjectType => WorldObjectType.Both; + + protected override void RebuildWorldObjects(OWScene scene) + { + QSBWorldSync.Init(x => x.playerTrackingZone); + QSBWorldSync.Init(x => x._watchPlayerVolume); + QSBWorldSync.Init(x => x._triggerVolume); + QSBWorldSync.Init(x => x._cageTrigger); + QSBWorldSync.Init(x => x._smokeSphereTrigger); + QSBWorldSync.Init(x => x._maskZoneTrigger); + } + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBCharacterTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBCharacterTrigger.cs new file mode 100644 index 00000000..271b213b --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBCharacterTrigger.cs @@ -0,0 +1,12 @@ +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBCharacterTrigger : QSBTrigger + { + public override void Init() + { + base.Init(); + AttachedObject.OnEntry -= TriggerOwner.OnZoneEntry; + AttachedObject.OnExit -= TriggerOwner.OnZoneExit; + } + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBEyeShuttleTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBEyeShuttleTrigger.cs new file mode 100644 index 00000000..d2e3a535 --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBEyeShuttleTrigger.cs @@ -0,0 +1,20 @@ +using QSB.Player; + +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBEyeShuttleTrigger : QSBTrigger + { + public override void Init() + { + base.Init(); + AttachedObject.OnEntry -= TriggerOwner.OnEnterShuttle; + AttachedObject.OnExit -= TriggerOwner.OnExitShuttle; + } + + protected override void OnEnter(PlayerInfo player) + => player.IsInEyeShuttle = true; + + protected override void OnExit(PlayerInfo player) + => player.IsInEyeShuttle = false; + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBInflationTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBInflationTrigger.cs new file mode 100644 index 00000000..9e79a503 --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBInflationTrigger.cs @@ -0,0 +1,98 @@ +using QSB.Player; +using QSB.Utility; +using UnityEngine; + +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBInflationTrigger : QSBTrigger + { + protected override string CompareTag => "PlayerCameraDetector"; + + public override void Init() + { + base.Init(); + AttachedObject.OnEntry -= TriggerOwner.OnEnterFogSphere; + } + + protected override void OnEnter(PlayerInfo player) + { + if (TriggerOwner._state != CosmicInflationController.State.ReadyToCollapse) + { + return; + } + + if (player == QSBPlayerManager.LocalPlayer) + { + AttachedObject.OnEntry -= OnEnterEvent; + + AttachedObject.SetTriggerActivation(false); + TriggerOwner._probeDestroyTrigger.SetTriggerActivation(false); + + DebugLog.DebugWrite("disable input, wait for other players to enter"); + + var repelVolume = (WhiteHoleFluidVolume)TriggerOwner._repelVolume; + repelVolume._flowSpeed = -repelVolume._flowSpeed; + repelVolume._massiveFlowSpeed = -repelVolume._massiveFlowSpeed; + repelVolume.SetVolumeActivation(true); + QSBPlayerManager.HideAllPlayers(); + + ReticleController.Hide(); + Locator.GetFlashlight().TurnOff(false); + Locator.GetPromptManager().SetPromptsVisible(false); + OWInput.ChangeInputMode(InputMode.None); + } + else + { + DebugLog.DebugWrite($"fade out player {player.PlayerId}"); + player.DitheringAnimator.SetVisible(false, 3); + } + + if (Occupants.Count == QSBPlayerManager.PlayerList.Count) + { + StartCollapse(); + } + } + + protected override void OnExit(PlayerInfo player) + { + // wait 1 frame for player to be removed + QSBCore.UnityEvents.FireOnNextUpdate(() => + { + if (QSBCore.IsInMultiplayer && Occupants.Count == QSBPlayerManager.PlayerList.Count) + { + StartCollapse(); + } + }); + } + + private void StartCollapse() + { + DebugLog.DebugWrite("fade in everyone, fog sphere collapse"); + + var repelVolume = (WhiteHoleFluidVolume)TriggerOwner._repelVolume; + repelVolume.SetVolumeActivation(false); + QSBPlayerManager.ShowAllPlayers(); + + TriggerOwner._state = CosmicInflationController.State.Collapsing; + TriggerOwner._stateChangeTime = Time.time; + TriggerOwner._collapseStartPos = TriggerOwner._possibilitySphereRoot.localPosition; + AttachedObject.SetTriggerActivation(false); + TriggerOwner._inflationLight.FadeTo(1f, 1f); + TriggerOwner._possibilitySphereController.OnCollapse(); + if (TriggerOwner._campsiteController.GetUseAltPostCollapseSocket()) + { + TriggerOwner._playerPostCollapseSocket = TriggerOwner._altPlayerPostCollapseSocket; + TriggerOwner._altTravelerToHidePostCollapse.SetActive(false); + } + + Locator.GetPlayerBody().SetPosition(TriggerOwner._playerPostCollapseSocket.position); + Locator.GetPlayerBody().SetRotation(TriggerOwner._playerPostCollapseSocket.rotation); + Locator.GetPlayerBody().SetVelocity(-TriggerOwner._playerPostCollapseSocket.forward); + Locator.GetPlayerTransform().GetRequiredComponent().LockOn(TriggerOwner._possibilitySphereRoot, 2f); + foreach (var particles in TriggerOwner._smokeSphereParticles) + { + particles.Stop(); + } + } + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBMaskZoneTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBMaskZoneTrigger.cs new file mode 100644 index 00000000..8e78422d --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBMaskZoneTrigger.cs @@ -0,0 +1,38 @@ +using QSB.Player; + +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBMaskZoneTrigger : QSBTrigger + { + public override void Init() + { + base.Init(); + AttachedObject.OnEntry -= TriggerOwner.OnEnterMaskZone; + AttachedObject.OnExit -= TriggerOwner.OnExitMaskZone; + } + + protected override void OnEnter(PlayerInfo player) + { + if (Occupants.Count == 1) + { + TriggerOwner._whiteSphere.SetActive(true); + TriggerOwner._groundSignal.SetSignalActivation(false); + TriggerOwner._skySignal.SetSignalActivation(true); + TriggerOwner._skeletonTower.SetIsQuantum(TriggerOwner._hasPlayerLookedAtSky); + TriggerOwner.enabled = true; + } + } + + protected override void OnExit(PlayerInfo player) + { + if (Occupants.Count == 0 && !TriggerOwner._shuttle.HasLaunched()) + { + TriggerOwner._whiteSphere.SetActive(false); + TriggerOwner._skeletonTower.SetIsQuantum(false); + TriggerOwner._groundSignal.SetSignalActivation(true); + TriggerOwner._skySignal.SetSignalActivation(false); + TriggerOwner.enabled = false; + } + } + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBShrineTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBShrineTrigger.cs new file mode 100644 index 00000000..61420721 --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBShrineTrigger.cs @@ -0,0 +1,11 @@ +using QSB.Player; + +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBShrineTrigger : QSBTrigger + { + protected override void OnEnter(PlayerInfo player) => player.IsInShrine = true; + + protected override void OnExit(PlayerInfo player) => player.IsInShrine = false; + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBSolanumTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBSolanumTrigger.cs new file mode 100644 index 00000000..5eb34e0d --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBSolanumTrigger.cs @@ -0,0 +1,12 @@ +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBSolanumTrigger : QSBTrigger + { + public override void Init() + { + base.Init(); + AttachedObject.OnEntry -= TriggerOwner.OnEnterWatchVolume; + AttachedObject.OnExit -= TriggerOwner.OnExitWatchVolume; + } + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBTrigger.cs new file mode 100644 index 00000000..33fad18e --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBTrigger.cs @@ -0,0 +1,106 @@ +using QSB.Messaging; +using QSB.Player; +using QSB.TriggerSync.Messages; +using QSB.WorldSync; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace QSB.TriggerSync.WorldObjects +{ + public interface IQSBTrigger : IWorldObject + { + List Occupants { get; } + + void Enter(PlayerInfo player); + + void Exit(PlayerInfo player); + } + + public abstract class QSBTrigger : WorldObject, IQSBTrigger + { + public TO TriggerOwner { get; init; } + + public List Occupants { get; } = new(); + + protected virtual string CompareTag => "PlayerDetector"; + + public override void Init() + { + AttachedObject.OnEntry += OnEnterEvent; + AttachedObject.OnExit += OnExitEvent; + + QSBPlayerManager.OnRemovePlayer += OnPlayerLeave; + + QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllObjectsReady, () => + { + if (AttachedObject._trackedObjects != null && AttachedObject._trackedObjects.Any(x => x.CompareTag(CompareTag))) + { + ((IQSBTrigger)this).SendMessage(new TriggerMessage(true)); + } + }); + } + + public override void OnRemoval() + { + AttachedObject.OnEntry -= OnEnterEvent; + AttachedObject.OnExit -= OnExitEvent; + + QSBPlayerManager.OnRemovePlayer -= OnPlayerLeave; + } + + protected void OnEnterEvent(GameObject hitObj) + { + if (hitObj.CompareTag(CompareTag)) + { + ((IQSBTrigger)this).SendMessage(new TriggerMessage(true)); + } + } + + protected void OnExitEvent(GameObject hitObj) + { + if (hitObj.CompareTag(CompareTag)) + { + ((IQSBTrigger)this).SendMessage(new TriggerMessage(false)); + } + } + + private void OnPlayerLeave(PlayerInfo player) + { + if (Occupants.Contains(player)) + { + Exit(player); + } + } + + public void Enter(PlayerInfo player) + { + if (!Occupants.SafeAdd(player)) + { + return; + } + + OnEnter(player); + } + + public void Exit(PlayerInfo player) + { + if (!Occupants.QuickRemove(player)) + { + return; + } + + OnExit(player); + } + + /// + /// called when a player enters this trigger + /// + protected virtual void OnEnter(PlayerInfo player) { } + + /// + /// called when a player exits this trigger or leaves the game + /// + protected virtual void OnExit(PlayerInfo player) { } + } +} diff --git a/QSB/TriggerSync/WorldObjects/QSBVesselCageTrigger.cs b/QSB/TriggerSync/WorldObjects/QSBVesselCageTrigger.cs new file mode 100644 index 00000000..12838e74 --- /dev/null +++ b/QSB/TriggerSync/WorldObjects/QSBVesselCageTrigger.cs @@ -0,0 +1,27 @@ +using QSB.Player; +using UnityEngine; + +namespace QSB.TriggerSync.WorldObjects +{ + public class QSBVesselCageTrigger : QSBTrigger + { + public override void Init() + { + base.Init(); + AttachedObject.OnExit -= TriggerOwner.OnExitCageTrigger; + } + + protected override void OnExit(PlayerInfo player) + { + if (Occupants.Count == 0 && TriggerOwner._hasPower) + { + TriggerOwner._cageClosed = true; + TriggerOwner._cageAnimator.TranslateToLocalPosition(new Vector3(0f, -8.1f, 0f), 5f); + TriggerOwner._cageAnimator.RotateToLocalEulerAngles(new Vector3(0f, 180f, 0f), 5f); + TriggerOwner._cageAnimator.OnTranslationComplete -= TriggerOwner.OnCageAnimationComplete; + TriggerOwner._cageAnimator.OnTranslationComplete += TriggerOwner.OnCageAnimationComplete; + TriggerOwner._cageLoopingAudio.FadeIn(1f); + } + } + } +} diff --git a/QSB/Utility/DebugActions.cs b/QSB/Utility/DebugActions.cs index 9ed0c9e0..4b6608d0 100644 --- a/QSB/Utility/DebugActions.cs +++ b/QSB/Utility/DebugActions.cs @@ -47,7 +47,7 @@ namespace QSB.Utility * 3 - Destroy probe * 4 - Damage ship electricals * 5 - Trigger supernova - * 6 - + * 6 - Set MET_SOLANUM * 7 - Warp to vessel * 8 - Place warp core into vessel * 9 - Load eye scene @@ -83,6 +83,14 @@ namespace QSB.Utility new DebugTriggerSupernovaMessage().Send(); } + if (Keyboard.current[Key.Numpad6].wasPressedThisFrame) + { + PlayerData.SetPersistentCondition("MET_SOLANUM", true); + PlayerData.SetPersistentCondition("MET_PRISONER", true); + DialogueConditionManager.SharedInstance.SetConditionState("MET_SOLANUM", true); + DialogueConditionManager.SharedInstance.SetConditionState("MET_PRISONER", true); + } + if (Keyboard.current[Key.Numpad7].wasPressedThisFrame) { GoToVessel(); @@ -95,8 +103,17 @@ namespace QSB.Utility if (Keyboard.current[Key.Numpad9].wasPressedThisFrame) { - PlayerData.SaveWarpedToTheEye(60); - LoadManager.LoadSceneAsync(OWScene.EyeOfTheUniverse, true, LoadManager.FadeType.ToWhite); + if (Keyboard.current[Key.LeftShift].isPressed) + { + PlayerData._currentGameSave.warpedToTheEye = false; + PlayerData.SaveCurrentGame(); + LoadManager.LoadSceneAsync(OWScene.SolarSystem, true, LoadManager.FadeType.ToBlack); + } + else + { + PlayerData.SaveWarpedToTheEye(60); + LoadManager.LoadSceneAsync(OWScene.EyeOfTheUniverse, true, LoadManager.FadeType.ToWhite); + } } } } diff --git a/QSB/Utility/DebugGUI.cs b/QSB/Utility/DebugGUI.cs index 9dae58b5..fc3d7324 100644 --- a/QSB/Utility/DebugGUI.cs +++ b/QSB/Utility/DebugGUI.cs @@ -251,6 +251,8 @@ namespace QSB.Utility DrawWorldObjectLabels(); } + public void OnRenderObject() => DrawWorldObjectLines(); + private static void DrawWorldObjectLabels() { if (!QSBCore.ShowDebugLabels) @@ -265,13 +267,34 @@ namespace QSB.Utility return; } - if (obj.ShouldDisplayLabel()) + if (obj.ShouldDisplayDebug()) { DrawLabel(obj.ReturnObject().transform, obj.ReturnLabel()); } } } + private static void DrawWorldObjectLines() + { + if (!QSBCore.ShowLinesInDebug) + { + return; + } + + foreach (var obj in QSBWorldSync.GetWorldObjects()) + { + if (obj.ReturnObject() == null) + { + return; + } + + if (obj.ShouldDisplayDebug()) + { + obj.DisplayLines(); + } + } + } + public static void DrawLabel(Transform obj, string label) { var camera = Locator.GetPlayerCamera(); diff --git a/QSB/Utility/DebugLog.cs b/QSB/Utility/DebugLog.cs index d5b38c70..c224f904 100644 --- a/QSB/Utility/DebugLog.cs +++ b/QSB/Utility/DebugLog.cs @@ -37,6 +37,6 @@ namespace QSB.Utility private static string GetCallingType(StackTrace frame) => frame.GetFrames()! .Select(x => x.GetMethod().DeclaringType!.Name) - .First(x => x == nameof(DebugLog)); + .First(x => x != nameof(DebugLog)); } } \ No newline at end of file diff --git a/QSB/WorldSync/IWorldObject.cs b/QSB/WorldSync/IWorldObject.cs index b815bd6d..7778aefa 100644 --- a/QSB/WorldSync/IWorldObject.cs +++ b/QSB/WorldSync/IWorldObject.cs @@ -9,7 +9,8 @@ namespace QSB.WorldSync void OnRemoval(); MonoBehaviour ReturnObject(); - bool ShouldDisplayLabel(); + bool ShouldDisplayDebug(); string ReturnLabel(); + void DisplayLines(); } } diff --git a/QSB/WorldSync/QSBWorldSync.cs b/QSB/WorldSync/QSBWorldSync.cs index 637bd847..dac20854 100644 --- a/QSB/WorldSync/QSBWorldSync.cs +++ b/QSB/WorldSync/QSBWorldSync.cs @@ -1,5 +1,7 @@ using OWML.Common; +using QSB.ConversationSync.Patches; using QSB.LogSync; +using QSB.TriggerSync.WorldObjects; using QSB.Utility; using System; using System.Collections.Generic; @@ -10,13 +12,53 @@ namespace QSB.WorldSync { public static class QSBWorldSync { - public static readonly List OldDialogueTrees = new(); - public static readonly Dictionary DialogueConditions = new(); - public static readonly List ShipLogFacts = new(); + public static List OldDialogueTrees { get; private set; } = new(); + public static Dictionary DialogueConditions { get; private set; } = new(); + public static Dictionary PersistentConditions { get; private set; } = new(); + public static List ShipLogFacts { get; private set; } = new(); private static readonly List WorldObjects = new(); private static readonly Dictionary WorldObjectsToUnityObjects = new(); + public static void Init() + { + DebugLog.DebugWrite($"Init QSBWorldSync", MessageType.Info); + + OldDialogueTrees.Clear(); + OldDialogueTrees.AddRange(GetUnityObjects()); + + if (!QSBCore.IsHost) + { + return; + } + + DebugLog.DebugWrite($"DIALOGUE CONDITIONS :"); + DialogueConditions = (Dictionary)DialogueConditionManager.SharedInstance._dictConditions; + foreach (var item in DialogueConditions) + { + DebugLog.DebugWrite($"- {item.Key}, {item.Value}"); + } + + DebugLog.DebugWrite($"PERSISTENT CONDITIONS :"); + var dictConditions = PlayerData._currentGameSave.dictConditions; + var syncedConditions = dictConditions.Where(x => ConversationPatches.PersistentConditionsToSync.Contains(x.Key)); + PersistentConditions = syncedConditions.ToDictionary(x => x.Key, x => x.Value); + foreach (var item in PersistentConditions) + { + DebugLog.DebugWrite($"- {item.Key}, {item.Value}"); + } + } + + public static void Reset() + { + DebugLog.DebugWrite($"Reset QSBWorldSync", MessageType.Info); + + OldDialogueTrees.Clear(); + DialogueConditions.Clear(); + PersistentConditions.Clear(); + ShipLogFacts.Clear(); + } + public static IEnumerable GetWorldObjects() => WorldObjects; public static IEnumerable GetWorldObjects() @@ -122,11 +164,33 @@ namespace QSB.WorldSync { //DebugLog.DebugWrite($"{typeof(TWorldObject).Name} init : {listToInitFrom.Count()} instances.", MessageType.Info); foreach (var item in listToInitFrom) + { + var obj = new TWorldObject + { + AttachedObject = item, + ObjectId = WorldObjects.Count + }; + + obj.Init(); + WorldObjects.Add(obj); + WorldObjectsToUnityObjects.Add(item, obj); + } + } + + public static void Init(Func triggerSelector) + where TWorldObject : QSBTrigger, new() + where TUnityObject : MonoBehaviour + { + var list = GetUnityObjects() + .Select(x => (triggerSelector(x), x)) + .Where(x => x.Item1); + foreach (var (item, owner) in list) { var obj = new TWorldObject { AttachedObject = item, ObjectId = WorldObjects.Count, + TriggerOwner = owner }; obj.Init(); @@ -139,13 +203,24 @@ namespace QSB.WorldSync { if (!QSBCore.IsHost) { - DebugLog.ToConsole("Warning - Cannot write to condition dict when not server!", MessageType.Warning); + DebugLog.ToConsole("Warning - Cannot write to dialogue condition dict when not server!", MessageType.Warning); return; } DialogueConditions[name] = state; } + public static void SetPersistentCondition(string name, bool state) + { + if (!QSBCore.IsHost) + { + DebugLog.ToConsole("Warning - Cannot write to persistent condition dict when not server!", MessageType.Warning); + return; + } + + PersistentConditions[name] = state; + } + public static void AddFactReveal(string id, bool saveGame) { if (!QSBCore.IsHost) diff --git a/QSB/WorldSync/WorldObject.cs b/QSB/WorldSync/WorldObject.cs index d079c9ed..5ad5e041 100644 --- a/QSB/WorldSync/WorldObject.cs +++ b/QSB/WorldSync/WorldObject.cs @@ -9,13 +9,14 @@ namespace QSB.WorldSync public int ObjectId { get; init; } public T AttachedObject { get; init; } public string Name => AttachedObject == null ? "" : AttachedObject.name; - public string LogName => $"{QSBPlayerManager.LocalPlayerId}.{ObjectId}:{GetType().Name}"; + public string LogName => $"{QSBPlayerManager.LocalPlayerId}.{ObjectId}:{GetType().Name} ({Name})"; public virtual void Init() { } public virtual void OnRemoval() { } public MonoBehaviour ReturnObject() => AttachedObject; - public virtual bool ShouldDisplayLabel() => true; + public virtual bool ShouldDisplayDebug() => AttachedObject != null && AttachedObject.gameObject.activeInHierarchy; public virtual string ReturnLabel() => LogName; + public virtual void DisplayLines() { } /// indicates that this won't become ready immediately protected void StartDelayedReady() => WorldObjectManager._numObjectsReadying++; diff --git a/QSB/WorldSync/WorldObjectManager.cs b/QSB/WorldSync/WorldObjectManager.cs index f0e6c0f3..94f38606 100644 --- a/QSB/WorldSync/WorldObjectManager.cs +++ b/QSB/WorldSync/WorldObjectManager.cs @@ -1,5 +1,6 @@ using OWML.Common; using QSB.Player; +using QSB.Player.TransformSync; using QSB.Utility; using System; using System.Collections.Generic; @@ -66,10 +67,10 @@ namespace QSB.WorldSync return; } - if (QSBPlayerManager.LocalPlayerId == uint.MaxValue) + if (PlayerTransformSync.LocalInstance == null) { DebugLog.ToConsole($"Warning - Tried to rebuild WorldObjects when LocalPlayer is not ready! Building when ready...", MessageType.Warning); - QSBCore.UnityEvents.RunWhen(() => QSBPlayerManager.LocalPlayerId != uint.MaxValue, () => Rebuild(scene)); + QSBCore.UnityEvents.RunWhen(() => PlayerTransformSync.LocalInstance, () => Rebuild(scene)); return; } diff --git a/QSB/manifest.json b/QSB/manifest.json index b1d99183..e694ff9d 100644 --- a/QSB/manifest.json +++ b/QSB/manifest.json @@ -8,6 +8,6 @@ }, "uniqueName": "Raicuparta.QuantumSpaceBuddies", "version": "0.15.0", - "owmlVersion": "2.2.0", + "owmlVersion": "2.3.1", "dependencies": [ "_nebula.MenuFramework" ] } diff --git a/QSBTests/MessageTests.cs b/QSBTests/MessageTests.cs index 4eefe65f..9dfe3233 100644 --- a/QSBTests/MessageTests.cs +++ b/QSBTests/MessageTests.cs @@ -2,6 +2,7 @@ using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; +using MonoMod.Cil; using QSB.Messaging; using QSB.Utility; using System; @@ -34,7 +35,7 @@ namespace QSBTests foreach (var field in fields) { - if (!field.Eq(fromField) && !field.Eq(toField) && !field.Eq(objectIdField)) + if (!field.GenericEq(fromField) && !field.GenericEq(toField) && !field.GenericEq(objectIdField)) { constructor.CheckUses(field, Util.UseType.Store); } @@ -46,60 +47,45 @@ namespace QSBTests } } - internal static class Util + public static partial class Util { public const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - public static bool Eq(this MemberReference a, MemberReference b) => + /// + /// ignores open vs closed generic type + /// + public static bool GenericEq(this MemberReference a, MemberReference b) => a.DeclaringType.Namespace == b.DeclaringType.Namespace && a.DeclaringType.Name == b.DeclaringType.Name && a.Name == b.Name; - public static bool IsOp(this Instruction instruction, OpCode opCode, out T operand) - { - if (instruction.OpCode == opCode) - { - operand = (T)instruction.Operand; - return true; - } - - operand = default; - return false; - } - - public enum UseType { Store, Load }; + public enum UseType { Store, Load } public static void CheckUses(this MethodDefinition method, FieldReference field, UseType useType) { - var opCode = useType switch + Func matches = useType switch { - UseType.Store => OpCodes.Stfld, - UseType.Load => OpCodes.Ldfld, + UseType.Store => x => x.MatchStfld(out var f) && f.GenericEq(field), + UseType.Load => x => x.MatchLdfld(out var f) && f.GenericEq(field), _ => throw new ArgumentOutOfRangeException(nameof(useType), useType, null) }; while (true) { var il = method.Body.Instructions; - var uses = il.Any(x => - x.IsOp(opCode, out FieldReference f) && - f.Eq(field) - ); + var uses = il.Any(matches); if (uses) { return; } var baseMethod = method.GetBaseMethod(); - if (baseMethod.Eq(method)) + if (baseMethod == method) { break; } - var callsBase = il.Any(x => - x.IsOp(OpCodes.Call, out MethodReference m) && - m.Eq(baseMethod) - ); + var callsBase = il.Any(x => x.MatchCall(out var m) && m.GenericEq(baseMethod)); if (!callsBase) { break; diff --git a/QSBTests/QSBTests.csproj b/QSBTests/QSBTests.csproj index ad94ca53..87c9ec81 100644 --- a/QSBTests/QSBTests.csproj +++ b/QSBTests/QSBTests.csproj @@ -19,12 +19,12 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/QuantumUNET/QNetworkServerSimple.cs b/QuantumUNET/QNetworkServerSimple.cs index fe94ce6f..94abc133 100644 --- a/QuantumUNET/QNetworkServerSimple.cs +++ b/QuantumUNET/QNetworkServerSimple.cs @@ -153,10 +153,6 @@ namespace QuantumUNET do { networkEventType = NetworkTransport.ReceiveFromHost(serverHostId, out var connectionId, out var channelId, messageBuffer, messageBuffer.Length, out var receivedSize, out var b); - if (networkEventType != NetworkEventType.Nothing) - { - Debug.Log($"Server event: host={serverHostId} event={networkEventType} error={b}"); - } switch (networkEventType) { diff --git a/QuantumUNET/QuantumUNET.csproj b/QuantumUNET/QuantumUNET.csproj index 79e0422b..c0bce768 100644 --- a/QuantumUNET/QuantumUNET.csproj +++ b/QuantumUNET/QuantumUNET.csproj @@ -13,7 +13,7 @@ pdbonly - + \ No newline at end of file