Merge branch 'dev' into message-manager

# Conflicts:
#	QSB/Events/QSBEvent.cs
#	QSB/Events/QSBEventManager.cs
#	QSB/Messaging/MessageHandler.cs
#	QSB/Patches/QSBPatchManager.cs
#	QSB/QSBCore.cs
#	QSB/QSBNetworkManager.cs
This commit is contained in:
JohnCorby 2021-12-11 18:31:28 -08:00
commit a925327c0c
61 changed files with 1136 additions and 295 deletions

View File

@ -191,54 +191,54 @@ namespace QSB.Anglerfish.Patches
__instance.ApplyDrag(1f);
return false;
case AnglerfishController.AnglerState.Investigating:
{
var targetPos = __instance._brambleBody.transform.TransformPoint(__instance._localDisturbancePos);
__instance.RotateTowardsTarget(targetPos, __instance._turnSpeed, __instance._turnSpeed);
if (!__instance._turningInPlace)
{
__instance.MoveTowardsTarget(targetPos, __instance._investigateSpeed, __instance._acceleration);
return false;
var targetPos = __instance._brambleBody.transform.TransformPoint(__instance._localDisturbancePos);
__instance.RotateTowardsTarget(targetPos, __instance._turnSpeed, __instance._turnSpeed);
if (!__instance._turningInPlace)
{
__instance.MoveTowardsTarget(targetPos, __instance._investigateSpeed, __instance._acceleration);
return false;
}
break;
}
break;
}
case AnglerfishController.AnglerState.Chasing:
{
var velocity = qsbAngler.TargetVelocity;
var normalized = velocity.normalized;
var from = __instance._anglerBody.GetPosition() + __instance.transform.TransformDirection(__instance._mouthOffset) - qsbAngler.TargetTransform.position;
var magnitude = velocity.magnitude;
var num = Vector3.Angle(from, normalized);
var num2 = magnitude * 2f;
var d = num2;
if (num < 90f)
{
var magnitude2 = from.magnitude;
var num3 = magnitude2 * Mathf.Sin(num * 0.017453292f);
var num4 = magnitude2 * Mathf.Cos(num * 0.017453292f);
var magnitude3 = __instance._anglerBody.GetVelocity().magnitude;
var num5 = num4 / Mathf.Max(magnitude, 0.0001f);
var num6 = num3 / Mathf.Max(magnitude3, 0.0001f);
var num7 = num5 / num6;
if (num7 <= 1f)
var velocity = qsbAngler.TargetVelocity;
var normalized = velocity.normalized;
var from = __instance._anglerBody.GetPosition() + __instance.transform.TransformDirection(__instance._mouthOffset) - qsbAngler.TargetTransform.position;
var magnitude = velocity.magnitude;
var num = Vector3.Angle(from, normalized);
var num2 = magnitude * 2f;
var d = num2;
if (num < 90f)
{
var t = Mathf.Clamp01(num7);
d = Mathf.Lerp(num2, num4, t);
var magnitude2 = from.magnitude;
var num3 = magnitude2 * Mathf.Sin(num * 0.017453292f);
var num4 = magnitude2 * Mathf.Cos(num * 0.017453292f);
var magnitude3 = __instance._anglerBody.GetVelocity().magnitude;
var num5 = num4 / Mathf.Max(magnitude, 0.0001f);
var num6 = num3 / Mathf.Max(magnitude3, 0.0001f);
var num7 = num5 / num6;
if (num7 <= 1f)
{
var t = Mathf.Clamp01(num7);
d = Mathf.Lerp(num2, num4, t);
}
else
{
var num8 = Mathf.InverseLerp(1f, 4f, num7);
d = Mathf.Lerp(num4, 0f, num8 * num8);
}
}
else
__instance._targetPos = qsbAngler.TargetTransform.position + normalized * d;
__instance.RotateTowardsTarget(__instance._targetPos, __instance._turnSpeed, __instance._quickTurnSpeed);
if (!__instance._turningInPlace)
{
var num8 = Mathf.InverseLerp(1f, 4f, num7);
d = Mathf.Lerp(num4, 0f, num8 * num8);
__instance.MoveTowardsTarget(__instance._targetPos, __instance._chaseSpeed, __instance._acceleration);
return false;
}
break;
}
__instance._targetPos = qsbAngler.TargetTransform.position + normalized * d;
__instance.RotateTowardsTarget(__instance._targetPos, __instance._turnSpeed, __instance._quickTurnSpeed);
if (!__instance._turningInPlace)
{
__instance.MoveTowardsTarget(__instance._targetPos, __instance._chaseSpeed, __instance._acceleration);
return false;
}
break;
}
case AnglerfishController.AnglerState.Consuming:
__instance.ApplyDrag(1f);
return false;

View File

@ -11,6 +11,7 @@ namespace QSB.Anglerfish.TransformSync
{
public override bool IsReady => WorldObjectManager.AllObjectsAdded;
public override bool UseInterpolation => false;
public override bool IsPlayerObject => false;
private QSBAngler _qsbAngler;
private static readonly List<AnglerTransformSync> _instances = new();

View File

@ -187,19 +187,45 @@ namespace QSB.Animation.Player
DebugLog.ToConsole($"Error - Suited controller is null. ({PlayerId})", MessageType.Error);
}
if (_unsuitedGraphics == null)
{
DebugLog.ToConsole($"Warning - _unsuitedGraphics is null! ({PlayerId})", MessageType.Warning);
}
if (_suitedGraphics == null)
{
DebugLog.ToConsole($"Warning - _suitedGraphics is null! ({PlayerId})", MessageType.Warning);
}
RuntimeAnimatorController controller = default;
switch (type)
{
case AnimationType.PlayerSuited:
controller = _suitedAnimController;
_unsuitedGraphics?.SetActive(false);
_suitedGraphics?.SetActive(true);
if (_unsuitedGraphics != null)
{
_unsuitedGraphics?.SetActive(false);
}
if (_suitedGraphics != null)
{
_suitedGraphics?.SetActive(true);
}
break;
case AnimationType.PlayerUnsuited:
controller = _unsuitedAnimController;
_unsuitedGraphics?.SetActive(true);
_suitedGraphics?.SetActive(false);
if (_unsuitedGraphics != null)
{
_unsuitedGraphics?.SetActive(true);
}
if (_suitedGraphics != null)
{
_suitedGraphics?.SetActive(false);
}
break;
case AnimationType.Chert:
@ -223,25 +249,66 @@ namespace QSB.Animation.Player
break;
}
InvisibleAnimator.runtimeAnimatorController = controller;
VisibleAnimator.runtimeAnimatorController = controller;
if (InvisibleAnimator == null)
{
DebugLog.ToConsole($"Error - InvisibleAnimator is null. ({PlayerId})", MessageType.Error);
}
else
{
InvisibleAnimator.runtimeAnimatorController = controller;
}
if (VisibleAnimator == null)
{
DebugLog.ToConsole($"Error - VisibleAnimator is null. ({PlayerId})", MessageType.Error);
}
else
{
VisibleAnimator.runtimeAnimatorController = controller;
}
if (type is not AnimationType.PlayerSuited and not AnimationType.PlayerUnsuited)
{
VisibleAnimator.SetTrigger("Playing");
InvisibleAnimator.SetTrigger("Playing");
if (VisibleAnimator != null)
{
VisibleAnimator.SetTrigger("Playing");
}
if (InvisibleAnimator != null)
{
InvisibleAnimator.SetTrigger("Playing");
}
}
else
{
// Avoids "jumping" when exiting instrument and putting on suit
VisibleAnimator.SetTrigger("Grounded");
InvisibleAnimator.SetTrigger("Grounded");
if (VisibleAnimator != null)
{
VisibleAnimator.SetTrigger("Grounded");
}
if (InvisibleAnimator != null)
{
InvisibleAnimator.SetTrigger("Grounded");
}
}
NetworkAnimator.animator = InvisibleAnimator; // Probably not needed.
Mirror.RebuildFloatParams();
for (var i = 0; i < InvisibleAnimator.parameterCount; i++)
if (NetworkAnimator == null)
{
NetworkAnimator.SetParameterAutoSend(i, true);
DebugLog.ToConsole($"Error - NetworkAnimator is null. ({PlayerId})", MessageType.Error);
}
else if (Mirror == null)
{
DebugLog.ToConsole($"Error - Mirror is null. ({PlayerId})", MessageType.Error);
}
else if (InvisibleAnimator != null)
{
NetworkAnimator.animator = InvisibleAnimator; // Probably not needed.
Mirror.RebuildFloatParams();
for (var i = 0; i < InvisibleAnimator.parameterCount; i++)
{
NetworkAnimator.SetParameterAutoSend(i, true);
}
}
}
}

View File

@ -1,6 +1,5 @@
using QSB.Events;
using QSB.Player;
using QSB.WorldSync;
namespace QSB.Animation.Player.Events
{
@ -28,6 +27,11 @@ namespace QSB.Animation.Player.Events
return;
}
if (animationSync.VisibleAnimator == null)
{
return;
}
animationSync.VisibleAnimator.SetTrigger(message.Name);
}
}

View File

@ -2,7 +2,6 @@
using QSB.Instruments;
using QSB.Messaging;
using QSB.Player;
using QSB.WorldSync;
namespace QSB.Animation.Player.Events
{

View File

@ -1,7 +1,6 @@
using QSB.Events;
using QSB.Messaging;
using QSB.Player;
using QSB.WorldSync;
namespace QSB.Animation.Player.Events
{

Binary file not shown.

View File

@ -1,12 +1,12 @@
ManifestFileVersion: 0
CRC: 2906651145
CRC: 1208921857
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 0fa5758f55c8803c7ba77a52ab2c9488
Hash: e6fb281706df372893c7d91213b2598a
TypeTreeHash:
serializedVersion: 2
Hash: 87b5c87f221cc0cbe8c4eefab7d02419
Hash: 91770441465e7cb2442c311d5ad605d6
HashAppended: 0
ClassTypes:
- Class: 1
@ -17,8 +17,6 @@ ClassTypes:
Script: {fileID: -1208705890, guid: 8929207a0d76fd54a8a2a820c652720f, type: 3}
- Class: 114
Script: {fileID: 1142416158, guid: 8929207a0d76fd54a8a2a820c652720f, type: 3}
- Class: 114
Script: {fileID: 519208029, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: -790547616, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
@ -29,18 +27,10 @@ ClassTypes:
Script: {fileID: -1164351254, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: -1309757293, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: 316226861, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: 78926581, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: -1381557116, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: -1937550126, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: -749020886, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: -2281650, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
Script: {fileID: 677635994, guid: 27687deae413b90448366870cb0de502, type: 3}
- Class: 114
@ -49,10 +39,6 @@ ClassTypes:
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/Prefabs/NetworkJellyfish.prefab
- Assets/Prefabs/NetworkProbe.prefab
- Assets/Prefabs/NetworkObject.prefab
- Assets/Prefabs/NETWORK_Player_Body.prefab
- Assets/Prefabs/NetworkOrb.prefab
- Assets/Prefabs/NetworkAngler.prefab
- Assets/Prefabs/NetworkShip.prefab
Dependencies: []

View File

@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using QSB.Events;
using QSB.Events;
using QSB.Utility;
using QuantumUNET;
using QuantumUNET.Components;
using System.Collections.Generic;
using System.Linq;
namespace QSB.AuthoritySync
{
@ -72,7 +72,7 @@ namespace QSB.AuthoritySync
}
// DebugLog.DebugWrite($"{identity.NetId}:{identity.gameObject.name} - "
// + $"set authority to {id}");
// + $"set authority to {id}");
}
#endregion

View File

@ -1,5 +1,4 @@
using QSB.Events;
using QSB.WorldSync;
using QuantumUNET.Components;
namespace QSB.AuthoritySync

View File

@ -40,7 +40,7 @@ namespace QSB.ElevatorSync.WorldObjects
if (_elevatorTrigger.IsTrackingObject(Locator.GetPlayerDetector()))
{
SetDirection(isGoingUp);
AttachedObject._attachPoint.AttachPlayer();
if (Locator.GetPlayerSuit().IsWearingSuit(true) && Locator.GetPlayerSuit().IsTrainingSuit())

View File

@ -102,5 +102,8 @@
public const string QSBSatelliteRepaired = nameof(QSBSatelliteRepairTick);
public const string QSBAuthorityQueue = nameof(QSBAuthorityQueue);
public const string QSBJellyfishRising = nameof(QSBJellyfishRising);
public const string QSBTornadoFormState = nameof(QSBTornadoFormState);
public const string QSBRequestGameDetails = nameof(QSBRequestGameDetails);
public const string QSBGameDetails = nameof(QSBGameDetails);
}
}

View File

@ -1,4 +1,3 @@
using System;
using JetBrains.Annotations;
using OWML.Utils;
using QSB.Messaging;
@ -6,6 +5,7 @@ using QSB.Player;
using QSB.Player.TransformSync;
using QSB.WorldSync;
using QuantumUNET.Transport;
using System;
namespace QSB.Events
{

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using OWML.Common;

View File

@ -58,7 +58,6 @@ namespace QSB.Inputs
public void SetInputsEnabled(bool enabled)
{
DebugLog.DebugWrite($"INPUTS ENABLED? : {enabled}");
InputsEnabled = enabled;
}
}

View File

@ -1,10 +1,10 @@
using System.Collections.Generic;
using QSB.JellyfishSync.WorldObjects;
using QSB.JellyfishSync.WorldObjects;
using QSB.Syncs;
using QSB.Syncs.Unsectored.Rigidbodies;
using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET.Transport;
using System.Collections.Generic;
using UnityEngine;
namespace QSB.JellyfishSync.TransformSync
@ -13,6 +13,7 @@ namespace QSB.JellyfishSync.TransformSync
{
public override bool IsReady => WorldObjectManager.AllObjectsAdded;
public override bool UseInterpolation => false;
public override bool IsPlayerObject => false;
private QSBJellyfish _qsbJellyfish;
private static readonly List<JellyfishTransformSync> _instances = new();
@ -93,11 +94,6 @@ namespace QSB.JellyfishSync.TransformSync
var targetPos = ReferenceTransform.DecodePos(transform.position);
var targetRot = ReferenceTransform.DecodeRot(transform.rotation);
if (targetPos == Vector3.zero || transform.position == Vector3.zero)
{
return false;
}
var positionToSet = targetPos;
var rotationToSet = targetRot;

View File

@ -1,4 +1,5 @@
using UnityEngine;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace QSB.Menus
@ -6,9 +7,16 @@ namespace QSB.Menus
public interface IMenuAPI
{
// Title screen
[Obsolete]
GameObject TitleScreen_MakeMenuOpenButton(string name, Menu menuToOpen);
[Obsolete]
GameObject TitleScreen_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null);
[Obsolete]
Button TitleScreen_MakeSimpleButton(string name);
GameObject TitleScreen_MakeMenuOpenButton(string name, int index, Menu menuToOpen);
GameObject TitleScreen_MakeSceneLoadButton(string name, int index, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null);
Button TitleScreen_MakeSimpleButton(string name, int index);
// Pause menu
GameObject PauseMenu_MakeMenuOpenButton(string name, Menu menuToOpen, Menu customMenu = null);
GameObject PauseMenu_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null, Menu customMenu = null);

View File

@ -1,5 +1,9 @@
using QSB.Player;
using QSB.Events;
using QSB.Player;
using QSB.Player.TransformSync;
using QSB.Utility;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
@ -11,13 +15,27 @@ namespace QSB.Menus
public static MenuManager Instance;
private IMenuAPI MenuApi => QSBCore.MenuApi;
private PopupMenu PopupMenu;
private Button HostButton;
private GameObject ClientButton;
private Button DisconnectButton;
private PopupMenu IPPopup;
private PopupMenu InfoPopup;
private bool _addedPauseLock;
// Pause menu only
private Button HostButton;
private GameObject QuitButton;
private GameObject DisconnectButton;
private PopupMenu DisconnectPopup;
private StringBuilder _nowLoadingSB;
protected Text _loadingText;
// title screen only
private GameObject ResumeGameButton;
private GameObject NewGameButton;
private GameObject ClientButton;
private const int _ClientButtonIndex = 2;
private const int _DisconnectIndex = 3;
public void Start()
{
Instance = this;
@ -42,6 +60,51 @@ namespace QSB.Menus
}
}
private void ResetStringBuilder()
{
if (_nowLoadingSB == null)
{
_nowLoadingSB = new StringBuilder();
return;
}
_nowLoadingSB.Length = 0;
}
private void Update()
{
if (QSBCore.IsInMultiplayer
&& (LoadManager.GetLoadingScene() == OWScene.SolarSystem || LoadManager.GetLoadingScene() == OWScene.EyeOfTheUniverse)
&& _loadingText != null)
{
var num = LoadManager.GetAsyncLoadProgress();
num = num < 0.1f
? Mathf.InverseLerp(0f, 0.1f, num) * 0.9f
: 0.9f + (Mathf.InverseLerp(0.1f, 1f, num) * 0.1f);
ResetStringBuilder();
_nowLoadingSB.Append(UITextLibrary.GetString(UITextType.LoadingMessage));
_nowLoadingSB.Append(num.ToString("P0"));
_loadingText.text = _nowLoadingSB.ToString();
}
}
public void JoinGame(bool inEye, bool inSolarSystem)
{
if (inEye)
{
LoadManager.LoadSceneAsync(OWScene.EyeOfTheUniverse, true, LoadManager.FadeType.ToBlack, 1f, false);
Locator.GetMenuInputModule().DisableInputs();
}
else if (inSolarSystem)
{
LoadManager.LoadSceneAsync(OWScene.SolarSystem, true, LoadManager.FadeType.ToBlack, 1f, false);
Locator.GetMenuInputModule().DisableInputs();
}
else
{
DebugLog.DebugWrite("tried to join game that wasnt in solar system or eye??");
}
}
private void OpenInfoPopup(string message, string buttonText)
{
InfoPopup.SetUpPopup(message, InputLibrary.menuConfirm, InputLibrary.cancel, new ScreenPrompt(buttonText), null, true, false);
@ -70,72 +133,108 @@ namespace QSB.Menus
OWTime.Unpause(OWTime.PauseType.System);
OWInput.RestorePreviousInputs();
if (QSBSceneManager.IsInUniverse)
{
LoadManager.LoadScene(OWScene.TitleScreen, LoadManager.FadeType.ToBlack, 2f, true);
}
}
private void CreateCommonPopups()
{
PopupMenu = MenuApi.MakeInputFieldPopup("IP Address", "IP Address", "Connect", "Cancel");
PopupMenu.OnPopupConfirm += Connect;
IPPopup = MenuApi.MakeInputFieldPopup("IP Address", "IP Address", "Connect", "Cancel");
IPPopup.OnPopupConfirm += Connect;
InfoPopup = MenuApi.MakeInfoPopup("", "");
InfoPopup.OnDeactivateMenu += OnCloseInfoPopup;
}
private void SetButtonActive(Button button, bool active)
=> SetButtonActive(button?.gameObject, active);
private void SetButtonActive(GameObject button, bool active)
{
if (button == null)
{
DebugLog.DebugWrite($"Warning - Tried to set button to {active}, but it was null.", OWML.Common.MessageType.Warning);
return;
}
button.SetActive(active);
button.GetComponent<CanvasGroup>().alpha = active ? 1 : 0;
}
private void InitPauseMenus()
{
CreateCommonPopups();
HostButton = MenuApi.PauseMenu_MakeSimpleButton("MULTIPLAYER (HOST)");
HostButton = MenuApi.PauseMenu_MakeSimpleButton("OPEN TO MULTIPLAYER");
HostButton.onClick.AddListener(Host);
ClientButton = MenuApi.PauseMenu_MakeMenuOpenButton("MULTIPLAYER (CONNECT)", PopupMenu);
DisconnectPopup = MenuApi.MakeTwoChoicePopup("Are you sure you want to disconnect?\r\nThis will send you back to the main menu.", "YES", "NO");
DisconnectPopup.OnPopupConfirm += Disconnect;
DisconnectButton = MenuApi.PauseMenu_MakeSimpleButton("DISCONNECT");
DisconnectButton.onClick.AddListener(Disconnect);
DisconnectButton = MenuApi.PauseMenu_MakeMenuOpenButton("DISCONNECT", DisconnectPopup);
QuitButton = FindObjectOfType<PauseMenuManager>()._exitToMainMenuAction.gameObject;
if (QSBCore.IsInMultiplayer)
{
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
SetButtonActive(HostButton, false);
SetButtonActive(DisconnectButton, true);
SetButtonActive(QuitButton, false);
}
else
{
DisconnectButton.gameObject.SetActive(false);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
SetButtonActive(HostButton, true);
SetButtonActive(DisconnectButton, false);
SetButtonActive(QuitButton, true);
}
OnConnected();
var text = QSBCore.IsHost
? "STOP HOSTING"
: "DISCONNECT";
DisconnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = text;
var popupText = QSBCore.IsHost
? "Are you sure you want to stop hosting?\r\nThis will disconnect all clients and send everyone back to the main menu."
: "Are you sure you want to disconnect?\r\nThis will send you back to the main menu.";
DisconnectPopup._labelText.text = popupText;
}
private void MakeTitleMenus()
{
CreateCommonPopups();
HostButton = MenuApi.TitleScreen_MakeSimpleButton("MULTIPLAYER (HOST)");
HostButton.onClick.AddListener(Host);
ClientButton = MenuApi.TitleScreen_MakeMenuOpenButton("CONNECT TO MULTIPLAYER", _ClientButtonIndex, IPPopup);
ClientButton = MenuApi.TitleScreen_MakeMenuOpenButton("MULTIPLAYER (CONNECT)", PopupMenu);
_loadingText = ClientButton.transform.GetChild(0).GetChild(1).GetComponent<Text>();
DisconnectButton = MenuApi.TitleScreen_MakeSimpleButton("DISCONNECT");
DisconnectButton.onClick.AddListener(Disconnect);
ResumeGameButton = GameObject.Find("MainMenuLayoutGroup/Button-ResumeGame");
NewGameButton = GameObject.Find("MainMenuLayoutGroup/Button-NewGame");
if (QSBCore.IsInMultiplayer)
{
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
SetButtonActive(ClientButton, false);
if (QSBCore.IsHost)
{
SetButtonActive(ResumeGameButton, StandaloneProfileManager.SharedInstance.currentProfileGameSave.loopCount > 1);
SetButtonActive(NewGameButton, true);
}
else
{
SetButtonActive(ResumeGameButton, false);
SetButtonActive(NewGameButton, false);
}
}
else
{
DisconnectButton.gameObject.SetActive(false);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
SetButtonActive(ClientButton, true);
SetButtonActive(ResumeGameButton, StandaloneProfileManager.SharedInstance.currentProfileGameSave.loopCount > 1);
SetButtonActive(NewGameButton, true);
}
OnConnected();
if (QSBCore.SkipTitleScreen)
{
Application.runInBackground = true;
@ -159,37 +258,68 @@ namespace QSB.Menus
private void Disconnect()
{
QSBNetworkManager.Instance.StopHost();
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
SetButtonActive(DisconnectButton.gameObject, false);
Locator.GetSceneMenuManager().pauseMenu._pauseMenu.EnableMenu(false);
Locator.GetSceneMenuManager().pauseMenu._isPaused = false;
OWInput.RestorePreviousInputs();
LoadManager.LoadScene(OWScene.TitleScreen, LoadManager.FadeType.ToBlack, 2f, true);
}
private void Host()
{
QSBNetworkManager.Instance.StartHost();
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
}
if (QSBNetworkManager.Instance.StartHost() != null)
{
SetButtonActive(DisconnectButton, true);
SetButtonActive(HostButton, false);
SetButtonActive(QuitButton, false);
}
else
{
OpenInfoPopup($"Failed to start server.", "OK");
}
private void Connect()
{
QSBNetworkManager.Instance.networkAddress = string.Concat((PopupMenu as PopupInputMenu).GetInputText().Where(c => !char.IsWhiteSpace(c)));
QSBNetworkManager.Instance.StartClient();
DisconnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = "CONNECTING... (STOP)";
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
}
private void OnConnected()
{
var text = QSBCore.IsHost
? "STOP HOSTING"
: "DISCONNECT";
DisconnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = text;
var popupText = QSBCore.IsHost
? "Are you sure you want to stop hosting?\r\nThis will disconnect all clients and send everyone back to the main menu."
: "Are you sure you want to disconnect?\r\nThis will send you back to the main menu.";
DisconnectPopup._labelText.text = popupText;
}
private void Connect()
{
QSBNetworkManager.Instance.networkAddress = string.Concat((IPPopup as PopupInputMenu).GetInputText().Where(c => !char.IsWhiteSpace(c)));
QSBNetworkManager.Instance.StartClient();
if (QSBSceneManager.CurrentScene == OWScene.TitleScreen)
{
SetButtonActive(ResumeGameButton, false);
SetButtonActive(NewGameButton, false);
}
if (QSBSceneManager.IsInUniverse)
{
SetButtonActive(QuitButton, false);
}
}
private void OnConnected()
{
if (QSBCore.IsHost || !QSBCore.IsInMultiplayer)
{
return;
}
QSBCore.UnityEvents.RunWhen(() => QSBEventManager.Ready && PlayerTransformSync.LocalInstance != null, () =>
{
QSBEventManager.FireEvent(EventNames.QSBRequestGameDetails);
});
}
public void OnKicked(KickReason reason)
@ -199,14 +329,16 @@ namespace QSB.Menus
KickReason.QSBVersionNotMatching => "Server refused connection as QSB version does not match.",
KickReason.GameVersionNotMatching => "Server refused connection as Outer Wilds version does not match.",
KickReason.GamePlatformNotMatching => "Server refused connection as Outer Wilds platform does not match. (Steam/Epic)",
KickReason.DLCNotMatching => "Server refused connection as DLC installation state does not match.",
KickReason.None => "Kicked from server. No reason given.",
_ => $"Kicked from server. KickReason:{reason}",
};
OpenInfoPopup(text, "OK");
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
SetButtonActive(DisconnectButton, false);
SetButtonActive(ClientButton, true);
SetButtonActive(HostButton, true);
SetButtonActive(QuitButton, true);
}
private void OnDisconnected(NetworkError error)
@ -223,9 +355,12 @@ namespace QSB.Menus
};
OpenInfoPopup(text, "OK");
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
SetButtonActive(DisconnectButton, false);
SetButtonActive(ClientButton, true);
SetButtonActive(QuitButton, true);
SetButtonActive(HostButton, true);
SetButtonActive(ResumeGameButton, StandaloneProfileManager.SharedInstance.currentProfileGameSave.loopCount > 1);
SetButtonActive(NewGameButton, true);
}
private void OnClientError(NetworkError error)
@ -241,9 +376,13 @@ namespace QSB.Menus
{
case NetworkError.DNSFailure:
text = "Internal QNet client error!\r\nDNS Faliure. Address was invalid or could not be resolved.";
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
DebugLog.DebugWrite($"dns failure");
SetButtonActive(DisconnectButton, false);
SetButtonActive(ClientButton, true);
SetButtonActive(HostButton, true);
SetButtonActive(ResumeGameButton, StandaloneProfileManager.SharedInstance.currentProfileGameSave.loopCount > 1);
SetButtonActive(NewGameButton, true);
SetButtonActive(QuitButton, true);
break;
default:
text = $"Internal QNet client error!\n\nNetworkError:{error}";

View File

@ -0,0 +1 @@


View File

@ -1,11 +1,11 @@
using System.Linq;
using OWML.Common;
using OWML.Common;
using QSB.AuthoritySync;
using QSB.Events;
using QSB.OrbSync.TransformSync;
using QSB.Utility;
using QSB.WorldSync;
using QSB.WorldSync.Events;
using System.Linq;
namespace QSB.OrbSync.Events
{

View File

@ -11,6 +11,8 @@ namespace QSB.OrbSync.TransformSync
{
public static List<NomaiOrbTransformSync> OrbTransformSyncs = new();
public override bool IsPlayerObject => false;
private int _index => OrbTransformSyncs.IndexOf(this);
public override void OnStartClient() => OrbTransformSyncs.Add(this);

View File

@ -29,7 +29,7 @@ namespace QSB.Player.Events
public override void OnReceiveRemote(bool server, PlayerInformationMessage message)
{
DebugLog.DebugWrite($"Received playerstate of player ID {message.AboutId}", MessageType.Info);
RequestStateResyncEvent._waitingForEvent = false;
if (QSBPlayerManager.PlayerExists(message.AboutId))
{
QSBPlayerManager.HandleFullStateMessage(message);

View File

@ -19,7 +19,8 @@ namespace QSB.Player.Events
PlayerName = name,
QSBVersion = QSBCore.QSBVersion,
GameVersion = QSBCore.GameVersion,
Platform = QSBCore.Platform
Platform = QSBCore.Platform,
DlcInstalled = QSBCore.DLCInstalled
};
public override void OnReceiveRemote(bool server, PlayerJoinMessage message)
@ -51,6 +52,15 @@ namespace QSB.Player.Events
if (server)
{
DebugLog.ToConsole($"Error - Client {message.PlayerName} connecting with wrong game platform. (Client:{message.Platform}, Server:{QSBCore.Platform})", MessageType.Error);
QSBEventManager.FireEvent(EventNames.QSBPlayerKick, message.AboutId, KickReason.DLCNotMatching);
}
}
if (message.DlcInstalled != QSBCore.DLCInstalled)
{
if (server)
{
DebugLog.ToConsole($"Error - Client {message.PlayerName} connecting with wrong DLC installation state. (Client:{message.DlcInstalled}, Server:{QSBCore.DLCInstalled})", MessageType.Error);
QSBEventManager.FireEvent(EventNames.QSBPlayerKick, message.AboutId, KickReason.GamePlatformNotMatching);
}
}
@ -58,7 +68,7 @@ namespace QSB.Player.Events
var player = QSBPlayerManager.GetPlayer(message.AboutId);
player.Name = message.PlayerName;
DebugLog.ToAll($"{player.Name} joined!", MessageType.Info);
DebugLog.DebugWrite($"{player.Name} joined. id:{player.PlayerId}, qsbVersion:{message.QSBVersion}, gameVersion:{message.GameVersion}, platform:{message.Platform}", MessageType.Info);
DebugLog.DebugWrite($"{player.Name} joined. id:{player.PlayerId}, qsbVersion:{message.QSBVersion}, gameVersion:{message.GameVersion}, platform:{message.Platform}. dlcInstalled:{message.DlcInstalled}", MessageType.Info);
}
public override void OnReceiveLocal(bool server, PlayerJoinMessage message)

View File

@ -9,6 +9,7 @@ namespace QSB.Player.Events
public string QSBVersion { get; set; }
public string GameVersion { get; set; }
public GamePlatform Platform { get; set; }
public bool DlcInstalled { get; set; }
public override void Deserialize(QNetworkReader reader)
{
@ -17,6 +18,7 @@ namespace QSB.Player.Events
QSBVersion = reader.ReadString();
GameVersion = reader.ReadString();
Platform = (GamePlatform)reader.ReadInt32();
DlcInstalled = reader.ReadBoolean();
}
public override void Serialize(QNetworkWriter writer)
@ -26,6 +28,7 @@ namespace QSB.Player.Events
writer.Write(QSBVersion);
writer.Write(GameVersion);
writer.Write((int)Platform);
writer.Write(DlcInstalled);
}
}
}

View File

@ -34,14 +34,14 @@ namespace QSB.Player.Events
private static void HandleServer(ToggleMessage message)
{
DebugLog.DebugWrite($"[SERVER] Get ready event from {message.FromId}", MessageType.Success);
DebugLog.DebugWrite($"[SERVER] Get ready event from {message.FromId} (ready = {message.ToggleValue})", MessageType.Success);
QSBPlayerManager.GetPlayer(message.AboutId).IsReady = message.ToggleValue;
QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
}
private void HandleClient(ToggleMessage message)
{
DebugLog.DebugWrite($"[CLIENT] Get ready event from {message.FromId}", MessageType.Success);
DebugLog.DebugWrite($"[CLIENT] Get ready event from {message.FromId} (ready = {message.ToggleValue})", MessageType.Success);
if (!QSBPlayerManager.PlayerExists(message.FromId))
{
DebugLog.ToConsole(
@ -49,6 +49,8 @@ namespace QSB.Player.Events
MessageType.Error);
return;
}
QSBPlayerManager.GetPlayer(message.AboutId).IsReady = message.ToggleValue;
}
}
}

View File

@ -1,4 +1,5 @@
using OWML.Utils;
using System.Linq;
using OWML.Utils;
using QSB.CampfireSync.WorldObjects;
using QSB.ClientServerStateSync;
using QSB.Events;
@ -7,27 +8,51 @@ using QSB.MeteorSync.WorldObjects;
using QSB.QuantumSync;
using QSB.Tools.TranslatorTool.TranslationSync;
using QSB.Tools.TranslatorTool.TranslationSync.WorldObjects;
using QSB.TornadoSync;
using QSB.TornadoSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using System.Linq;
namespace QSB.Player.Events
{
// Can be sent by any client (including host) to signal they want latest worldobject, player, and server infomation
public class RequestStateResyncEvent : QSBEvent<PlayerMessage>
{
public static bool _waitingForEvent;
public override bool RequireWorldObjectsReady => false;
public override void SetupListener() => GlobalMessenger.AddListener(EventNames.QSBRequestStateResync, Handler);
public override void CloseListener() => GlobalMessenger.RemoveListener(EventNames.QSBRequestStateResync, Handler);
private void Handler() => SendEvent(CreateMessage());
private void Handler()
{
if (_waitingForEvent)
{
return;
}
_waitingForEvent = true;
SendEvent(CreateMessage());
}
private PlayerMessage CreateMessage() => new()
{
AboutId = LocalPlayerId
};
public override void OnReceiveLocal(bool isHost, PlayerMessage message)
{
QSBCore.UnityEvents.FireInNUpdates(() =>
{
if (_waitingForEvent)
{
DebugLog.ToConsole($"Did not receive PlayerInformationEvent in time. Setting _waitingForEvent to false.", OWML.Common.MessageType.Info);
_waitingForEvent = false;
}
}, 60);
}
public override void OnReceiveRemote(bool isHost, PlayerMessage message)
{
// send response only to the requesting client
@ -94,6 +119,9 @@ namespace QSB.Player.Events
QSBWorldSync.GetWorldObjects<QSBFragment>().ForEach(fragment
=> QSBEventManager.FireEvent(EventNames.QSBFragmentResync, fragment));
QSBWorldSync.GetWorldObjects<QSBTornado>().ForEach(tornado
=> QSBEventManager.FireEvent(EventNames.QSBTornadoFormState, tornado));
}
}
}

View File

@ -5,6 +5,7 @@
None,
QSBVersionNotMatching,
GameVersionNotMatching,
GamePlatformNotMatching
GamePlatformNotMatching,
DLCNotMatching
}
}

View File

@ -21,7 +21,6 @@ namespace QSB.Player
public void Init(PlayerInfo player)
{
DebugLog.DebugWrite($"Init {player.PlayerId} name:{player.Name}");
_player = player;
_player.HudMarker = this;
_needsInitializing = true;

View File

@ -142,7 +142,7 @@ namespace QSB.Player
return null;
}
return CameraBody.transform.Find("ProbeLauncher").GetComponent<PlayerProbeLauncher>();
return CameraBody?.transform.Find("ProbeLauncher").GetComponent<PlayerProbeLauncher>();
}
}
@ -170,7 +170,7 @@ namespace QSB.Player
return null;
}
return CameraBody.transform.Find("Signalscope").GetComponent<Signalscope>();
return CameraBody?.transform.Find("Signalscope").GetComponent<Signalscope>();
}
}
@ -184,7 +184,7 @@ namespace QSB.Player
return null;
}
return CameraBody.transform.Find("NomaiTranslatorProp").GetComponent<NomaiTranslator>();
return CameraBody?.transform.Find("NomaiTranslatorProp").GetComponent<NomaiTranslator>();
}
}
@ -197,6 +197,12 @@ namespace QSB.Player
public void UpdateObjectsFromStates()
{
if (OWInput.GetInputMode() == InputMode.None)
{
// ? why is this here lmao
return;
}
if (CameraBody == null)
{
return;
}
@ -225,7 +231,30 @@ namespace QSB.Player
QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
}
private QSBTool GetToolByType(ToolType type) => CameraBody?.GetComponentsInChildren<QSBTool>()
.FirstOrDefault(x => x.Type == type);
private QSBTool GetToolByType(ToolType type)
{
if (CameraBody == null)
{
DebugLog.ToConsole($"Warning - Tried to GetToolByType({type}) on player {PlayerId}, but CameraBody was null.", MessageType.Warning);
return null;
}
var tools = CameraBody.GetComponentsInChildren<QSBTool>();
if (tools == null || tools.Length == 0)
{
DebugLog.ToConsole($"Warning - Couldn't find any QSBTools for player {PlayerId}.", MessageType.Warning);
return null;
}
var tool = tools.FirstOrDefault(x => x.Type == type);
if (tool == null)
{
DebugLog.ToConsole($"Warning - No tool found on player {PlayerId} matching ToolType {type}.", MessageType.Warning);
}
return tool;
}
}
}

View File

@ -89,7 +89,7 @@ namespace QSB.Player
player.SignalscopeEquipped = message.SignalscopeEquipped;
player.TranslatorEquipped = message.TranslatorEquipped;
player.ProbeActive = message.ProbeActive;
if (LocalPlayer.IsReady)
if (LocalPlayer.IsReady && player.IsReady)
{
player.UpdateObjectsFromStates();
}
@ -178,7 +178,7 @@ namespace QSB.Player
return null;
}
return playerList.Where(x => x.IsReady).OrderBy(x => Vector3.Distance(x.Body.transform.position, worldPoint)).FirstOrDefault();
return playerList.Where(x => x.IsReady && x.Body != null).OrderBy(x => Vector3.Distance(x.Body.transform.position, worldPoint)).FirstOrDefault();
}
public static IEnumerable<Tuple<PlayerInfo, IQSBOWItem>> GetPlayerCarryItems()

View File

@ -17,6 +17,8 @@ namespace QSB.Player.TransformSync
{
static PlayerTransformSync() => AnimControllerPatch.Init();
public override bool IsPlayerObject => true;
private Transform _visibleCameraRoot;
private Transform _networkCameraRoot => gameObject.transform.GetChild(0);
@ -58,12 +60,13 @@ namespace QSB.Player.TransformSync
base.OnSceneLoaded(oldScene, newScene, isInUniverse);
}
if (isInUniverse)
if (isInUniverse && !_isInitialized)
{
Player.IsReady = true;
QSBEventManager.FireEvent(EventNames.QSBPlayerReady, true);
Player.IsReady = false;
QSBEventManager.FireEvent(EventNames.QSBPlayerReady, false);
}
else
if (!isInUniverse)
{
Player.IsReady = false;
QSBEventManager.FireEvent(EventNames.QSBPlayerReady, false);
@ -72,6 +75,14 @@ namespace QSB.Player.TransformSync
base.OnSceneLoaded(oldScene, newScene, isInUniverse);
}
protected override void Init()
{
base.Init();
Player.IsReady = true;
QSBEventManager.FireEvent(EventNames.QSBPlayerReady, true);
}
protected override void OnDestroy()
{
// TODO : Maybe move this to a leave event...? Would ensure everything could finish up before removing the player

View File

@ -1,5 +1,4 @@
using System.Linq;
using OWML.Common;
using OWML.Common;
using OWML.ModHelper;
using OWML.ModHelper.Input;
using QSB.ConversationSync;
@ -15,6 +14,7 @@ using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET;
using QuantumUNET.Components;
using System.Linq;
using UnityEngine;
/*
@ -49,7 +49,7 @@ namespace QSB
public static bool ShowQuantumDebugBoxes => DebugMode && DebugSettings.ShowQuantumDebugBoxes;
public static bool AvoidTimeSync => DebugMode && DebugSettings.AvoidTimeSync;
public static bool SkipTitleScreen => DebugMode && DebugSettings.SkipTitleScreen;
public static AssetBundle NetworkAssetBundle { get; private set; }
public static AssetBundle NetworkAssetBundle { get; internal set; }
public static AssetBundle InstrumentAssetBundle { get; private set; }
public static AssetBundle ConversationAssetBundle { get; private set; }
public static AssetBundle DebugAssetBundle { get; private set; }
@ -60,6 +60,7 @@ namespace QSB
public static GamePlatform Platform => typeof(Achievements).Assembly.GetTypes().Any(x => x.Name == "EpicEntitlementRetriever")
? GamePlatform.Epic
: GamePlatform.Steam;
public static bool DLCInstalled => EntitlementsManager.IsDlcOwned() == EntitlementsManager.AsyncOwnershipStatus.Owned;
public static IMenuAPI MenuApi { get; private set; }
private static DebugSettings DebugSettings { get; set; } = new DebugSettings();

View File

@ -1,11 +1,11 @@
using System;
using System.Linq;
using OWML.Common;
using OWML.Common;
using OWML.Utils;
using QSB.Anglerfish.TransformSync;
using QSB.AuthoritySync;
using QSB.ClientServerStateSync;
using QSB.DeathSync;
using QSB.Events;
using QSB.JellyfishSync.TransformSync;
using QSB.Messaging;
using QSB.OrbSync.TransformSync;
using QSB.Patches;
@ -14,10 +14,14 @@ using QSB.Player.TransformSync;
using QSB.PoolSync;
using QSB.ShipSync.TransformSync;
using QSB.TimeSync;
using QSB.Tools.ProbeTool.TransformSync;
using QSB.TornadoSync.TransformSync;
using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET;
using QuantumUNET.Components;
using System;
using System.Linq;
using UnityEngine;
using UnityEngine.Networking;
@ -37,12 +41,12 @@ namespace QSB
public GameObject ShipPrefab { get; private set; }
public GameObject AnglerPrefab { get; private set; }
public GameObject JellyfishPrefab { get; private set; }
public GameObject OccasionalPrefab { get; private set; }
public string PlayerName { get; private set; }
private const int MaxConnections = 128;
private const int MaxBufferedPackets = 64;
private AssetBundle _assetBundle;
private GameObject _probePrefab;
private bool _everConnected;
@ -52,25 +56,27 @@ namespace QSB
Instance = this;
PlayerName = GetPlayerName();
_assetBundle = QSBCore.NetworkAssetBundle;
playerPrefab = _assetBundle.LoadAsset<GameObject>("Assets/Prefabs/NETWORK_Player_Body.prefab");
playerPrefab = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NETWORK_Player_Body.prefab");
ShipPrefab = _assetBundle.LoadAsset<GameObject>("assets/Prefabs/networkship.prefab");
ShipPrefab = MakeNewNetworkObject(2, "NetworkShip", typeof(ShipTransformSync));
spawnPrefabs.Add(ShipPrefab);
_probePrefab = _assetBundle.LoadAsset<GameObject>("assets/Prefabs/networkprobe.prefab");
_probePrefab = MakeNewNetworkObject(3, "NetworkProbe", typeof(PlayerProbeSync));
spawnPrefabs.Add(_probePrefab);
OrbPrefab = _assetBundle.LoadAsset<GameObject>("assets/Prefabs/networkorb.prefab");
OrbPrefab = MakeNewNetworkObject(4, "NetworkOrb", typeof(NomaiOrbTransformSync));
spawnPrefabs.Add(OrbPrefab);
AnglerPrefab = _assetBundle.LoadAsset<GameObject>("assets/Prefabs/networkangler.prefab");
AnglerPrefab = MakeNewNetworkObject(5, "NetworkAngler", typeof(AnglerTransformSync));
spawnPrefabs.Add(AnglerPrefab);
JellyfishPrefab = _assetBundle.LoadAsset<GameObject>("assets/Prefabs/networkjellyfish.prefab");
JellyfishPrefab = MakeNewNetworkObject(6, "NetworkJellyfish", typeof(JellyfishTransformSync));
spawnPrefabs.Add(JellyfishPrefab);
OccasionalPrefab = MakeNewNetworkObject(7, "NetworkOccasional", typeof(OccasionalTransformSync));
spawnPrefabs.Add(OccasionalPrefab);
ConfigureNetworkManager();
}
@ -91,6 +97,24 @@ namespace QSB
}
}
/// create a new network prefab from the network object prefab template.
/// this works by calling Unload(false) and then reloading the AssetBundle,
/// which makes LoadAsset give you a new resource.
/// see https://docs.unity3d.com/Manual/AssetBundles-Native.html.
private static GameObject MakeNewNetworkObject(int assetId, string name, Type transformSyncType)
{
QSBCore.NetworkAssetBundle.Unload(false);
QSBCore.NetworkAssetBundle = QSBCore.Helper.Assets.LoadBundle("AssetBundles/network");
var template = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NetworkObject.prefab");
DebugLog.DebugWrite($"MakeNewNetworkObject - prefab id {template.GetInstanceID()} "
+ $"for {assetId} {name} {transformSyncType.Name}");
template.name = name;
template.GetRequiredComponent<QNetworkIdentity>().SetValue("m_AssetId", assetId);
template.AddComponent(transformSyncType);
return template;
}
private void ConfigureNetworkManager()
{
networkAddress = QSBCore.DefaultServerIP;

View File

@ -2,7 +2,6 @@
using QSB.Events;
using System.Linq;
using System.Reflection;
using QSB.WorldSync;
using UnityEngine;
namespace QSB.QuantumSync.Events

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using QSB.Utility;
using QSB.Utility;
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.UI;
namespace QSB.QuantumSync.WorldObjects

View File

@ -112,7 +112,7 @@ namespace QSB.QuantumSync.WorldObjects
}
}
public List<ShapeVisibilityTracker> GetVisibilityTrackers()
public List<ShapeVisibilityTracker> GetVisibilityTrackers()
=> AttachedObject?._visibilityTrackers == null
? new()
: AttachedObject._visibilityTrackers.Select(x => (ShapeVisibilityTracker)x).ToList();

View File

@ -56,6 +56,12 @@ namespace QSB.RespawnSync
return;
}
if (PlayerTransformSync.LocalInstance == null)
{
DebugLog.ToConsole($"Error - Tried to init when PlayerTransformSync.LocalInstance was null!", OWML.Common.MessageType.Error);
return;
}
QSBPlayerManager.ShowAllPlayers();
QSBPlayerManager.LocalPlayer.UpdateStatesFromObjects();
QSBPlayerManager.PlayerList.ForEach(x => x.IsDead = false);

View File

@ -0,0 +1,47 @@
using QSB.Events;
using QSB.Menus;
using QSB.Utility;
namespace QSB.SaveSync.Events
{
// only to be sent from host
internal class GameStateEvent : QSBEvent<GameStateMessage>
{
public override bool RequireWorldObjectsReady => false;
public override void SetupListener() => GlobalMessenger<uint>.AddListener(EventNames.QSBGameDetails, Handler);
public override void CloseListener() => GlobalMessenger<uint>.RemoveListener(EventNames.QSBGameDetails, Handler);
private void Handler(uint toId) => SendEvent(CreateMessage(toId));
private GameStateMessage CreateMessage(uint toId) => new()
{
AboutId = LocalPlayerId,
ForId = toId,
InSolarSystem = QSBSceneManager.CurrentScene == OWScene.SolarSystem,
InEye = QSBSceneManager.CurrentScene == OWScene.EyeOfTheUniverse,
LaunchCodesGiven = PlayerData.KnowsLaunchCodes(),
LoopCount = StandaloneProfileManager.SharedInstance.currentProfileGameSave.loopCount,
KnownFrequencies = StandaloneProfileManager.SharedInstance.currentProfileGameSave.knownFrequencies,
KnownSignals = StandaloneProfileManager.SharedInstance.currentProfileGameSave.knownSignals
};
public override void OnReceiveRemote(bool isHost, GameStateMessage message)
{
var gameSave = StandaloneProfileManager.SharedInstance.currentProfileGameSave;
gameSave.loopCount = message.LoopCount;
gameSave.knownFrequencies = message.KnownFrequencies;
gameSave.knownSignals = message.KnownSignals;
PlayerData.SetPersistentCondition("LAUNCH_CODES_GIVEN", message.LaunchCodesGiven);
PlayerData.SaveCurrentGame();
if (message.InEye != (QSBSceneManager.CurrentScene == OWScene.EyeOfTheUniverse)
|| message.InSolarSystem != (QSBSceneManager.CurrentScene == OWScene.SolarSystem))
{
MenuManager.Instance.JoinGame(message.InEye, message.InSolarSystem);
}
}
}
}

View File

@ -0,0 +1,66 @@
using QSB.Messaging;
using QuantumUNET.Transport;
using System;
using System.Collections.Generic;
namespace QSB.SaveSync.Events
{
internal class GameStateMessage : PlayerMessage
{
public bool InSolarSystem { get; set; }
public bool InEye { get; set; }
public bool LaunchCodesGiven { get; set; }
public int LoopCount { get; set; }
public bool[] KnownFrequencies { get; set; }
public Dictionary<int, bool> KnownSignals { get; set; } = new();
public override void Deserialize(QNetworkReader reader)
{
base.Deserialize(reader);
InSolarSystem = reader.ReadBoolean();
InEye = reader.ReadBoolean();
LaunchCodesGiven = reader.ReadBoolean();
LoopCount = reader.ReadInt32();
var frequenciesLength = reader.ReadInt32();
var knownFrequencies = KnownFrequencies;
Array.Resize(ref knownFrequencies, frequenciesLength);
KnownFrequencies = knownFrequencies;
for (var i = 0; i < frequenciesLength; i++)
{
KnownFrequencies[i] = reader.ReadBoolean();
}
var signalsLength = reader.ReadInt32();
KnownSignals.Clear();
for (var i = 0; i < signalsLength; i++)
{
var key = reader.ReadInt32();
var value = reader.ReadBoolean();
KnownSignals.Add(key, value);
}
}
public override void Serialize(QNetworkWriter writer)
{
base.Serialize(writer);
writer.Write(InSolarSystem);
writer.Write(InEye);
writer.Write(LaunchCodesGiven);
writer.Write(LoopCount);
writer.Write(KnownFrequencies.Length);
foreach (var item in KnownFrequencies)
{
writer.Write(item);
}
writer.Write(KnownSignals.Count);
foreach (var item in KnownSignals)
{
writer.Write(item.Key);
writer.Write(item.Value);
}
}
}
}

View File

@ -0,0 +1,23 @@
using QSB.Events;
using QSB.Messaging;
namespace QSB.SaveSync.Events
{
internal class RequestGameStateEvent : QSBEvent<PlayerMessage>
{
public override bool RequireWorldObjectsReady => false;
public override void SetupListener() => GlobalMessenger.AddListener(EventNames.QSBRequestGameDetails, Handler);
public override void CloseListener() => GlobalMessenger.RemoveListener(EventNames.QSBRequestGameDetails, Handler);
private void Handler() => SendEvent(CreateMessage());
private PlayerMessage CreateMessage() => new()
{
AboutId = LocalPlayerId,
OnlySendToHost = true
};
public override void OnReceiveRemote(bool isHost, PlayerMessage message) => QSBEventManager.FireEvent(EventNames.QSBGameDetails, message.FromId);
}
}

View File

@ -127,7 +127,6 @@ namespace QSB.SectorSync
if (_sectorDetector == null || _attachedOWRigidbody == null || _targetType == TargetType.None)
{
IsReady = false;
DebugLog.ToConsole($"Error - SectorSync is no longer ready. Detector Null : {_sectorDetector == null}, OWRigidbody Null : {_attachedOWRigidbody == null}, None TargetType : {_targetType == TargetType.None}", MessageType.Error);
return null;
}

View File

@ -3,8 +3,8 @@ using OWML.Utils;
using QSB.Events;
using QSB.Patches;
using QSB.Utility;
using System;
using QSB.WorldSync;
using System;
using UnityEngine;
namespace QSB.ShipSync.Patches

View File

@ -10,6 +10,8 @@ namespace QSB.ShipSync.TransformSync
{
public static ShipTransformSync LocalInstance { get; private set; }
public override bool IsPlayerObject => false;
private const int ForcePositionAfterUpdates = 50;
private int _updateCount;

View File

@ -28,8 +28,6 @@ namespace QSB.StatueSync.Events
public override void OnReceiveLocal(bool server, StartStatueMessage message)
{
DebugLog.DebugWrite($"OnReceiveLocal StartStatueEvent");
if (!QSBCore.IsHost)
{
return;
@ -40,8 +38,14 @@ namespace QSB.StatueSync.Events
public override void OnReceiveRemote(bool server, StartStatueMessage message)
{
DebugLog.DebugWrite($"OnReceiveRemote StartStatueEvent");
StatueManager.Instance.BeginSequence(message.PlayerPosition, message.PlayerRotation, message.CameraDegrees);
if (!QSBCore.IsHost)
{
return;
}
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.InStatueCutscene);
}
}
}

View File

@ -1,4 +1,6 @@
using QSB.Player;
using QSB.Player.TransformSync;
using QSB.Utility;
using System.Collections;
using UnityEngine;
@ -25,6 +27,12 @@ namespace QSB.StatueSync
return;
}
if (PlayerTransformSync.LocalInstance == null)
{
DebugLog.ToConsole($"Error - Tried to run OnUniverseSceneLoaded when PlayerTransformSync.LocalInstance was null!", OWML.Common.MessageType.Error);
return;
}
QSBPlayerManager.ShowAllPlayers();
QSBPlayerManager.LocalPlayer.UpdateStatesFromObjects();
}

View File

@ -94,10 +94,20 @@ namespace QSB.Syncs.Sectored.Rigidbodies
protected void SetValuesToSync()
{
transform.position = ReferenceTransform.EncodePos(AttachedObject.transform.position);
transform.rotation = ReferenceTransform.EncodeRot(AttachedObject.transform.rotation);
_relativeVelocity = ReferenceTransform.GetAttachedOWRigidbody().EncodeVel(((OWRigidbody)AttachedObject).GetVelocity(), AttachedObject.transform.position);
_relativeAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().EncodeAngVel(((OWRigidbody)AttachedObject).GetAngularVelocity());
if (ReferenceTransform != null)
{
transform.position = ReferenceTransform.EncodePos(AttachedObject.transform.position);
transform.rotation = ReferenceTransform.EncodeRot(AttachedObject.transform.rotation);
_relativeVelocity = ReferenceTransform.GetAttachedOWRigidbody().EncodeVel(((OWRigidbody)AttachedObject).GetVelocity(), AttachedObject.transform.position);
_relativeAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().EncodeAngVel(((OWRigidbody)AttachedObject).GetAngularVelocity());
}
else
{
transform.position = Vector3.zero;
transform.rotation = Quaternion.identity;
_relativeVelocity = Vector3.zero;
_relativeAngularVelocity = Vector3.zero;
}
}
protected override bool UpdateTransform()

View File

@ -18,28 +18,6 @@ namespace QSB.Syncs
public abstract class SyncBase : QNetworkTransform
{
private static readonly Dictionary<uint, Dictionary<Type, SyncBase>> _storedTransformSyncs = new();
public static T GetPlayers<T>(PlayerInfo player)
where T : SyncBase
{
var dictOfOwnedSyncs = _storedTransformSyncs[player.PlayerId];
var wantedSync = dictOfOwnedSyncs[typeof(T)];
if (wantedSync == default)
{
DebugLog.ToConsole($"Error - _storedTransformSyncs does not contain type:{typeof(T)} under player {player.PlayerId}. Attempting to find manually...", MessageType.Error);
var allSyncs = QSBWorldSync.GetUnityObjects<T>();
wantedSync = allSyncs.First(x => x.Player == player);
if (wantedSync == default)
{
DebugLog.ToConsole($"Error - Could not find type:{typeof(T)} for player {player.PlayerId} manually!", MessageType.Error);
return default;
}
}
return (T)wantedSync;
}
public uint AttachedNetId
{
get
@ -58,6 +36,11 @@ namespace QSB.Syncs
{
get
{
if (!IsPlayerObject)
{
return uint.MaxValue;
}
if (NetIdentity == null)
{
DebugLog.ToConsole($"Error - Trying to get PlayerId with null NetIdentity! Type:{GetType().Name} GrandType:{GetType().GetType().Name}", MessageType.Error);
@ -71,17 +54,49 @@ namespace QSB.Syncs
}
public PlayerInfo Player => QSBPlayerManager.GetPlayer(PlayerId);
private bool _baseIsReady => QSBPlayerManager.PlayerExists(PlayerId)
&& Player != null
// && Player.IsReady
&& NetId.Value != uint.MaxValue
&& NetId.Value != 0U
&& WorldObjectManager.AllObjectsAdded;
private bool _baseIsReady
{
get
{
if (NetId.Value is uint.MaxValue or 0U)
{
return false;
}
if (!WorldObjectManager.AllObjectsAdded)
{
return false;
}
if (IsPlayerObject)
{
if (!QSBPlayerManager.PlayerExists(PlayerId))
{
return false;
}
if (Player == null)
{
return false;
}
if (!Player.IsReady && !IsLocalPlayer)
{
return false;
}
}
return true;
}
}
public abstract bool IsReady { get; }
public abstract bool UseInterpolation { get; }
public abstract bool IgnoreDisabledAttachedObject { get; }
public abstract bool IgnoreNullReferenceTransform { get; }
public abstract bool ShouldReparentAttachedObject { get; }
public abstract bool IsPlayerObject { get; }
public Component AttachedObject { get; set; }
public Transform ReferenceTransform { get; set; }
@ -99,26 +114,15 @@ namespace QSB.Syncs
public virtual void Start()
{
var lowestBound = QSBWorldSync.GetUnityObjects<PlayerTransformSync>()
if (IsPlayerObject)
{
var lowestBound = QSBWorldSync.GetUnityObjects<PlayerTransformSync>()
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
}
DontDestroyOnLoad(gameObject);
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
if (Player == null)
{
DebugLog.ToConsole($"Error - Player in start of {LogName} was null!", MessageType.Error);
return;
}
if (!_storedTransformSyncs.ContainsKey(PlayerId))
{
_storedTransformSyncs.Add(PlayerId, new Dictionary<Type, SyncBase>());
}
var playerDict = _storedTransformSyncs[PlayerId];
playerDict[GetType()] = this;
}
protected virtual void OnDestroy()
@ -132,14 +136,6 @@ namespace QSB.Syncs
}
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
if (!QSBPlayerManager.PlayerExists(PlayerId))
{
return;
}
var playerDict = _storedTransformSyncs[PlayerId];
playerDict.Remove(GetType());
}
protected virtual void Init()
@ -168,7 +164,6 @@ namespace QSB.Syncs
{
if (!_isInitialized && IsReady && _baseIsReady)
{
try
{
Init();

View File

@ -1,5 +1,4 @@
using OWML.Common;
using QSB.Utility;
using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET.Transport;
using UnityEngine;

View File

@ -153,6 +153,11 @@ namespace QSB.TimeSync
var myTime = Time.timeSinceLevelLoad;
var diff = myTime - _serverTime;
if (ServerStateManager.Instance.GetServerState() is not ServerState.InSolarSystem and not ServerState.InEye)
{
return;
}
if (diff > PauseOrFastForwardThreshold)
{
StartPausing(PauseReason.TooFarAhead);
@ -272,7 +277,6 @@ namespace QSB.TimeSync
{
if (CurrentState != State.Pausing)
{
DebugLog.DebugWrite($"Wait for other clients to be ready");
StartPausing(PauseReason.WaitingForAllPlayersToBeReady);
}
}
@ -281,7 +285,6 @@ namespace QSB.TimeSync
{
if (clientState == ClientState.AliveInSolarSystem && serverState == ServerState.InSolarSystem)
{
DebugLog.DebugWrite($"start of new loop!");
ResetTimeScale();
}
}
@ -346,24 +349,16 @@ namespace QSB.TimeSync
if (serverState == ServerState.NotLoaded && CurrentState != State.Pausing && QSBSceneManager.IsInUniverse)
{
DebugLog.DebugWrite($"Server Not Loaded");
StartPausing(PauseReason.ServerNotStarted);
}
if (serverState == ServerState.WaitingForAllPlayersToReady && CurrentState != State.Pausing && clientState == ClientState.WaitingForOthersToReadyInSolarSystem)
{
DebugLog.DebugWrite($"Awaiting Play Confirmation");
StartPausing(PauseReason.WaitingForAllPlayersToBeReady);
}
if (serverState == ServerState.InSolarSystem && (clientState == ClientState.WaitingForOthersToReadyInSolarSystem || clientState == ClientState.WaitingForOthersToDieInSolarSystem))
{
DebugLog.DebugWrite($"Server is still running game normally, but this player has died from an accepted death!", MessageType.Warning);
}
if (serverState == ServerState.WaitingForAllPlayersToDie && clientState == ClientState.WaitingForOthersToReadyInSolarSystem)
{
DebugLog.DebugWrite($"Wait for others to load new scene");
StartPausing(PauseReason.WaitingForAllPlayersToBeReady);
}
@ -373,7 +368,6 @@ namespace QSB.TimeSync
{
if (serverState != ServerState.NotLoaded)
{
DebugLog.DebugWrite($"Server started!");
ResetTimeScale();
}
}
@ -382,7 +376,6 @@ namespace QSB.TimeSync
{
if (clientState == ClientState.AliveInSolarSystem && serverState == ServerState.InSolarSystem)
{
DebugLog.DebugWrite($"start of new loop!");
ResetTimeScale();
}
}
@ -391,7 +384,6 @@ namespace QSB.TimeSync
{
if (Time.timeSinceLevelLoad <= _serverTime)
{
DebugLog.DebugWrite($"Done pausing to match time!");
ResetTimeScale();
}
}
@ -400,7 +392,6 @@ namespace QSB.TimeSync
{
if (Time.timeSinceLevelLoad >= _serverTime)
{
DebugLog.DebugWrite($"Done fast-forwarding to match time!");
ResetTimeScale();
}
}

View File

@ -15,6 +15,7 @@ namespace QSB.Tools.ProbeTool.TransformSync
protected override float DistanceLeeway => 10f;
public override bool UseInterpolation => true;
public override bool IgnoreDisabledAttachedObject => true;
public override bool IsPlayerObject => true;
public static PlayerProbeSync LocalInstance { get; private set; }

View File

@ -0,0 +1,32 @@
using QSB.Events;
using QSB.TornadoSync.WorldObjects;
using QSB.WorldSync;
using QSB.WorldSync.Events;
namespace QSB.TornadoSync.Events
{
public class TornadoFormStateEvent : QSBEvent<BoolWorldObjectMessage>
{
public override bool RequireWorldObjectsReady => true;
public override void SetupListener()
=> GlobalMessenger<QSBTornado>.AddListener(EventNames.QSBTornadoFormState, Handler);
public override void CloseListener()
=> GlobalMessenger<QSBTornado>.RemoveListener(EventNames.QSBTornadoFormState, Handler);
private void Handler(QSBTornado qsbTornado) => SendEvent(CreateMessage(qsbTornado));
private BoolWorldObjectMessage CreateMessage(QSBTornado qsbTornado) => new()
{
ObjectId = qsbTornado.ObjectId,
State = qsbTornado.FormState
};
public override void OnReceiveRemote(bool isHost, BoolWorldObjectMessage message)
{
var qsbTornado = QSBWorldSync.GetWorldFromId<QSBTornado>(message.ObjectId);
qsbTornado.FormState = message.State;
}
}
}

View File

@ -0,0 +1,71 @@
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
using QSB.TornadoSync.WorldObjects;
using QSB.WorldSync;
using UnityEngine;
namespace QSB.TornadoSync.Patches
{
public class TornadoPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(TornadoController), nameof(TornadoController.FixedUpdate))]
public static bool FixedUpdate(TornadoController __instance)
{
if (QSBCore.IsHost && __instance._secondsUntilFormation > 0f)
{
__instance._secondsUntilFormation -= Time.fixedDeltaTime;
if (__instance._secondsUntilFormation < 0f)
{
__instance.StartFormation();
var qsbTornado = QSBWorldSync.GetWorldFromUnity<QSBTornado>(__instance);
QSBEventManager.FireEvent(EventNames.QSBTornadoFormState, qsbTornado);
return false;
}
}
else
{
if (__instance._tornadoCollapsing)
{
__instance.UpdateCollapse();
}
else if (__instance._tornadoForming)
{
__instance.UpdateFormation();
}
if (__instance._isSectorOccupied)
{
__instance.UpdateAnimation();
if (__instance._wander)
{
var num = Mathf.PerlinNoise(Time.time * __instance._wanderRate, 0f) * 2f - 1f;
var num2 = Mathf.PerlinNoise(Time.time * __instance._wanderRate, 5f) * 2f - 1f;
var localEulerAngles = new Vector3(num * __instance._wanderDegreesX, 0f, num2 * __instance._wanderDegreesZ);
__instance.transform.localEulerAngles = localEulerAngles;
}
}
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(TornadoController), nameof(TornadoController.OnEnterCollapseTrigger))]
public static bool OnEnterCollapseTrigger(TornadoController __instance,
GameObject hitObject)
{
if (QSBCore.IsHost && hitObject.GetComponentInParent<OWRigidbody>().GetMass() > 50f)
{
__instance.StartCollapse();
var qsbTornado = QSBWorldSync.GetWorldFromUnity<QSBTornado>(__instance);
QSBEventManager.FireEvent(EventNames.QSBTornadoFormState, qsbTornado);
}
return false;
}
}
}

View File

@ -0,0 +1,49 @@
using QSB.TornadoSync.TransformSync;
using QSB.TornadoSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET;
namespace QSB.TornadoSync
{
public class TornadoManager : WorldObjectManager
{
protected override void RebuildWorldObjects(OWScene scene)
{
QSBWorldSync.Init<QSBTornado, TornadoController>();
if (!QSBCore.IsHost)
{
return;
}
foreach (var transformSync in QSBWorldSync.GetUnityObjects<OccasionalTransformSync>())
{
QNetworkServer.Destroy(transformSync.gameObject);
}
var gdBody = Locator._giantsDeep.GetOWRigidbody();
// cannon
var cannon = Locator._orbitalProbeCannon.GetRequiredComponent<OrbitalProbeLaunchController>();
SpawnOccasional(cannon.GetAttachedOWRigidbody(), gdBody);
foreach (var proxy in cannon._realDebrisSectorProxies)
{
SpawnOccasional(proxy.transform.root.GetAttachedOWRigidbody(), gdBody);
}
SpawnOccasional(cannon._probeBody, gdBody);
// islands
foreach (var island in QSBWorldSync.GetUnityObjects<IslandController>())
{
SpawnOccasional(island._islandBody, gdBody);
}
}
private static void SpawnOccasional(OWRigidbody body, OWRigidbody refBody)
{
var transformSync = Instantiate(QSBNetworkManager.Instance.OccasionalPrefab).GetRequiredComponent<OccasionalTransformSync>();
transformSync.InitBodyIndexes(body, refBody);
transformSync.gameObject.SpawnWithServerAuthority();
}
}
}

View File

@ -0,0 +1,185 @@
using System.Collections.Generic;
using System.Linq;
using QSB.Player.TransformSync;
using QSB.ShipSync.TransformSync;
using QSB.Syncs;
using QSB.Syncs.Unsectored.Rigidbodies;
using QSB.Tools.ProbeTool.TransformSync;
using QSB.WorldSync;
using QuantumUNET.Transport;
using UnityEngine;
namespace QSB.TornadoSync.TransformSync
{
public class OccasionalTransformSync : UnsectoredRigidbodySync
{
public override bool IsReady => WorldObjectManager.AllObjectsReady;
public override bool UseInterpolation => false;
public override bool IsPlayerObject => false;
protected override OWRigidbody GetRigidbody() => CenterOfTheUniverse.s_rigidbodies[_bodyIndex];
private int _bodyIndex = -1;
private int _refBodyIndex = -1;
private Sector[] _sectors;
private OWRigidbody[] _orbs;
public void InitBodyIndexes(OWRigidbody body, OWRigidbody refBody)
{
_bodyIndex = CenterOfTheUniverse.s_rigidbodies.IndexOf(body);
_refBodyIndex = CenterOfTheUniverse.s_rigidbodies.IndexOf(refBody);
}
public override float GetNetworkSendInterval() => 20;
protected override void Init()
{
base.Init();
SetReferenceTransform(CenterOfTheUniverse.s_rigidbodies[_refBodyIndex].transform);
_sectors = SectorManager.s_sectors
.Where(x => x._attachedOWRigidbody == AttachedObject).ToArray();
_orbs = QSBWorldSync.OldOrbList
.Where(x => _sectors.Contains(x._sector))
.Select(x => x._orbBody).ToArray();
}
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
base.SerializeTransform(writer, initialState);
if (initialState)
{
writer.Write(_bodyIndex);
writer.Write(_refBodyIndex);
}
}
private bool _shouldUpdate;
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
base.DeserializeTransform(reader, initialState);
if (initialState)
{
_bodyIndex = reader.ReadInt32();
_refBodyIndex = reader.ReadInt32();
}
if (!WorldObjectManager.AllObjectsReady || HasAuthority)
{
return;
}
_shouldUpdate = true;
}
protected override bool UpdateTransform()
{
if (HasAuthority)
{
SetValuesToSync();
return true;
}
if (!_shouldUpdate)
{
return false;
}
_shouldUpdate = false;
var hasMoved = CustomHasMoved(
transform.position,
_localPrevPosition,
transform.rotation,
_localPrevRotation,
_relativeVelocity,
_localPrevVelocity,
_relativeAngularVelocity,
_localPrevAngularVelocity);
_localPrevPosition = transform.position;
_localPrevRotation = transform.rotation;
_localPrevVelocity = _relativeVelocity;
_localPrevAngularVelocity = _relativeAngularVelocity;
if (!hasMoved)
{
return true;
}
if (_sectors.Contains(PlayerTransformSync.LocalInstance?.ReferenceSector?.AttachedObject))
{
QueueMove(Locator._playerBody);
}
if (_sectors.Contains(ShipTransformSync.LocalInstance?.ReferenceSector?.AttachedObject))
{
QueueMove(Locator._shipBody);
}
if (_sectors.Contains(PlayerProbeSync.LocalInstance?.ReferenceSector?.AttachedObject))
{
QueueMove(Locator._probe._owRigidbody);
}
foreach (var orb in _orbs)
{
QueueMove(orb);
}
var pos = ReferenceTransform.DecodePos(transform.position);
((OWRigidbody)AttachedObject).SetPosition(pos);
((OWRigidbody)AttachedObject).SetRotation(ReferenceTransform.DecodeRot(transform.rotation));
((OWRigidbody)AttachedObject).SetVelocity(ReferenceTransform.GetAttachedOWRigidbody().DecodeVel(_relativeVelocity, pos));
((OWRigidbody)AttachedObject).SetAngularVelocity(ReferenceTransform.GetAttachedOWRigidbody().DecodeAngVel(_relativeAngularVelocity));
Move();
return true;
}
private readonly List<MoveData> _toMove = new();
private struct MoveData
{
public OWRigidbody Child;
public Vector3 RelPos;
public Quaternion RelRot;
public Vector3 RelVel;
public Vector3 RelAngVel;
}
private void QueueMove(OWRigidbody child)
{
if (child.transform.parent != null)
{
// it's parented to AttachedObject or one of its children
return;
}
var pos = child.GetPosition();
_toMove.Add(new MoveData
{
Child = child,
RelPos = ((OWRigidbody)AttachedObject).transform.EncodePos(pos),
RelRot = ((OWRigidbody)AttachedObject).transform.EncodeRot(child.GetRotation()),
RelVel = ((OWRigidbody)AttachedObject).EncodeVel(child.GetVelocity(), pos),
RelAngVel = ((OWRigidbody)AttachedObject).EncodeAngVel(child.GetAngularVelocity())
});
}
private void Move()
{
foreach (var data in _toMove)
{
var pos = ((OWRigidbody)AttachedObject).transform.DecodePos(data.RelPos);
data.Child.SetPosition(pos);
data.Child.SetRotation(((OWRigidbody)AttachedObject).transform.DecodeRot(data.RelRot));
data.Child.SetVelocity(((OWRigidbody)AttachedObject).DecodeVel(data.RelVel, pos));
data.Child.SetAngularVelocity(((OWRigidbody)AttachedObject).DecodeAngVel(data.RelAngVel));
}
_toMove.Clear();
}
}
}

View File

@ -0,0 +1,37 @@
using QSB.WorldSync;
namespace QSB.TornadoSync.WorldObjects
{
public class QSBTornado : WorldObject<TornadoController>
{
public override void Init(TornadoController attachedObject, int id)
{
ObjectId = id;
AttachedObject = attachedObject;
}
public bool FormState
{
get => AttachedObject._tornadoRoot.activeSelf // forming or formed or collapsing
&& !AttachedObject._tornadoCollapsing; // and not collapsing
set
{
if (FormState == value)
{
return;
}
if (value)
{
AttachedObject._tornadoCollapsing = false;
AttachedObject.StartFormation();
}
else
{
AttachedObject._secondsUntilFormation = 0;
AttachedObject.StartCollapse();
}
}
}
}
}

View File

@ -1,9 +1,7 @@
using QSB.ClientServerStateSync;
using QSB.OrbSync.TransformSync;
using QSB.OrbSync.WorldObjects;
using QSB.Player;
using QSB.QuantumSync;
using QSB.QuantumSync.WorldObjects;
using QSB.ShipSync;
using QSB.ShipSync.TransformSync;
using QSB.ShipSync.WorldObjects;
@ -11,7 +9,6 @@ using QSB.TimeSync;
using QSB.WorldSync;
using System.Linq;
using UnityEngine;
using UnityEngine.Assertions.Must;
namespace QSB.Utility
{
@ -112,6 +109,12 @@ namespace QSB.Utility
WriteLine(1, $"Timescale : {OWTime.GetTimeScale()}");
WriteLine(1, $"Time Remaining : {Mathf.Floor(TimeLoop.GetSecondsRemaining() / 60f)}:{Mathf.Round(TimeLoop.GetSecondsRemaining() % 60f * 100f / 100f)}");
WriteLine(1, $"Loop Count : {TimeLoop.GetLoopCount()}");
WriteLine(1, $"TimeLoop Initialized : {TimeLoop._initialized}");
if (TimeLoop._initialized)
{
WriteLine(1, $"TimeLoop IsTimeFlowing : {TimeLoop.IsTimeFlowing()}");
WriteLine(1, $"TimeLoop IsTimeLoopEnabled : {TimeLoop.IsTimeLoopEnabled()}");
}
}
#endregion

View File

@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OWML.Common;
using OWML.Common;
using QSB.OrbSync.TransformSync;
using QSB.OrbSync.WorldObjects;
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QSB.WorldSync

View File

@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using OWML.Common;
using OWML.Common;
using QSB.Player;
using QSB.Utility;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace QSB.WorldSync
@ -49,25 +49,19 @@ namespace QSB.WorldSync
{
if (!QSBNetworkManager.Instance.IsReady)
{
DebugLog.ToConsole($"Warning - Tried to rebuild WorldObjects when Network Manager not ready!", OWML.Common.MessageType.Warning);
DebugLog.ToConsole($"Warning - Tried to rebuild WorldObjects when Network Manager not ready! Building when ready...", MessageType.Warning);
QSBCore.UnityEvents.RunWhen(() => QSBNetworkManager.Instance.IsReady, () => Rebuild(scene));
return;
}
if (QSBPlayerManager.LocalPlayerId == uint.MaxValue)
{
DebugLog.ToConsole($"Warning - Tried to rebuild WorldObjects when LocalPlayer is not ready!", OWML.Common.MessageType.Warning);
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));
return;
}
if (QSBPlayerManager.LocalPlayer.IsReady)
{
DoRebuild(scene);
return;
}
QSBCore.UnityEvents.RunWhen(() => QSBPlayerManager.LocalPlayer.IsReady, () => DoRebuild(scene));
DoRebuild(scene);
}
private static void DoRebuild(OWScene scene)

View File

@ -1,6 +1,6 @@
{
"debugMode": true,
"drawLines": true,
"drawLines": false,
"showQuantumVisibilityObjects": false,
"showQuantumDebugBoxes": false,
"avoidTimeSync": false,

View File

@ -1,6 +1,6 @@
using QuantumUNET.Components;
using System.Collections.Generic;
using QuantumUNET.Messages;
using System.Collections.Generic;
using UnityEngine;
namespace QuantumUNET

View File

@ -1259,7 +1259,16 @@ namespace QuantumUNET
if (handlers.ContainsKey(msgType) && m_LocalConnection != null)
{
var writer = new QNetworkWriter();
msg.Serialize(writer);
try
{
msg.Serialize(writer);
}
catch (Exception ex)
{
QLog.Error($"Error serializing msgId:{msgType} - {ex}");
return false;
}
var reader = new QNetworkReader(writer);
m_LocalConnection.InvokeHandler(msgType, reader, channelId);
result = true;