quantum-space-buddies/QSB/TimeSync/WakeUpSync.cs

463 lines
11 KiB
C#
Raw Normal View History

using Mirror;
using OWML.Common;
2021-08-09 10:49:58 +00:00
using QSB.ClientServerStateSync;
using QSB.ClientServerStateSync.Messages;
2021-02-10 19:34:41 +00:00
using QSB.DeathSync;
2021-06-11 13:34:27 +00:00
using QSB.Inputs;
2021-12-24 01:07:29 +00:00
using QSB.Messaging;
using QSB.Player;
2021-12-24 01:07:29 +00:00
using QSB.Player.Messages;
using QSB.TimeSync.Messages;
using QSB.TimeSync.Patches;
2021-02-10 19:34:41 +00:00
using QSB.Utility;
using QSB.WorldSync;
using System;
2021-08-09 10:49:58 +00:00
using UnityEngine;
2022-03-03 03:46:33 +00:00
namespace QSB.TimeSync;
2020-12-02 21:29:53 +00:00
2023-03-09 16:02:05 +00:00
public class WakeUpSync : MonoBehaviour, IAddComponentOnStart
2022-03-03 03:46:33 +00:00
{
public static WakeUpSync LocalInstance { get; private set; }
2020-12-03 08:28:05 +00:00
2022-03-03 03:46:33 +00:00
private const float PauseOrFastForwardThreshold = 1.0f;
private const float TimescaleBounds = 0.3f;
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
private const float MaxFastForwardSpeed = 60f;
private const float MaxFastForwardDiff = 20f;
private const float MinFastForwardSpeed = 2f;
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
public enum State { NotLoaded, Loaded, FastForwarding, Pausing }
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
public State CurrentState { get; private set; } = State.NotLoaded;
public Enum CurrentReason { get; private set; }
2021-11-11 19:34:25 +00:00
2022-03-03 03:46:33 +00:00
private float _sendTimer;
private float _serverTime;
private int _serverLoopCount;
2023-04-26 21:10:11 +00:00
public bool HasWokenUp;
2021-11-11 19:34:25 +00:00
2022-03-03 03:46:33 +00:00
public void OnDisconnect()
{
OWTime.SetTimeScale(1f);
OWTime.SetMaxDeltaTime(0.06666667f);
Locator.GetActiveCamera().enabled = true;
CurrentState = State.NotLoaded;
CurrentReason = null;
Physics.SyncTransforms();
SpinnerUI.Hide();
TimeSyncUI.Stop();
QSBInputManager.Instance.SetInputsEnabled(true);
}
2022-03-03 03:46:33 +00:00
public void Start()
{
if (QSBSceneManager.IsInUniverse)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
Init();
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
2021-06-18 21:38:32 +00:00
2022-03-03 03:46:33 +00:00
GlobalMessenger.AddListener(OWEvents.WakeUp, OnWakeUp);
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
public float GetTimeDifference()
{
2024-05-05 19:19:10 +00:00
if (QSBCore.IsHost)
{
return 0f;
}
var myTime = Time.timeSinceLevelLoad;
2022-03-03 03:46:33 +00:00
return myTime - _serverTime;
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
private void OnWakeUp()
{
DebugLog.DebugWrite($"OnWakeUp", MessageType.Info);
if (QSBCore.IsHost)
2021-03-25 23:07:53 +00:00
{
2023-04-26 21:10:11 +00:00
new ServerStateMessage(ServerState.InSolarSystem).Send();
2022-03-03 03:46:33 +00:00
RespawnOnDeath.Instance.Init();
2021-03-25 23:07:53 +00:00
}
2023-04-26 21:10:11 +00:00
HasWokenUp = true;
2022-03-03 03:46:33 +00:00
}
public void OnDestroy()
{
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
GlobalMessenger.RemoveListener(OWEvents.WakeUp, OnWakeUp);
}
private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isInUniverse)
{
2023-04-26 21:10:11 +00:00
HasWokenUp = false;
2022-03-03 03:46:33 +00:00
if (isInUniverse)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
if (newScene == OWScene.EyeOfTheUniverse)
2020-12-02 21:29:53 +00:00
{
2023-04-26 21:10:11 +00:00
HasWokenUp = true;
2020-12-02 21:29:53 +00:00
}
2021-06-18 21:38:32 +00:00
2023-03-09 16:38:17 +00:00
LocalInstance = this;
2022-03-03 03:46:33 +00:00
Init();
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
else
2020-12-02 21:29:53 +00:00
{
2023-03-09 16:38:17 +00:00
LocalInstance = null;
2022-03-03 03:46:33 +00:00
CurrentState = State.NotLoaded;
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
private void Init()
{
new RequestStateResyncMessage().Send();
CurrentState = State.Loaded;
2023-03-09 16:02:05 +00:00
if (QSBCore.IsHost)
2020-12-02 21:29:53 +00:00
{
2024-05-05 19:19:10 +00:00
_serverTime = Time.timeSinceLevelLoad;
2022-03-03 03:46:33 +00:00
SendServerTime();
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
else
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
if (!QSBCore.DebugSettings.AvoidTimeSync)
{
2022-03-03 03:46:33 +00:00
WakeUpOrSleep();
2020-12-02 21:29:53 +00:00
}
else
{
// dont bother sleeping, just wake up
2023-04-26 21:10:11 +00:00
if (!HasWokenUp)
{
Delay.RunWhen(() => QSBWorldSync.AllObjectsReady, WakeUp);
}
}
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
private void SendServerTime()
2022-08-14 23:35:19 +00:00
=> new ServerTimeMessage(_serverTime, PlayerData.LoadLoopCount(), TimeLoop.GetSecondsRemaining()).Send();
2020-12-02 21:29:53 +00:00
2022-08-14 23:35:19 +00:00
public void OnClientReceiveMessage(float time, int count, float secondsRemaining)
2022-03-03 03:46:33 +00:00
{
_serverTime = time;
_serverLoopCount = count;
// prevents accidental supernova at start of loop
if (_serverLoopCount == PlayerData.LoadLoopCount())
{
2022-08-29 05:21:20 +00:00
TimeLoop.SetSecondsRemaining(secondsRemaining);
}
2022-03-03 03:46:33 +00:00
}
private void WakeUpOrSleep()
{
if (CurrentState == State.NotLoaded)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
return;
2020-12-02 21:29:53 +00:00
}
2023-03-09 16:02:05 +00:00
if (PlayerData.LoadLoopCount() != _serverLoopCount && !QSBCore.IsHost)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
DebugLog.ToConsole($"Warning - ServerLoopCount is not the same as local loop count! local:{PlayerData.LoadLoopCount()} server:{_serverLoopCount}");
return;
}
2021-06-11 13:34:27 +00:00
2024-05-05 19:19:10 +00:00
var diff = GetTimeDifference();
if (ServerStateManager.Instance.GetServerState() is not (ServerState.InSolarSystem or ServerState.InEye))
2022-03-03 03:46:33 +00:00
{
return;
}
2021-06-11 13:34:27 +00:00
2022-03-03 03:46:33 +00:00
if (diff > PauseOrFastForwardThreshold)
{
2022-03-03 03:46:33 +00:00
StartPausing(PauseReason.TooFarAhead);
}
else if (diff < -PauseOrFastForwardThreshold)
2022-03-03 03:46:33 +00:00
{
StartFastForwarding(FastForwardReason.TooFarBehind);
}
else
{
// should only happen from Init so we gotta wait
2023-04-26 21:10:11 +00:00
if (!HasWokenUp)
{
Delay.RunWhen(() => QSBWorldSync.AllObjectsReady, WakeUp);
}
}
2022-03-03 03:46:33 +00:00
}
2022-03-03 03:46:33 +00:00
private void StartFastForwarding(FastForwardReason reason)
{
2024-05-05 19:19:10 +00:00
if (QSBCore.IsHost)
{
DebugLog.ToConsole($"Tried to fast-forward as server??? What???? _serverTime = {_serverTime}, GetTimeDifference() = {GetTimeDifference()}", MessageType.Error);
return;
}
2022-03-03 03:46:33 +00:00
if (CurrentState == State.FastForwarding)
{
2020-12-19 19:06:13 +00:00
TimeSyncUI.TargetTime = _serverTime;
2022-03-03 03:46:33 +00:00
return;
2020-12-02 21:29:53 +00:00
}
DebugLog.DebugWrite($"START FASTFORWARD (Target:{_serverTime} Current:{Time.timeSinceLevelLoad})", MessageType.Info);
2022-03-03 03:46:33 +00:00
if (Locator.GetActiveCamera() != null)
2020-12-02 21:29:53 +00:00
{
Locator.GetActiveCamera().enabled = false;
2022-03-03 03:46:33 +00:00
}
2021-06-11 13:34:27 +00:00
2022-03-03 03:46:33 +00:00
//OWInput.ChangeInputMode(InputMode.None);
QSBInputManager.Instance.SetInputsEnabled(false);
2022-03-03 03:46:33 +00:00
CurrentState = State.FastForwarding;
CurrentReason = reason;
OWTime.SetMaxDeltaTime(0.033333335f);
TimeSyncUI.TargetTime = _serverTime;
TimeSyncUI.Start(TimeSyncType.FastForwarding, reason);
}
private void StartPausing(PauseReason reason)
{
if (CurrentState == State.Pausing)
{
2022-01-23 03:14:37 +00:00
TimeSyncUI.TargetTime = _serverTime;
2022-03-03 03:46:33 +00:00
return;
2020-12-02 21:29:53 +00:00
}
DebugLog.DebugWrite($"START PAUSING (Target:{_serverTime} Current:{Time.timeSinceLevelLoad})", MessageType.Info);
2022-03-03 03:46:33 +00:00
Locator.GetActiveCamera().enabled = false;
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
//OWInput.ChangeInputMode(InputMode.None);
QSBInputManager.Instance.SetInputsEnabled(false);
2022-03-03 03:46:33 +00:00
OWTime.SetTimeScale(0f);
CurrentState = State.Pausing;
CurrentReason = reason;
SpinnerUI.Show();
TimeSyncUI.TargetTime = _serverTime;
TimeSyncUI.Start(TimeSyncType.Pausing, reason);
}
2022-03-03 03:46:33 +00:00
private void ResetTimeScale()
{
OWTime.SetTimeScale(1f);
OWTime.SetMaxDeltaTime(0.06666667f);
Locator.GetActiveCamera().enabled = true;
CurrentState = State.Loaded;
CurrentReason = null;
DebugLog.DebugWrite($"RESET TIMESCALE", MessageType.Info);
Physics.SyncTransforms();
SpinnerUI.Hide();
TimeSyncUI.Stop();
new RequestStateResyncMessage().Send();
RespawnOnDeath.Instance.Init();
QSBInputManager.Instance.SetInputsEnabled(true);
2023-04-26 21:10:11 +00:00
if (!HasWokenUp)
2022-03-03 03:46:33 +00:00
{
WakeUp();
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
private void WakeUp()
=> Locator.GetPlayerCamera().GetComponent<PlayerCameraEffectController>().WakeUp();
2022-03-03 03:46:33 +00:00
public void Update()
{
2023-03-09 16:02:05 +00:00
if (QSBCore.IsHost)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
UpdateServer();
2020-12-02 21:29:53 +00:00
}
2023-03-09 16:38:17 +00:00
else if (NetworkClient.active && QSBSceneManager.IsInUniverse && !QSBCore.DebugSettings.AvoidTimeSync)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
UpdateClient();
}
}
2021-11-24 22:16:56 +00:00
2022-03-03 03:46:33 +00:00
private void UpdateServer()
{
_serverTime = Time.timeSinceLevelLoad;
2022-03-03 03:46:33 +00:00
if (ServerStateManager.Instance == null)
{
return;
}
2022-03-03 03:46:33 +00:00
if (QSBPlayerManager.LocalPlayer == null)
{
return;
}
2022-03-03 03:46:33 +00:00
var serverState = ServerStateManager.Instance.GetServerState();
var clientState = QSBPlayerManager.LocalPlayer.State;
2021-10-25 15:31:15 +00:00
2022-03-03 03:46:33 +00:00
if (serverState == ServerState.WaitingForAllPlayersToReady && clientState == ClientState.WaitingForOthersToBeReady)
{
if (CurrentState != State.Pausing)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
StartPausing(PauseReason.WaitingForAllPlayersToBeReady);
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
if (CurrentState == State.Pausing && (PauseReason)CurrentReason == PauseReason.WaitingForAllPlayersToBeReady)
{
2022-08-05 19:01:55 +00:00
if ((clientState == ClientState.AliveInSolarSystem && serverState == ServerState.InSolarSystem) ||
(clientState == ClientState.AliveInEye && serverState == ServerState.InEye))
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
ResetTimeScale();
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
if (serverState == ServerState.WaitingForAllPlayersToDie && clientState == ClientState.WaitingForOthersToBeReady)
{
if (CurrentState == State.Pausing && (PauseReason)CurrentReason == PauseReason.WaitingForAllPlayersToBeReady)
{
2022-03-03 03:46:33 +00:00
//?
DebugLog.ToConsole($"Warning - Server waiting for players to die, but players waiting for ready signal! Assume players correct.", MessageType.Warning);
new ServerStateMessage(ServerState.WaitingForAllPlayersToReady).Send();
}
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
if (CurrentState != State.Loaded)
{
2022-03-03 03:46:33 +00:00
return;
}
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
_sendTimer += Time.unscaledDeltaTime;
if (_sendTimer > 1)
{
SendServerTime();
_sendTimer = 0;
}
}
2022-03-03 03:46:33 +00:00
private void UpdateClient()
{
_serverTime += Time.unscaledDeltaTime;
2022-01-23 03:14:37 +00:00
2022-03-03 03:46:33 +00:00
var serverState = ServerStateManager.Instance.GetServerState();
var clientState = QSBPlayerManager.LocalPlayer.State;
var currentScene = QSBSceneManager.CurrentScene;
2021-07-29 22:44:59 +00:00
2022-03-03 03:46:33 +00:00
// set fastforwarding timescale
2022-03-03 03:46:33 +00:00
if (CurrentState == State.FastForwarding && (FastForwardReason)CurrentReason == FastForwardReason.TooFarBehind)
{
if (Locator.GetPlayerCamera() != null && !Locator.GetPlayerCamera().enabled)
{
2022-03-03 03:46:33 +00:00
Locator.GetPlayerCamera().enabled = false;
}
var diff = _serverTime - Time.timeSinceLevelLoad;
2022-03-03 03:46:33 +00:00
OWTime.SetTimeScale(Mathf.SmoothStep(MinFastForwardSpeed, MaxFastForwardSpeed, Mathf.Abs(diff) / MaxFastForwardDiff));
2022-03-03 03:46:33 +00:00
TimeSyncUI.TargetTime = _serverTime;
}
2022-03-03 03:46:33 +00:00
if (CurrentState == State.Pausing && (PauseReason)CurrentReason == PauseReason.TooFarAhead)
{
TimeSyncUI.TargetTime = _serverTime;
}
2022-03-03 03:46:33 +00:00
if (CurrentState != State.Loaded && CurrentState != State.NotLoaded && CurrentReason == null)
{
DebugLog.ToConsole($"Warning - CurrentReason is null.", MessageType.Warning);
}
2022-03-03 03:46:33 +00:00
// Checks to pause/fastforward
2020-12-02 21:29:53 +00:00
2022-03-03 03:46:33 +00:00
if (clientState is ClientState.NotLoaded or ClientState.InTitleScreen)
{
return;
}
2022-03-03 03:46:33 +00:00
if (serverState == ServerState.NotLoaded && CurrentState != State.Pausing && QSBSceneManager.IsInUniverse)
{
StartPausing(PauseReason.ServerNotStarted);
}
2022-03-03 03:46:33 +00:00
if (serverState == ServerState.WaitingForAllPlayersToReady && CurrentState != State.Pausing && clientState == ClientState.WaitingForOthersToBeReady)
{
StartPausing(PauseReason.WaitingForAllPlayersToBeReady);
}
2020-12-02 21:29:53 +00:00
if (serverState == ServerState.WaitingForAllPlayersToDie && CurrentState != State.Pausing && clientState == ClientState.WaitingForOthersToBeReady)
2022-03-03 03:46:33 +00:00
{
StartPausing(PauseReason.WaitingForAllPlayersToBeReady);
}
// Checks to revert to normal
if (CurrentState == State.Pausing && (PauseReason)CurrentReason == PauseReason.ServerNotStarted)
{
if (serverState != ServerState.NotLoaded)
2020-12-02 21:29:53 +00:00
{
2022-03-03 03:46:33 +00:00
ResetTimeScale();
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2021-03-25 23:07:53 +00:00
2022-03-03 03:46:33 +00:00
if (CurrentState == State.Pausing && (PauseReason)CurrentReason == PauseReason.WaitingForAllPlayersToBeReady)
{
2022-08-05 19:01:55 +00:00
if ((clientState == ClientState.AliveInSolarSystem && serverState == ServerState.InSolarSystem) ||
(clientState == ClientState.AliveInEye && serverState == ServerState.InEye))
2021-03-25 23:07:53 +00:00
{
2022-03-03 03:46:33 +00:00
ResetTimeScale();
2021-03-25 23:07:53 +00:00
}
2022-03-03 03:46:33 +00:00
}
2021-08-10 13:54:23 +00:00
2022-03-03 03:46:33 +00:00
if (CurrentState == State.Pausing && (PauseReason)CurrentReason == PauseReason.TooFarAhead)
{
if (Time.timeSinceLevelLoad <= _serverTime)
{
2022-03-03 03:46:33 +00:00
ResetTimeScale();
}
2022-03-03 03:46:33 +00:00
}
2022-03-03 03:46:33 +00:00
if (CurrentState == State.FastForwarding && (FastForwardReason)CurrentReason == FastForwardReason.TooFarBehind)
{
if (Time.timeSinceLevelLoad >= _serverTime)
2021-08-10 13:54:23 +00:00
{
2022-03-03 03:46:33 +00:00
ResetTimeScale();
2021-08-10 13:54:23 +00:00
}
2021-03-25 23:07:53 +00:00
}
2022-03-03 03:46:33 +00:00
if (CurrentState == State.Loaded)
2021-03-25 23:07:53 +00:00
{
2022-03-03 03:46:33 +00:00
CheckTimeDifference();
}
}
2021-03-25 23:07:53 +00:00
2022-03-03 03:46:33 +00:00
private void CheckTimeDifference()
{
var diff = GetTimeDifference();
2021-03-25 23:07:53 +00:00
if (diff is > PauseOrFastForwardThreshold or < -PauseOrFastForwardThreshold)
2022-03-03 03:46:33 +00:00
{
WakeUpOrSleep();
return;
}
2021-06-18 21:38:32 +00:00
2022-03-03 03:46:33 +00:00
var mappedTimescale = diff.Map(-PauseOrFastForwardThreshold, PauseOrFastForwardThreshold, 1 + TimescaleBounds, 1 - TimescaleBounds, true);
if (mappedTimescale > 100f)
{
DebugLog.ToConsole($"Warning - CheckTimeDifference() returned over 100 - should have switched into fast-forward!", MessageType.Warning);
mappedTimescale = 0f;
}
2021-06-18 21:38:32 +00:00
2022-03-03 03:46:33 +00:00
if (mappedTimescale < 0)
{
DebugLog.ToConsole($"Warning - CheckTimeDifference() returned below 0 - should have switched into pausing!", MessageType.Warning);
mappedTimescale = 0f;
2020-12-02 21:29:53 +00:00
}
2022-03-03 03:46:33 +00:00
OWTime.SetTimeScale(mappedTimescale);
2020-12-02 21:29:53 +00:00
}
}