From 11c167dd6a7fb37e63d9f9f1b33c61e43bae3332 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Sun, 8 Aug 2021 19:59:40 +0100 Subject: [PATCH] add server state --- .../Events/ServerStateEvent.cs | 30 +++++ QSB/ClientServerStateSync/ServerState.cs | 26 ++++ .../ServerStateManager.cs | 126 ++++++++++++++++++ QSB/Events/EventNames.cs | 1 + QSB/Events/EventType.cs | 1 + QSB/Events/QSBEventManager.cs | 1 + QSB/QSB.csproj | 3 + QSB/QSBNetworkManager.cs | 1 + 8 files changed, 189 insertions(+) create mode 100644 QSB/ClientServerStateSync/Events/ServerStateEvent.cs create mode 100644 QSB/ClientServerStateSync/ServerState.cs create mode 100644 QSB/ClientServerStateSync/ServerStateManager.cs diff --git a/QSB/ClientServerStateSync/Events/ServerStateEvent.cs b/QSB/ClientServerStateSync/Events/ServerStateEvent.cs new file mode 100644 index 00000000..e93d7af8 --- /dev/null +++ b/QSB/ClientServerStateSync/Events/ServerStateEvent.cs @@ -0,0 +1,30 @@ +using QSB.Events; +using QSB.Messaging; + +namespace QSB.ClientServerStateSync.Events +{ + internal class ServerStateEvent : QSBEvent> + { + public override EventType Type => EventType.ServerState; + + public override void SetupListener() + => GlobalMessenger.AddListener(EventNames.QSBServerState, Handler); + + public override void CloseListener() + => GlobalMessenger.RemoveListener(EventNames.QSBServerState, Handler); + + private void Handler(ServerState state) => SendEvent(CreateMessage(state)); + + private EnumMessage CreateMessage(ServerState state) => new EnumMessage + { + AboutId = LocalPlayerId, + EnumValue = state + }; + + public override void OnReceiveLocal(bool server, EnumMessage message) + => OnReceiveRemote(server, message); + + public override void OnReceiveRemote(bool server, EnumMessage message) + => ServerStateManager.Instance.ChangeServerState(message.EnumValue); + } +} diff --git a/QSB/ClientServerStateSync/ServerState.cs b/QSB/ClientServerStateSync/ServerState.cs new file mode 100644 index 00000000..f2d1d91c --- /dev/null +++ b/QSB/ClientServerStateSync/ServerState.cs @@ -0,0 +1,26 @@ +namespace QSB.ClientServerStateSync +{ + public enum ServerState + { + // When in menus + NotLoaded, + + // When in any credits + Credits, + + // For normal play in SolarSystem + InSolarSystem, + + // For normal play in EyeOfTheUniverse + InEye, + + // At end of loop, waiting for everyone to be ready to reload the scene + WaitingForDeath, + + // At start of loop, waiting for everybody to be ready to start playing + AwaitingPlayConfirmation, + + // When the statue has been activated + InStatueCutscene + } +} diff --git a/QSB/ClientServerStateSync/ServerStateManager.cs b/QSB/ClientServerStateSync/ServerStateManager.cs new file mode 100644 index 00000000..4481ab45 --- /dev/null +++ b/QSB/ClientServerStateSync/ServerStateManager.cs @@ -0,0 +1,126 @@ +using QSB.Events; +using QSB.Player; +using QSB.Player.TransformSync; +using QSB.Utility; +using System.Linq; +using UnityEngine; + +namespace QSB.ClientServerStateSync +{ + class ServerStateManager : MonoBehaviour + { + public static ServerStateManager Instance { get; private set; } + + public event ChangeStateEvent OnChangeState; + public delegate void ChangeStateEvent(ServerState newState); + + private ServerState _currentState; + + private void Awake() + => Instance = this; + + private void Start() + { + if (!QSBCore.IsHost) + { + return; + } + QSBSceneManager.OnSceneLoaded += OnSceneLoaded; + GlobalMessenger.AddListener("TriggerSupernova", OnTriggerSupernova); + + QSBCore.UnityEvents.RunWhen(() => PlayerTransformSync.LocalInstance != null, () => QSBEventManager.FireEvent(EventNames.QSBServerState, ForceGetCurrentState())); + } + + public void ChangeServerState(ServerState newState) + { + if (_currentState == newState) + { + return; + } + DebugLog.DebugWrite($"CHANGE SERVER STATE FROM {_currentState} to {newState}"); + _currentState = newState; + OnChangeState?.Invoke(newState); + } + + public ServerState GetServerState() + => _currentState; + + private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool inUniverse) + { + switch (newScene) + { + case OWScene.Credits_Fast: + case OWScene.Credits_Final: + case OWScene.PostCreditsScene: + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.Credits); + break; + + case OWScene.TitleScreen: + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.NotLoaded); + break; + + case OWScene.SolarSystem: + if (oldScene == OWScene.SolarSystem) + { + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.AwaitingPlayConfirmation); + } + else + { + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.InSolarSystem); + } + break; + + case OWScene.EyeOfTheUniverse: + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.AwaitingPlayConfirmation); + break; + + case OWScene.None: + case OWScene.Undefined: + default: + DebugLog.ToConsole($"Warning - newScene is {newScene}!", OWML.Common.MessageType.Warning); + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.NotLoaded); + break; + } + } + + private void OnTriggerSupernova() + { + DebugLog.DebugWrite($"TriggerSupernova"); + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForDeath); + } + + private ServerState ForceGetCurrentState() + { + var currentScene = LoadManager.GetCurrentScene(); + var lastScene = LoadManager.GetPreviousScene(); + + switch (currentScene) + { + case OWScene.SolarSystem: + return ServerState.InSolarSystem; + case OWScene.EyeOfTheUniverse: + return ServerState.InEye; + default: + return ServerState.NotLoaded; + } + } + + private void Update() + { + if (!QSBCore.IsHost) + { + return; + } + + if (_currentState == ServerState.AwaitingPlayConfirmation) + { + if (QSBPlayerManager.PlayerList.All(x => x.State == ClientState.WaitingForOthersToReadyInSolarSystem)) + { + DebugLog.DebugWrite($"All ready!!"); + QSBEventManager.FireEvent(EventNames.QSBStartLoop); + QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.InSolarSystem); + } + } + } + } +} diff --git a/QSB/Events/EventNames.cs b/QSB/Events/EventNames.cs index adf307e3..f101776b 100644 --- a/QSB/Events/EventNames.cs +++ b/QSB/Events/EventNames.cs @@ -83,6 +83,7 @@ public static string QSBLaunchProbe = "QSBLaunchProbe"; public static string QSBPlayerLaunchProbe = "QSBPlayerLaunchProbe"; public static string QSBEndLoop = "QSBEndLoop"; + public static string QSBServerState = "QSBServerState"; public static string QSBClientState = "QSBClientState"; } } \ No newline at end of file diff --git a/QSB/Events/EventType.cs b/QSB/Events/EventType.cs index b2cdd081..ac4c9feb 100644 --- a/QSB/Events/EventType.cs +++ b/QSB/Events/EventType.cs @@ -6,6 +6,7 @@ ServerTime, StartStatue, EndLoop, + ServerState, ClientState, /* diff --git a/QSB/Events/QSBEventManager.cs b/QSB/Events/QSBEventManager.cs index 825dcac3..5816f8d9 100644 --- a/QSB/Events/QSBEventManager.cs +++ b/QSB/Events/QSBEventManager.cs @@ -64,6 +64,7 @@ namespace QSB.Events new PlayerRetrieveProbeEvent(), new PlayerLaunchProbeEvent(), new EndLoopEvent(), + new ServerStateEvent(), new ClientStateEvent(), // World Objects new ElevatorEvent(), diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj index c0aa3516..485d456f 100644 --- a/QSB/QSB.csproj +++ b/QSB/QSB.csproj @@ -256,6 +256,9 @@ + + + diff --git a/QSB/QSBNetworkManager.cs b/QSB/QSBNetworkManager.cs index e0cc0878..f724f998 100644 --- a/QSB/QSBNetworkManager.cs +++ b/QSB/QSBNetworkManager.cs @@ -152,6 +152,7 @@ namespace QSB QSBEventManager.Init(); gameObject.AddComponent(); + gameObject.AddComponent(); gameObject.AddComponent(); if (QSBSceneManager.IsInUniverse)