2020-02-28 22:07:39 +01:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using OWML.ModHelper.Events;
|
2020-02-15 20:48:02 +01:00
|
|
|
|
using QSB.Messaging;
|
2020-02-28 22:07:39 +01:00
|
|
|
|
using UnityEngine;
|
2020-02-24 19:55:16 +01:00
|
|
|
|
using UnityEngine.Networking;
|
2020-02-28 22:07:39 +01:00
|
|
|
|
using UnityEngine.SceneManagement;
|
2020-02-14 22:14:24 +01:00
|
|
|
|
|
2020-02-24 19:55:16 +01:00
|
|
|
|
namespace QSB.TimeSync
|
2020-02-15 20:48:02 +01:00
|
|
|
|
{
|
2020-02-24 19:55:16 +01:00
|
|
|
|
public class WakeUpSync : NetworkBehaviour
|
2020-02-15 20:48:02 +01:00
|
|
|
|
{
|
2020-02-28 22:07:39 +01:00
|
|
|
|
private const float TimeThreshold = 0.5f;
|
|
|
|
|
|
|
|
|
|
private enum State { NotLoaded, EyesClosed, Awake, Sleeping, Pausing }
|
|
|
|
|
private State _state = State.NotLoaded;
|
|
|
|
|
|
2020-02-21 23:36:07 +01:00
|
|
|
|
private MessageHandler<WakeUpMessage> _wakeUpHandler;
|
2020-02-28 22:07:39 +01:00
|
|
|
|
private Campfire _campfire;
|
|
|
|
|
|
|
|
|
|
private float _sendTimer;
|
|
|
|
|
private float _serverTime;
|
2020-02-15 20:48:02 +01:00
|
|
|
|
|
|
|
|
|
private void Start()
|
|
|
|
|
{
|
2020-02-24 19:55:16 +01:00
|
|
|
|
if (!isLocalPlayer)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-02-28 22:07:39 +01:00
|
|
|
|
|
2020-02-14 22:14:24 +01:00
|
|
|
|
DebugLog.Screen("Start WakeUpSync");
|
|
|
|
|
GlobalMessenger.AddListener("WakeUp", OnWakeUp);
|
2020-02-28 22:07:39 +01:00
|
|
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
|
|
|
|
2020-02-21 23:36:07 +01:00
|
|
|
|
_wakeUpHandler = new MessageHandler<WakeUpMessage>();
|
|
|
|
|
_wakeUpHandler.OnClientReceiveMessage += OnClientReceiveMessage;
|
2020-02-14 22:14:24 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-28 22:07:39 +01:00
|
|
|
|
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|
|
|
|
{
|
|
|
|
|
if (scene.name == "SolarSystem")
|
|
|
|
|
{
|
|
|
|
|
_campfire = GameObject.FindObjectsOfType<Campfire>().Single(x => x.GetValue<Sector>("_sector").name == "Sector_Village");
|
|
|
|
|
_state = State.EyesClosed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-15 20:48:02 +01:00
|
|
|
|
private void OnWakeUp()
|
|
|
|
|
{
|
2020-02-28 22:07:39 +01:00
|
|
|
|
_state = State.Awake;
|
2020-02-29 09:39:15 +01:00
|
|
|
|
gameObject.AddComponent<PreserveTimeScale>();
|
2020-02-28 22:07:39 +01:00
|
|
|
|
if (isServer)
|
2020-02-15 20:48:02 +01:00
|
|
|
|
{
|
2020-02-28 22:07:39 +01:00
|
|
|
|
SendServerTime();
|
2020-02-14 22:14:24 +01:00
|
|
|
|
}
|
2020-02-28 22:07:39 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
WakeUpOrSleep();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SendServerTime()
|
|
|
|
|
{
|
|
|
|
|
DebugLog.Screen("Sending server time to all my friends: " + Time.timeSinceLevelLoad);
|
|
|
|
|
var message = new WakeUpMessage
|
|
|
|
|
{
|
|
|
|
|
ServerTime = Time.timeSinceLevelLoad
|
|
|
|
|
};
|
|
|
|
|
_wakeUpHandler.SendToAll(message);
|
2020-02-14 22:14:24 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-21 23:36:07 +01:00
|
|
|
|
private void OnClientReceiveMessage(WakeUpMessage message)
|
2020-02-15 20:48:02 +01:00
|
|
|
|
{
|
2020-02-24 19:55:16 +01:00
|
|
|
|
if (isServer)
|
2020-02-15 20:48:02 +01:00
|
|
|
|
{
|
2020-02-14 22:14:24 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2020-02-28 22:07:39 +01:00
|
|
|
|
_serverTime = message.ServerTime;
|
|
|
|
|
WakeUpOrSleep();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void WakeUpOrSleep()
|
|
|
|
|
{
|
|
|
|
|
if (_state == State.NotLoaded)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_state == State.EyesClosed)
|
|
|
|
|
{
|
|
|
|
|
OpenEyes();
|
|
|
|
|
_state = State.Awake;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var myTime = Time.timeSinceLevelLoad;
|
|
|
|
|
var diff = myTime - _serverTime;
|
|
|
|
|
|
|
|
|
|
if (diff > TimeThreshold)
|
|
|
|
|
{
|
|
|
|
|
DebugLog.Screen($"My time ({myTime}) is {diff} ahead server ({_serverTime})");
|
|
|
|
|
StartPausing();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-02-14 22:14:24 +01:00
|
|
|
|
|
2020-02-28 22:07:39 +01:00
|
|
|
|
if (diff < -TimeThreshold)
|
|
|
|
|
{
|
|
|
|
|
DebugLog.Screen($"My time ({myTime}) is {-diff} behind server ({_serverTime})");
|
|
|
|
|
StartSleeping();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebugLog.Screen($"My time ({myTime}) is within threshold of server time ({_serverTime})");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OpenEyes()
|
|
|
|
|
{
|
2020-02-14 22:14:24 +01:00
|
|
|
|
// I copied all of this from my AutoResume mod, since that already wakes up the player instantly.
|
|
|
|
|
// There must be a simpler way to do this though, I just couldn't find it.
|
|
|
|
|
|
|
|
|
|
// Skip wake up animation.
|
|
|
|
|
var cameraEffectController = FindObjectOfType<PlayerCameraEffectController>();
|
|
|
|
|
cameraEffectController.OpenEyes(0, true);
|
|
|
|
|
cameraEffectController.SetValue("_wakeLength", 0f);
|
|
|
|
|
cameraEffectController.SetValue("_waitForWakeInput", false);
|
|
|
|
|
|
|
|
|
|
// Skip wake up prompt.
|
|
|
|
|
LateInitializerManager.pauseOnInitialization = false;
|
|
|
|
|
Locator.GetPauseCommandListener().RemovePauseCommandLock();
|
|
|
|
|
Locator.GetPromptManager().RemoveScreenPrompt(cameraEffectController.GetValue<ScreenPrompt>("_wakePrompt"));
|
|
|
|
|
OWTime.Unpause(OWTime.PauseType.Sleeping);
|
|
|
|
|
cameraEffectController.Invoke("WakeUp");
|
|
|
|
|
|
2020-02-15 20:48:02 +01:00
|
|
|
|
// Enable all inputs immediately.
|
2020-02-14 22:14:24 +01:00
|
|
|
|
OWInput.ChangeInputMode(InputMode.Character);
|
|
|
|
|
typeof(OWInput).SetValue("_inputFadeFraction", 0f);
|
|
|
|
|
GlobalMessenger.FireEvent("TakeFirstFlashbackSnapshot");
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-28 22:07:39 +01:00
|
|
|
|
private void StartSleeping()
|
|
|
|
|
{
|
|
|
|
|
if (_state == State.Sleeping)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
DebugLog.Screen("Starting sleeping");
|
2020-02-29 10:28:21 +01:00
|
|
|
|
var wakePrompt = _campfire.GetValue<ScreenPrompt>("_wakePrompt");
|
|
|
|
|
Locator.GetPromptManager().RemoveScreenPrompt(wakePrompt, PromptPosition.Center);
|
2020-02-28 22:07:39 +01:00
|
|
|
|
_campfire.Invoke("StartSleeping");
|
|
|
|
|
_state = State.Sleeping;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StopSleeping()
|
|
|
|
|
{
|
|
|
|
|
if (_state != State.Sleeping)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
DebugLog.Screen("Stopping sleeping");
|
|
|
|
|
_campfire.StopSleeping();
|
|
|
|
|
_state = State.Awake;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StartPausing()
|
|
|
|
|
{
|
|
|
|
|
if (_state == State.Pausing)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
OWTime.Pause(OWTime.PauseType.Menu);
|
|
|
|
|
Time.timeScale = 0f;
|
|
|
|
|
_state = State.Pausing;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StopPausing()
|
|
|
|
|
{
|
|
|
|
|
if (_state != State.Pausing)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
OWTime.Unpause(OWTime.PauseType.Menu);
|
|
|
|
|
_state = State.Awake;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
{
|
|
|
|
|
if (isServer)
|
|
|
|
|
{
|
|
|
|
|
UpdateServer();
|
|
|
|
|
}
|
|
|
|
|
else if (isLocalPlayer)
|
|
|
|
|
{
|
|
|
|
|
UpdateLocal();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateServer()
|
|
|
|
|
{
|
|
|
|
|
if (_state != State.Awake)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_sendTimer += Time.unscaledDeltaTime;
|
|
|
|
|
if (_sendTimer > 1)
|
|
|
|
|
{
|
|
|
|
|
SendServerTime();
|
|
|
|
|
_sendTimer = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateLocal()
|
|
|
|
|
{
|
|
|
|
|
_serverTime += Time.unscaledDeltaTime;
|
|
|
|
|
|
|
|
|
|
if (_state == State.NotLoaded || _state == State.EyesClosed)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_state == State.Sleeping && Time.timeSinceLevelLoad >= _serverTime)
|
|
|
|
|
{
|
|
|
|
|
StopSleeping();
|
|
|
|
|
}
|
|
|
|
|
else if (_state == State.Pausing && Time.timeSinceLevelLoad < _serverTime)
|
|
|
|
|
{
|
|
|
|
|
StopPausing();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 22:14:24 +01:00
|
|
|
|
}
|
|
|
|
|
}
|