Merge pull request #311 from misternebula/fixes

Fixes
This commit is contained in:
_nebula 2021-10-18 09:43:43 +01:00 committed by GitHub
commit 94e746b0e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
167 changed files with 2978 additions and 2440 deletions

Binary file not shown.

View File

@ -1,24 +1,24 @@
ManifestFileVersion: 0
CRC: 3469869292
CRC: 1518538429
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 55d90dfc169d4fd552679840c1474222
Hash: cda9c91e090f27b94734bfca3a7cb9e2
TypeTreeHash:
serializedVersion: 2
Hash: 6ce89620af51ba381c9e4f226a2ebb1b
Hash: 90db08ff16f71e0f4005d38a4650eff2
HashAppended: 0
ClassTypes:
- Class: 1
Script: {instanceID: 0}
- Class: 114
Script: {fileID: 1741964061, guid: f70555f144d8491a825f0804e09c671c, type: 3}
Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
- Class: 114
Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
- Class: 114
Script: {fileID: -900027084, guid: f70555f144d8491a825f0804e09c671c, type: 3}
Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
- Class: 114
Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
Script: {fileID: 11500000, guid: e19747de3f5aca642ab2be37e372fb86, type: 3}
- Class: 115
Script: {instanceID: 0}
- Class: 222
@ -27,6 +27,7 @@ ClassTypes:
Script: {instanceID: 0}
- Class: 224
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/DialogueBubble.prefab
Dependencies: []

Binary file not shown.

View File

@ -1,26 +1,34 @@
ManifestFileVersion: 0
CRC: 2815158869
CRC: 3009665417
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 5677b7876f2afae05c0920067ef29e8a
Hash: dbc913ca95e649d2e00d188ff573830e
TypeTreeHash:
serializedVersion: 2
Hash: 4d6a73cb377370ba69c96eb5da1b5028
Hash: b2ece8ae09df261ff59d764d08696641
HashAppended: 0
ClassTypes:
- Class: 1
Script: {instanceID: 0}
- Class: 4
Script: {instanceID: 0}
- Class: 21
Script: {instanceID: 0}
- Class: 23
Script: {instanceID: 0}
- Class: 28
Script: {instanceID: 0}
- Class: 33
Script: {instanceID: 0}
- Class: 43
Script: {instanceID: 0}
- Class: 48
Script: {instanceID: 0}
- Class: 114
Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
- Class: 114
Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
- Class: 115
Script: {instanceID: 0}
- Class: 128
@ -31,6 +39,11 @@ ClassTypes:
Script: {instanceID: 0}
- Class: 224
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/Cube.prefab
- Assets/Capsule.prefab
- Assets/DebugVis.mat
- Assets/LogCanvas.prefab
- Assets/Sphere.prefab
Dependencies: []

Binary file not shown.

View File

@ -1,12 +1,12 @@
ManifestFileVersion: 0
CRC: 3621554448
CRC: 1991351671
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: c9002a0b83220186e94179a065236b5c
Hash: 494875ba5d9a67b7d87421e95e386357
TypeTreeHash:
serializedVersion: 2
Hash: 8b6abf066340f652e25eed06e6b72102
Hash: 6968c5d2bbef57a79632abd61ea01bb3
HashAppended: 0
ClassTypes:
- Class: 1
@ -14,13 +14,14 @@ ClassTypes:
- Class: 4
Script: {instanceID: 0}
- Class: 114
Script: {fileID: 372142912, guid: dc443db3e92b4983b9738c1131f555cb, type: 3}
Script: {fileID: 372142912, guid: 93b08009869340045a8e7321508b6355, type: 3}
- Class: 114
Script: {fileID: -1768714887, guid: dc443db3e92b4983b9738c1131f555cb, type: 3}
Script: {fileID: -1768714887, guid: 93b08009869340045a8e7321508b6355, type: 3}
- Class: 114
Script: {fileID: -1267208747, guid: dc443db3e92b4983b9738c1131f555cb, type: 3}
Script: {fileID: -1267208747, guid: 93b08009869340045a8e7321508b6355, type: 3}
- Class: 115
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/NetworkProbe.prefab
- Assets/NETWORK_Player_Body.prefab

View File

@ -12,7 +12,7 @@ namespace QSB.Animation.NPC
QSBWorldSync.Init<QSBCharacterAnimController, CharacterAnimController>();
QSBWorldSync.Init<QSBTravelerController, TravelerController>();
//TODO : this is the wrong place to put this... move it to Conversations?
//MOVE : this is the wrong place to put this... move it to Conversations?
QSBWorldSync.OldDialogueTrees.Clear();
QSBWorldSync.OldDialogueTrees = Resources.FindObjectsOfTypeAll<CharacterDialogueTree>().ToList();
}

View File

@ -1,4 +1,5 @@
using OWML.Common;
using HarmonyLib;
using OWML.Common;
using QSB.Animation.NPC.WorldObjects;
using QSB.ConversationSync;
using QSB.Events;
@ -12,22 +13,14 @@ using UnityEngine;
namespace QSB.Animation.NPC.Patches
{
[HarmonyPatch]
public class CharacterAnimationPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(CharacterAnimController_OnAnimatorIK));
Prefix(nameof(CharacterAnimController_OnZoneEntry));
Prefix(nameof(CharacterAnimController_OnZoneExit));
Prefix(nameof(FacePlayerWhenTalking_OnStartConversation));
Prefix(nameof(CharacterDialogueTree_StartConversation));
Prefix(nameof(CharacterDialogueTree_EndConversation));
Prefix(nameof(KidRockController_Update));
}
public static bool CharacterAnimController_OnAnimatorIK(
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterAnimController), nameof(CharacterAnimController.OnAnimatorIK))]
public static bool AnimatorIKReplacement(
CharacterAnimController __instance,
float ___headTrackingWeight,
bool ___lookOnlyWhenTalking,
@ -39,14 +32,14 @@ namespace QSB.Animation.NPC.Patches
Animator ____animator,
CharacterDialogueTree ____dialogueTree)
{
if (!WorldObjectManager.AllReady)
if (!WorldObjectManager.AllReady || ConversationManager.Instance == null)
{
return false;
}
var playerId = ConversationManager.Instance.GetPlayerTalkingToTree(____dialogueTree);
var player = QSBPlayerManager.GetPlayer(playerId);
var qsbObj = QSBWorldSync.GetWorldFromUnity<QSBCharacterAnimController, CharacterAnimController>(__instance); // TODO : maybe cache this somewhere... or assess how slow this is
var qsbObj = QSBWorldSync.GetWorldFromUnity<QSBCharacterAnimController, CharacterAnimController>(__instance); // OPTIMIZE : maybe cache this somewhere... or assess how slow this is
PlayerInfo playerToUse = null;
if (____inConversation)
@ -63,7 +56,7 @@ namespace QSB.Animation.NPC.Patches
: player;
}
}
else if (!___lookOnlyWhenTalking && qsbObj.GetPlayersInHeadZone().Count != 0) // TODO : maybe this would be more fun if characters looked between players at random times? :P
else if (!___lookOnlyWhenTalking && qsbObj.GetPlayersInHeadZone().Count != 0) // IDEA : maybe this would be more fun if characters looked between players at random times? :P
{
playerToUse = QSBPlayerManager.GetClosestPlayerToWorldPoint(qsbObj.GetPlayersInHeadZone(), __instance.transform.position);
}
@ -103,21 +96,27 @@ namespace QSB.Animation.NPC.Patches
}
public static bool CharacterAnimController_OnZoneExit(CharacterAnimController __instance)
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterAnimController), nameof(CharacterAnimController.OnZoneExit))]
public static bool HeadZoneExit(CharacterAnimController __instance)
{
var qsbObj = QSBWorldSync.GetWorldFromUnity<QSBCharacterAnimController, CharacterAnimController>(__instance);
QSBEventManager.FireEvent(EventNames.QSBExitHeadZone, qsbObj.ObjectId);
return false;
}
public static bool CharacterAnimController_OnZoneEntry(CharacterAnimController __instance)
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterAnimController), nameof(CharacterAnimController.OnZoneEntry))]
public static bool HeadZoneEntry(CharacterAnimController __instance)
{
var qsbObj = QSBWorldSync.GetWorldFromUnity<QSBCharacterAnimController, CharacterAnimController>(__instance);
QSBEventManager.FireEvent(EventNames.QSBEnterHeadZone, qsbObj.ObjectId);
return false;
}
public static bool FacePlayerWhenTalking_OnStartConversation(
[HarmonyPrefix]
[HarmonyPatch(typeof(FacePlayerWhenTalking), nameof(FacePlayerWhenTalking.OnStartConversation))]
public static bool OnStartConversation(
FacePlayerWhenTalking __instance,
CharacterDialogueTree ____dialogueTree)
{
@ -140,7 +139,9 @@ namespace QSB.Animation.NPC.Patches
return false;
}
public static bool CharacterDialogueTree_StartConversation(CharacterDialogueTree __instance)
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.StartConversation))]
public static bool StartConversation(CharacterDialogueTree __instance)
{
var allNpcAnimControllers = QSBWorldSync.GetWorldObjects<INpcAnimController>();
var ownerOfThis = allNpcAnimControllers.FirstOrDefault(x => x.GetDialogueTree() == __instance);
@ -154,7 +155,9 @@ namespace QSB.Animation.NPC.Patches
return true;
}
public static bool CharacterDialogueTree_EndConversation(CharacterDialogueTree __instance)
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.EndConversation))]
public static bool EndConversation(CharacterDialogueTree __instance)
{
var allNpcAnimControllers = QSBWorldSync.GetWorldObjects<INpcAnimController>();
var ownerOfThis = allNpcAnimControllers.FirstOrDefault(x => x.GetDialogueTree() == __instance);
@ -168,7 +171,9 @@ namespace QSB.Animation.NPC.Patches
return true;
}
public static bool KidRockController_Update(
[HarmonyPrefix]
[HarmonyPatch(typeof(KidRockController), nameof(KidRockController.Update))]
public static bool UpdateReplacement(
KidRockController __instance,
bool ____throwingRock,
CharacterDialogueTree ____dialogueTree,

View File

@ -41,7 +41,7 @@ namespace QSB.Animation.Player
return;
}
var jumpChargeFraction = _playerController.GetJumpChargeFraction();
var jumpChargeFraction = _playerController.GetJumpCrouchFraction();
_crouchValue = jumpChargeFraction;
}

View File

@ -1,4 +1,5 @@
using QSB.Events;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
using QSB.Player;
using QSB.Utility;
@ -6,27 +7,27 @@ using UnityEngine;
namespace QSB.Animation.Patches
{
[HarmonyPatch]
internal class PlayerAnimationPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
=> Prefix(nameof(PlayerAnimController_LateUpdate));
public static bool PlayerAnimController_LateUpdate(
PlayerAnimController __instance,
PlayerCharacterController ____playerController,
ThrusterModel ____playerJetpack,
ref float ____ungroundedTime,
Animator ____animator,
ref bool ____justBecameGrounded,
ref bool ____justTookFallDamage,
ref bool ____leftFootGrounded,
ref bool ____rightFootGrounded,
ref bool ____rightArmHidden,
GameObject[] ____rightArmObjects,
int ____defaultLayer,
int ____probeOnlyLayer)
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerAnimController), nameof(PlayerAnimController.LateUpdate))]
public static bool LateUpdateReplacement(
PlayerAnimController __instance,
PlayerCharacterController ____playerController,
ThrusterModel ____playerJetpack,
ref float ____ungroundedTime,
Animator ____animator,
ref bool ____justBecameGrounded,
ref bool ____justTookFallDamage,
ref bool ____leftFootGrounded,
ref bool ____rightFootGrounded,
ref bool ____rightArmHidden,
GameObject[] ____rightArmObjects,
int ____defaultLayer,
int ____probeOnlyLayer)
{
var isGrounded = ____playerController.IsGrounded();
var isAttached = PlayerState.IsAttached();
@ -66,7 +67,7 @@ namespace QSB.Animation.Patches
____animator.SetFloat("RunSpeedY", movementVector.z / 3f);
____animator.SetFloat("TurnSpeed", ____playerController.GetTurning());
____animator.SetBool("Grounded", isGrounded || isAttached || PlayerState.IsRecentlyDetached());
____animator.SetLayerWeight(1, ____playerController.GetJumpChargeFraction());
____animator.SetLayerWeight(1, ____playerController.GetJumpCrouchFraction());
____animator.SetFloat("FreefallSpeed", freefallMagnitude / 15f * (timeInFreefall / 3f));
____animator.SetBool("InZeroG", isInZeroG || isFlying);
____animator.SetBool("UsingJetpack", isInZeroG && PlayerState.IsWearingSuit());

View File

@ -1,20 +1,22 @@
using QSB.CampfireSync.WorldObjects;
using HarmonyLib;
using QSB.CampfireSync.WorldObjects;
using QSB.Events;
using QSB.Patches;
using QSB.WorldSync;
namespace QSB.CampfireSync.Patches
{
[HarmonyPatch]
internal class CampfirePatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches() => Prefix(nameof(Campfire_OnPressInteract));
public static bool Campfire_OnPressInteract(Campfire __instance, Campfire.State ____state)
[HarmonyPrefix]
[HarmonyPatch(typeof(Campfire), nameof(Campfire.OnPressInteract))]
public static bool LightCampfireEvent(Campfire __instance)
{
var qsbCampfire = QSBWorldSync.GetWorldFromUnity<QSBCampfire, Campfire>(__instance);
if (____state == Campfire.State.LIT)
if (__instance._state == Campfire.State.LIT)
{
qsbCampfire.StartRoasting();
}

View File

@ -8,6 +8,8 @@
DeadInSolarSystem,
AliveInEye,
WaitingForOthersToDieInSolarSystem,
WaitingForOthersToReadyInSolarSystem
WaitingForOthersToReadyInSolarSystem,
WatchingLongCredits,
WatchingShortCredits
}
}

View File

@ -13,7 +13,7 @@ namespace QSB.ClientServerStateSync
public event ChangeStateEvent OnChangeState;
public delegate void ChangeStateEvent(ClientState newState);
private void Awake()
private void Awake()
=> Instance = this;
private void Start()
@ -28,6 +28,7 @@ namespace QSB.ClientServerStateSync
{
return;
}
DebugLog.DebugWrite($"CHANGE CLIENT STATE FROM {QSBPlayerManager.LocalPlayer.State} to {newState}");
QSBPlayerManager.LocalPlayer.State = newState;
OnChangeState?.Invoke(newState);
@ -37,48 +38,99 @@ namespace QSB.ClientServerStateSync
{
var serverState = ServerStateManager.Instance.GetServerState();
ClientState newState;
if (QSBCore.IsHost)
{
if (newScene == OWScene.SolarSystem && oldScene != OWScene.SolarSystem)
{
DebugLog.DebugWrite($"Server is loading SolarSystem just after creating server.");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.AliveInSolarSystem);
}
if (newScene == OWScene.SolarSystem && oldScene == OWScene.SolarSystem)
switch (newScene)
{
DebugLog.DebugWrite($"Server is reloading SolarSystem");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.WaitingForOthersToReadyInSolarSystem);
}
if (newScene == OWScene.TitleScreen)
{
DebugLog.DebugWrite($"Server has gone back to title screen");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.InTitleScreen);
case OWScene.TitleScreen:
DebugLog.DebugWrite($"SERVER LOAD TITLESCREEN");
newState = ClientState.InTitleScreen;
break;
case OWScene.Credits_Fast:
DebugLog.DebugWrite($"SERVER LOAD SHORT CREDITS");
newState = ClientState.WatchingShortCredits;
break;
case OWScene.Credits_Final:
case OWScene.PostCreditsScene:
DebugLog.DebugWrite($"SERVER LOAD LONG CREDITS");
newState = ClientState.WatchingLongCredits;
break;
case OWScene.SolarSystem:
if (oldScene == OWScene.SolarSystem)
{
// reloading scene
DebugLog.DebugWrite($"SERVER RELOAD SOLARSYSTEM");
newState = ClientState.WaitingForOthersToReadyInSolarSystem;
}
else
{
// loading in from title screen
DebugLog.DebugWrite($"SERVER LOAD SOLARSYSTEM");
newState = ClientState.AliveInSolarSystem;
}
break;
default:
newState = ClientState.NotLoaded;
break;
}
}
else
{
if (newScene == OWScene.SolarSystem && oldScene != OWScene.SolarSystem && serverState != ServerState.AwaitingPlayConfirmation)
switch (newScene)
{
DebugLog.DebugWrite($"Client is loading SolarSystem just after connecting.");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.AliveInSolarSystem);
}
case OWScene.TitleScreen:
DebugLog.DebugWrite($"CLIENT LOAD TITLESCREEN");
newState = ClientState.InTitleScreen;
break;
case OWScene.Credits_Fast:
DebugLog.DebugWrite($"CLIENT LOAD SHORT CREDITS");
newState = ClientState.WatchingShortCredits;
break;
case OWScene.Credits_Final:
case OWScene.PostCreditsScene:
DebugLog.DebugWrite($"CLIENT LOAD LONG CREDITS");
newState = ClientState.WatchingLongCredits;
break;
case OWScene.SolarSystem:
if (serverState == ServerState.WaitingForAllPlayersToDie)
{
DebugLog.DebugWrite($"SEVER IN DEATH PHASE - WAIT");
newState = ClientState.WaitingForOthersToReadyInSolarSystem;
break;
}
if (newScene == OWScene.SolarSystem && oldScene == OWScene.SolarSystem)
{
DebugLog.DebugWrite($"Client is reloading SolarSystem");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.WaitingForOthersToReadyInSolarSystem);
}
if (serverState == ServerState.WaitingForDeath)
{
DebugLog.DebugWrite($"Client loaded new scene while server is waiting for all players to die");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.WaitingForOthersToReadyInSolarSystem);
if (oldScene == OWScene.SolarSystem)
{
// reloading scene
DebugLog.DebugWrite($"CLIENT RELOAD SOLARSYSTEM");
newState = ClientState.WaitingForOthersToReadyInSolarSystem;
}
else
{
// loading in from title screen
DebugLog.DebugWrite($"CLIENT LOAD SOLARSYSTEM");
if (serverState == ServerState.WaitingForAllPlayersToReady)
{
newState = ClientState.WaitingForOthersToReadyInSolarSystem;
}
else
{
newState = ClientState.AliveInSolarSystem;
}
}
break;
default:
newState = ClientState.NotLoaded;
break;
}
}
QSBEventManager.FireEvent(EventNames.QSBClientState, newState);
}
public void OnDeath()
{
var currentScene = QSBSceneManager.CurrentScene;
@ -97,29 +149,48 @@ namespace QSB.ClientServerStateSync
}
}
public void OnRespawn()
{
var currentScene = QSBSceneManager.CurrentScene;
if (currentScene == OWScene.SolarSystem)
{
DebugLog.DebugWrite($"RESPAWN!");
QSBEventManager.FireEvent(EventNames.QSBClientState, ClientState.AliveInSolarSystem);
}
else
{
DebugLog.ToConsole($"Error - Player tried to respawn in scene {currentScene}", OWML.Common.MessageType.Error);
}
}
private ClientState ForceGetCurrentState()
{
DebugLog.DebugWrite($"ForceGetCurrentState");
var currentScene = LoadManager.GetCurrentScene();
var lastScene = LoadManager.GetPreviousScene();
if (currentScene == OWScene.TitleScreen || currentScene == OWScene.Credits_Fast || currentScene == OWScene.Credits_Final)
switch (currentScene)
{
return ClientState.InTitleScreen;
case OWScene.TitleScreen:
DebugLog.DebugWrite($"- TitleScreen");
return ClientState.InTitleScreen;
case OWScene.Credits_Fast:
DebugLog.DebugWrite($"- Short Credits");
return ClientState.WatchingShortCredits;
case OWScene.Credits_Final:
case OWScene.PostCreditsScene:
DebugLog.DebugWrite($"- Long Credits");
return ClientState.WatchingLongCredits;
case OWScene.SolarSystem:
DebugLog.DebugWrite($"- SolarSystem");
return ClientState.AliveInSolarSystem;
case OWScene.EyeOfTheUniverse:
DebugLog.DebugWrite($"- Eye");
return ClientState.AliveInEye;
default:
DebugLog.DebugWrite($"- Not Loaded");
return ClientState.NotLoaded;
}
// cant join while dead...
if (currentScene == OWScene.SolarSystem)
{
return ClientState.AliveInSolarSystem;
}
if (currentScene == OWScene.EyeOfTheUniverse)
{
return ClientState.AliveInEye;
}
return ClientState.NotLoaded;
}
}
}

View File

@ -28,12 +28,12 @@ namespace QSB.ClientServerStateSync.Events
public override void OnReceiveRemote(bool server, EnumMessage<ClientState> message)
{
DebugLog.DebugWrite($"Remote receive id:{message.AboutId} state:{message.EnumValue}");
if (message.AboutId == uint.MaxValue)
{
DebugLog.DebugWrite($"Error - ID is uint.MaxValue!", OWML.Common.MessageType.Error);
return;
}
var player = QSBPlayerManager.GetPlayer(message.AboutId);
player.State = message.EnumValue;
}

View File

@ -21,10 +21,10 @@ namespace QSB.ClientServerStateSync.Events
EnumValue = state
};
public override void OnReceiveLocal(bool server, EnumMessage<ServerState> message)
public override void OnReceiveLocal(bool server, EnumMessage<ServerState> message)
=> OnReceiveRemote(server, message);
public override void OnReceiveRemote(bool server, EnumMessage<ServerState> message)
public override void OnReceiveRemote(bool server, EnumMessage<ServerState> message)
=> ServerStateManager.Instance.ChangeServerState(message.EnumValue);
}
}

View File

@ -15,10 +15,10 @@
InEye,
// At end of loop, waiting for everyone to be ready to reload the scene
WaitingForDeath,
WaitingForAllPlayersToDie,
// At start of loop, waiting for everybody to be ready to start playing
AwaitingPlayConfirmation,
WaitingForAllPlayersToReady,
// When the statue has been activated
InStatueCutscene

View File

@ -16,7 +16,7 @@ namespace QSB.ClientServerStateSync
private ServerState _currentState;
private void Awake()
private void Awake()
=> Instance = this;
private void Start()
@ -25,6 +25,7 @@ namespace QSB.ClientServerStateSync
{
return;
}
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
GlobalMessenger.AddListener("TriggerSupernova", OnTriggerSupernova);
@ -37,12 +38,12 @@ namespace QSB.ClientServerStateSync
{
return;
}
DebugLog.DebugWrite($"CHANGE SERVER STATE FROM {_currentState} to {newState}");
_currentState = newState;
OnChangeState?.Invoke(newState);
}
public ServerState GetServerState()
public ServerState GetServerState()
=> _currentState;
private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool inUniverse)
@ -52,26 +53,31 @@ namespace QSB.ClientServerStateSync
case OWScene.Credits_Fast:
case OWScene.Credits_Final:
case OWScene.PostCreditsScene:
DebugLog.DebugWrite($"SERVER LOAD CREDITS");
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.Credits);
break;
case OWScene.TitleScreen:
DebugLog.DebugWrite($"SERVER LOAD TITLE SCREEN");
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.NotLoaded);
break;
case OWScene.SolarSystem:
DebugLog.DebugWrite($"SERVER LOAD SOLARSYSTEM");
if (oldScene == OWScene.SolarSystem)
{
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.AwaitingPlayConfirmation);
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForAllPlayersToReady);
}
else
{
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.InSolarSystem);
}
break;
case OWScene.EyeOfTheUniverse:
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.AwaitingPlayConfirmation);
DebugLog.DebugWrite($"EYE");
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForAllPlayersToReady);
break;
case OWScene.None:
@ -86,21 +92,26 @@ namespace QSB.ClientServerStateSync
private void OnTriggerSupernova()
{
DebugLog.DebugWrite($"TriggerSupernova");
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForDeath);
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForAllPlayersToDie);
}
private ServerState ForceGetCurrentState()
{
DebugLog.DebugWrite($"ForceGetCurrentState");
var currentScene = LoadManager.GetCurrentScene();
var lastScene = LoadManager.GetPreviousScene();
switch (currentScene)
{
case OWScene.SolarSystem:
DebugLog.DebugWrite($"- SolarSystem");
return ServerState.InSolarSystem;
case OWScene.EyeOfTheUniverse:
DebugLog.DebugWrite($"- Eye");
return ServerState.InEye;
default:
DebugLog.DebugWrite($"- Not Loaded");
return ServerState.NotLoaded;
}
}
@ -112,7 +123,7 @@ namespace QSB.ClientServerStateSync
return;
}
if (_currentState == ServerState.AwaitingPlayConfirmation)
if (_currentState == ServerState.WaitingForAllPlayersToReady)
{
if (QSBPlayerManager.PlayerList.All(x => x.State == ClientState.WaitingForOthersToReadyInSolarSystem))
{

View File

@ -0,0 +1,30 @@
using UnityEngine;
public class CameraFacingBillboard : MonoBehaviour
{
private OWCamera _activeCam;
private void Awake()
=> GlobalMessenger<OWCamera>.AddListener("SwitchActiveCamera", OnSwitchActiveCamera);
private void Start()
{
_activeCam = Locator.GetActiveCamera();
UpdateRotation();
}
private void OnDestroy()
=> GlobalMessenger<OWCamera>.RemoveListener("SwitchActiveCamera", OnSwitchActiveCamera);
private void OnSwitchActiveCamera(OWCamera activeCamera)
{
_activeCam = activeCamera;
UpdateRotation();
}
void LateUpdate()
=> UpdateRotation();
private void UpdateRotation()
=> transform.LookAt(transform.position + (_activeCam.transform.rotation * Vector3.forward), _activeCam.transform.rotation * Vector3.up);
}

View File

@ -1,5 +1,4 @@
using OWML.Common;
using OWML.Utils;
using QSB.Events;
using QSB.Player;
using QSB.Utility;
@ -23,7 +22,7 @@ namespace QSB.ConversationSync
Instance = this;
_boxPrefab = QSBCore.ConversationAssetBundle.LoadAsset<GameObject>("assets/dialoguebubble.prefab");
// TODO : make dynamic so it can be different sizes!
// BUG : make dynamic so it can be different sizes!
// the dynamic font seems to be super lo-res at this size...?
var font = (Font)Resources.Load(@"fonts\english - latin\spacemono-bold");
if (font == null)
@ -91,7 +90,7 @@ namespace QSB.ConversationSync
Destroy(playerBox);
}
QSBPlayerManager.GetPlayer(playerId).CurrentDialogueBox = CreateBox(player.Body.transform, 25, text);
QSBPlayerManager.GetPlayer(playerId).CurrentDialogueBox = CreateBox(player.Body.transform, 2, text);
}
public void DisplayCharacterConversationBox(int index, string text)
@ -120,10 +119,7 @@ namespace QSB.ConversationSync
newBox.transform.SetParent(parent);
newBox.transform.localPosition = new Vector3(0, vertOffset, 0);
newBox.transform.rotation = parent.rotation;
var lookAt = newBox.AddComponent<FaceActiveCamera>();
lookAt.SetValue("_useLookAt", false);
lookAt.SetValue("_localFacingVector", Vector3.back);
lookAt.SetValue("_localRotationAxis", Vector3.up);
newBox.AddComponent<CameraFacingBillboard>();
newBox.GetComponent<Text>().text = text;
newBox.AddComponent<ZOverride>();
newBox.SetActive(true);

View File

@ -1,4 +1,5 @@
using OWML.Common;
using HarmonyLib;
using OWML.Common;
using QSB.Patches;
using QSB.Player;
using QSB.Utility;
@ -7,18 +8,13 @@ using System.Collections.Generic;
namespace QSB.ConversationSync.Patches
{
[HarmonyPatch]
public class ConversationPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Postfix(nameof(DialogueNode_GetNextPage));
Prefix(nameof(CharacterDialogueTree_InputDialogueOption));
Prefix(nameof(CharacterDialogueTree_StartConversation));
Prefix(nameof(CharacterDialogueTree_EndConversation));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.StartConversation))]
public static void CharacterDialogueTree_StartConversation(CharacterDialogueTree __instance)
{
var index = QSBWorldSync.OldDialogueTrees.FindIndex(x => x == __instance);
@ -31,6 +27,8 @@ namespace QSB.ConversationSync.Patches
ConversationManager.Instance.SendConvState(index, true);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.EndConversation))]
public static bool CharacterDialogueTree_EndConversation(CharacterDialogueTree __instance)
{
if (!__instance.enabled)
@ -51,6 +49,8 @@ namespace QSB.ConversationSync.Patches
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.InputDialogueOption))]
public static bool CharacterDialogueTree_InputDialogueOption(int optionIndex, DialogueBoxVer2 ____currentDialogueBox)
{
if (optionIndex < 0)
@ -65,6 +65,8 @@ namespace QSB.ConversationSync.Patches
return true;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(DialogueNode), nameof(DialogueNode.GetNextPage))]
public static void DialogueNode_GetNextPage(string ____name, List<string> ____listPagesToDisplay, int ____currentPage)
{
var key = ____name + ____listPagesToDisplay[____currentPage];

View File

@ -20,20 +20,21 @@ namespace QSB.DeathSync.Events
EnumValue = type
};
public override void OnReceiveLocal(bool server, EnumMessage<EndLoopReason> message)
public override void OnReceiveLocal(bool server, EnumMessage<EndLoopReason> message)
=> OnReceiveRemote(server, message);
public override void OnReceiveRemote(bool server, EnumMessage<EndLoopReason> message)
{
DebugLog.DebugWrite($" ~~~~ END LOOP - Reason:{message.EnumValue} ~~~~ ");
switch (message.EnumValue)
{
case EndLoopReason.AllPlayersDead:
DebugLog.DebugWrite($"all players dead");
Locator.GetDeathManager().KillPlayer(DeathType.TimeLoop);
if (QSBCore.IsHost)
{
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForDeath);
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.WaitingForAllPlayersToDie);
}
break;
}
}

View File

@ -23,7 +23,6 @@ namespace QSB.DeathSync.Events
public override void OnReceiveLocal(bool server, PlayerDeathMessage message)
{
DebugLog.DebugWrite($"RECEIVE LOCAL PLAYER DEATH");
var player = QSBPlayerManager.GetPlayer(message.AboutId);
RespawnManager.Instance.OnPlayerDeath(player);
ClientStateManager.Instance.OnDeath();
@ -31,7 +30,6 @@ namespace QSB.DeathSync.Events
public override void OnReceiveRemote(bool server, PlayerDeathMessage message)
{
DebugLog.DebugWrite($"RECEIVE REMOTE PLAYER DEATH");
var player = QSBPlayerManager.GetPlayer(message.AboutId);
var playerName = player.Name;
var deathMessage = Necronomicon.GetPhrase(message.EnumValue, message.NecronomiconIndex);

View File

@ -1,4 +1,5 @@
using QSB.Events;
using QSB.ClientServerStateSync;
using QSB.Events;
using QSB.Messaging;
using QSB.Player;
@ -29,6 +30,7 @@ namespace QSB.DeathSync.Events
if (message.AboutId == LocalPlayerId)
{
RespawnManager.Instance.Respawn();
ClientStateManager.Instance.OnRespawn();
}
RespawnManager.Instance.OnPlayerRespawn(QSBPlayerManager.GetPlayer(message.AboutId));

View File

@ -1,46 +1,45 @@
using Harmony;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
using QSB.Player;
using QSB.ShipSync;
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using UnityEngine;
namespace QSB.DeathSync.Patches
{
[HarmonyPatch]
public class DeathPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(DeathManager_KillPlayer_Prefix));
Postfix(nameof(DeathManager_KillPlayer_Postfix));
Prefix(nameof(ShipDetachableLeg_Detach));
Prefix(nameof(ShipDetachableModule_Detach));
Empty("ShipEjectionSystem_OnPressInteract");
Postfix(nameof(ShipDamageController_Awake));
Prefix(nameof(DestructionVolume_VanishShip));
Prefix(nameof(HighSpeedImpactSensor_FixedUpdate));
Prefix(nameof(PlayerResources_OnImpact));
}
// TODO : Remove with future functionality.
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipEjectionSystem), nameof(ShipEjectionSystem.OnPressInteract))]
public static bool DisableEjection()
=> false;
// TODO : Remove with future functionality.
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipDetachableLeg), nameof(ShipDetachableLeg.Detach))]
public static bool ShipDetachableLeg_Detach(ref OWRigidbody __result)
{
__result = null;
return false;
}
// TODO : Remove with future functionality.
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipDetachableModule), nameof(ShipDetachableModule.Detach))]
public static bool ShipDetachableModule_Detach(ref OWRigidbody __result)
{
__result = null;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerResources), nameof(PlayerResources.OnImpact))]
public static bool PlayerResources_OnImpact(ImpactData impact, PlayerResources __instance, float ____currentHealth)
{
if (PlayerState.IsInsideShip())
@ -66,6 +65,8 @@ namespace QSB.DeathSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(HighSpeedImpactSensor), nameof(HighSpeedImpactSensor.FixedUpdate))]
public static bool HighSpeedImpactSensor_FixedUpdate(
HighSpeedImpactSensor __instance,
bool ____isPlayer,
@ -186,9 +187,10 @@ namespace QSB.DeathSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DeathManager), nameof(DeathManager.KillPlayer))]
public static bool DeathManager_KillPlayer_Prefix(DeathType deathType)
{
DebugLog.DebugWrite($"KILL PLAYER PREFIX stacetrace : \r\n {Environment.StackTrace}");
if (RespawnOnDeath.Instance == null)
{
return true;
@ -205,21 +207,20 @@ namespace QSB.DeathSync.Patches
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(DeathManager), nameof(DeathManager.KillPlayer))]
public static void DeathManager_KillPlayer_Postfix(DeathType deathType)
{
DebugLog.DebugWrite($"KILL PLAYER POSTFIX");
QSBEventManager.FireEvent(EventNames.QSBPlayerDeath, deathType);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ShipDamageController), nameof(ShipDamageController.Awake))]
public static void ShipDamageController_Awake(ref bool ____exploded)
=> ____exploded = true;
public static IEnumerable<CodeInstruction> ReturnNull(IEnumerable<CodeInstruction> instructions) => new List<CodeInstruction>
{
new CodeInstruction(OpCodes.Ldnull),
new CodeInstruction(OpCodes.Ret)
};
[HarmonyPrefix]
[HarmonyPatch(typeof(DestructionVolume), nameof(DestructionVolume.VanishShip))]
public static bool DestructionVolume_VanishShip(DeathType ____deathType)
{
if (RespawnOnDeath.Instance == null)

View File

@ -7,11 +7,11 @@ namespace QSB.DeathSync.Patches
{
public override QSBPatchTypes Type => QSBPatchTypes.RespawnTime;
public override void DoPatches()
{
Prefix(nameof(MapController_LateUpdate));
Prefix(nameof(MapController_EnterMapView));
}
//public override void DoPatches()
//{
// Prefix<MapController>(nameof(MapController.LateUpdate), nameof(MapController_LateUpdate));
// Prefix<MapController>(nameof(MapController.EnterMapView), nameof(MapController_EnterMapView));
//}
public static bool MapController_EnterMapView(
MapController __instance,
@ -164,9 +164,9 @@ namespace QSB.DeathSync.Patches
var zoomInput = 0f;
if (canInteractWith)
{
XZinput = OWInput.GetValue(InputLibrary.moveXZ, InputMode.All);
lookInput = InputLibrary.look.GetValue(false);
zoomInput = OWInput.GetValue(InputLibrary.mapZoom, InputMode.All);
XZinput = OWInput.GetAxisValue(InputLibrary.moveXZ, InputMode.All);
lookInput = InputLibrary.look.GetAxisValue(false);
zoomInput = OWInput.GetValue(InputLibrary.mapZoomIn, InputMode.All) - OWInput.GetValue(InputLibrary.mapZoomOut, InputMode.All);
lookInput.y *= -1f;
zoomInput *= -1f;
}

View File

@ -1,18 +1,22 @@
using OWML.Utils;
using HarmonyLib;
using OWML.Utils;
using QSB.Patches;
namespace QSB.DeathSync.Patches
{
[HarmonyPatch]
internal class RespawnPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(PlayerRecoveryPoint_OnGainFocus));
Prefix(nameof(PlayerRecoveryPoint_OnPressInteract));
}
//public override void DoPatches()
//{
// Prefix<PlayerRecoveryPoint>(nameof(PlayerRecoveryPoint.OnGainFocus), nameof(PlayerRecoveryPoint_OnGainFocus));
// Prefix<PlayerRecoveryPoint>(nameof(PlayerRecoveryPoint.OnPressInteract), nameof(PlayerRecoveryPoint_OnPressInteract));
//}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerRecoveryPoint), nameof(PlayerRecoveryPoint.OnGainFocus))]
public static bool PlayerRecoveryPoint_OnGainFocus(
PlayerResources ____playerResources,
bool ____refuelsPlayer,
@ -100,6 +104,8 @@ namespace QSB.DeathSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerRecoveryPoint), nameof(PlayerRecoveryPoint.OnPressInteract))]
public static bool PlayerRecoveryPoint_OnPressInteract(
PlayerRecoveryPoint __instance,
PlayerResources ____playerResources,

View File

@ -28,7 +28,7 @@ namespace QSB.DeathSync
private Vector3 _deathPositionRelative;
public Transform DeathClosestAstroObject { get; private set; }
public Vector3 DeathPositionWorld
public Vector3 DeathPositionWorld
=> DeathClosestAstroObject == null
? Vector3.zero
: DeathClosestAstroObject.TransformPoint(_deathPositionRelative);

View File

@ -1,4 +1,5 @@
using OWML.Utils;
using HarmonyLib;
using OWML.Utils;
using QSB.ElevatorSync.WorldObjects;
using QSB.Events;
using QSB.Patches;
@ -6,18 +7,18 @@ using QSB.WorldSync;
namespace QSB.ElevatorSync.Patches
{
[HarmonyPatch]
public class ElevatorPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(typeof(Elevator), nameof(Elevator.StartLift))]
public static void Elevator_StartLift(Elevator __instance)
{
var isGoingUp = __instance.GetValue<bool>("_goingToTheEnd");
var id = QSBWorldSync.GetIdFromUnity<QSBElevator, Elevator>(__instance);
QSBEventManager.FireEvent(EventNames.QSBStartLift, id, isGoingUp);
}
public override void DoPatches()
=> Postfix(nameof(Elevator_StartLift));
}
}

View File

@ -1,22 +1,22 @@
using QSB.Events;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
namespace QSB.FrequencySync.Patches
{
[HarmonyPatch]
public class FrequencyPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Postfix(nameof(AudioSignal_IdentifyFrequency));
Postfix(nameof(AudioSignal_IdentifySignal));
}
public static void AudioSignal_IdentifyFrequency(SignalFrequency ____frequency)
[HarmonyPostfix]
[HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.IdentifyFrequency))]
static void IdentifyFrequencyEvent(SignalFrequency ____frequency)
=> QSBEventManager.FireEvent(EventNames.QSBIdentifyFrequency, ____frequency);
public static void AudioSignal_IdentifySignal(SignalName ____name)
[HarmonyPostfix]
[HarmonyPatch(typeof(AudioSignal), nameof(AudioSignal.IdentifySignal))]
static void IdentifySignalEvent(SignalName ____name)
=> QSBEventManager.FireEvent(EventNames.QSBIdentifySignal, ____name);
}
}

View File

@ -1,11 +1,16 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
namespace QSB.GeyserSync.Patches
{
[HarmonyPatch]
internal class GeyserPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnNonServerClientConnect;
public override void DoPatches() => Empty("GeyserController_Update");
[HarmonyPrefix]
[HarmonyPatch(typeof(GeyserController), nameof(GeyserController.Update))]
public static bool Empty()
=> false;
}
}

View File

@ -1,14 +1,15 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
namespace QSB.Inputs.Patches
{
[HarmonyPatch]
internal class InputPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
=> Prefix(nameof(OWInput_Update));
[HarmonyPrefix]
[HarmonyPatch(typeof(OWInput), nameof(OWInput.Update))]
public static bool OWInput_Update()
=> QSBInputManager.Instance.InputsEnabled;
}

View File

@ -55,7 +55,7 @@ namespace QSB.Instruments.QSBCamera
private void UpdateInput()
{
var input = OWInput.GetValue(InputLibrary.look, false);
var input = InputLibrary.look.GetAxisValue(false);
_degreesX += input.x * 180f * Time.fixedDeltaTime;
_degreesY += input.y * 180f * Time.fixedDeltaTime;
}

View File

@ -9,7 +9,7 @@ namespace QSB.ItemSync
{
protected override void RebuildWorldObjects(OWScene scene)
{
DebugLog.DebugWrite("Rebuilding OWItems...", MessageType.Warning);
DebugLog.DebugWrite("Rebuilding OWItems...", MessageType.Info);
QSBWorldSync.Init<QSBScrollSocket, ScrollSocket>();
QSBWorldSync.Init<QSBScrollItem, ScrollItem>();
QSBWorldSync.Init<QSBSharedStoneSocket, SharedStoneSocket>();

View File

@ -1,4 +1,5 @@
using OWML.Common;
using HarmonyLib;
using OWML.Common;
using QSB.Events;
using QSB.Patches;
using QSB.Utility;
@ -7,19 +8,13 @@ using UnityEngine;
namespace QSB.ItemSync.Patches
{
[HarmonyPatch]
internal class ItemPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(ItemTool_MoveItemToCarrySocket));
Prefix(nameof(ItemTool_SocketItem));
Prefix(nameof(ItemTool_StartUnsocketItem));
Prefix(nameof(ItemTool_CompleteUnsocketItem));
Prefix(nameof(ItemTool_DropItem));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemTool), nameof(ItemTool.MoveItemToCarrySocket))]
public static bool ItemTool_MoveItemToCarrySocket(OWItem item)
{
var itemId = QSBWorldSync.GetIdFromTypeSubset(ItemManager.GetObject(item));
@ -27,6 +22,8 @@ namespace QSB.ItemSync.Patches
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemTool), nameof(ItemTool.SocketItem))]
public static bool ItemTool_SocketItem(OWItem ____heldItem, OWItemSocket socket)
{
var socketId = QSBWorldSync.GetIdFromTypeSubset(ItemManager.GetObject(socket));
@ -35,6 +32,8 @@ namespace QSB.ItemSync.Patches
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemTool), nameof(ItemTool.StartUnsocketItem))]
public static bool ItemTool_StartUnsocketItem(OWItemSocket socket)
{
var socketId = QSBWorldSync.GetIdFromTypeSubset(ItemManager.GetObject(socket));
@ -42,6 +41,8 @@ namespace QSB.ItemSync.Patches
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemTool), nameof(ItemTool.CompleteUnsocketItem))]
public static bool ItemTool_CompleteUnsocketItem(OWItem ____heldItem)
{
var itemId = QSBWorldSync.GetIdFromTypeSubset(ItemManager.GetObject(____heldItem));
@ -49,7 +50,9 @@ namespace QSB.ItemSync.Patches
return true;
}
public static bool ItemTool_DropItem(RaycastHit hit, OWRigidbody targetRigidbody, DetachableFragment detachableFragment, ref OWItem ____heldItem)
[HarmonyPrefix]
[HarmonyPatch(typeof(ItemTool), nameof(ItemTool.DropItem))]
public static bool ItemTool_DropItem(RaycastHit hit, OWRigidbody targetRigidbody, IItemDropTarget customDropTarget, ref OWItem ____heldItem)
{
Locator.GetPlayerAudioController().PlayDropItem(____heldItem.GetItemType());
var hitGameObject = hit.collider.gameObject;
@ -65,13 +68,21 @@ namespace QSB.ItemSync.Patches
if (sectorGroup != null)
{
sector = sectorGroup.GetSector();
if (sector == null && sectorGroup is SectorCullGroup)
{
SectorProxy controllingProxy = (sectorGroup as SectorCullGroup).GetControllingProxy();
if (controllingProxy != null)
{
sector = controllingProxy.GetSector();
}
}
}
var parent = (detachableFragment != null)
? detachableFragment.transform
: targetRigidbody.transform;
var parent = (customDropTarget == null)
? targetRigidbody.transform
: customDropTarget.GetItemDropTargetTransform(hit.collider.gameObject);
var objectId = QSBWorldSync.GetIdFromTypeSubset(ItemManager.GetObject(____heldItem));
____heldItem.DropItem(hit.point, hit.normal, parent, sector, detachableFragment);
____heldItem.DropItem(hit.point, hit.normal, parent, sector, customDropTarget);
____heldItem = null;
Locator.GetToolModeSwapper().UnequipTool();
var parentSector = parent.GetComponentInChildren<Sector>();

View File

@ -1,12 +1,16 @@
using QSB.Events;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
namespace QSB.LogSync.Patches
{
[HarmonyPatch]
public class LogPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(typeof(ShipLogManager), nameof(ShipLogManager.RevealFact))]
public static void ShipLogManager_RevealFact(string id, bool saveGame, bool showNotification, bool __result)
{
if (!__result)
@ -16,7 +20,5 @@ namespace QSB.LogSync.Patches
QSBEventManager.FireEvent(EventNames.QSBRevealFact, id, saveGame, showNotification);
}
public override void DoPatches() => Postfix(nameof(ShipLogManager_RevealFact));
}
}

22
QSB/Menus/IMenuAPI.cs Normal file
View File

@ -0,0 +1,22 @@
using UnityEngine;
using UnityEngine.UI;
namespace QSB.Menus
{
public interface IMenuAPI
{
// Title screen
GameObject TitleScreen_MakeMenuOpenButton(string name, Menu menuToOpen);
GameObject TitleScreen_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null);
Button TitleScreen_MakeSimpleButton(string name);
// 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);
Button PauseMenu_MakeSimpleButton(string name, Menu customMenu = null);
Menu PauseMenu_MakePauseListMenu(string title);
// Misc
PopupMenu MakeTwoChoicePopup(string message, string confirmText, string cancelText);
PopupInputMenu MakeInputFieldPopup(string message, string placeholderMessage, string confirmText, string cancelText);
PopupMenu MakeInfoPopup(string message, string continueButtonText);
}
}

251
QSB/Menus/MenuManager.cs Normal file
View File

@ -0,0 +1,251 @@
using QSB.Player;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
namespace QSB.Menus
{
class MenuManager : MonoBehaviour
{
public static MenuManager Instance;
private IMenuAPI MenuApi => QSBCore.MenuApi;
private PopupMenu PopupMenu;
private Button HostButton;
private GameObject ClientButton;
private Button DisconnectButton;
private PopupMenu InfoPopup;
private bool _addedPauseLock;
public void Start()
{
Instance = this;
MakeTitleMenus();
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
QSBNetworkManager.Instance.OnClientConnected += OnConnected;
QSBNetworkManager.Instance.OnClientDisconnected += OnDisconnected;
QSBNetworkManager.Instance.OnClientErrorThrown += OnClientError;
}
void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isUniverse)
{
if (isUniverse)
{
InitPauseMenus();
return;
}
if (newScene == OWScene.TitleScreen)
{
MakeTitleMenus();
}
}
private void OpenInfoPopup(string message, string buttonText)
{
InfoPopup.SetUpPopup(message, InputLibrary.menuConfirm, InputLibrary.cancel, new ScreenPrompt(buttonText), null, true, false);
OWTime.Pause(OWTime.PauseType.System);
OWInput.ChangeInputMode(InputMode.Menu);
var pauseCommandListener = Locator.GetPauseCommandListener();
if (pauseCommandListener != null)
{
pauseCommandListener.AddPauseCommandLock();
_addedPauseLock = true;
}
InfoPopup.EnableMenu(true);
}
private void OnCloseInfoPopup()
{
var pauseCommandListener = Locator.GetPauseCommandListener();
if (pauseCommandListener != null && _addedPauseLock)
{
pauseCommandListener.RemovePauseCommandLock();
_addedPauseLock = false;
}
OWTime.Unpause(OWTime.PauseType.System);
OWInput.RestorePreviousInputs();
}
private void CreateCommonPopups()
{
PopupMenu = MenuApi.MakeInputFieldPopup("IP Address", "IP Address", "Connect", "Cancel");
PopupMenu.OnPopupConfirm += Connect;
InfoPopup = MenuApi.MakeInfoPopup("", "");
InfoPopup.OnDeactivateMenu += OnCloseInfoPopup;
}
private void InitPauseMenus()
{
CreateCommonPopups();
HostButton = MenuApi.PauseMenu_MakeSimpleButton("MULTIPLAYER (HOST)");
HostButton.onClick.AddListener(Host);
ClientButton = MenuApi.PauseMenu_MakeMenuOpenButton("MULTIPLAYER (CONNECT)", PopupMenu);
DisconnectButton = MenuApi.PauseMenu_MakeSimpleButton("DISCONNECT");
DisconnectButton.onClick.AddListener(Disconnect);
if (QSBCore.IsInMultiplayer)
{
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
}
else
{
DisconnectButton.gameObject.SetActive(false);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
}
OnConnected();
}
private void MakeTitleMenus()
{
CreateCommonPopups();
HostButton = MenuApi.TitleScreen_MakeSimpleButton("MULTIPLAYER (HOST)");
HostButton.onClick.AddListener(Host);
ClientButton = MenuApi.TitleScreen_MakeMenuOpenButton("MULTIPLAYER (CONNECT)", PopupMenu);
DisconnectButton = MenuApi.TitleScreen_MakeSimpleButton("DISCONNECT");
DisconnectButton.onClick.AddListener(Disconnect);
if (QSBCore.IsInMultiplayer)
{
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
}
else
{
DisconnectButton.gameObject.SetActive(false);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
}
OnConnected();
}
private void Disconnect()
{
QSBNetworkManager.Instance.StopHost();
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
}
private void Host()
{
QSBNetworkManager.Instance.StartHost();
DisconnectButton.gameObject.SetActive(true);
DisconnectButton.GetComponent<CanvasGroup>().alpha = 1f;
ClientButton.SetActive(false);
HostButton.gameObject.SetActive(false);
}
private void Connect()
{
QSBNetworkManager.Instance.networkAddress = (PopupMenu as PopupInputMenu).GetInputText();
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;
}
public void OnKicked(KickReason reason)
{
string text;
switch (reason)
{
case KickReason.QSBVersionNotMatching:
text = "Server refused connection as QSB version does not match.";
break;
case KickReason.GameVersionNotMatching:
text = "Server refused connection as Outer Wilds version does not match.";
break;
case KickReason.None:
text = "Kicked from server. No reason given.";
break;
default:
text = $"Kicked from server. KickReason:{reason}";
break;
}
OpenInfoPopup(text, "OK");
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
}
private void OnDisconnected(NetworkError error)
{
if (error == NetworkError.Ok)
{
return;
}
string text;
switch (error)
{
case NetworkError.Timeout:
text = "Client disconnected with error!\r\nConnection timed out.";
break;
default:
text = $"Client disconnected with error!\r\nNetworkError:{error}";
break;
}
OpenInfoPopup(text, "OK");
DisconnectButton.gameObject.SetActive(false);
ClientButton.SetActive(true);
HostButton.gameObject.SetActive(true);
}
private void OnClientError(NetworkError error)
{
if (error == NetworkError.Ok)
{
// lol wut
return;
}
string text;
switch (error)
{
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);
break;
default:
text = $"Internal QNet client error!\n\nNetworkError:{error}";
break;
}
OpenInfoPopup(text, "OK");
}
}
}

View File

@ -84,9 +84,17 @@ namespace QSB.OrbSync.Events
return;
}
if (orbIdentity.ClientAuthorityOwner != null && orbIdentity.ClientAuthorityOwner != fromPlayer)
var currentOwner = orbIdentity.ClientAuthorityOwner;
var newOwner = fromPlayer;
if (currentOwner == newOwner)
{
orbIdentity.RemoveClientAuthority(orbIdentity.ClientAuthorityOwner);
return;
}
if (currentOwner != null && currentOwner != fromPlayer)
{
orbIdentity.RemoveClientAuthority(currentOwner);
}
orbIdentity.AssignClientAuthority(fromPlayer);

View File

@ -26,7 +26,10 @@ namespace QSB.OrbSync
{
NomaiOrbTransformSync.OrbTransformSyncs.ForEach(x => QNetworkServer.Destroy(x.gameObject));
NomaiOrbTransformSync.OrbTransformSyncs.Clear();
QSBWorldSync.OldOrbList.ForEach(x => QNetworkServer.Spawn(Instantiate(QSBNetworkManager.Instance.OrbPrefab)));
foreach (var orb in QSBWorldSync.OldOrbList)
{
Instantiate(QSBNetworkManager.Instance.OrbPrefab).SpawnWithServerAuthority();
}
}
DebugLog.DebugWrite($"Finished orb build with {QSBWorldSync.OldOrbList.Count} orbs.", MessageType.Success);

View File

@ -1,4 +1,5 @@
using QSB.Events;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
using QSB.Utility;
using QSB.WorldSync;
@ -6,10 +7,13 @@ using UnityEngine;
namespace QSB.OrbSync.Patches
{
[HarmonyPatch]
public class OrbPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(typeof(NomaiInterfaceOrb), nameof(NomaiInterfaceOrb.StartDragFromPosition))]
public static void NomaiInterfaceOrb_StartDragFromPosition(bool __result, NomaiInterfaceOrb __instance)
{
if (__result)
@ -18,6 +22,8 @@ namespace QSB.OrbSync.Patches
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiInterfaceSlot), nameof(NomaiInterfaceSlot.CheckOrbCollision))]
public static bool NomaiInterfaceSlot_CheckOrbCollision(ref bool __result, NomaiInterfaceSlot __instance, NomaiInterfaceOrb orb,
bool ____ignoreDraggedOrbs, float ____radius, float ____exitRadius, ref NomaiInterfaceOrb ____occupyingOrb)
{
@ -60,11 +66,5 @@ namespace QSB.OrbSync.Patches
__result = true;
return false;
}
public override void DoPatches()
{
Postfix(nameof(NomaiInterfaceOrb_StartDragFromPosition));
Prefix(nameof(NomaiInterfaceSlot_CheckOrbCollision));
}
}
}

View File

@ -1,4 +1,4 @@
using QSB.Syncs.TransformSync;
using QSB.Syncs.Unsectored.Transforms;
using QSB.Utility;
using QSB.WorldSync;
using System.Collections.Generic;
@ -6,7 +6,7 @@ using UnityEngine;
namespace QSB.OrbSync.TransformSync
{
internal class NomaiOrbTransformSync : UnparentedBaseTransformSync
internal class NomaiOrbTransformSync : UnsectoredTransformSync
{
public static List<NomaiOrbTransformSync> OrbTransformSyncs = new List<NomaiOrbTransformSync>();
@ -17,7 +17,7 @@ namespace QSB.OrbSync.TransformSync
protected override void OnDestroy()
{
OrbTransformSyncs.Remove(this);
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
base.OnDestroy();
}
protected override void Init()
@ -59,6 +59,7 @@ namespace QSB.OrbSync.TransformSync
protected override Component InitLocalTransform() => GetTransform();
protected override Component InitRemoteTransform() => GetTransform();
protected override float DistanceLeeway => 1f;
public override bool IsReady => QSBCore.WorldObjectsReady;
public override bool UseInterpolation => false;
}

View File

@ -1,119 +1,14 @@
using Harmony;
using OWML.Common;
using OWML.Utils;
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HarmonyLib;
namespace QSB.Patches
{
public abstract class QSBPatch
{
public abstract QSBPatchTypes Type { get; }
public abstract void DoPatches();
public void DoUnpatches()
public void DoPatches(Harmony instance)
{
foreach (var item in _patchedMethods)
{
//DebugLog.DebugWrite($"[Unpatch] {item.DeclaringType}.{item.Name}", MessageType.Info);
Unpatch(item);
}
_patchedMethods.Clear();
}
private List<MethodInfo> _patchedMethods = new List<MethodInfo>();
public void Empty(string patchName)
{
//DebugLog.DebugWrite($"[Empty] {patchName}", MessageType.Success);
var method = GetMethodInfo(patchName);
QSBCore.Helper.HarmonyHelper.EmptyMethod(method);
_patchedMethods.Add(method);
}
public void Prefix(string patchName)
=> DoPrefixPostfix(true, patchName);
public void Postfix(string patchName)
=> DoPrefixPostfix(false, patchName);
private void DoPrefixPostfix(bool isPrefix, string patchName)
{
var method = GetMethodInfo(patchName);
if (method != null)
{
if (isPrefix)
{
QSBCore.Helper.HarmonyHelper.AddPrefix(method, GetType(), patchName);
}
else
{
QSBCore.Helper.HarmonyHelper.AddPostfix(method, GetType(), patchName);
}
_patchedMethods.Add(method);
}
//DebugLog.DebugWrite($"{(isPrefix ? "[Prefix]" : "[Postfix]")} {patchName}", method == null ? MessageType.Error : MessageType.Success);
}
private MethodInfo GetMethodInfo(string patchName)
{
var splitName = patchName.Split('_');
var typeName = splitName[0];
var methodName = splitName[1];
var type = GetFirstTypeByName(typeName);
if (type == null)
{
DebugLog.ToConsole($"Error - Couldn't find type for patch name {patchName}!", MessageType.Error);
return null;
}
var method = type.GetAnyMethod(methodName);
if (method == null)
{
DebugLog.ToConsole($"Error - Couldn't find method for patch name {patchName}!", MessageType.Error);
return null;
}
return method;
}
private Type GetFirstTypeByName(string typeName)
{
var a = typeof(OWRigidbody).Assembly;
var assemblyTypes = a.GetTypes();
for (var j = 0; j < assemblyTypes.Length; j++)
{
if (assemblyTypes[j].Name == typeName)
{
return assemblyTypes[j];
}
}
return null;
}
private void Unpatch(MethodInfo method)
{
var dictionary = typeof(HarmonySharedState).Invoke<Dictionary<MethodBase, byte[]>>("GetState", new object[0]);
var methodBase = dictionary.Keys.First(m =>
m.DeclaringType == method.DeclaringType
&& m.Name == method.Name);
var patchInfo = PatchInfoSerialization.Deserialize(dictionary.GetValueSafe(methodBase));
patchInfo.RemovePostfix(QSBCore.Helper.Manifest.UniqueName);
patchInfo.RemovePrefix(QSBCore.Helper.Manifest.UniqueName);
patchInfo.RemoveTranspiler(QSBCore.Helper.Manifest.UniqueName);
PatchFunctions.UpdateWrapper(methodBase, patchInfo, QSBCore.Helper.Manifest.UniqueName);
dictionary[methodBase] = patchInfo.Serialize();
instance.PatchAll(GetType());
}
}
}

View File

@ -1,4 +1,6 @@
using OWML.Common;
using HarmonyLib;
using OWML.Common;
using OWML.Utils;
using QSB.Animation.NPC.Patches;
using QSB.Animation.Patches;
using QSB.CampfireSync.Patches;
@ -34,6 +36,8 @@ namespace QSB.Patches
private static List<QSBPatch> _patchList = new List<QSBPatch>();
public static Dictionary<QSBPatchTypes, Harmony> TypeToInstance = new Dictionary<QSBPatchTypes, Harmony>();
public static void Init()
{
_patchList = new List<QSBPatch>
@ -66,6 +70,14 @@ namespace QSB.Patches
new LauncherPatches()
};
TypeToInstance = new Dictionary<QSBPatchTypes, Harmony>
{
{ QSBPatchTypes.OnClientConnect, new Harmony("QSB.Client") },
{ QSBPatchTypes.OnServerClientConnect, new Harmony("QSB.Server") },
{ QSBPatchTypes.OnNonServerClientConnect, new Harmony("QSB.NonServer") },
{ QSBPatchTypes.RespawnTime, new Harmony("QSB.Death") }
};
DebugLog.DebugWrite("Patch Manager ready.", MessageType.Success);
}
@ -76,7 +88,14 @@ namespace QSB.Patches
foreach (var patch in _patchList.Where(x => x.Type == type))
{
//DebugLog.DebugWrite($" - Patching in {patch.GetType().Name}", MessageType.Info);
patch.DoPatches();
try
{
patch.DoPatches(TypeToInstance[type]);
}
catch (Exception ex)
{
DebugLog.DebugWrite($"Error while patching {patch.GetType().Name} :\r\n{ex}", MessageType.Error);
}
}
}
@ -84,11 +103,7 @@ namespace QSB.Patches
{
OnUnpatchType?.SafeInvoke(type);
//DebugLog.DebugWrite($"Unpatch block {Enum.GetName(typeof(QSBPatchTypes), type)}", MessageType.Info);
foreach (var patch in _patchList.Where(x => x.Type == type))
{
//DebugLog.DebugWrite($" - Unpatching in {patch.GetType().Name}", MessageType.Info);
patch.DoUnpatches();
}
TypeToInstance[type].UnpatchSelf();
}
}
}

View File

@ -49,7 +49,6 @@ namespace QSB.Player.Events
public override void OnReceiveRemote(bool server, EnumWorldObjectMessage<EnterLeaveType> message)
{
var player = QSBPlayerManager.GetPlayer(message.FromId);
DebugLog.DebugWrite($"{message.FromId} {message.EnumValue}", OWML.Common.MessageType.Info);
switch (message.EnumValue)
{
case EnterLeaveType.EnterMoon:

View File

@ -17,22 +17,38 @@ namespace QSB.Player.Events
{
AboutId = LocalPlayerId,
PlayerName = name,
QSBVersion = QSBCore.QSBVersion
QSBVersion = QSBCore.QSBVersion,
GameVersion = QSBCore.GameVersion
};
public override void OnReceiveRemote(bool server, PlayerJoinMessage message)
{
if (server && (message.QSBVersion != QSBCore.QSBVersion))
if (message.QSBVersion != QSBCore.QSBVersion)
{
DebugLog.ToConsole($"Error - Client {message.PlayerName} connecting with wrong version. (Client:{message.QSBVersion}, Server:{QSBCore.QSBVersion})", MessageType.Error);
QSBEventManager.FireEvent(EventNames.QSBPlayerKick, message.AboutId, KickReason.VersionNotMatching);
if (server)
{
DebugLog.ToConsole($"Error - Client {message.PlayerName} connecting with wrong QSB version. (Client:{message.QSBVersion}, Server:{QSBCore.QSBVersion})", MessageType.Error);
QSBEventManager.FireEvent(EventNames.QSBPlayerKick, message.AboutId, KickReason.QSBVersionNotMatching);
}
return;
}
if (message.GameVersion != QSBCore.GameVersion)
{
if (server)
{
DebugLog.ToConsole($"Error - Client {message.PlayerName} connecting with wrong game version. (Client:{message.GameVersion}, Server:{QSBCore.GameVersion})", MessageType.Error);
QSBEventManager.FireEvent(EventNames.QSBPlayerKick, message.AboutId, KickReason.GameVersionNotMatching);
}
return;
}
var player = QSBPlayerManager.GetPlayer(message.AboutId);
player.Name = message.PlayerName;
DebugLog.ToAll($"{player.Name} joined!", MessageType.Info);
DebugLog.DebugWrite($"{player.Name} joined as id {player.PlayerId}", MessageType.Info);
DebugLog.DebugWrite($"{player.Name} joined. id:{player.PlayerId}, qsbVersion:{message.QSBVersion}, gameVersion:{message.GameVersion}", MessageType.Info);
}
public override void OnReceiveLocal(bool server, PlayerJoinMessage message)

View File

@ -7,12 +7,14 @@ namespace QSB.Player.Events
{
public string PlayerName { get; set; }
public string QSBVersion { get; set; }
public string GameVersion { get; set; }
public override void Deserialize(QNetworkReader reader)
{
base.Deserialize(reader);
PlayerName = reader.ReadString();
QSBVersion = reader.ReadString();
GameVersion = reader.ReadString();
}
public override void Serialize(QNetworkWriter writer)
@ -20,6 +22,7 @@ namespace QSB.Player.Events
base.Serialize(writer);
writer.Write(PlayerName);
writer.Write(QSBVersion);
writer.Write(GameVersion);
}
}
}

View File

@ -1,4 +1,5 @@
using QSB.Events;
using QSB.Menus;
using QSB.Messaging;
using QSB.Utility;
using QuantumUNET;
@ -49,6 +50,7 @@ namespace QSB.Player.Events
}
DebugLog.ToAll($"Kicked from server. Reason : {message.EnumValue}");
MenuManager.Instance.OnKicked(message.EnumValue);
}
}
}

View File

@ -20,11 +20,7 @@ namespace QSB.Player.Events
public override void SetupListener() => GlobalMessenger.AddListener(EventNames.QSBRequestStateResync, Handler);
public override void CloseListener() => GlobalMessenger.RemoveListener(EventNames.QSBRequestStateResync, Handler);
private void Handler()
{
DebugLog.DebugWrite($"Sending QSBRequestStateResync");
SendEvent(CreateMessage());
}
private void Handler() => SendEvent(CreateMessage());
private PlayerMessage CreateMessage() => new PlayerMessage
{
@ -33,16 +29,11 @@ namespace QSB.Player.Events
public override void OnReceiveRemote(bool isHost, PlayerMessage message)
{
DebugLog.DebugWrite($"OnReceiveRemote RequestStateResyncEvent");
// if host, send worldobject and server states
if (isHost)
{
DebugLog.DebugWrite($"SENDING SERVER STATE");
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerStateManager.Instance.GetServerState());
DebugLog.DebugWrite($"SENDING PLAYER INFORMATION");
QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
SendWorldObjectInfo();
@ -51,15 +42,11 @@ namespace QSB.Player.Events
}
// if client, send player and client states
DebugLog.DebugWrite($"SENDING PLAYER INFORMATION");
QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
}
private void SendWorldObjectInfo()
{
DebugLog.DebugWrite($"SENDING WORLDOBJECT INFORMATION");
QSBWorldSync.DialogueConditions.ForEach(condition
=> QSBEventManager.FireEvent(EventNames.DialogueCondition, condition.Key, condition.Value));

View File

@ -2,6 +2,8 @@
{
public enum KickReason
{
VersionNotMatching
None,
QSBVersionNotMatching,
GameVersionNotMatching
}
}

View File

@ -1,17 +1,15 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
namespace QSB.Player.Patches
{
[HarmonyPatch]
internal class PlayerPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(PlayerCrushedController_CrushPlayer));
Prefix(nameof(PauseMenuManager_OnExitToMainMenu));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerCrushedController), nameof(PlayerCrushedController.CrushPlayer))]
public static bool PlayerCrushedController_CrushPlayer()
{
// #CrushIt https://www.twitch.tv/videos/846916781?t=00h03m51s
@ -20,6 +18,9 @@ namespace QSB.Player.Patches
return false;
}
public static void PauseMenuManager_OnExitToMainMenu() => QSBPlayerManager.LocalPlayer.PlayerStates.IsReady = false;
[HarmonyPrefix]
[HarmonyPatch(typeof(PauseMenuManager), nameof(PauseMenuManager.OnExitToMainMenu))]
public static void PauseMenuManager_OnExitToMainMenu()
=> QSBPlayerManager.LocalPlayer.PlayerStates.IsReady = false;
}
}

View File

@ -9,7 +9,7 @@ namespace QSB.Player
private bool _needsInitializing;
private bool _isReady;
protected override void InitCanvasMarker()
public override void InitCanvasMarker()
{
_markerRadius = 2f;

View File

@ -32,7 +32,7 @@ namespace QSB.Player
// Tools
public GameObject ProbeBody { get; set; }
public QSBProbe Probe { get; set; }
public QSBFlashlight FlashLight
public QSBFlashlight FlashLight
{
get
{
@ -66,8 +66,8 @@ namespace QSB.Player
public JetpackAccelerationSync JetpackAcceleration { get; set; }
// Misc
public bool IsInMoon; // TODO : move into PlayerStates?
public bool IsInShrine; // TODO : move into PlayerStates?
public bool IsInMoon; // MOVE : move into PlayerStates?
public bool IsInShrine; // MOVE : move into PlayerStates?
public IQSBQuantumObject EntangledObject;
public bool IsDead { get; set; }
public ClientState State { get; set; }
@ -87,7 +87,7 @@ namespace QSB.Player
}
}
public Flashlight LocalFlashlight
public Flashlight LocalFlashlight
{
get
{
@ -129,7 +129,6 @@ namespace QSB.Player
}
}
public PlayerInfo(uint id)
{
PlayerId = id;

View File

@ -35,6 +35,7 @@ namespace QSB.Player
}
public static Action<uint> OnRemovePlayer;
public static Action<uint> OnAddPlayer;
public static PlayerInfo LocalPlayer => GetPlayer(LocalPlayerId);
public static List<PlayerInfo> PlayerList { get; } = new List<PlayerInfo>();
@ -43,12 +44,6 @@ namespace QSB.Player
public static PlayerInfo GetPlayer(uint id)
{
if (!QSBNetworkManager.Instance.IsReady)
{
DebugLog.ToConsole($"Warning - GetPlayer() (id<{id}>) called when Network Manager not ready! Is a Player Sync Object still active? " +
$"{Environment.NewLine} Stacktrace :\r\n{Environment.StackTrace}", MessageType.Warning);
}
if (id == uint.MaxValue || id == 0U)
{
return default;
@ -69,6 +64,7 @@ namespace QSB.Player
DebugLog.DebugWrite($"Create Player : id<{id}> Stacktrace :\r\n{Environment.StackTrace}", MessageType.Info);
player = new PlayerInfo(id);
PlayerList.Add(player);
OnAddPlayer?.Invoke(id);
return player;
}
@ -83,7 +79,6 @@ namespace QSB.Player
public static void HandleFullStateMessage(PlayerInformationMessage message)
{
DebugLog.DebugWrite($"Handle full state message of {message.AboutId}");
var player = GetPlayer(message.AboutId);
player.Name = message.PlayerName;
player.PlayerStates = message.PlayerState;
@ -91,6 +86,7 @@ namespace QSB.Player
{
player.UpdateStateObjects();
}
player.State = message.ClientState;
}
@ -116,6 +112,16 @@ namespace QSB.Player
{
cameraList.Add(LocalPlayer);
}
else if (includeLocalCamera && (LocalPlayer == default || LocalPlayer.Camera == null))
{
if (LocalPlayer == default)
{
DebugLog.ToConsole($"Error - LocalPlayer is null.", MessageType.Error);
return cameraList;
}
DebugLog.DebugWrite($"Error - LocalPlayer.Camera is null.", MessageType.Error);
}
return cameraList;
}

View File

@ -4,7 +4,7 @@ using QSB.Events;
using QSB.Instruments;
using QSB.RoastingSync;
using QSB.SectorSync;
using QSB.Syncs.TransformSync;
using QSB.Syncs.Sectored.Transforms;
using QSB.Tools;
using QSB.Utility;
using QSB.WorldSync;
@ -86,7 +86,7 @@ namespace QSB.Player.TransformSync
protected override Component InitLocalTransform()
{
QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllReady, () => SectorSync.Init(Locator.GetPlayerSectorDetector(), this));
QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllReady, () => SectorSync.Init(Locator.GetPlayerSectorDetector(), TargetType.Player));
// player body
var player = Locator.GetPlayerTransform();
@ -108,7 +108,6 @@ namespace QSB.Player.TransformSync
_visibleStickPivot = pivot;
_visibleStickTip = pivot.Find("Stick_Tip");
DebugLog.DebugWrite("PlayerTransformSync init done - Request state!");
QSBEventManager.FireEvent(EventNames.QSBRequestStateResync);
return player;
@ -275,7 +274,5 @@ namespace QSB.Player.TransformSync
public static PlayerTransformSync LocalInstance { get; private set; }
public override bool UseInterpolation => true;
public override TargetType Type => TargetType.Player;
}
}

View File

@ -360,7 +360,8 @@ namespace QSB.PoolSync
continue;
}
var hologram = item.Value.transform.GetChild(0);
//var hologram = item.Value.transform.GetChild(0);
var hologram = item.Value.transform;
hologram.position = TransformPoint(item.Key.Body.transform.position, this, _slavePlatform);
hologram.rotation = TransformRotation(item.Key.Body.transform.rotation, this, _slavePlatform);
}
@ -719,7 +720,7 @@ namespace QSB.PoolSync
hologramCopy.GetChild(0).Find("player_mesh_noSuit:Traveller_HEA_Player/player_mesh_noSuit:Player_Head").gameObject.layer = 0;
hologramCopy.GetChild(0).Find("Traveller_Mesh_v01:Traveller_Geo/Traveller_Mesh_v01:PlayerSuit_Helmet").gameObject.layer = 0;
// TODO : Look at this again... probably need to sync head rotation to something else
// BUG : Look at this again... probably need to sync head rotation to something else
//var ikSync = hologramCopy.GetChild(0).gameObject.AddComponent<PlayerHeadRotationSync>();
//ikSync.Init(player.CameraBody.transform);

View File

@ -13,7 +13,7 @@ namespace QSB.PoolSync
private NomaiRemoteCameraStreaming _oldStreaming;
private bool _hasLoadedAssets;
protected override void Awake()
public override void Awake()
{
base.Awake();
_oldStreaming = GetComponent<NomaiRemoteCameraStreaming>();
@ -48,7 +48,7 @@ namespace QSB.PoolSync
}
}
protected override void OnSectorOccupantAdded(SectorDetector sectorDetector)
public override void OnSectorOccupantAdded(SectorDetector sectorDetector)
{
if (sectorDetector.GetOccupantType() == DynamicOccupant.Player && StreamingManager.isStreamingEnabled)
{
@ -56,7 +56,7 @@ namespace QSB.PoolSync
}
}
protected override void OnSectorOccupantRemoved(SectorDetector sectorDetector)
public override void OnSectorOccupantRemoved(SectorDetector sectorDetector)
{
if (sectorDetector.GetOccupantType() == DynamicOccupant.Player)
{

View File

@ -1,34 +1,51 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
namespace QSB.PoolSync.Patches
{
[HarmonyPatch]
internal class PoolPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(NomaiRemoteCameraPlatform_Awake));
Prefix(nameof(NomaiRemoteCameraPlatform_Update));
Prefix(nameof(NomaiRemoteCameraPlatform_OnSocketableRemoved));
Prefix(nameof(NomaiRemoteCameraPlatform_OnSocketableDonePlacing));
Prefix(nameof(NomaiRemoteCameraPlatform_OnPedestalContact));
Prefix(nameof(NomaiRemoteCameraStreaming_FixedUpdate));
Prefix(nameof(NomaiRemoteCameraStreaming_OnSectorOccupantAdded));
Prefix(nameof(NomaiRemoteCameraStreaming_OnSectorOccupantRemoved));
Prefix(nameof(NomaiRemoteCameraStreaming_OnEntry));
Prefix(nameof(NomaiRemoteCameraStreaming_OnExit));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.Awake))]
public static bool NomaiRemoteCameraPlatform_Awake() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.Update))]
public static bool NomaiRemoteCameraPlatform_Update() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.OnSocketableRemoved))]
public static bool NomaiRemoteCameraPlatform_OnSocketableRemoved() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.OnSocketableDonePlacing))]
public static bool NomaiRemoteCameraPlatform_OnSocketableDonePlacing() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.OnPedestalContact))]
public static bool NomaiRemoteCameraPlatform_OnPedestalContact() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.FixedUpdate))]
public static bool NomaiRemoteCameraStreaming_FixedUpdate() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.OnSectorOccupantAdded))]
public static bool NomaiRemoteCameraStreaming_OnSectorOccupantAdded() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.OnSectorOccupantRemoved))]
public static bool NomaiRemoteCameraStreaming_OnSectorOccupantRemoved() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.OnEntry))]
public static bool NomaiRemoteCameraStreaming_OnEntry() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.OnExit))]
public static bool NomaiRemoteCameraStreaming_OnExit() => false;
}
}

View File

@ -25,6 +25,11 @@ namespace QSB.ProbeSync.Events
public override void OnReceiveRemote(bool server, EnumMessage<ProbeEvent> message)
{
var player = QSBPlayerManager.GetPlayer(message.AboutId);
if (!player.PlayerStates.IsReady || player.Probe == null)
{
return;
}
var probe = player.Probe;
probe.HandleEvent(message.EnumValue);

View File

@ -25,6 +25,11 @@ namespace QSB.ProbeSync.Events
public override void OnReceiveRemote(bool server, FloatMessage message)
{
var player = QSBPlayerManager.GetPlayer(message.AboutId);
if (!player.PlayerStates.IsReady || player.Probe == null)
{
return;
}
var probe = player.Probe;
probe.OnStartRetrieve(message.Value);
}

View File

@ -9,7 +9,6 @@ namespace QSB.ProbeSync
public OWAudioSource _flightLoopAudio;
public OWAudioSource _anchorAudio;
public ParticleSystem _anchorParticles;
public ParticleSystem _underwaterAnchorParticles;
private QSBProbe _probe;

View File

@ -12,7 +12,6 @@ namespace QSB.ProbeSync
private QSBProbe _probe;
private OWLight2 _light;
private bool _inFlight;
private float _timer;
private void Awake()
@ -64,15 +63,12 @@ namespace QSB.ProbeSync
{
StartFadeIn();
}
_inFlight = true;
}
private void OnAnchorOrRetrieve()
{
_light.GetLight().enabled = false;
enabled = false;
_inFlight = false;
}
}
}

View File

@ -1,7 +1,7 @@
using OWML.Common;
using OWML.Utils;
using QSB.SectorSync;
using QSB.Syncs.TransformSync;
using QSB.Syncs.Sectored.Transforms;
using QSB.Tools;
using QSB.Tools.ProbeLauncherTool;
using QSB.Utility;
@ -14,7 +14,6 @@ namespace QSB.ProbeSync.TransformSync
{
protected override float DistanceLeeway => 10f;
public override bool UseInterpolation => true;
public override TargetType Type => TargetType.Probe;
public override bool IgnoreDisabledAttachedObject => true;
public static PlayerProbeSync LocalInstance { get; private set; }
@ -23,7 +22,7 @@ namespace QSB.ProbeSync.TransformSync
protected override Component InitLocalTransform()
{
QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllReady, () => SectorSync.Init(Locator.GetProbe().GetSectorDetector(), this));
QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllReady, () => SectorSync.Init(Locator.GetProbe().GetSectorDetector(), TargetType.Probe));
var body = Locator.GetProbe().transform;
Player.ProbeBody = body.gameObject;
@ -53,8 +52,8 @@ namespace QSB.ProbeSync.TransformSync
return default;
}
var body = probe.gameObject.activeSelf
? probe.InstantiateInactive()
var body = probe.gameObject.activeSelf
? probe.InstantiateInactive()
: Instantiate(probe);
body.name = "RemoteProbeTransform";
@ -89,8 +88,16 @@ namespace QSB.ProbeSync.TransformSync
probeOWRigidbody.SetPosition(launcherTransform.position);
probeOWRigidbody.SetRotation(launcherTransform.rotation);
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
if (ReferenceTransform != null)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
}
else
{
_intermediaryTransform.SetPosition(Vector3.zero);
_intermediaryTransform.SetRotation(Quaternion.identity);
}
var currentReferenceSector = ReferenceSector;
var playerReferenceSector = Player.TransformSync.ReferenceSector;

View File

@ -9,9 +9,10 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>QSB</RootNamespace>
<AssemblyName>QSB</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -21,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -33,77 +35,6 @@
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp-firstpass, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.AnimationModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.AudioModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.IMGUIModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.Networking">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.Networking.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.ParticleSystemModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.PhysicsModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UIModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UIModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.UNETModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UNETModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Animation\NPC\AnimationEvent.cs" />
<Compile Include="Animation\NPC\CharacterAnimManager.cs" />
@ -134,6 +65,7 @@
<Compile Include="CampfireSync\WorldObjects\QSBCampfire.cs" />
<Compile Include="ClientServerStateSync\ClientStateManager.cs" />
<Compile Include="ClientServerStateSync\Events\ClientStateEvent.cs" />
<Compile Include="ConversationSync\CameraFacingBillboard.cs" />
<Compile Include="ConversationSync\Events\DialogueConditionEvent.cs" />
<Compile Include="ConversationSync\Events\DialogueConditionMessage.cs" />
<Compile Include="ConversationSync\Events\ConversationEvent.cs" />
@ -170,6 +102,8 @@
<Compile Include="Instruments\QSBCamera\CameraManager.cs" />
<Compile Include="Instruments\QSBCamera\CameraMode.cs" />
<Compile Include="Instruments\InstrumentsManager.cs" />
<Compile Include="Menus\IMenuAPI.cs" />
<Compile Include="Menus\MenuManager.cs" />
<Compile Include="Messaging\BoolMessage.cs" />
<Compile Include="OrbSync\TransformSync\NomaiOrbTransformSync.cs" />
<Compile Include="Player\Events\PlayerInformationEvent.cs" />
@ -228,7 +162,6 @@
<Compile Include="ProbeSync\QSBProbeEffects.cs" />
<Compile Include="ProbeSync\QSBProbeLantern.cs" />
<Compile Include="ProbeSync\QSBProbeSpotlight.cs" />
<Compile Include="QSBNetworkLobby.cs" />
<Compile Include="Patches\QSBPatch.cs" />
<Compile Include="Patches\QSBPatchTypes.cs" />
<Compile Include="QSBSceneManager.cs" />
@ -278,10 +211,13 @@
<Compile Include="ShipSync\Events\RepairTickMessage.cs" />
<Compile Include="ShipSync\WorldObjects\QSBShipComponent.cs" />
<Compile Include="ShipSync\WorldObjects\QSBShipHull.cs" />
<Compile Include="Syncs\ISectoredSync.cs" />
<Compile Include="Syncs\RigidbodySync\UnparentedBaseRigidbodySync.cs" />
<Compile Include="Syncs\RigidbodySync\SectoredRigidbodySync.cs" />
<Compile Include="Syncs\Sectored\BaseSectoredSync.cs" />
<Compile Include="Syncs\Sectored\Rigidbodies\SectoredRigidbodySync.cs" />
<Compile Include="Syncs\Sectored\Transforms\SectoredTransformSync.cs" />
<Compile Include="Syncs\SyncBase.cs" />
<Compile Include="Syncs\Unsectored\BaseUnsectoredSync.cs" />
<Compile Include="Syncs\Unsectored\Rigidbodies\UnsectoredRigidbodySync.cs" />
<Compile Include="Syncs\Unsectored\Transforms\UnsectoredTransformSync.cs" />
<Compile Include="TimeSync\FastForwardReason.cs" />
<Compile Include="TimeSync\Patches\TimePatches.cs" />
<Compile Include="TimeSync\PauseReason.cs" />
@ -309,10 +245,7 @@
<Compile Include="StatueSync\Events\StartStatueMessage.cs" />
<Compile Include="StatueSync\Patches\StatuePatches.cs" />
<Compile Include="StatueSync\StatueManager.cs" />
<Compile Include="Syncs\TransformSync\BaseTransformSync.cs" />
<Compile Include="Syncs\IntermediaryTransform.cs" />
<Compile Include="Syncs\TransformSync\SectoredTransformSync.cs" />
<Compile Include="Syncs\TransformSync\UnparentedBaseTransformSync.cs" />
<Compile Include="TranslationSync\Events\SetAsTranslatedEvent.cs" />
<Compile Include="TranslationSync\Events\SetAsTranslatedMessage.cs" />
<Compile Include="TranslationSync\NomaiTextType.cs" />
@ -359,7 +292,6 @@
<Compile Include="Utility\Popcron.Gizmos\Drawers\PolygonDrawer.cs" />
<Compile Include="Utility\Popcron.Gizmos\Drawers\SquareDrawer.cs" />
<Compile Include="Utility\RepeatingManager.cs" />
<Compile Include="Utility\Tuple.cs" />
<Compile Include="Utility\UnitTestDetector.cs" />
<Compile Include="WorldSync\Events\BoolWorldObjectMessage.cs" />
<Compile Include="WorldSync\Events\EnumWorldObjectMessage.cs" />
@ -399,6 +331,7 @@
<Compile Include="WorldSync\WorldObjectManager.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="default-config.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
@ -406,18 +339,89 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp_publicized">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\publicized_assemblies\Assembly-CSharp_publicized.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
</Reference>
<Reference Include="netstandard">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\netstandard.dll</HintPath>
</Reference>
<Reference Include="System">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll</HintPath>
</Reference>
<Reference Include="Unity.InputSystem, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(GameDir)\OuterWilds_Data\Managed\Unity.InputSystem.dll</HintPath>
</Reference>
<Reference Include="UnityEngine">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AnimationModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AssetBundleModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AssetBundleModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AudioModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputLegacyModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.InputLegacyModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.InputModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.Networking">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.Networking.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ParticleSystemModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.PhysicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextCoreModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UI.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UNETModule">
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.UNETModule.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QuantumUNET\QuantumUNET.csproj">
<Project>{C8C53004-1508-4F86-A419-4292C188DC2A}</Project>
<Project>{c8c53004-1508-4f86-a419-4292c188dc2a}</Project>
<Name>QuantumUNET</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="lib\UnityEngine.Networking.dll" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="HarmonyX">
<Version>2.5.5</Version>
</PackageReference>
<PackageReference Include="OWML">
<Version>1.1.8</Version>
<Version>2.0.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>md "$(OwmlDir)\Mods\$(ProjectName)"
@ -425,11 +429,18 @@ md "$(OwmlDir)\Mods\$(ProjectName)\assets"
del "$(OwmlDir)\Mods\$(ProjectName)\config.json"
copy /y "$(ProjectDir)\default-config.json" "$(OwmlDir)\Mods\$(ProjectName)"
copy /y "$(SolutionDir)\AssetBundles" "$(OwmlDir)\Mods\$(ProjectName)\assets
copy /y "$(SolutionDir)\AssetBundles" "$(OwmlDir)\Mods\$(ProjectName)\assets"
copy /y "$(ProjectDir)\manifest.json" "$(OwmlDir)\Mods\$(ProjectName)"
"$(SolutionDir)\QNetWeaver\bin\Debug\QNetWeaver.exe" "$(GameDir)\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll" "$(OwmlDir)\Mods\$(ProjectName)\QuantumUNET.dll" "$(GameDir)\OuterWilds_Data\Managed\UnityEngine.Networking.dll" "$(SolutionDir)\WeavedFiles" "$(TargetPath)"
"$(SolutionDir)\QNetWeaver\bin\Debug\QNetWeaver.exe" "$(GameDir)\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll" "$(OwmlDir)\Mods\$(ProjectName)\QuantumUNET.dll" "$(ProjectDir)\lib\UnityEngine.Networking.dll" "$(SolutionDir)\WeavedFiles" "$(TargetPath)"
copy /y "$(SolutionDir)\WeavedFiles\QSB.dll" "$(OwmlDir)\Mods\$(ProjectName)"</PostBuildEvent>
copy /y "$(SolutionDir)\WeavedFiles\QSB.dll" "$(OwmlDir)\Mods\$(ProjectName)"
xcopy /y "$(ProjectDir)\lib" "$(OwmlDir)\Mods\$(ProjectName)"</PostBuildEvent>
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties manifest_1json__JsonSchema="" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GameDir>E:\Epic\Epic Games\OuterWilds</GameDir>
<GameDir>D:\EpicGames\OuterWilds</GameDir>
<OwmlDir>C:\Users\Henry\AppData\Roaming\OuterWildsModManager\OWML</OwmlDir>
<ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup>

View File

@ -1,7 +1,6 @@
using OWML.Common;
using OWML.ModHelper;
using OWML.ModHelper.Input;
using OWML.Utils;
using QSB.Animation.NPC;
using QSB.CampfireSync;
using QSB.ConversationSync;
@ -10,6 +9,7 @@ using QSB.ElevatorSync;
using QSB.GeyserSync;
using QSB.Inputs;
using QSB.ItemSync;
using QSB.Menus;
using QSB.OrbSync;
using QSB.Patches;
using QSB.Player;
@ -59,14 +59,17 @@ namespace QSB
public static AssetBundle NetworkAssetBundle { get; private set; }
public static AssetBundle InstrumentAssetBundle { get; private set; }
public static AssetBundle ConversationAssetBundle { get; private set; }
public static AssetBundle DebugAssetBundle { get; private set; }
public static bool WorldObjectsReady => WorldObjectManager.AllReady && IsInMultiplayer && PlayerTransformSync.LocalInstance != null;
public static bool IsHost => QNetworkServer.active;
public static bool IsInMultiplayer => QNetworkManager.singleton.isNetworkActive;
public static string QSBVersion => Helper.Manifest.Version;
public static string GameVersion => Application.version;
public static IMenuAPI MenuApi { get; private set; }
public void Awake()
{
var instance = TextTranslation.Get().GetValue<TextTranslation.TranslationTable>("m_table");
var instance = TextTranslation.Get().m_table;
instance.theUITable[(int)UITextType.PleaseUseController] =
"<color=orange>Quantum Space Buddies</color> is best experienced with friends...";
}
@ -76,14 +79,16 @@ namespace QSB
Helper = ModHelper;
DebugLog.ToConsole($"* Start of QSB version {QSBVersion} - authored by {Helper.Manifest.Author}", MessageType.Info);
MenuApi = ModHelper.Interaction.GetModApi<IMenuAPI>("_nebula.MenuFramework");
NetworkAssetBundle = Helper.Assets.LoadBundle("assets/network");
InstrumentAssetBundle = Helper.Assets.LoadBundle("assets/instruments");
ConversationAssetBundle = Helper.Assets.LoadBundle("assets/conversation");
DebugAssetBundle = Helper.Assets.LoadBundle("assets/debug");
QSBPatchManager.Init();
gameObject.AddComponent<QSBNetworkManager>();
gameObject.AddComponent<QNetworkManagerHUD>();
gameObject.AddComponent<DebugActions>();
gameObject.AddComponent<ConversationManager>();
gameObject.AddComponent<QSBInputManager>();
@ -91,6 +96,7 @@ namespace QSB
gameObject.AddComponent<RepeatingManager>();
gameObject.AddComponent<PlayerEntanglementWatcher>();
gameObject.AddComponent<DebugGUI>();
gameObject.AddComponent<MenuManager>();
gameObject.AddComponent<RespawnManager>();
// WorldObject managers
@ -112,9 +118,6 @@ namespace QSB
Helper.HarmonyHelper.EmptyMethod<ModCommandListener>("Update");
// Stop players being able to pause
Helper.HarmonyHelper.EmptyMethod(typeof(OWTime).GetMethod("Pause"));
QSBPatchManager.OnPatchType += OnPatchType;
QSBPatchManager.OnUnpatchType += OnUnpatchType;
}
@ -177,4 +180,5 @@ namespace QSB
* Teleskärm
* Daft Punk
* Natalie Holt
* WMD
*/

View File

@ -1,71 +0,0 @@
using OWML.Utils;
using QuantumUNET;
using System;
using System.Linq;
using UnityEngine;
namespace QSB
{
public class QSBNetworkLobby : QNetworkBehaviour
{
public bool CanEditName { get; set; }
public string PlayerName { get; private set; }
// TODO : Could delete a lot of this - shouldnt be possible to not have a profile and still play
private readonly string[] _defaultNames = {
"Arkose",
"Chert",
"Esker",
"Hal",
"Hornfels",
"Feldspar",
"Gabbro",
"Galena",
"Gneiss",
"Gossan",
"Marl",
"Mica",
"Moraine",
"Porphy",
"Riebeck",
"Rutile",
"Slate",
"Spinel",
"Tektite",
"Tephra",
"Tuff",
"Jinha"
};
public void Awake()
{
PlayerName = GetPlayerName();
CanEditName = true;
}
private string GetPlayerName()
{
var profileManager = StandaloneProfileManager.SharedInstance;
profileManager.Initialize();
var profile = profileManager.GetValue<StandaloneProfileManager.ProfileData>("_currentProfile");
var profileName = profile?.profileName;
return !string.IsNullOrEmpty(profileName)
? profileName
: _defaultNames.OrderBy(x => Guid.NewGuid()).First();
}
public void OnGUI()
{
GUI.Label(new Rect(10, 10, 200f, 20f), "Name:");
if (CanEditName)
{
PlayerName = GUI.TextField(new Rect(60, 10, 145, 20f), PlayerName);
}
else
{
GUI.Label(new Rect(60, 10, 145, 20f), PlayerName);
}
}
}
}

View File

@ -30,15 +30,18 @@ namespace QSB
public static QSBNetworkManager Instance { get; private set; }
public event Action OnNetworkManagerReady;
public event Action OnClientConnected;
public event Action<NetworkError> OnClientDisconnected;
public event Action<NetworkError> OnClientErrorThrown;
public bool IsReady { get; private set; }
public GameObject OrbPrefab { get; private set; }
public GameObject ShipPrefab { get; private set; }
public string PlayerName { get; private set; }
private const int MaxConnections = 128;
private const int MaxBufferedPackets = 64;
private QSBNetworkLobby _lobby;
private AssetBundle _assetBundle;
private GameObject _probePrefab;
private bool _everConnected;
@ -48,11 +51,11 @@ namespace QSB
base.Awake();
Instance = this;
_lobby = gameObject.AddComponent<QSBNetworkLobby>();
PlayerName = GetPlayerName();
_assetBundle = QSBCore.NetworkAssetBundle;
playerPrefab = _assetBundle.LoadAsset<GameObject>("assets/NETWORK_Player_Body.prefab");
SetupNetworkId(playerPrefab);
SetupNetworkId(playerPrefab, 1);
SetupNetworkTransform(playerPrefab);
playerPrefab.AddComponent<PlayerTransformSync>();
playerPrefab.AddComponent<AnimationSync>();
@ -62,19 +65,19 @@ namespace QSB
playerPrefab.AddComponent<InstrumentsManager>();
ShipPrefab = _assetBundle.LoadAsset<GameObject>("assets/networkship.prefab");
SetupNetworkId(ShipPrefab);
SetupNetworkId(ShipPrefab, 2);
SetupNetworkTransform(ShipPrefab);
ShipPrefab.AddComponent<ShipTransformSync>();
spawnPrefabs.Add(ShipPrefab);
_probePrefab = _assetBundle.LoadAsset<GameObject>("assets/networkprobe.prefab");
SetupNetworkId(_probePrefab);
SetupNetworkId(_probePrefab, 3);
SetupNetworkTransform(_probePrefab);
_probePrefab.AddComponent<PlayerProbeSync>();
spawnPrefabs.Add(_probePrefab);
OrbPrefab = _assetBundle.LoadAsset<GameObject>("assets/networkorb.prefab");
SetupNetworkId(OrbPrefab);
SetupNetworkId(OrbPrefab, 4);
SetupNetworkTransform(OrbPrefab);
OrbPrefab.AddComponent<NomaiOrbTransformSync>();
spawnPrefabs.Add(OrbPrefab);
@ -82,12 +85,22 @@ namespace QSB
ConfigureNetworkManager();
}
private void SetupNetworkId(GameObject go)
private string GetPlayerName()
{
var profileManager = StandaloneProfileManager.SharedInstance;
profileManager.Initialize();
var profile = profileManager.GetValue<StandaloneProfileManager.ProfileData>("_currentProfile");
var profileName = profile.profileName;
return profileName;
}
private void SetupNetworkId(GameObject go, int assetId)
{
var ident = go.AddComponent<QNetworkIdentity>();
ident.LocalPlayerAuthority = true;
ident.SetValue("m_AssetId", go.GetComponent<NetworkIdentity>().assetId);
ident.SetValue("m_SceneId", go.GetComponent<NetworkIdentity>().sceneId);
var networkIdentity = go.GetComponent<NetworkIdentity>();
ident.SetValue("m_AssetId", assetId);
ident.SetValue("m_SceneId", networkIdentity.GetComponent<NetworkIdentity>().sceneId);
}
private void SetupNetworkTransform(GameObject go)
@ -138,17 +151,21 @@ namespace QSB
public override void OnStartClient(QNetworkClient _)
{
DebugLog.DebugWrite($"Setting defaultServerIP to {networkAddress}");
var config = QSBCore.Helper.Config;
config.SetSettingsValue("defaultServerIP", networkAddress);
QSBCore.Helper.Storage.Save(config, Constants.ModConfigFileName);
}
public override void OnClientError(QNetworkConnection conn, int errorCode)
=> OnClientErrorThrown?.SafeInvoke((NetworkError)errorCode);
public override void OnClientConnect(QNetworkConnection connection) // Called on the client when connecting to a server
{
DebugLog.DebugWrite("OnClientConnect", MessageType.Info);
base.OnClientConnect(connection);
OnClientConnected?.SafeInvoke();
QSBEventManager.Init();
gameObject.AddComponent<RespawnOnDeath>();
@ -164,13 +181,11 @@ namespace QSB
QSBPatchManager.DoPatchType(specificType);
QSBPatchManager.DoPatchType(QSBPatchTypes.OnClientConnect);
_lobby.CanEditName = false;
OnNetworkManagerReady?.SafeInvoke();
IsReady = true;
QSBCore.UnityEvents.RunWhen(() => QSBEventManager.Ready && PlayerTransformSync.LocalInstance != null,
() => QSBEventManager.FireEvent(EventNames.QSBPlayerJoin, _lobby.PlayerName));
() => QSBEventManager.FireEvent(EventNames.QSBPlayerJoin, PlayerName));
if (!QSBCore.IsHost)
{
@ -202,12 +217,16 @@ namespace QSB
QSBPatchManager.DoUnpatchType(QSBPatchTypes.OnClientConnect);
}
_lobby.CanEditName = true;
IsReady = false;
_everConnected = false;
}
public override void OnClientDisconnect(QNetworkConnection conn)
{
base.OnClientDisconnect(conn);
OnClientDisconnected?.SafeInvoke(conn.LastError);
}
public override void OnServerDisconnect(QNetworkConnection connection) // Called on the server when any client disconnects
{
base.OnServerDisconnect(connection);

View File

@ -1,21 +1,21 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
using System.Reflection;
namespace QSB.QuantumSync.Patches
{
[HarmonyPatch]
public class ClientQuantumPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnNonServerClientConnect;
public override void DoPatches()
{
Prefix(nameof(QuantumMoon_ChangeQuantumState));
Postfix(nameof(QuantumMoon_Start));
}
[HarmonyPostfix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.Start))]
public static void QuantumMoon_Start(QuantumMoon __instance)
=> __instance.GetType().GetMethod("SetSurfaceState", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, new object[] { -1 });
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.ChangeQuantumState))]
public static bool QuantumMoon_ChangeQuantumState()
=> false;
}

View File

@ -1,4 +1,5 @@
using OWML.Common;
using HarmonyLib;
using OWML.Common;
using QSB.Events;
using QSB.Patches;
using QSB.Player;
@ -12,26 +13,13 @@ using UnityEngine;
namespace QSB.QuantumSync.Patches
{
[HarmonyPatch]
public class QuantumPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(SocketedQuantumObject_ChangeQuantumState));
Postfix(nameof(SocketedQuantumObject_MoveToSocket));
Prefix(nameof(QuantumShuffleObject_ChangeQuantumState));
Prefix(nameof(MultiStateQuantumObject_ChangeQuantumState));
Postfix(nameof(QuantumState_SetVisible));
Prefix(nameof(QuantumShrine_IsPlayerInDarkness));
Prefix(nameof(QuantumShrine_ChangeQuantumState));
Prefix(nameof(QuantumShrine_OnEntry));
Prefix(nameof(QuantumShrine_OnExit));
Prefix(nameof(QuantumMoon_CheckPlayerFogProximity));
Prefix(nameof(QuantumObject_IsLockedByPlayerContact));
Prefix(nameof(MultiStateQuantumObject_Start));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.IsLockedByPlayerContact))]
public static bool QuantumObject_IsLockedByPlayerContact(ref bool __result, QuantumObject __instance)
{
var playersEntangled = QuantumManager.GetEntangledPlayers(__instance);
@ -39,6 +27,8 @@ namespace QSB.QuantumSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(SocketedQuantumObject), nameof(SocketedQuantumObject.ChangeQuantumState))]
public static bool SocketedQuantumObject_ChangeQuantumState(
SocketedQuantumObject __instance,
ref bool __result,
@ -149,6 +139,8 @@ namespace QSB.QuantumSync.Patches
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(SocketedQuantumObject), nameof(SocketedQuantumObject.MoveToSocket))]
public static void SocketedQuantumObject_MoveToSocket(SocketedQuantumObject __instance, QuantumSocket socket)
{
if (!WorldObjectManager.AllReady)
@ -183,6 +175,8 @@ namespace QSB.QuantumSync.Patches
__instance.transform.localRotation);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShuffleObject), nameof(QuantumShuffleObject.ChangeQuantumState))]
public static bool QuantumShuffleObject_ChangeQuantumState(
QuantumShuffleObject __instance,
ref List<int> ____indexList,
@ -227,6 +221,8 @@ namespace QSB.QuantumSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(MultiStateQuantumObject), nameof(MultiStateQuantumObject.Start))]
public static bool MultiStateQuantumObject_Start(MultiStateQuantumObject __instance, Sector ____sector, bool ____collapseOnStart)
{
if (!WorldObjectManager.AllReady)
@ -250,17 +246,19 @@ namespace QSB.QuantumSync.Patches
if (____sector == null)
{
__instance.GetType().GetMethod("CheckEnabled", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, null);
__instance.CheckEnabled();
}
if (____collapseOnStart)
{
__instance.GetType().GetMethod("Collapse", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, new object[] { true });
__instance.Collapse(true);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(MultiStateQuantumObject), nameof(MultiStateQuantumObject.ChangeQuantumState))]
public static bool MultiStateQuantumObject_ChangeQuantumState(MultiStateQuantumObject __instance)
{
if (!WorldObjectManager.AllReady)
@ -278,6 +276,8 @@ namespace QSB.QuantumSync.Patches
return isInControl;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(QuantumState), nameof(QuantumState.SetVisible))]
public static void QuantumState_SetVisible(QuantumState __instance, bool visible)
{
if (!WorldObjectManager.AllReady)
@ -292,7 +292,13 @@ namespace QSB.QuantumSync.Patches
var allMultiStates = QSBWorldSync.GetWorldObjects<QSBMultiStateQuantumObject>();
var stateObject = QSBWorldSync.GetWorldFromUnity<QSBQuantumState, QuantumState>(__instance);
var owner = allMultiStates.First(x => x.QuantumStates.Contains(stateObject));
var owner = allMultiStates.FirstOrDefault(x => x.QuantumStates.Contains(stateObject));
if (owner == default)
{
DebugLog.DebugWrite($"Error - Could not find QSBMultiStateQuantumObject for state {__instance.name}", MessageType.Error);
return;
}
if (owner.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return;
@ -305,6 +311,8 @@ namespace QSB.QuantumSync.Patches
stateIndex);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.IsPlayerInDarkness))]
public static bool QuantumShrine_IsPlayerInDarkness(ref bool __result, Light[] ____lamps, float ____fadeFraction, bool ____isProbeInside, NomaiGateway ____gate)
{
foreach (var lamp in ____lamps)
@ -344,13 +352,15 @@ namespace QSB.QuantumSync.Patches
return false;
}
// TODO : make this *really* check for all players - check other probes and other jetpacks!
// BUG : make this *really* check for all players - check other probes and other jetpacks!
__result = ____gate.GetOpenFraction() == 0f
&& !____isProbeInside
&& Locator.GetThrusterLightTracker().GetLightRange() <= 0f;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.ChangeQuantumState))]
public static bool QuantumShrine_ChangeQuantumState(QuantumShrine __instance)
{
var shrineWorldObject = QSBWorldSync.GetWorldFromUnity<QSBSocketedQuantumObject, SocketedQuantumObject>(__instance);
@ -358,6 +368,8 @@ namespace QSB.QuantumSync.Patches
return isInControl;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.OnEntry))]
public static bool QuantumShrine_OnEntry(
GameObject hitObj,
ref bool ____isPlayerInside,
@ -380,6 +392,8 @@ namespace QSB.QuantumSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.OnExit))]
public static bool QuantumShrine_OnExit(
GameObject hitObj,
ref bool ____isPlayerInside,
@ -402,6 +416,8 @@ namespace QSB.QuantumSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.CheckPlayerFogProximity))]
public static bool QuantumMoon_CheckPlayerFogProximity(
QuantumMoon __instance,
int ____stateIndex,
@ -429,7 +445,7 @@ namespace QSB.QuantumSync.Patches
fogAlpha = Mathf.InverseLerp(____fogThickness + ____fogRolloffDistance, ____fogThickness, distanceFromFog);
if (distanceFromFog < 0f)
{
if ((bool)__instance.GetType().GetMethod("IsLockedByProbeSnapshot", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, null) || QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, true).First)
if ((bool)__instance.GetType().GetMethod("IsLockedByProbeSnapshot", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, null) || QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, true).Item1)
{
____isPlayerInside = true;
__instance.GetType().GetMethod("SetSurfaceState", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, new object[] { ____stateIndex });
@ -450,7 +466,7 @@ namespace QSB.QuantumSync.Patches
if (____stateIndex != 5)
{
____isPlayerInside = false;
if (!(bool)__instance.GetType().GetMethod("IsLockedByProbeSnapshot", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, null) && !QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, true).First)
if (!(bool)__instance.GetType().GetMethod("IsLockedByProbeSnapshot", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, null) && !QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, true).Item1)
{
__instance.GetType().GetMethod("Collapse", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(__instance, new object[] { true });
}

View File

@ -1,4 +1,5 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using QSB.Utility;
using System.Linq;
@ -7,34 +8,33 @@ using UnityEngine;
namespace QSB.QuantumSync.Patches
{
[HarmonyPatch]
public class QuantumVisibilityPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(ShapeVisibilityTracker_IsVisibleUsingCameraFrustum));
Prefix(nameof(ShapeVisibilityTracker_IsVisible));
Prefix(nameof(RendererVisibilityTracker_IsVisibleUsingCameraFrustum));
Prefix(nameof(VisibilityObject_CheckIllumination));
Postfix(nameof(Shape_OnEnable));
Postfix(nameof(Shape_OnDisable));
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Shape), nameof(Shape.OnEnable))]
public static void Shape_OnEnable(Shape __instance)
=> __instance.RaiseEvent("OnShapeActivated", __instance);
[HarmonyPostfix]
[HarmonyPatch(typeof(Shape), nameof(Shape.OnDisable))]
public static void Shape_OnDisable(Shape __instance)
=> __instance.RaiseEvent("OnShapeDeactivated", __instance);
// ShapeVisibilityTracker patches
[HarmonyPrefix]
[HarmonyPatch(typeof(ShapeVisibilityTracker), nameof(ShapeVisibilityTracker.IsVisibleUsingCameraFrustum))]
public static bool ShapeVisibilityTracker_IsVisibleUsingCameraFrustum(ShapeVisibilityTracker __instance, ref bool __result)
{
__result = QuantumManager.IsVisibleUsingCameraFrustum(__instance, false).First;
__result = QuantumManager.IsVisibleUsingCameraFrustum(__instance, false).Item1;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShapeVisibilityTracker), nameof(ShapeVisibilityTracker.IsVisible))]
public static bool ShapeVisibilityTracker_IsVisible(ShapeVisibilityTracker __instance, ref bool __result)
{
__result = QuantumManager.IsVisible(__instance, false);
@ -43,6 +43,8 @@ namespace QSB.QuantumSync.Patches
// RendererVisibilityTracker patches - probably not needed as i don't think RendererVisibilityTracker is ever used?
[HarmonyPrefix]
[HarmonyPatch(typeof(RendererVisibilityTracker), nameof(RendererVisibilityTracker.IsVisibleUsingCameraFrustum))]
public static bool RendererVisibilityTracker_IsVisibleUsingCameraFrustum(RendererVisibilityTracker __instance, ref bool __result, Renderer ____renderer, bool ____checkFrustumOcclusion)
{
__result = QSBPlayerManager.GetPlayersWithCameras()
@ -56,6 +58,8 @@ namespace QSB.QuantumSync.Patches
// VisibilityObject
[HarmonyPrefix]
[HarmonyPatch(typeof(VisibilityObject), nameof(VisibilityObject.CheckIllumination))]
public static bool VisibilityObject_CheckIllumination(VisibilityObject __instance, ref bool __result, bool ____checkIllumination, Vector3 ____localIlluminationOffset, float ____illuminationRadius, Light[] ____lightSources)
{
if (!____checkIllumination)
@ -66,8 +70,8 @@ namespace QSB.QuantumSync.Patches
var point = __instance.transform.TransformPoint(____localIlluminationOffset);
var tupleFlashlights = QSBPlayerManager.GetPlayerFlashlights();
var localFlashlight = tupleFlashlights.First;
var playerFlashlights = tupleFlashlights.Second;
var localFlashlight = tupleFlashlights.Item1;
var playerFlashlights = tupleFlashlights.Item2;
// local player flashlight
if (localFlashlight.CheckIlluminationAtPoint(point, ____illuminationRadius))
@ -83,14 +87,14 @@ namespace QSB.QuantumSync.Patches
return false;
}
// TODO : Implement checking for other probes!
// BUG : Implement checking for other probes!
if (Locator.GetProbe() != null && Locator.GetProbe().IsLaunched() && Locator.GetProbe().CheckIlluminationAtPoint(point, ____illuminationRadius))
{
__result = true;
return false;
}
// TODO : Implement checking for other player's thrusters!
// BUG : Implement checking for other player's thrusters!
if (Locator.GetThrusterLightTracker().CheckIlluminationAtPoint(point, ____illuminationRadius))
{
__result = true;

View File

@ -1,4 +1,5 @@
using OWML.Common;
using HarmonyLib;
using OWML.Common;
using QSB.Events;
using QSB.Patches;
using QSB.Player;
@ -9,13 +10,13 @@ using UnityEngine;
namespace QSB.QuantumSync.Patches
{
[HarmonyPatch]
public class ServerQuantumPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnServerClientConnect;
public override void DoPatches()
=> Prefix(nameof(QuantumMoon_ChangeQuantumState));
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.ChangeQuantumState))]
public static bool QuantumMoon_ChangeQuantumState(
QuantumMoon __instance,
ref bool __result,
@ -38,9 +39,14 @@ namespace QSB.QuantumSync.Patches
GameObject[] ____deactivateAtEye
)
{
if (!QSBCore.WorldObjectsReady)
{
return false;
}
var isVisibleOutput = QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, skipInstantVisibilityCheck);
//var moonVisible = isVisibleOutput.First;
var moonVisiblePlayers = isVisibleOutput.Second;
var moonVisiblePlayers = isVisibleOutput.Item2;
var inMoonPlayers = QSBPlayerManager.PlayerList.Where(x => x.IsInMoon);
if (inMoonPlayers == null)
{
@ -148,7 +154,7 @@ namespace QSB.QuantumSync.Patches
Physics.SyncTransforms();
}
if (__instance.IsPlayerEntangled() || !QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, skipInstantVisibilityCheck).First)
if (__instance.IsPlayerEntangled() || !QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)____visibilityTracker, skipInstantVisibilityCheck).Item1)
{
____moonBody.transform.position = position;
if (!Physics.autoSyncTransforms)

View File

@ -4,6 +4,7 @@ using QSB.Player;
using QSB.QuantumSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -31,7 +32,7 @@ namespace QSB.QuantumSync
protected override void RebuildWorldObjects(OWScene scene)
{
DebugLog.DebugWrite("Rebuilding quantum objects...", MessageType.Warning);
DebugLog.DebugWrite("Rebuilding quantum objects...", MessageType.Info);
QSBWorldSync.Init<QSBQuantumState, QuantumState>();
QSBWorldSync.Init<QSBSocketedQuantumObject, SocketedQuantumObject>();
QSBWorldSync.Init<QSBMultiStateQuantumObject, MultiStateQuantumObject>();
@ -87,7 +88,7 @@ namespace QSB.QuantumSync
var playersWithCameras = QSBPlayerManager.GetPlayersWithCameras(!ignoreLocalCamera);
if (playersWithCameras.Count == 0)
{
DebugLog.ToConsole($"Warning - Trying to run IsVisibleUsingCameraFrustum when there are no players!", MessageType.Warning);
DebugLog.ToConsole($"Warning - Could not find any players with cameras!", MessageType.Warning);
return new Tuple<bool, List<PlayerInfo>>(false, new List<PlayerInfo>());
}
@ -120,7 +121,7 @@ namespace QSB.QuantumSync
}
public static bool IsVisible(ShapeVisibilityTracker tracker, bool ignoreLocalCamera) => tracker.gameObject.activeInHierarchy
&& IsVisibleUsingCameraFrustum(tracker, ignoreLocalCamera).First
&& IsVisibleUsingCameraFrustum(tracker, ignoreLocalCamera).Item1
&& QSBPlayerManager.GetPlayersWithCameras(!ignoreLocalCamera)
.Any(x => VisibilityOccluder.CanYouSee(tracker, x.Camera.mainCamera.transform.position));

View File

@ -11,7 +11,7 @@ namespace QSB.QuantumSync.WorldObjects
{
public List<QSBQuantumState> QuantumStates { get; private set; }
public Text DebugBoxText;
public int CurrentState => AttachedObject.GetValue<int>("_stateIndex");
public int CurrentState => AttachedObject._stateIndex;
public override void OnRemoval()
{
@ -26,15 +26,25 @@ namespace QSB.QuantumSync.WorldObjects
{
ObjectId = id;
AttachedObject = attachedObject;
QuantumStates = AttachedObject.GetValue<QuantumState[]>("_states").ToList().Select(x => QSBWorldSync.GetWorldFromUnity<QSBQuantumState, QuantumState>(x)).ToList();
if (QSBCore.DebugMode)
{
DebugBoxText = DebugBoxManager.CreateBox(AttachedObject.transform, 0, CurrentState.ToString()).GetComponent<Text>();
DebugBoxText = DebugBoxManager.CreateBox(AttachedObject.transform, 0, $"Multistate\r\nid:{id}\r\nstate:{CurrentState}").GetComponent<Text>();
}
base.Init(attachedObject, id);
}
public override void PostInit()
{
QuantumStates = AttachedObject._states.ToList().Select(x => QSBWorldSync.GetWorldFromUnity<QSBQuantumState, QuantumState>(x)).ToList();
if (QuantumStates.Any(x => x == null))
{
DebugLog.ToConsole($"Error - {AttachedObject.name} has one or more null QSBQuantumStates assigned!", OWML.Common.MessageType.Error);
}
}
public void ChangeState(int newStateIndex)
{
if (CurrentState != -1)
@ -43,10 +53,10 @@ namespace QSB.QuantumSync.WorldObjects
}
QuantumStates[newStateIndex].SetVisible(true);
AttachedObject.SetValue("_stateIndex", newStateIndex);
AttachedObject._stateIndex = newStateIndex;
if (QSBCore.DebugMode)
{
DebugBoxText.text = newStateIndex.ToString();
DebugBoxText.text = $"Multistate\r\nid:{ObjectId}\r\nstate:{CurrentState}";
}
}
}

View File

@ -6,6 +6,7 @@ using QSB.Utility;
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.WorldObjects
{
@ -29,6 +30,26 @@ namespace QSB.QuantumSync.WorldObjects
public override void Init(T attachedObject, int id)
{
var debugBundle = QSBCore.DebugAssetBundle;
var sphere = debugBundle.LoadAsset<GameObject>("Assets/Sphere.prefab");
var cube = debugBundle.LoadAsset<GameObject>("Assets/Cube.prefab");
var capsule = debugBundle.LoadAsset<GameObject>("Assets/Capsule.prefab");
if (cube == null)
{
DebugLog.DebugWrite($"CUBE IS NULL");
}
if (sphere == null)
{
DebugLog.DebugWrite($"SPHERE IS NULL");
}
if (capsule == null)
{
DebugLog.DebugWrite($"CAPSULE IS NULL");
}
foreach (var shape in GetAttachedShapes())
{
if (shape == null)
@ -42,6 +63,31 @@ namespace QSB.QuantumSync.WorldObjects
shape.OnShapeDeactivated += (Shape s)
=> QSBCore.UnityEvents.FireOnNextUpdate(() => OnDisable(s));
if (shape is BoxShape boxShape)
{
var newCube = UnityEngine.Object.Instantiate(cube);
newCube.transform.parent = shape.transform;
newCube.transform.localPosition = Vector3.zero;
newCube.transform.localRotation = Quaternion.Euler(0, 0, 0);
newCube.transform.localScale = boxShape.size;
}
else if (shape is SphereShape sphereShape)
{
var newSphere = UnityEngine.Object.Instantiate(sphere);
newSphere.transform.parent = shape.transform;
newSphere.transform.localPosition = Vector3.zero;
newSphere.transform.localRotation = Quaternion.Euler(0, 0, 0);
newSphere.transform.localScale = Vector3.one * (sphereShape.radius * 2);
}
else if (shape is CapsuleShape capsuleShape)
{
var newCapsule = Object.Instantiate(capsule);
newCapsule.transform.parent = shape.transform;
newCapsule.transform.localPosition = Vector3.zero;
newCapsule.transform.localRotation = Quaternion.Euler(0, 0, 0);
newCapsule.transform.localScale = new Vector3(capsuleShape.radius * 2, capsuleShape.height, capsuleShape.radius * 2);
}
}
if (GetAttachedShapes().Any(x => !x.enabled || !x.active))

View File

@ -20,7 +20,7 @@ namespace QSB.QuantumSync.WorldObjects
base.Init(quantumObject, id);
if (QSBCore.DebugMode)
{
DebugBoxText = DebugBoxManager.CreateBox(AttachedObject.transform, 0, ObjectId.ToString()).GetComponent<Text>();
DebugBoxText = DebugBoxManager.CreateBox(AttachedObject.transform, 0, $"Socketed\r\nid:{ObjectId}").GetComponent<Text>();
}
}

View File

@ -1,28 +1,34 @@
using QSB.Events;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
using UnityEngine;
namespace QSB.RoastingSync.Patches
{
[HarmonyPatch]
internal class RoastingPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(RoastingStickController_UpdateMarshmallowInput));
Prefix(nameof(Marshmallow_Burn));
Prefix(nameof(Marshmallow_Shrivel));
Prefix(nameof(Marshmallow_RemoveMallow));
Prefix(nameof(Marshmallow_SpawnMallow));
}
//public override void DoPatches()
//{
// Prefix<RoastingStickController>(nameof(RoastingStickController.UpdateMarshmallowInput), nameof(RoastingStickController_UpdateMarshmallowInput));
// Prefix<Marshmallow>(nameof(Marshmallow.Burn), nameof(Marshmallow_Burn));
// Prefix<Marshmallow>(nameof(Marshmallow.Shrivel), nameof(Marshmallow_Shrivel));
// Prefix<Marshmallow>(nameof(Marshmallow.RemoveMallow), nameof(Marshmallow_RemoveMallow));
// Prefix<Marshmallow>(nameof(Marshmallow.SpawnMallow), nameof(Marshmallow_SpawnMallow));
//}
[HarmonyPrefix]
[HarmonyPatch(typeof(Marshmallow), nameof(Marshmallow.SpawnMallow))]
public static bool Marshmallow_SpawnMallow()
{
QSBEventManager.FireEvent(EventNames.QSBMarshmallowEvent, MarshmallowEventType.Replace);
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Marshmallow), nameof(Marshmallow.Burn))]
public static bool Marshmallow_Burn(
ref Marshmallow.MallowState ____mallowState,
MeshRenderer ____fireRenderer,
@ -43,6 +49,8 @@ namespace QSB.RoastingSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Marshmallow), nameof(Marshmallow.Shrivel))]
public static bool Marshmallow_Shrivel(
ref Marshmallow.MallowState ____mallowState,
ref float ____initShrivelTime)
@ -57,6 +65,8 @@ namespace QSB.RoastingSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Marshmallow), nameof(Marshmallow.RemoveMallow))]
public static bool Marshmallow_RemoveMallow(
ParticleSystem ____smokeParticles,
MeshRenderer ____fireRenderer,
@ -73,6 +83,8 @@ namespace QSB.RoastingSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(RoastingStickController), nameof(RoastingStickController.UpdateMarshmallowInput))]
public static bool RoastingStickController_UpdateMarshmallowInput(
float ____extendFraction,
Marshmallow ____marshmallow,
@ -96,7 +108,7 @@ namespace QSB.RoastingSync.Patches
if (____marshmallow.IsBurned())
{
showRemovePrompt = true;
if (OWInput.IsNewlyPressed(InputLibrary.cancel, true, InputMode.Roasting))
if (OWInput.IsNewlyPressed(InputLibrary.cancel, InputMode.Roasting))
{
____marshmallow.Remove();
Locator.GetPlayerAudioController().PlayMarshmallowToss();

View File

@ -4,6 +4,6 @@
{
public Sector AttachedSector;
protected override void Awake() { }
public override void Awake() { }
}
}

View File

@ -1,6 +1,6 @@
using OWML.Common;
using QSB.SectorSync.WorldObjects;
using QSB.Syncs;
using QSB.Syncs.Sectored;
using QSB.Utility;
using QSB.WorldSync;
using System.Collections.Generic;
@ -18,8 +18,7 @@ namespace QSB.SectorSync
private void OnEnable() => RepeatingManager.Repeatings.Add(this);
private void OnDisable() => RepeatingManager.Repeatings.Remove(this);
public List<SyncBase> SectoredTransformSyncs = new List<SyncBase>();
public List<SyncBase> SectoredRigidbodySyncs = new List<SyncBase>();
public List<BaseSectoredSync> SectoredSyncs = new List<BaseSectoredSync>();
public void Invoke()
{
@ -28,7 +27,7 @@ namespace QSB.SectorSync
return;
}
foreach (var sync in SectoredTransformSyncs)
foreach (var sync in SectoredSyncs)
{
if (sync.AttachedObject == null)
{
@ -37,24 +36,10 @@ namespace QSB.SectorSync
if (sync.HasAuthority
&& sync.AttachedObject.gameObject.activeInHierarchy
&& sync.IsReady)
&& sync.IsReady
&& sync.SectorSync.IsReady)
{
CheckTransformSyncSector(sync as ISectoredSync<Transform>);
}
}
foreach (var sync in SectoredRigidbodySyncs)
{
if (sync.AttachedObject == null)
{
continue;
}
if (sync.HasAuthority
&& sync.AttachedObject.gameObject.activeInHierarchy
&& sync.IsReady)
{
CheckTransformSyncSector(sync as ISectoredSync<OWRigidbody>);
CheckTransformSyncSector(sync);
}
}
}
@ -68,7 +53,7 @@ namespace QSB.SectorSync
protected override void RebuildWorldObjects(OWScene scene)
{
DebugLog.DebugWrite("Rebuilding sectors...", MessageType.Warning);
DebugLog.DebugWrite("Rebuilding sectors...", MessageType.Info);
if (QSBSceneManager.CurrentScene == OWScene.SolarSystem)
{
var timeLoopRing = GameObject.Find("TimeLoopRing_Body");
@ -89,10 +74,9 @@ namespace QSB.SectorSync
IsReady = QSBWorldSync.GetWorldObjects<QSBSector>().Any();
}
private void CheckTransformSyncSector<T>(ISectoredSync<T> transformSync)
where T : Component
private void CheckTransformSyncSector(BaseSectoredSync transformSync)
{
var attachedObject = (transformSync as SyncBase).AttachedObject;
var attachedObject = transformSync.AttachedObject;
var closestSector = transformSync.SectorSync.GetClosestSector(attachedObject.transform);
if (closestSector == default(QSBSector))
{

View File

@ -1,9 +1,9 @@
using OWML.Common;
using OWML.Utils;
using QSB.SectorSync.WorldObjects;
using QSB.Syncs;
using QSB.Utility;
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
@ -12,12 +12,12 @@ namespace QSB.SectorSync
{
public class SectorSync : MonoBehaviour
{
public bool IsReady { get; private set; }
public List<QSBSector> SectorList = new List<QSBSector>();
private OWRigidbody _attachedOWRigidbody;
private SectorDetector _sectorDetector;
private TargetType _targetType;
private bool _isReady;
private void OnDestroy()
{
@ -26,10 +26,11 @@ namespace QSB.SectorSync
_sectorDetector.OnEnterSector -= AddSector;
_sectorDetector.OnExitSector -= RemoveSector;
}
_isReady = false;
IsReady = false;
}
public void Init<T>(SectorDetector detector, ISectoredSync<T> sectoredSync)
public void Init(SectorDetector detector, TargetType type)
{
if (_sectorDetector != null)
{
@ -55,8 +56,8 @@ namespace QSB.SectorSync
PopulateSectorList();
_targetType = sectoredSync.Type;
_isReady = true;
_targetType = type;
IsReady = true;
}
private void PopulateSectorList()
@ -117,15 +118,15 @@ namespace QSB.SectorSync
return null;
}
if (!_isReady)
if (!IsReady)
{
DebugLog.ToConsole($"Warning - Tried to use GetClosestSector before it was initialized. Transform:{trans.name}", MessageType.Warning);
DebugLog.ToConsole($"Warning - Tried to use GetClosestSector() before this SectorSync is ready. Transform:{trans.name} Stacktrace:\r\n{Environment.StackTrace}", MessageType.Warning);
return null;
}
if (_sectorDetector == null || _attachedOWRigidbody == null || _targetType == TargetType.None)
{
_isReady = false;
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

@ -1,30 +1,20 @@
using OWML.Utils;
using HarmonyLib;
using OWML.Utils;
using QSB.Events;
using QSB.Patches;
using QSB.Utility;
using System;
using UnityEngine;
namespace QSB.ShipSync.Patches
{
[HarmonyPatch]
internal class ShipPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
{
Prefix(nameof(HatchController_OnPressInteract));
Prefix(nameof(HatchController_OnEntry));
Prefix(nameof(ShipTractorBeamSwitch_OnTriggerExit));
Prefix(nameof(InteractZone_UpdateInteractVolume));
Prefix(nameof(ShipElectricalComponent_OnEnterShip));
Prefix(nameof(ShipElectricalComponent_OnExitShip));
Prefix(nameof(ShipComponent_SetDamaged));
Prefix(nameof(ShipHull_FixedUpdate));
Prefix(nameof(ShipDamageController_OnImpact));
Postfix(nameof(ShipComponent_RepairTick));
Prefix(nameof(ShipHull_RepairTick));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(HatchController), nameof(HatchController.OnPressInteract))]
public static bool HatchController_OnPressInteract()
{
if (!PlayerState.IsInsideShip())
@ -37,6 +27,8 @@ namespace QSB.ShipSync.Patches
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(HatchController), nameof(HatchController.OnEntry))]
public static bool HatchController_OnEntry(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
@ -47,9 +39,11 @@ namespace QSB.ShipSync.Patches
return true;
}
public static bool ShipTractorBeamSwitch_OnTriggerExit(Collider hitCollider, bool ____isPlayerInShip, bool ____functional)
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipTractorBeamSwitch), nameof(ShipTractorBeamSwitch.OnTriggerExit))]
public static bool ShipTractorBeamSwitch_OnTriggerExit(ShipTractorBeamSwitch __instance, Collider hitCollider)
{
if (!____isPlayerInShip && ____functional && hitCollider.CompareTag("PlayerDetector") && !ShipManager.Instance.HatchController.GetValue<GameObject>("_hatchObject").activeSelf)
if (!__instance._isPlayerInShip && __instance._functional && hitCollider.CompareTag("PlayerDetector") && !ShipManager.Instance.HatchController._hatchObject.activeSelf)
{
ShipManager.Instance.HatchController.Invoke("CloseHatch");
ShipManager.Instance.ShipTractorBeam.DeactivateTractorBeam();
@ -59,7 +53,16 @@ namespace QSB.ShipSync.Patches
return false;
}
public static bool InteractZone_UpdateInteractVolume(InteractZone __instance, OWCamera ____playerCam, ref bool ____focused)
[HarmonyReversePatch]
[HarmonyPatch(typeof(SingleInteractionVolume), nameof(SingleInteractionVolume.UpdateInteractVolume))]
public static void SingleInteractionVolume_UpdateInteractVolume_Stub(object instance)
{
throw new NotImplementedException();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(InteractZone), nameof(InteractZone.UpdateInteractVolume))]
public static bool InteractZone_UpdateInteractVolume(InteractZone __instance)
{
/* Angle for interaction with the ship hatch
*
@ -78,64 +81,86 @@ namespace QSB.ShipSync.Patches
return true;
}
var angle = 2f * Vector3.Angle(____playerCam.transform.forward, __instance.transform.forward);
var angle = 2f * Vector3.Angle(__instance._playerCam.transform.forward, __instance.transform.forward);
____focused = PlayerState.IsInsideShip()
__instance._focused = PlayerState.IsInsideShip()
? angle <= 80
: angle >= 280;
__instance.CallBase<InteractZone, SingleInteractionVolume>("UpdateInteractVolume");
SingleInteractionVolume_UpdateInteractVolume_Stub(__instance as SingleInteractionVolume);
return false;
}
public static bool ShipElectricalComponent_OnEnterShip(ShipElectricalComponent __instance, bool ____damaged, ElectricalSystem ____electricalSystem)
[HarmonyReversePatch]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.OnEnterShip))]
public static void ShipComponent_OnEnterShip_Stub(object instance)
{
__instance.CallBase<ShipElectricalComponent, ShipComponent>("OnEnterShip");
throw new NotImplementedException();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipElectricalComponent), nameof(ShipElectricalComponent.OnEnterShip))]
public static bool ShipElectricalComponent_OnEnterShip(ShipElectricalComponent __instance)
{
ShipComponent_OnEnterShip_Stub(__instance as ShipComponent);
return false;
}
public static bool ShipElectricalComponent_OnExitShip(ShipElectricalComponent __instance, bool ____damaged, ElectricalSystem ____electricalSystem)
[HarmonyReversePatch]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.OnExitShip))]
public static void ShipComponent_OnExitShip_Stub(object instance)
{
__instance.CallBase<ShipElectricalComponent, ShipComponent>("OnExitShip");
throw new NotImplementedException();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipElectricalComponent), nameof(ShipElectricalComponent.OnExitShip))]
public static bool ShipElectricalComponent_OnExitShip(ShipElectricalComponent __instance)
{
ShipComponent_OnExitShip_Stub(__instance as ShipComponent);
return false;
}
public static bool ShipComponent_SetDamaged(ShipComponent __instance, bool damaged, ref bool ____damaged, ref float ____repairFraction, DamageEffect ____damageEffect)
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.SetDamaged))]
public static bool ShipComponent_SetDamaged(ShipComponent __instance, bool damaged)
{
if (____damaged == damaged)
if (__instance._damaged == damaged)
{
return false;
}
if (damaged)
{
____damaged = true;
____repairFraction = 0f;
__instance._damaged = true;
__instance._repairFraction = 0f;
__instance.GetType().GetAnyMethod("OnComponentDamaged").Invoke(__instance, null);
__instance.RaiseEvent("OnDamaged", __instance);
QSBEventManager.FireEvent(EventNames.QSBComponentDamaged, __instance);
}
else
{
____damaged = false;
____repairFraction = 1f;
__instance._damaged = false;
__instance._repairFraction = 1f;
__instance.GetType().GetAnyMethod("OnComponentRepaired").Invoke(__instance, null);
__instance.RaiseEvent("OnRepaired", __instance);
QSBEventManager.FireEvent(EventNames.QSBComponentRepaired, __instance);
}
__instance.GetType().GetAnyMethod("UpdateColliderState").Invoke(__instance, null);
if (____damageEffect)
if (__instance._damageEffect)
{
____damageEffect.SetEffectBlend(1f - ____repairFraction);
__instance._damageEffect.SetEffectBlend(1f - __instance._repairFraction);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipHull), nameof(ShipHull.FixedUpdate))]
public static bool ShipHull_FixedUpdate(ShipHull __instance, ref ImpactData ____dominantImpact, ref float ____integrity, ref bool ____damaged, DamageEffect ____damageEffect, ShipComponent[] ____components)
{
if (____dominantImpact != null)
@ -186,15 +211,21 @@ namespace QSB.ShipSync.Patches
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipDamageController), nameof(ShipDamageController.OnImpact))]
public static bool ShipDamageController_OnImpact()
=> ShipManager.Instance.HasAuthority;
[HarmonyPostfix]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.RepairTick))]
public static void ShipComponent_RepairTick(ShipComponent __instance, float ____repairFraction)
{
QSBEventManager.FireEvent(EventNames.QSBComponentRepairTick, __instance, ____repairFraction);
return;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipHull), nameof(ShipHull.RepairTick))]
public static bool ShipHull_RepairTick(ShipHull __instance, ref float ____integrity, ref bool ____damaged, DamageEffect ____damageEffect, float ____repairTime)
{
if (!____damaged)

View File

@ -78,6 +78,7 @@ namespace QSB.ShipSync
DebugLog.ToConsole($"Warning - ShipTransformSync's LocalInstance is not null, but it's gameobject is null!", MessageType.Warning);
return;
}
QNetworkServer.Destroy(ShipTransformSync.LocalInstance.gameObject);
}
@ -85,7 +86,8 @@ namespace QSB.ShipSync
{
DebugLog.ToConsole($"Error - Tried to spawn ship, but LocalPlayer's TransformSync is null!", MessageType.Error);
}
QNetworkServer.SpawnWithClientAuthority(Instantiate(QSBNetworkManager.Instance.ShipPrefab), QSBPlayerManager.LocalPlayer.TransformSync.gameObject);
Instantiate(QSBNetworkManager.Instance.ShipPrefab).SpawnWithServerAuthority();
}
QSBWorldSync.Init<QSBShipComponent, ShipComponent>();
@ -106,6 +108,9 @@ namespace QSB.ShipSync
UpdateElectricalComponent();
}
public bool IsPlayerInShip(PlayerInfo player)
=> _playersInShip.Contains(player);
private void UpdateElectricalComponent()
{
var electricalSystem = ShipElectricalComponent.GetValue<ElectricalSystem>("_electricalSystem");

View File

@ -1,9 +1,6 @@
using QSB.Player;
using QSB.SectorSync;
using QSB.Syncs.RigidbodySync;
using QSB.Utility;
using QSB.Syncs.Sectored.Rigidbodies;
using QSB.WorldSync;
using UnityEngine;
namespace QSB.ShipSync.TransformSync
{
@ -11,6 +8,9 @@ namespace QSB.ShipSync.TransformSync
{
public static ShipTransformSync LocalInstance { get; private set; }
private const int ForcePositionAfterUpdates = 50;
private int _updateCount;
public override bool IsReady
=> Locator.GetShipBody() != null;
@ -20,34 +20,65 @@ namespace QSB.ShipSync.TransformSync
LocalInstance = this;
}
protected override Component InitLocalTransform() => throw new System.NotImplementedException();
protected override Component InitRemoteTransform() => throw new System.NotImplementedException();
protected override OWRigidbody GetRigidbody()
{
QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllReady, () => SectorSync.Init(Locator.GetShipDetector().GetComponent<SectorDetector>(), this));
QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllReady, () => SectorSync.Init(Locator.GetShipDetector().GetComponent<SectorDetector>(), TargetType.Ship));
return Locator.GetShipBody();
}
private void ForcePosition()
{
if (ReferenceTransform == null)
{
return;
}
var targetPos = _intermediaryTransform.GetTargetPosition_Unparented();
var targetRot = _intermediaryTransform.GetTargetRotation_Unparented();
(AttachedObject as OWRigidbody).SetPosition(targetPos);
(AttachedObject as OWRigidbody).SetRotation(targetRot);
}
protected override bool UpdateTransform()
{
if (HasAuthority && ShipManager.Instance.CurrentFlyer != QSBPlayerManager.LocalPlayerId && ShipManager.Instance.CurrentFlyer != uint.MaxValue)
if (!UpdateSectors())
{
DebugLog.ToConsole("Warning - Has authority, but is not current flyer!", OWML.Common.MessageType.Warning);
return false;
}
if (!HasAuthority && ShipManager.Instance.CurrentFlyer == QSBPlayerManager.LocalPlayerId)
// Dont do base... this is a replacement!
if (HasAuthority)
{
DebugLog.ToConsole($"Warning - Doesn't have authority, but is current flyer!", OWML.Common.MessageType.Warning);
return false;
SetValuesToSync();
return true;
}
return base.UpdateTransform();
_updateCount++;
if (_updateCount >= ForcePositionAfterUpdates)
{
_updateCount = 0;
ForcePosition();
}
if (ReferenceTransform == null)
{
return true;
}
var targetPos = _intermediaryTransform.GetTargetPosition_Unparented();
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().GetPointVelocity(targetPos) + _relativeVelocity;
var targetAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().GetAngularVelocity() + _relativeAngularVelocity;
SetVelocity(AttachedObject as OWRigidbody, targetVelocity);
(AttachedObject as OWRigidbody).SetAngularVelocity(targetAngularVelocity);
return true;
}
public override TargetType Type => TargetType.Ship;
public override bool UseInterpolation => true;
protected override float DistanceLeeway => 20f;
}

View File

@ -31,6 +31,7 @@ namespace QSB.StatueSync.Events
{
return;
}
QSBEventManager.FireEvent(EventNames.QSBServerState, ServerState.InStatueCutscene);
}

View File

@ -1,17 +1,18 @@
using QSB.Events;
using HarmonyLib;
using QSB.Events;
using QSB.Patches;
using QSB.Player;
using UnityEngine;
namespace QSB.StatueSync.Patches
{
[HarmonyPatch]
internal class StatuePatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
=> Prefix(nameof(MemoryUplinkTrigger_Update));
[HarmonyPrefix]
[HarmonyPatch(typeof(MemoryUplinkTrigger), nameof(MemoryUplinkTrigger.Update))]
public static bool MemoryUplinkTrigger_Update(bool ____waitForPlayerGrounded)
{
if (StatueManager.Instance.HasStartedStatueLocally)

View File

@ -1,14 +0,0 @@
using QSB.SectorSync;
using QSB.SectorSync.WorldObjects;
namespace QSB.Syncs
{
public interface ISectoredSync<T>
{
SectorSync.SectorSync SectorSync { get; }
QSBSector ReferenceSector { get; }
TargetType Type { get; }
void SetReferenceSector(QSBSector sector);
}
}

View File

@ -1,6 +1,6 @@
using OWML.Common;
using QSB.Utility;
using System.Reflection;
using System;
using UnityEngine;
namespace QSB.Syncs
@ -58,7 +58,7 @@ namespace QSB.Syncs
{
if (_referenceTransform == null)
{
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} ({MethodBase.GetCurrentMethod().Name})", MessageType.Error);
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} \r\n{Environment.StackTrace}", MessageType.Error);
return;
}
@ -73,7 +73,7 @@ namespace QSB.Syncs
{
if (_referenceTransform == null)
{
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} ({MethodBase.GetCurrentMethod().Name})", MessageType.Error);
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} \r\n{Environment.StackTrace}", MessageType.Error);
return;
}
@ -99,7 +99,7 @@ namespace QSB.Syncs
{
if (_referenceTransform == null)
{
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} ({MethodBase.GetCurrentMethod().Name})", MessageType.Error);
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} \r\n{Environment.StackTrace}", MessageType.Error);
return Vector3.zero;
}
@ -113,7 +113,7 @@ namespace QSB.Syncs
{
if (_referenceTransform == null)
{
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} ({MethodBase.GetCurrentMethod().Name})", MessageType.Error);
DebugLog.ToConsole($"Error - _referenceTransform has not been set for {_attachedTransform.name} \r\n{Environment.StackTrace}", MessageType.Error);
return Quaternion.identity;
}

View File

@ -1,120 +0,0 @@
using QSB.SectorSync;
using QSB.SectorSync.WorldObjects;
using QSB.WorldSync;
using QuantumUNET.Transport;
namespace QSB.Syncs.RigidbodySync
{
public abstract class SectoredRigidbodySync : UnparentedBaseRigidbodySync, ISectoredSync<OWRigidbody>
{
public QSBSector ReferenceSector { get; set; }
public SectorSync.SectorSync SectorSync { get; private set; }
public abstract TargetType Type { get; }
public override bool IgnoreDisabledAttachedObject => false;
public override bool IgnoreNullReferenceTransform => true;
public override void Start()
{
SectorSync = gameObject.AddComponent<SectorSync.SectorSync>();
QSBSectorManager.Instance.SectoredRigidbodySyncs.Add(this);
base.Start();
}
protected override void OnDestroy()
{
base.OnDestroy();
QSBSectorManager.Instance.SectoredRigidbodySyncs.Remove(this);
if (SectorSync != null)
{
Destroy(SectorSync);
}
}
protected override void Init()
{
base.Init();
if (!QSBSectorManager.Instance.IsReady)
{
return;
}
if (!HasAuthority)
{
return;
}
var closestSector = SectorSync.GetClosestSector(AttachedObject.transform);
if (closestSector != null)
{
SetReferenceTransform(closestSector.Transform);
}
}
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
if (ReferenceSector != null)
{
writer.Write(ReferenceSector.ObjectId);
}
else
{
writer.Write(-1);
}
base.SerializeTransform(writer, initialState);
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
if (!QSBCore.WorldObjectsReady)
{
reader.ReadInt32();
reader.ReadVector3();
DeserializeRotation(reader);
return;
}
var sectorId = reader.ReadInt32();
var sector = sectorId == -1
? null
: QSBWorldSync.GetWorldFromId<QSBSector>(sectorId);
if (sector != ReferenceSector)
{
SetReferenceSector(sector);
}
base.DeserializeTransform(reader, initialState);
}
protected override bool UpdateTransform()
{
if ((ReferenceTransform == null || ReferenceSector == null || _intermediaryTransform.GetReferenceTransform() == null) && QSBSectorManager.Instance.IsReady && HasAuthority)
{
var closestSector = SectorSync.GetClosestSector(AttachedObject.transform);
if (closestSector != null)
{
SetReferenceTransform(closestSector.Transform);
}
else
{
return false;
}
}
return base.UpdateTransform();
}
public void SetReferenceSector(QSBSector sector)
{
ReferenceSector = sector;
SetReferenceTransform(sector?.Transform);
}
}
}

View File

@ -4,32 +4,30 @@ using QSB.SectorSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET.Transport;
using UnityEngine;
namespace QSB.Syncs.TransformSync
namespace QSB.Syncs.Sectored
{
public abstract class SectoredTransformSync : BaseTransformSync, ISectoredSync<Transform>
public abstract class BaseSectoredSync : SyncBase
{
public override bool IgnoreDisabledAttachedObject => false;
public override bool IgnoreNullReferenceTransform => true;
public QSBSector ReferenceSector { get; set; }
public SectorSync.SectorSync SectorSync { get; private set; }
public abstract TargetType Type { get; }
public override bool IgnoreNullReferenceTransform => true;
public override bool IgnoreDisabledAttachedObject => false;
private int _sectorIdWaitingSlot = int.MinValue;
public override void Start()
{
SectorSync = gameObject.AddComponent<SectorSync.SectorSync>();
QSBSectorManager.Instance.SectoredTransformSyncs.Add(this);
QSBSectorManager.Instance.SectoredSyncs.Add(this);
base.Start();
}
protected override void OnDestroy()
{
base.OnDestroy();
QSBSectorManager.Instance.SectoredTransformSyncs.Remove(this);
QSBSectorManager.Instance.SectoredSyncs.Remove(this);
if (SectorSync != null)
{
Destroy(SectorSync);
@ -49,6 +47,11 @@ namespace QSB.Syncs.TransformSync
return;
}
QSBCore.UnityEvents.RunWhen(() => SectorSync.IsReady, InitSector);
}
private void InitSector()
{
var closestSector = SectorSync.GetClosestSector(AttachedObject.transform);
if (closestSector != null)
{
@ -56,7 +59,7 @@ namespace QSB.Syncs.TransformSync
}
else
{
DebugLog.DebugWrite($"INIT - {PlayerId}.{GetType().Name}'s closest sector is null!");
DebugLog.ToConsole($"Warning - {_logName}'s initial sector was null.", OWML.Common.MessageType.Warning);
}
}
@ -104,26 +107,25 @@ namespace QSB.Syncs.TransformSync
if (!QSBPlayerManager.PlayerExists(PlayerId))
{
DebugLog.ToConsole($"Warning - Tried to serialize {_logName} before the right player exists.", OWML.Common.MessageType.Warning);
writer.Write(-1);
}
else if (!Player.PlayerStates.IsReady)
{
DebugLog.ToConsole($"Warning - Tried to serialize {_logName} before the player was ready.", OWML.Common.MessageType.Warning);
writer.Write(-1);
}
if (ReferenceSector != null)
else if (ReferenceSector != null)
{
writer.Write(ReferenceSector.ObjectId);
}
else
{
DebugLog.ToConsole($"Warning - ReferenceSector of {PlayerId}.{GetType().Name} is null.", OWML.Common.MessageType.Warning);
if (_isInitialized)
{
DebugLog.ToConsole($"Warning - ReferenceSector of {PlayerId}.{GetType().Name} is null.", OWML.Common.MessageType.Warning);
}
writer.Write(-1);
}
base.SerializeTransform(writer, initialState);
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
@ -134,11 +136,10 @@ namespace QSB.Syncs.TransformSync
sectorId = reader.ReadInt32();
if (initialState && sectorId != -1)
{
DebugLog.DebugWrite($"SET WAITING FOR SECTOR SET - id {sectorId}");
DebugLog.DebugWrite($"{_logName} set waiting sector id:{sectorId}");
_sectorIdWaitingSlot = sectorId;
}
reader.ReadVector3();
DeserializeRotation(reader);
return;
}
@ -152,17 +153,14 @@ namespace QSB.Syncs.TransformSync
if (sector == null)
{
DebugLog.ToConsole($"Error - {PlayerId}.{GetType().Name} got sector of ID -1.", OWML.Common.MessageType.Error);
base.DeserializeTransform(reader, initialState);
return;
}
SetReferenceSector(sector);
}
base.DeserializeTransform(reader, initialState);
}
protected override bool UpdateTransform()
protected bool UpdateSectors()
{
var referenceNull = ReferenceTransform == null || ReferenceSector == null || _intermediaryTransform.GetReferenceTransform() == null;
var sectorManagerReady = QSBSectorManager.Instance.IsReady;
@ -175,31 +173,44 @@ namespace QSB.Syncs.TransformSync
$"Transform:{ReferenceTransform == null}, Sector:{ReferenceSector == null}, Intermediary:{_intermediaryTransform.GetReferenceTransform() == null}",
OWML.Common.MessageType.Warning);
}
return base.UpdateTransform();
DebugLog.DebugWrite($"{_logName} : Sector Manager not ready.");
return false;
}
if (!HasAuthority)
{
return base.UpdateTransform();
return true;
}
if (referenceNull)
{
var closestSector = SectorSync.GetClosestSector(AttachedObject.transform);
if (closestSector != null)
if (SectorSync.IsReady)
{
SetReferenceTransform(closestSector.Transform);
var closestSector = SectorSync.GetClosestSector(AttachedObject.transform);
if (closestSector != null)
{
SetReferenceTransform(closestSector.Transform);
return true;
}
else
{
DebugLog.ToConsole($"Error - No closest sector found to {PlayerId}.{GetType().Name}!", OWML.Common.MessageType.Error);
return false;
}
}
else
{
DebugLog.ToConsole($"Error - No closest sector found to {PlayerId}.{GetType().Name}!", OWML.Common.MessageType.Error);
return false;
}
}
return base.UpdateTransform();
return true;
}
protected override bool UpdateTransform()
=> UpdateSectors();
public void SetReferenceSector(QSBSector sector)
{
ReferenceSector = sector;

View File

@ -1,63 +1,46 @@
using OWML.Common;
using OWML.Utils;
using QSB.Player.TransformSync;
using QSB.Utility;
using QuantumUNET.Transport;
using System.Linq;
using UnityEngine;
namespace QSB.Syncs.RigidbodySync
namespace QSB.Syncs.Sectored.Rigidbodies
{
public abstract class UnparentedBaseRigidbodySync : SyncBase
public abstract class SectoredRigidbodySync : BaseSectoredSync
{
public override bool ShouldReparentAttachedObject => false;
public const float PositionMovedThreshold = 0.05f;
public const float AngleRotatedThreshold = 0.05f;
public const float VelocityChangeThreshold = 0.05f;
public const float AngVelocityChangeThreshold = 0.05f;
protected Vector3 _relativeVelocity;
protected Vector3 _relativeAngularVelocity;
protected Vector3 _prevVelocity;
protected Vector3 _prevAngularVelocity;
/// <summary>
/// The previous position of the VISIBLE object, as if parented to the reference.
/// </summary>
protected Vector3 _localPrevPosition;
/// <summary>
/// The previous rotation of the VISIBLE object, as if parented to the reference.
/// </summary>
protected Quaternion _localPrevRotation;
protected Vector3 _localPrevVelocity;
protected Vector3 _localPrevAngularVelocity;
protected abstract OWRigidbody GetRigidbody();
public virtual void Start()
{
var lowestBound = Resources.FindObjectsOfTypeAll<PlayerTransformSync>()
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
DontDestroyOnLoad(gameObject);
_intermediaryTransform = new IntermediaryTransform(transform);
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
}
protected virtual void OnDestroy() => QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isInUniverse)
=> _isInitialized = false;
protected override void Init()
{
if (!QSBSceneManager.IsInUniverse)
{
DebugLog.ToConsole($"Error - {_logName} is being init-ed when not in the universe!", MessageType.Error);
}
AttachedObject = GetRigidbody();
_isInitialized = true;
}
protected override Component SetAttachedObject()
=> GetRigidbody();
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
/* We need to send :
* - Position
* - Rotation
* - Velocity
* - Angular velocity
* We can't store the last two on the IntermediaryTransform, so they come from fields.
*/
base.SerializeTransform(writer, initialState);
var worldPos = _intermediaryTransform.GetPosition();
var worldRot = _intermediaryTransform.GetRotation();
@ -77,6 +60,8 @@ namespace QSB.Syncs.RigidbodySync
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
base.DeserializeTransform(reader, initialState);
if (!QSBCore.WorldObjectsReady)
{
reader.ReadVector3();
@ -112,14 +97,24 @@ namespace QSB.Syncs.RigidbodySync
}
}
protected void SetValuesToSync()
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
_relativeVelocity = GetRelativeVelocity();
_relativeAngularVelocity = (AttachedObject as OWRigidbody).GetRelativeAngularVelocity(ReferenceTransform.GetAttachedOWRigidbody());
}
protected override bool UpdateTransform()
{
if (!base.UpdateTransform())
{
return false;
}
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
_relativeVelocity = GetRelativeVelocity();
_relativeAngularVelocity = (AttachedObject as OWRigidbody).GetRelativeAngularVelocity(ReferenceTransform.GetAttachedOWRigidbody());
SetValuesToSync();
return true;
}
@ -131,28 +126,101 @@ namespace QSB.Syncs.RigidbodySync
return false;
}
Vector3 positionToSet = targetPos;
Quaternion rotationToSet = targetRot;
if (UseInterpolation)
{
(AttachedObject as OWRigidbody).SetPosition(SmartSmoothDamp(AttachedObject.transform.position, targetPos));
(AttachedObject as OWRigidbody).SetRotation(QuaternionHelper.SmoothDamp(AttachedObject.transform.rotation, targetRot, ref _rotationSmoothVelocity, SmoothTime));
positionToSet = SmartSmoothDamp(AttachedObject.transform.position, targetPos);
rotationToSet = QuaternionHelper.SmoothDamp(AttachedObject.transform.rotation, targetRot, ref _rotationSmoothVelocity, SmoothTime);
}
else
var hasMoved = CustomHasMoved(
_intermediaryTransform.GetTargetPosition_ParentedToReference(),
_localPrevPosition,
_intermediaryTransform.GetTargetRotation_ParentedToReference(),
_localPrevRotation,
_relativeVelocity,
_localPrevVelocity,
_relativeAngularVelocity,
_localPrevAngularVelocity);
_localPrevPosition = _intermediaryTransform.GetTargetPosition_ParentedToReference();
_localPrevRotation = _intermediaryTransform.GetTargetRotation_ParentedToReference();
_localPrevVelocity = _relativeVelocity;
_localPrevAngularVelocity = _relativeAngularVelocity;
if (!hasMoved)
{
(AttachedObject as OWRigidbody).SetPosition(targetPos);
(AttachedObject as OWRigidbody).SetRotation(targetRot);
return true;
}
var currentVelocity = GetRelativeVelocity();
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().GetPointVelocity(targetPos) + _relativeVelocity;
var adjustedTarget = targetVelocity + Locator.GetCenterOfTheUniverse().GetStaticFrameWorldVelocity();
//(AttachedObject as OWRigidbody).SetPosition(positionToSet);
//(AttachedObject as OWRigidbody).SetRotation(rotationToSet);
SetVelocity((AttachedObject as OWRigidbody), targetVelocity);
(AttachedObject as OWRigidbody).SetAngularVelocity(ReferenceTransform.GetAttachedOWRigidbody().GetAngularVelocity() + _relativeAngularVelocity);
(AttachedObject as OWRigidbody).MoveToPosition(positionToSet);
(AttachedObject as OWRigidbody).MoveToRotation(rotationToSet);
var targetVelocity = ReferenceTransform.GetAttachedOWRigidbody().GetPointVelocity(targetPos) + _relativeVelocity;
var targetAngularVelocity = ReferenceTransform.GetAttachedOWRigidbody().GetAngularVelocity() + _relativeAngularVelocity;
SetVelocity(AttachedObject as OWRigidbody, targetVelocity);
(AttachedObject as OWRigidbody).SetAngularVelocity(targetAngularVelocity);
return true;
}
private void SetVelocity(OWRigidbody rigidbody, Vector3 relativeVelocity)
public override bool HasMoved()
=> CustomHasMoved(
_intermediaryTransform.GetPosition(),
_prevPosition,
_intermediaryTransform.GetRotation(),
_prevRotation,
_relativeVelocity,
_prevVelocity,
_relativeAngularVelocity,
_prevAngularVelocity);
// OPTIMIZE : optimize by using sqrMagnitude
private bool CustomHasMoved(
Vector3 newPosition,
Vector3 prevPosition,
Quaternion newRotation,
Quaternion prevRotation,
Vector3 newVelocity,
Vector3 prevVelocity,
Vector3 newAngVelocity,
Vector3 prevAngVelocity)
{
var displacementMagnitude = (newPosition - prevPosition).magnitude;
if (displacementMagnitude > PositionMovedThreshold)
{
return true;
}
if (Quaternion.Angle(newRotation, prevRotation) > AngleRotatedThreshold)
{
return true;
}
var velocityChangeMagnitude = (newVelocity - prevVelocity).magnitude;
var angularVelocityChangeMagnitude = (newAngVelocity - prevAngVelocity).magnitude;
if (velocityChangeMagnitude > VelocityChangeThreshold)
{
return true;
}
if (angularVelocityChangeMagnitude > AngVelocityChangeThreshold)
{
return true;
}
return false;
}
// TODO : why? isn't owrigidbody.setvelocity the same...? :P
protected void SetVelocity(OWRigidbody rigidbody, Vector3 relativeVelocity)
{
var isRunningKinematic = rigidbody.RunningKinematicSimulation();
var currentVelocity = rigidbody.GetValue<Vector3>("_currentVelocity");
@ -160,65 +228,18 @@ namespace QSB.Syncs.RigidbodySync
if (isRunningKinematic)
{
var kinematicRigidbody = rigidbody.GetValue<KinematicRigidbody>("_kinematicRigidbody");
kinematicRigidbody.velocity = relativeVelocity + Locator.GetCenterOfTheUniverse().GetStaticFrameWorldVelocity();
kinematicRigidbody.velocity = relativeVelocity + Locator.GetCenterOfTheUniverse().GetStaticFrameVelocity_Internal();
}
else
{
var normalRigidbody = rigidbody.GetValue<Rigidbody>("_rigidbody");
normalRigidbody.velocity = relativeVelocity + Locator.GetCenterOfTheUniverse().GetStaticFrameWorldVelocity();
normalRigidbody.velocity = relativeVelocity + Locator.GetCenterOfTheUniverse().GetStaticFrameVelocity_Internal();
}
rigidbody.SetValue("_lastVelocity", currentVelocity);
rigidbody.SetValue("_currentVelocity", relativeVelocity);
}
public void SetReferenceTransform(Transform transform)
{
if (ReferenceTransform == transform)
{
return;
}
ReferenceTransform = transform;
_intermediaryTransform.SetReferenceTransform(transform);
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
}
}
// TODO : optimize by using sqrMagnitude
public override bool HasMoved()
{
var displacementMagnitude = (_intermediaryTransform.GetPosition() - _prevPosition).magnitude;
if (displacementMagnitude > 1E-03f)
{
return true;
}
if (Quaternion.Angle(_intermediaryTransform.GetRotation(), _prevRotation) > 1E-03f)
{
return true;
}
var velocityChangeMagnitude = (_relativeVelocity - _prevVelocity).magnitude;
var angularVelocityChangeMagnitude = (_relativeAngularVelocity - _prevAngularVelocity).magnitude;
if (velocityChangeMagnitude > 1E-03f)
{
return true;
}
if (angularVelocityChangeMagnitude > 1E-03f)
{
return true;
}
return false;
}
public float GetVelocityChangeMagnitude()
=> (_relativeVelocity - _prevVelocity).magnitude;
@ -247,4 +268,4 @@ namespace QSB.Syncs.RigidbodySync
return (AttachedObject as OWRigidbody).GetVelocity() - pointVelocity;
}
}
}
}

View File

@ -0,0 +1,105 @@
using OWML.Common;
using QSB.Utility;
using QuantumUNET.Transport;
using UnityEngine;
namespace QSB.Syncs.Sectored.Transforms
{
public abstract class SectoredTransformSync : BaseSectoredSync
{
public override bool ShouldReparentAttachedObject => true;
protected abstract Component InitLocalTransform();
protected abstract Component InitRemoteTransform();
protected override Component SetAttachedObject()
=> HasAuthority ? InitLocalTransform() : InitRemoteTransform();
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
base.SerializeTransform(writer, initialState);
var worldPos = _intermediaryTransform.GetPosition();
var worldRot = _intermediaryTransform.GetRotation();
writer.Write(worldPos);
SerializeRotation(writer, worldRot);
_prevPosition = worldPos;
_prevRotation = worldRot;
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
base.DeserializeTransform(reader, initialState);
if (!QSBCore.WorldObjectsReady)
{
reader.ReadVector3();
DeserializeRotation(reader);
return;
}
var pos = reader.ReadVector3();
var rot = DeserializeRotation(reader);
if (HasAuthority)
{
return;
}
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
_intermediaryTransform.SetPosition(pos);
_intermediaryTransform.SetRotation(rot);
if (_intermediaryTransform.GetPosition() == Vector3.zero)
{
DebugLog.ToConsole($"Warning - {_logName} at (0,0,0)! - Given position was {pos}", MessageType.Warning);
}
}
protected override bool UpdateTransform()
{
if (!base.UpdateTransform())
{
return false;
}
if (HasAuthority)
{
if (ReferenceTransform != null)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
}
else
{
_intermediaryTransform.SetPosition(Vector3.zero);
_intermediaryTransform.SetRotation(Quaternion.identity);
}
return true;
}
var targetPos = _intermediaryTransform.GetTargetPosition_ParentedToReference();
var targetRot = _intermediaryTransform.GetTargetRotation_ParentedToReference();
if (targetPos != Vector3.zero && _intermediaryTransform.GetTargetPosition_Unparented() != Vector3.zero)
{
if (UseInterpolation)
{
AttachedObject.transform.localPosition = SmartSmoothDamp(AttachedObject.transform.localPosition, targetPos);
AttachedObject.transform.localRotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.localRotation, targetRot, ref _rotationSmoothVelocity, SmoothTime);
}
else
{
AttachedObject.transform.localPosition = targetPos;
AttachedObject.transform.localRotation = targetRot;
}
}
return true;
}
}
}

View File

@ -1,14 +1,45 @@
using OWML.Common;
using QSB.Player;
using QSB.Player.TransformSync;
using QSB.Utility;
using QSB.WorldSync;
using QuantumUNET.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QSB.Syncs
{
/*
* Rewrite number : 9
* God has cursed me for my hubris, and my work is never finished.
*/
public abstract class SyncBase : QNetworkTransform
{
private static readonly Dictionary<uint, Dictionary<Type, SyncBase>> _storedTransformSyncs = new Dictionary<uint, Dictionary<Type, SyncBase>>();
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 = Resources.FindObjectsOfTypeAll<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
@ -50,6 +81,7 @@ namespace QSB.Syncs
public abstract bool UseInterpolation { get; }
public abstract bool IgnoreDisabledAttachedObject { get; }
public abstract bool IgnoreNullReferenceTransform { get; }
public abstract bool ShouldReparentAttachedObject { get; }
public Component AttachedObject { get; set; }
public Transform ReferenceTransform { get; set; }
@ -63,22 +95,78 @@ namespace QSB.Syncs
protected IntermediaryTransform _intermediaryTransform;
protected bool _isInitialized;
protected abstract Component InitLocalTransform();
protected abstract Component InitRemoteTransform();
protected abstract Component SetAttachedObject();
protected abstract bool UpdateTransform();
protected abstract void Init();
protected Vector3 SmartSmoothDamp(Vector3 currentPosition, Vector3 targetPosition)
public virtual void Start()
{
var distance = Vector3.Distance(currentPosition, targetPosition);
if (distance > _previousDistance + DistanceLeeway)
var lowestBound = Resources.FindObjectsOfTypeAll<PlayerTransformSync>()
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
DontDestroyOnLoad(gameObject);
_intermediaryTransform = new IntermediaryTransform(transform);
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
if (Player == null)
{
_previousDistance = distance;
return targetPosition;
DebugLog.ToConsole($"Error - Player in start of {_logName} was null!", MessageType.Error);
return;
}
_previousDistance = distance;
return Vector3.SmoothDamp(currentPosition, targetPosition, ref _positionSmoothVelocity, SmoothTime);
if (!_storedTransformSyncs.ContainsKey(PlayerId))
{
_storedTransformSyncs.Add(PlayerId, new Dictionary<Type, SyncBase>());
}
var playerDict = _storedTransformSyncs[PlayerId];
playerDict[GetType()] = this;
}
protected virtual void OnDestroy()
{
if (ShouldReparentAttachedObject)
{
if (!HasAuthority && AttachedObject != null)
{
Destroy(AttachedObject.gameObject);
}
}
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
if (!QSBPlayerManager.PlayerExists(PlayerId))
{
return;
}
var playerDict = _storedTransformSyncs[PlayerId];
playerDict.Remove(GetType());
}
protected virtual void Init()
{
if (!QSBSceneManager.IsInUniverse)
{
DebugLog.ToConsole($"Error - {_logName} is being init-ed when not in the universe!", MessageType.Error);
}
// TODO : maybe make it's own option
if (ShouldReparentAttachedObject)
{
if (!HasAuthority && AttachedObject != null)
{
Destroy(AttachedObject.gameObject);
}
}
AttachedObject = SetAttachedObject();
_isInitialized = true;
}
protected virtual void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isInUniverse)
{
_isInitialized = false;
}
public override void Update()
@ -135,30 +223,72 @@ namespace QSB.Syncs
return;
}
var state = UpdateTransform();
if (!state)
UpdateTransform();
base.Update();
}
protected Vector3 SmartSmoothDamp(Vector3 currentPosition, Vector3 targetPosition)
{
var distance = Vector3.Distance(currentPosition, targetPosition);
if (distance > _previousDistance + DistanceLeeway)
{
/*
DebugLog.DebugWrite($"{_logName} moved too far!" +
$"\r\n CurrentPosition:{currentPosition}," +
$"\r\n TargetPosition:{targetPosition}");
*/
_previousDistance = distance;
return targetPosition;
}
_previousDistance = distance;
return Vector3.SmoothDamp(currentPosition, targetPosition, ref _positionSmoothVelocity, SmoothTime);
}
public void SetReferenceTransform(Transform transform)
{
if (ReferenceTransform == transform)
{
DebugLog.ToConsole($"{_logName} UpdateTransform() fail.", MessageType.Error);
base.Update();
return;
}
/*
var expectedPosition = _intermediaryTransform.GetTargetPosition_Unparented();
var actualPosition = AttachedObject.transform.position;
var distance = Vector3.Distance(expectedPosition, actualPosition);
if (distance > 20)
{
var intermediaryReference = _intermediaryTransform.GetReferenceTransform();
DebugLog.ToConsole($"Warning - {_logName}'s AttachedObject ({AttachedObject?.name}) is far away from it's expected position! Info:" +
$"\r\n AttachedObject's parent : {AttachedObject?.transform.parent?.name}" +
$"\r\n Distance : {distance}" +
$"\r\n ReferenceTransform : {(ReferenceTransform == null ? "NULL" : ReferenceTransform.name)}" +
$"\r\n Intermediary's ReferenceTransform : {(intermediaryReference == null ? "NULL" : intermediaryReference.name)}", MessageType.Warning);
}
*/
ReferenceTransform = transform;
_intermediaryTransform.SetReferenceTransform(transform);
base.Update();
if (ShouldReparentAttachedObject)
{
if (AttachedObject == null)
{
DebugLog.ToConsole($"Warning - AttachedObject was null for {_logName} when trying to set reference transform to {transform?.name}. Waiting until not null...", MessageType.Warning);
QSBCore.UnityEvents.RunWhen(
() => AttachedObject != null,
() => ReparentAttachedObject(transform));
return;
}
if (!HasAuthority)
{
ReparentAttachedObject(transform);
}
}
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
}
}
private void ReparentAttachedObject(Transform newParent)
{
if (AttachedObject.transform.parent != null && AttachedObject.transform.parent.GetComponent<Sector>() == null)
{
DebugLog.ToConsole($"Warning - Trying to reparent AttachedObject {AttachedObject.name} which wasnt attached to sector!", MessageType.Warning);
}
AttachedObject.transform.SetParent(newParent, true);
AttachedObject.transform.localScale = Vector3.one;
}
protected virtual void OnRenderObject()

View File

@ -1,258 +0,0 @@
using OWML.Common;
using QSB.Player;
using QSB.Player.TransformSync;
using QSB.Utility;
using QuantumUNET;
using QuantumUNET.Transport;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QSB.Syncs.TransformSync
{
/*
* Rewrite number : 7
* God has cursed me for my hubris, and my work is never finished.
*/
public abstract class BaseTransformSync : SyncBase
{
private static readonly Dictionary<PlayerInfo, Dictionary<Type, BaseTransformSync>> _storedTransformSyncs = new Dictionary<PlayerInfo, Dictionary<Type, BaseTransformSync>>();
public static T GetPlayers<T>(PlayerInfo player)
where T : BaseTransformSync
{
var dictOfOwnedSyncs = _storedTransformSyncs[player];
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 = Resources.FindObjectsOfTypeAll<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 virtual void Start()
{
var lowestBound = Resources.FindObjectsOfTypeAll<PlayerTransformSync>()
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
DontDestroyOnLoad(gameObject);
_intermediaryTransform = new IntermediaryTransform(transform);
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
if (!_storedTransformSyncs.ContainsKey(Player))
{
_storedTransformSyncs.Add(Player, new Dictionary<Type, BaseTransformSync>());
}
var playerDict = _storedTransformSyncs[Player];
playerDict[GetType()] = this;
}
protected virtual void OnDestroy()
{
if (!HasAuthority && AttachedObject != null)
{
Destroy(AttachedObject.gameObject);
}
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
if (!QSBPlayerManager.PlayerExists(PlayerId))
{
return;
}
var playerDict = _storedTransformSyncs[Player];
playerDict.Remove(GetType());
}
protected virtual void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isInUniverse)
=> _isInitialized = false;
protected override void Init()
{
if (!QSBSceneManager.IsInUniverse)
{
DebugLog.ToConsole($"Error - {_logName} is being init-ed when not in the universe!", MessageType.Error);
}
if (!HasAuthority && AttachedObject != null)
{
Destroy(AttachedObject.gameObject);
}
AttachedObject = HasAuthority ? InitLocalTransform() : InitRemoteTransform();
_isInitialized = true;
if (QSBCore.DebugMode)
{
DebugBoxManager.CreateBox(AttachedObject.transform, 0, _logName);
}
}
public override bool OnSerialize(QNetworkWriter writer, bool initialState)
{
if (!initialState)
{
if (SyncVarDirtyBits == 0U)
{
writer.WritePackedUInt32(0U);
return false;
}
writer.WritePackedUInt32(1U);
}
SerializeTransform(writer, initialState);
return true;
}
public override void OnDeserialize(QNetworkReader reader, bool initialState)
{
if (!IsServer || !QNetworkServer.localClientActive)
{
if (!initialState)
{
if (reader.ReadPackedUInt32() == 0U)
{
return;
}
}
DeserializeTransform(reader, initialState);
}
}
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
var worldPos = _intermediaryTransform.GetPosition();
var worldRot = _intermediaryTransform.GetRotation();
writer.Write(worldPos);
SerializeRotation(writer, worldRot);
_prevPosition = worldPos;
_prevRotation = worldRot;
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
if (!QSBCore.WorldObjectsReady)
{
reader.ReadVector3();
DeserializeRotation(reader);
return;
}
var pos = reader.ReadVector3();
var rot = DeserializeRotation(reader);
if (HasAuthority)
{
return;
}
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
_intermediaryTransform.SetPosition(pos);
_intermediaryTransform.SetRotation(rot);
if (_intermediaryTransform.GetPosition() == Vector3.zero)
{
DebugLog.ToConsole($"Warning - {_logName} at (0,0,0)! - Given position was {pos}", MessageType.Warning);
}
}
protected override bool UpdateTransform()
{
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
return true;
}
var targetPos = _intermediaryTransform.GetTargetPosition_ParentedToReference();
var targetRot = _intermediaryTransform.GetTargetRotation_ParentedToReference();
if (targetPos != Vector3.zero && _intermediaryTransform.GetTargetPosition_Unparented() != Vector3.zero)
{
if (UseInterpolation)
{
AttachedObject.transform.localPosition = SmartSmoothDamp(AttachedObject.transform.localPosition, targetPos);
AttachedObject.transform.localRotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.localRotation, targetRot, ref _rotationSmoothVelocity, SmoothTime);
}
else
{
AttachedObject.transform.localPosition = targetPos;
AttachedObject.transform.localRotation = targetRot;
}
}
return true;
}
public override bool HasMoved()
{
var displacementMagnitude = (_intermediaryTransform.GetPosition() - _prevPosition).magnitude;
return displacementMagnitude > 1E-03f
|| Quaternion.Angle(_intermediaryTransform.GetRotation(), _prevRotation) > 1E-03f;
}
public void SetReferenceTransform(Transform transform)
{
if (ReferenceTransform == transform)
{
return;
}
ReferenceTransform = transform;
_intermediaryTransform.SetReferenceTransform(transform);
if (AttachedObject == null)
{
DebugLog.ToConsole($"Warning - AttachedObject was null for {_logName} when trying to set reference transform to {transform?.name}. Waiting until not null...", MessageType.Warning);
QSBCore.UnityEvents.RunWhen(
() => AttachedObject != null,
() => ReparentAttachedObject(transform));
return;
}
if (!HasAuthority)
{
ReparentAttachedObject(transform);
}
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
}
}
private void ReparentAttachedObject(Transform newParent)
{
if (AttachedObject.transform.parent != null && AttachedObject.transform.parent.GetComponent<Sector>() == null)
{
DebugLog.ToConsole($"Warning - Trying to reparent AttachedObject {AttachedObject.name} which wasnt attached to sector!", MessageType.Warning);
}
AttachedObject.transform.SetParent(newParent, true);
AttachedObject.transform.localScale = Vector3.one;
}
}
}

View File

@ -1,144 +0,0 @@
using OWML.Common;
using QSB.Player.TransformSync;
using QSB.Utility;
using QuantumUNET.Transport;
using System.Linq;
using UnityEngine;
namespace QSB.Syncs.TransformSync
{
public abstract class UnparentedBaseTransformSync : SyncBase
{
public override bool IgnoreDisabledAttachedObject => false;
public override bool IgnoreNullReferenceTransform => false;
public virtual void Start()
{
var lowestBound = Resources.FindObjectsOfTypeAll<PlayerTransformSync>()
.Where(x => x.NetId.Value <= NetId.Value).OrderBy(x => x.NetId.Value).Last();
NetIdentity.SetRootIdentity(lowestBound.NetIdentity);
DontDestroyOnLoad(gameObject);
_intermediaryTransform = new IntermediaryTransform(transform);
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
}
protected virtual void OnDestroy()
{
DebugLog.DebugWrite($"OnDestroy {_logName}");
if (!HasAuthority && AttachedObject != null)
{
Destroy(AttachedObject.gameObject);
}
QSBSceneManager.OnSceneLoaded -= OnSceneLoaded;
}
protected void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isInUniverse) =>
_isInitialized = false;
protected override void Init()
{
AttachedObject = HasAuthority ? InitLocalTransform() : InitRemoteTransform();
_isInitialized = true;
}
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
var worldPos = _intermediaryTransform.GetPosition();
var worldRot = _intermediaryTransform.GetRotation();
writer.Write(worldPos);
SerializeRotation(writer, worldRot);
_prevPosition = worldPos;
_prevRotation = worldRot;
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
if (!QSBCore.WorldObjectsReady)
{
reader.ReadVector3();
DeserializeRotation(reader);
return;
}
var pos = reader.ReadVector3();
var rot = DeserializeRotation(reader);
if (HasAuthority)
{
return;
}
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
_intermediaryTransform.SetPosition(pos);
_intermediaryTransform.SetRotation(rot);
if (_intermediaryTransform.GetPosition() == Vector3.zero)
{
DebugLog.ToConsole($"Warning - {PlayerId}.{GetType().Name} at (0,0,0)! - Given position was {pos}", MessageType.Warning);
}
}
protected override bool UpdateTransform()
{
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
return true;
}
var targetPos = _intermediaryTransform.GetTargetPosition_Unparented();
var targetRot = _intermediaryTransform.GetTargetRotation_Unparented();
if (targetPos != Vector3.zero && _intermediaryTransform.GetTargetPosition_ParentedToReference() != Vector3.zero)
{
if (UseInterpolation)
{
AttachedObject.transform.position = SmartSmoothDamp(AttachedObject.transform.position, targetPos);
AttachedObject.transform.rotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.rotation, targetRot, ref _rotationSmoothVelocity, SmoothTime);
}
else
{
AttachedObject.transform.position = targetPos;
AttachedObject.transform.rotation = targetRot;
}
}
return true;
}
public override bool HasMoved()
{
var displacementMagnitude = (_intermediaryTransform.GetPosition() - _prevPosition).magnitude;
return displacementMagnitude > 1E-03f
|| Quaternion.Angle(_intermediaryTransform.GetRotation(), _prevRotation) > 1E-03f;
}
public void SetReferenceTransform(Transform transform)
{
if (ReferenceTransform == transform)
{
return;
}
ReferenceTransform = transform;
_intermediaryTransform.SetReferenceTransform(transform);
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
}
}
}
}

View File

@ -0,0 +1,19 @@
using QuantumUNET.Transport;
namespace QSB.Syncs.Unsectored
{
public abstract class BaseUnsectoredSync : SyncBase
{
public override bool IgnoreDisabledAttachedObject => false;
public override bool IgnoreNullReferenceTransform => false;
public override bool ShouldReparentAttachedObject => false;
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using UnityEngine;
namespace QSB.Syncs.Unsectored.Rigidbodies
{
public abstract class UnsectoredRigidbodySync : BaseUnsectoredSync
{
protected abstract OWRigidbody GetRigidbody();
protected override Component SetAttachedObject()
=> throw new NotImplementedException();
}
}

View File

@ -0,0 +1,91 @@
using OWML.Common;
using QSB.Utility;
using QuantumUNET.Transport;
using UnityEngine;
namespace QSB.Syncs.Unsectored.Transforms
{
public abstract class UnsectoredTransformSync : BaseUnsectoredSync
{
protected abstract Component InitLocalTransform();
protected abstract Component InitRemoteTransform();
protected override Component SetAttachedObject()
=> HasAuthority ? InitLocalTransform() : InitRemoteTransform();
public override void SerializeTransform(QNetworkWriter writer, bool initialState)
{
base.SerializeTransform(writer, initialState);
var worldPos = _intermediaryTransform.GetPosition();
var worldRot = _intermediaryTransform.GetRotation();
writer.Write(worldPos);
SerializeRotation(writer, worldRot);
_prevPosition = worldPos;
_prevRotation = worldRot;
}
public override void DeserializeTransform(QNetworkReader reader, bool initialState)
{
if (!QSBCore.WorldObjectsReady)
{
reader.ReadVector3();
DeserializeRotation(reader);
return;
}
var pos = reader.ReadVector3();
var rot = DeserializeRotation(reader);
if (HasAuthority)
{
return;
}
if (_intermediaryTransform == null)
{
_intermediaryTransform = new IntermediaryTransform(transform);
}
_intermediaryTransform.SetPosition(pos);
_intermediaryTransform.SetRotation(rot);
if (_intermediaryTransform.GetPosition() == Vector3.zero)
{
//DebugLog.ToConsole($"Warning - {_logName} at (0,0,0)! - Given position was {pos}", MessageType.Warning);
}
}
protected override bool UpdateTransform()
{
if (HasAuthority)
{
_intermediaryTransform.EncodePosition(AttachedObject.transform.position);
_intermediaryTransform.EncodeRotation(AttachedObject.transform.rotation);
return true;
}
var targetPos = _intermediaryTransform.GetTargetPosition_Unparented();
var targetRot = _intermediaryTransform.GetTargetRotation_Unparented();
if (targetPos != Vector3.zero && _intermediaryTransform.GetTargetPosition_Unparented() != Vector3.zero)
{
if (UseInterpolation)
{
AttachedObject.transform.position = SmartSmoothDamp(AttachedObject.transform.position, targetPos);
AttachedObject.transform.rotation = QuaternionHelper.SmoothDamp(AttachedObject.transform.rotation, targetRot, ref _rotationSmoothVelocity, SmoothTime);
}
else
{
AttachedObject.transform.position = targetPos;
AttachedObject.transform.rotation = targetRot;
}
}
else if (targetPos == Vector3.zero)
{
DebugLog.ToConsole($"Warning - TargetPos for {_logName} was (0,0,0).", MessageType.Warning);
}
return true;
}
}
}

View File

@ -2,6 +2,7 @@
{
public enum FastForwardReason
{
None,
TooFarBehind
}
}

View File

@ -1,15 +1,26 @@
using QSB.Patches;
using HarmonyLib;
using QSB.Patches;
namespace QSB.TimeSync.Patches
{
[HarmonyPatch]
internal class TimePatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
public override void DoPatches()
=> Prefix(nameof(PlayerCameraEffectController_OnStartOfTimeLoop));
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerCameraEffectController), nameof(PlayerCameraEffectController.OnStartOfTimeLoop))]
public static bool PlayerCameraEffectController_OnStartOfTimeLoop()
=> false;
[HarmonyPrefix]
[HarmonyPatch(typeof(OWTime), nameof(OWTime.Pause))]
public static bool StopPausing()
=> false;
[HarmonyPrefix]
[HarmonyPatch(typeof(SubmitActionSkipToNextLoop), nameof(SubmitActionSkipToNextLoop.AdvanceToNewTimeLoop))]
public static bool StopMeditation()
=> false;
}
}

View File

@ -2,6 +2,7 @@
{
public enum PauseReason
{
None,
TooFarAhead,
ServerNotStarted,
WaitingForAllPlayersToDie,

View File

@ -7,7 +7,8 @@ namespace QSB.TimeSync
{
public void Start()
{
QSBCore.Helper.Menus.PauseMenu.GetTitleButton("Button-EndCurrentLoop").Hide(); // Remove the meditation button
// BUG : Get this working for the new menu system. Can't use OWML's anymore.
//QSBCore.Helper.Menus.PauseMenu.GetTitleButton("Button-EndCurrentLoop").Hide(); // Remove the meditation button
// Allow server to sleep at campfires
if (IsServer)

Some files were not shown because too many files have changed in this diff Show More