diff --git a/MirrorWeaver/Program.cs b/MirrorWeaver/Program.cs index 2dd76cb7..a9734ba6 100644 --- a/MirrorWeaver/Program.cs +++ b/MirrorWeaver/Program.cs @@ -50,11 +50,14 @@ public static class Program var log = new ConsoleLogger(); var weaver = new Weaver(log); - if (!weaver.Weave(assembly, resolver, out _)) + if (!weaver.Weave(assembly, resolver, out var modified)) { Environment.Exit(1); } - assembly.Write(new WriterParameters { WriteSymbols = assembly.MainModule.HasSymbols }); + if (modified) + { + assembly.Write(new WriterParameters { WriteSymbols = assembly.MainModule.HasSymbols }); + } } -} \ No newline at end of file +} diff --git a/MirrorWeaver/QSBReaderWriterProcessor.cs b/MirrorWeaver/QSBReaderWriterProcessor.cs index 05951a4b..1f132060 100644 --- a/MirrorWeaver/QSBReaderWriterProcessor.cs +++ b/MirrorWeaver/QSBReaderWriterProcessor.cs @@ -14,7 +14,7 @@ public static class QSBReaderWriterProcessor /// traverses from non generic classes up thru base types /// in order to replace generic parameters with their corresponding generic arguments. /// - public static void Process(ModuleDefinition module, Writers writers, Readers readers, ref bool weavingFailed) + public static bool Process(ModuleDefinition module, Writers writers, Readers readers, ref bool weavingFailed) { var sw = Stopwatch.StartNew(); @@ -85,5 +85,6 @@ public static class QSBReaderWriterProcessor } Console.WriteLine($"got/generated {count} read/write funcs in {sw.ElapsedMilliseconds} ms"); + return count > 0; } } \ No newline at end of file diff --git a/MirrorWeaver/Weaver/Weaver.cs b/MirrorWeaver/Weaver/Weaver.cs index 8eb5afbb..9cd37252 100644 --- a/MirrorWeaver/Weaver/Weaver.cs +++ b/MirrorWeaver/Weaver/Weaver.cs @@ -207,7 +207,7 @@ namespace Mirror.Weaver Console.WriteLine($"Script Module: {moduleDefinition.Name}"); // CHANGED - QSBReaderWriterProcessor.Process(moduleDefinition, writers, readers, ref WeavingFailed); + modified |= QSBReaderWriterProcessor.Process(moduleDefinition, writers, readers, ref WeavingFailed); modified |= WeaveModule(moduleDefinition); diff --git a/QSB/Anglerfish/TransformSync/AnglerTransformSync.cs b/QSB/Anglerfish/TransformSync/AnglerTransformSync.cs index aeb2a75d..6bd58767 100644 --- a/QSB/Anglerfish/TransformSync/AnglerTransformSync.cs +++ b/QSB/Anglerfish/TransformSync/AnglerTransformSync.cs @@ -1,5 +1,5 @@ using QSB.Anglerfish.WorldObjects; -using QSB.AuthoritySync; +using QSB.OwnershipSync; using QSB.Syncs.Unsectored.Rigidbodies; using QSB.Utility.LinkedWorldObject; using QSB.WorldSync; @@ -22,7 +22,7 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi { if (QSBCore.IsHost) { - netIdentity.RegisterAuthQueue(); + netIdentity.RegisterOwnerQueue(); } base.OnStartClient(); @@ -32,7 +32,7 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi { if (QSBCore.IsHost) { - netIdentity.UnregisterAuthQueue(); + netIdentity.UnregisterOwnerQueue(); } base.OnStopClient(); @@ -48,7 +48,7 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi AttachedRigidbody.OnUnsuspendOWRigidbody += OnUnsuspend; AttachedRigidbody.OnSuspendOWRigidbody += OnSuspend; - netIdentity.UpdateAuthQueue(AttachedRigidbody.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add); + netIdentity.UpdateOwnerQueue(AttachedRigidbody.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add); } protected override void Uninit() @@ -59,8 +59,8 @@ public class AnglerTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehavi AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend; } - private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add); - private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove); + private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add); + private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove); protected override void OnRenderObject() { diff --git a/QSB/Anglerfish/WorldObjects/QSBAngler.cs b/QSB/Anglerfish/WorldObjects/QSBAngler.cs index b2ff1036..de8f0e1c 100644 --- a/QSB/Anglerfish/WorldObjects/QSBAngler.cs +++ b/QSB/Anglerfish/WorldObjects/QSBAngler.cs @@ -16,7 +16,7 @@ public class QSBAngler : LinkedWorldObject QSBNetworkManager.singleton.AnglerPrefab; - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; public override void SendInitialState(uint to) => this.SendMessage(new AnglerDataMessage(this) { To = to }); diff --git a/QSB/Animation/Player/AnimationSync.cs b/QSB/Animation/Player/AnimationSync.cs index d79b8773..8620c835 100644 --- a/QSB/Animation/Player/AnimationSync.cs +++ b/QSB/Animation/Player/AnimationSync.cs @@ -103,7 +103,7 @@ public class AnimationSync : PlayerSyncObject private void InitAccelerationSync() { Player.JetpackAcceleration = GetComponent(); - var thrusterModel = hasAuthority ? Locator.GetPlayerBody().GetComponent() : null; + var thrusterModel = isOwned ? Locator.GetPlayerBody().GetComponent() : null; Player.JetpackAcceleration.Init(thrusterModel); } diff --git a/QSB/AssetBundles/qsb_hud b/QSB/AssetBundles/qsb_hud index bf94b8c7..e10c8f5f 100644 Binary files a/QSB/AssetBundles/qsb_hud and b/QSB/AssetBundles/qsb_hud differ diff --git a/QSB/AuthoritySync/AuthorityManager.cs b/QSB/AuthoritySync/AuthorityManager.cs deleted file mode 100644 index 610d8d33..00000000 --- a/QSB/AuthoritySync/AuthorityManager.cs +++ /dev/null @@ -1,93 +0,0 @@ -using Mirror; -using QSB.Messaging; -using QSB.Utility; -using System.Collections.Generic; - -namespace QSB.AuthoritySync; - -public static class AuthorityManager -{ - #region host only - - /// - /// whoever is first gets authority - /// - private static readonly Dictionary> _authQueue = new(); - - public static void RegisterAuthQueue(this NetworkIdentity identity) => _authQueue.Add(identity, new List()); - public static void UnregisterAuthQueue(this NetworkIdentity identity) => _authQueue.Remove(identity); - - public static void ServerUpdateAuthQueue(this NetworkIdentity identity, uint id, AuthQueueAction action) - { - var authQueue = _authQueue[identity]; - var oldOwner = authQueue.Count != 0 ? authQueue[0] : uint.MaxValue; - - switch (action) - { - case AuthQueueAction.Add: - authQueue.SafeAdd(id); - break; - - case AuthQueueAction.Remove: - authQueue.Remove(id); - break; - - case AuthQueueAction.Force: - authQueue.Remove(id); - authQueue.Insert(0, id); - break; - } - - var newOwner = authQueue.Count != 0 ? authQueue[0] : uint.MaxValue; - if (oldOwner != newOwner) - { - SetAuthority(identity, newOwner); - } - } - - /// - /// transfer authority to a different client - /// - public static void OnDisconnect(NetworkConnectionToClient conn) - { - var id = conn.GetPlayerId(); - foreach (var identity in _authQueue.Keys) - { - identity.ServerUpdateAuthQueue(id, AuthQueueAction.Remove); - } - } - - public static void SetAuthority(this NetworkIdentity identity, uint id) - { - var oldConn = identity.connectionToClient; - var newConn = id != uint.MaxValue ? id.GetNetworkConnection() : null; - - if (oldConn == newConn) - { - return; - } - - identity.RemoveClientAuthority(); - - if (newConn != null) - { - identity.AssignClientAuthority(newConn); - } - } - - #endregion - - #region any client - - public static void UpdateAuthQueue(this NetworkIdentity identity, AuthQueueAction action) - { - if (action == AuthQueueAction.Force && identity.hasAuthority) - { - return; - } - - new AuthQueueMessage(identity.netId, action).Send(); - } - - #endregion -} diff --git a/QSB/AuthoritySync/IAuthWorldObject_Extensions.cs b/QSB/AuthoritySync/IAuthWorldObject_Extensions.cs deleted file mode 100644 index e0339625..00000000 --- a/QSB/AuthoritySync/IAuthWorldObject_Extensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -using QSB.Messaging; -using QSB.Player; - -namespace QSB.AuthoritySync; - -public static class IAuthWorldObject_Extensions -{ - /// - /// try and gain authority over the object - /// - public static void RequestOwnership(this IAuthWorldObject @this) - { - if (@this.Owner != 0) - { - return; - } - @this.SendMessage(new AuthWorldObjectMessage(QSBPlayerManager.LocalPlayerId)); - } - - /// - /// release authority over the object, - /// potentially to giving it to someone else - /// - public static void ReleaseOwnership(this IAuthWorldObject @this) - { - if (@this.Owner != QSBPlayerManager.LocalPlayerId) - { - return; - } - @this.SendMessage(new AuthWorldObjectMessage(0)); - } -} diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs index 8b84d710..10898524 100644 --- a/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs +++ b/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs @@ -1,8 +1,8 @@ using HarmonyLib; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.AlarmTotemSync.Messages; using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects; using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Patches; using QSB.Player; using QSB.Utility; diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs index b8a3affd..be38d6c2 100644 --- a/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs +++ b/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs @@ -1,10 +1,10 @@ -using QSB.AuthoritySync; -using QSB.EchoesOfTheEye.AlarmTotemSync.Messages; +using QSB.EchoesOfTheEye.AlarmTotemSync.Messages; using QSB.Messaging; +using QSB.OwnershipSync; namespace QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects; -public class QSBAlarmTotem : AuthWorldObject +public class QSBAlarmTotem : OwnedWorldObject { public override bool CanOwn => AttachedObject.enabled; diff --git a/QSB/EchoesOfTheEye/DreamRafts/Patches/DreamRaftPatches.cs b/QSB/EchoesOfTheEye/DreamRafts/Patches/DreamRaftPatches.cs index a0e9cd55..32907453 100644 --- a/QSB/EchoesOfTheEye/DreamRafts/Patches/DreamRaftPatches.cs +++ b/QSB/EchoesOfTheEye/DreamRafts/Patches/DreamRaftPatches.cs @@ -1,10 +1,10 @@ using HarmonyLib; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.DreamCandles.Patches; using QSB.EchoesOfTheEye.DreamObjectProjectors.WorldObject; using QSB.EchoesOfTheEye.DreamRafts.Messages; using QSB.EchoesOfTheEye.DreamRafts.WorldObjects; using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Patches; using QSB.WorldSync; @@ -75,10 +75,10 @@ public class DreamRaftPatches : QSBPatch if (__instance._lastUsedRaftProjector) { - // still release authority over the raft tho + // still release ownership over the raft tho __instance._lastUsedRaftProjector ._dreamRaftProjection.GetComponent().GetWorldObject() - .NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Remove); + .NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove); } return false; diff --git a/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBDreamRaft.cs b/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBDreamRaft.cs index 37391ee6..c91b5599 100644 --- a/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBDreamRaft.cs +++ b/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBDreamRaft.cs @@ -7,5 +7,5 @@ namespace QSB.EchoesOfTheEye.DreamRafts.WorldObjects; public class QSBDreamRaft : LinkedWorldObject { protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.RaftPrefab; - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; } diff --git a/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBSealRaft.cs b/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBSealRaft.cs index f4385f4e..e30c63fc 100644 --- a/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBSealRaft.cs +++ b/QSB/EchoesOfTheEye/DreamRafts/WorldObjects/QSBSealRaft.cs @@ -7,5 +7,5 @@ namespace QSB.EchoesOfTheEye.DreamRafts.WorldObjects; public class QSBSealRaft : LinkedWorldObject { protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.RaftPrefab; - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; } diff --git a/QSB/EchoesOfTheEye/EclipseDoors/WorldObjects/QSBEclipseDoorController.cs b/QSB/EchoesOfTheEye/EclipseDoors/WorldObjects/QSBEclipseDoorController.cs index 2d934932..0ba30766 100644 --- a/QSB/EchoesOfTheEye/EclipseDoors/WorldObjects/QSBEclipseDoorController.cs +++ b/QSB/EchoesOfTheEye/EclipseDoors/WorldObjects/QSBEclipseDoorController.cs @@ -10,7 +10,7 @@ internal class QSBEclipseDoorController : QSBRotatingElements LightSensors => AttachedObject._lightSensors; public override string ReturnLabel() - => $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- HasAuth:{NetworkBehaviour.hasAuthority}"; + => $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- IsOwned:{NetworkBehaviour.isOwned}"; protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.DoorPrefab; } diff --git a/QSB/EchoesOfTheEye/EclipseElevators/WorldObjects/QSBEclipseElevatorController.cs b/QSB/EchoesOfTheEye/EclipseElevators/WorldObjects/QSBEclipseElevatorController.cs index 222e3815..8f81fcb0 100644 --- a/QSB/EchoesOfTheEye/EclipseElevators/WorldObjects/QSBEclipseElevatorController.cs +++ b/QSB/EchoesOfTheEye/EclipseElevators/WorldObjects/QSBEclipseElevatorController.cs @@ -10,7 +10,7 @@ internal class QSBEclipseElevatorController : QSBRotatingElements LightSensors => AttachedObject._lightSensors; public override string ReturnLabel() - => $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- HasAuth:{NetworkBehaviour.hasAuthority}"; + => $"{base.ReturnLabel()}\r\n- SyncerValue:{NetworkBehaviour.Value?.Join()}\r\n- IsOwned:{NetworkBehaviour.isOwned}"; protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.ElevatorPrefab; } diff --git a/QSB/EchoesOfTheEye/LightSensorSync/Patches/LightSensorPatches.cs b/QSB/EchoesOfTheEye/LightSensorSync/Patches/LightSensorPatches.cs index dd0a4247..d33a14f1 100644 --- a/QSB/EchoesOfTheEye/LightSensorSync/Patches/LightSensorPatches.cs +++ b/QSB/EchoesOfTheEye/LightSensorSync/Patches/LightSensorPatches.cs @@ -1,8 +1,8 @@ using HarmonyLib; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.LightSensorSync.Messages; using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects; using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Patches; using QSB.Player; using QSB.Tools.FlashlightTool; diff --git a/QSB/EchoesOfTheEye/LightSensorSync/QSBPlayerLightSensor.cs b/QSB/EchoesOfTheEye/LightSensorSync/QSBPlayerLightSensor.cs index 5c7a7e42..acf44cc8 100644 --- a/QSB/EchoesOfTheEye/LightSensorSync/QSBPlayerLightSensor.cs +++ b/QSB/EchoesOfTheEye/LightSensorSync/QSBPlayerLightSensor.cs @@ -16,7 +16,7 @@ namespace QSB.EchoesOfTheEye.LightSensorSync; /// only purpose is to handle initial state sync. /// /// we don't have to worry about start illuminated or sectors. -/// authority is always given to local player light sensor. +/// ownership is always given to local player light sensor. /// /// 2 uses: /// - AlarmTotem.CheckPlayerVisible diff --git a/QSB/EchoesOfTheEye/LightSensorSync/WorldObjects/QSBLightSensor.cs b/QSB/EchoesOfTheEye/LightSensorSync/WorldObjects/QSBLightSensor.cs index 44fb9a27..65cd9386 100644 --- a/QSB/EchoesOfTheEye/LightSensorSync/WorldObjects/QSBLightSensor.cs +++ b/QSB/EchoesOfTheEye/LightSensorSync/WorldObjects/QSBLightSensor.cs @@ -1,7 +1,7 @@ using Cysharp.Threading.Tasks; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.LightSensorSync.Messages; using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Utility; using QSB.WorldSync; using System; @@ -14,7 +14,7 @@ using System.Threading; namespace QSB.EchoesOfTheEye.LightSensorSync.WorldObjects; -internal class QSBLightSensor : AuthWorldObject +internal class QSBLightSensor : OwnedWorldObject { internal bool _locallyIlluminated; diff --git a/QSB/EchoesOfTheEye/QSBRotatingElements.cs b/QSB/EchoesOfTheEye/QSBRotatingElements.cs index 9be7c3eb..765a3e83 100644 --- a/QSB/EchoesOfTheEye/QSBRotatingElements.cs +++ b/QSB/EchoesOfTheEye/QSBRotatingElements.cs @@ -1,7 +1,7 @@ using Cysharp.Threading.Tasks; using Mirror; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects; +using QSB.OwnershipSync; using QSB.Utility.LinkedWorldObject; using QSB.WorldSync; using System.Collections.Generic; @@ -52,7 +52,7 @@ internal abstract class QSBRotatingElements : LinkedWorldObject _litSensors++; if (_litSensors == 1) { - NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Add); + NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add); } } @@ -61,9 +61,9 @@ internal abstract class QSBRotatingElements : LinkedWorldObject _litSensors--; if (_litSensors == 0) { - NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Remove); + NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove); } } - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; } diff --git a/QSB/EchoesOfTheEye/RaftSync/Patches/RaftPatches.cs b/QSB/EchoesOfTheEye/RaftSync/Patches/RaftPatches.cs index d8b96b31..cff95f29 100644 --- a/QSB/EchoesOfTheEye/RaftSync/Patches/RaftPatches.cs +++ b/QSB/EchoesOfTheEye/RaftSync/Patches/RaftPatches.cs @@ -1,8 +1,8 @@ using HarmonyLib; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.RaftSync.Messages; using QSB.EchoesOfTheEye.RaftSync.WorldObjects; using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Patches; using QSB.Utility; using QSB.WorldSync; @@ -21,8 +21,8 @@ public class RaftPatches : QSBPatch __instance._interactReceiver.SetInteractionEnabled(false); var qsbRaft = __instance.GetWorldObject(); - qsbRaft.NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Force); - Delay.RunWhen(() => qsbRaft.NetworkBehaviour.hasAuthority, () => + qsbRaft.NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Force); + Delay.RunWhen(() => qsbRaft.NetworkBehaviour.isOwned, () => { var normalized = Vector3.ProjectOnPlane(Locator.GetPlayerCamera().transform.forward, __instance.transform.up).normalized; __instance._raftBody.AddVelocityChange(normalized * 5f); diff --git a/QSB/EchoesOfTheEye/RaftSync/TransformSync/RaftTransformSync.cs b/QSB/EchoesOfTheEye/RaftSync/TransformSync/RaftTransformSync.cs index 8cb1c579..5b6b2f37 100644 --- a/QSB/EchoesOfTheEye/RaftSync/TransformSync/RaftTransformSync.cs +++ b/QSB/EchoesOfTheEye/RaftSync/TransformSync/RaftTransformSync.cs @@ -1,4 +1,4 @@ -using QSB.AuthoritySync; +using QSB.OwnershipSync; using QSB.Syncs.Unsectored.Rigidbodies; using QSB.Utility; using QSB.Utility.LinkedWorldObject; @@ -33,7 +33,7 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou { if (QSBCore.IsHost) { - netIdentity.RegisterAuthQueue(); + netIdentity.RegisterOwnerQueue(); } base.OnStartClient(); @@ -43,7 +43,7 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou { if (QSBCore.IsHost) { - netIdentity.UnregisterAuthQueue(); + netIdentity.UnregisterOwnerQueue(); } base.OnStopClient(); @@ -56,7 +56,7 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou AttachedRigidbody.OnUnsuspendOWRigidbody += OnUnsuspend; AttachedRigidbody.OnSuspendOWRigidbody += OnSuspend; - netIdentity.UpdateAuthQueue(AttachedRigidbody.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add); + netIdentity.UpdateOwnerQueue(AttachedRigidbody.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add); } protected override void Uninit() @@ -67,12 +67,12 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend; } - private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add); - private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove); + private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add); + private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove); - public override void OnStartAuthority() => DebugLog.DebugWrite($"{this} + AUTH"); - public override void OnStopAuthority() => DebugLog.DebugWrite($"{this} - AUTH"); + public override void OnStartAuthority() => DebugLog.DebugWrite($"{this} + OWN"); + public override void OnStopAuthority() => DebugLog.DebugWrite($"{this} - OWN"); /// /// replacement for base method diff --git a/QSB/EchoesOfTheEye/RaftSync/WorldObjects/QSBRaft.cs b/QSB/EchoesOfTheEye/RaftSync/WorldObjects/QSBRaft.cs index bd1d6ddf..5c6dfe1f 100644 --- a/QSB/EchoesOfTheEye/RaftSync/WorldObjects/QSBRaft.cs +++ b/QSB/EchoesOfTheEye/RaftSync/WorldObjects/QSBRaft.cs @@ -1,8 +1,8 @@ using Cysharp.Threading.Tasks; -using QSB.AuthoritySync; using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects; using QSB.EchoesOfTheEye.RaftSync.TransformSync; using QSB.ItemSync.WorldObjects; +using QSB.OwnershipSync; using QSB.Utility.LinkedWorldObject; using QSB.WorldSync; using System.Linq; @@ -18,7 +18,7 @@ public class QSBRaft : LinkedWorldObject, IQS public override bool ShouldDisplayDebug() => false; protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.RaftPrefab; - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; private QSBLightSensor[] _lightSensors; @@ -49,7 +49,7 @@ public class QSBRaft : LinkedWorldObject, IQS { if (AttachedObject.IsPlayerRiding()) { - NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Force); + NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Force); } } } diff --git a/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs b/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs index c510a730..e8092da4 100644 --- a/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs +++ b/QSB/EchoesOfTheEye/RotatingElementsVariableSyncer.cs @@ -1,5 +1,5 @@ using Mirror; -using QSB.AuthoritySync; +using QSB.OwnershipSync; using QSB.Utility.LinkedWorldObject; using QSB.Utility.VariableSync; using QSB.WorldSync; @@ -15,7 +15,7 @@ internal abstract class RotatingElementsVariableSyncer : BaseVaria { if (QSBCore.IsHost) { - netIdentity.RegisterAuthQueue(); + netIdentity.RegisterOwnerQueue(); } base.OnStartClient(); @@ -25,7 +25,7 @@ internal abstract class RotatingElementsVariableSyncer : BaseVaria { if (QSBCore.IsHost) { - netIdentity.UnregisterAuthQueue(); + netIdentity.UnregisterOwnerQueue(); } base.OnStopClient(); diff --git a/QSB/HUD/MultiplayerHUDManager.cs b/QSB/HUD/MultiplayerHUDManager.cs index db963918..05e4404f 100644 --- a/QSB/HUD/MultiplayerHUDManager.cs +++ b/QSB/HUD/MultiplayerHUDManager.cs @@ -67,11 +67,14 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart private const int LINE_COUNT = 11; private const int CHAR_COUNT = 41; + private const float FADE_DELAY = 5f; + private const float FADE_TIME = 2f; private bool _writingMessage; private readonly string[] _lines = new string[LINE_COUNT]; // this should really be a deque, but eh private readonly ListStack _messages = new(false); + private float _lastMessageTime; public void WriteMessage(string message) { @@ -85,6 +88,8 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart * and set the lines correctly bottom-up. */ + _lastMessageTime = Time.time; + _messages.Push(message); if (_messages.Count > LINE_COUNT) @@ -145,6 +150,8 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart audioController.PlayNotificationTextScrolling(); Delay.RunFramesLater(10, () => audioController.StopNotificationTextScrolling()); } + + _textChat.GetComponent().alpha = 1; } private void Update() @@ -158,11 +165,12 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart var inSuit = Locator.GetPlayerSuit().IsWearingHelmet(); - if (OWInput.IsNewlyPressed(InputLibrary.enter, InputMode.Character) && !_writingMessage && inSuit) + if (OWInput.IsNewlyPressed(InputLibrary.enter, InputMode.Character) && !_writingMessage && inSuit && QSBCore.TextChatInput) { OWInput.ChangeInputMode(InputMode.KeyboardInput); _writingMessage = true; _inputField.ActivateInputField(); + _textChat.GetComponent().alpha = 1; } if (OWInput.IsNewlyPressed(InputLibrary.enter, InputMode.KeyboardInput) && _writingMessage) @@ -183,6 +191,20 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart OWInput.RestorePreviousInputs(); _writingMessage = false; } + + if (_writingMessage) + { + _lastMessageTime = Time.time; + } + + if (!_writingMessage + && Time.time > _lastMessageTime + FADE_DELAY + && Time.time < _lastMessageTime + FADE_DELAY + FADE_TIME + 1) + { + var difference = Time.time - (_lastMessageTime + FADE_DELAY); + var alpha = Mathf.Lerp(1, 0, difference / FADE_TIME); + _textChat.GetComponent().alpha = alpha; + } } private void OnWakeUp() @@ -243,6 +265,7 @@ internal class MultiplayerHUDManager : MonoBehaviour, IAddComponentOnStart _textChat.Find("Messages").Find("Message").GetComponent().text = ""; _lines.Clear(); _messages.Clear(); + _textChat.GetComponent().alpha = 0; } public void UpdateMinimapMarkers(Minimap minimap) diff --git a/QSB/HUD/PlayerBox.cs b/QSB/HUD/PlayerBox.cs index e634df53..3a59e16f 100644 --- a/QSB/HUD/PlayerBox.cs +++ b/QSB/HUD/PlayerBox.cs @@ -28,7 +28,9 @@ public class PlayerBox : MonoBehaviour if (player.Name != null) { - PlayerName.text = player.Name.ToUpper(); + Delay.RunWhen( + () => player.Name != null, + () => PlayerName.text = player.Name.ToUpper()); } InfoImage.sprite = MultiplayerHUDManager.UnknownSprite; diff --git a/QSB/JellyfishSync/TransformSync/JellyfishTransformSync.cs b/QSB/JellyfishSync/TransformSync/JellyfishTransformSync.cs index 6fcf78a9..a389a920 100644 --- a/QSB/JellyfishSync/TransformSync/JellyfishTransformSync.cs +++ b/QSB/JellyfishSync/TransformSync/JellyfishTransformSync.cs @@ -1,6 +1,6 @@ using Mirror; -using QSB.AuthoritySync; using QSB.JellyfishSync.WorldObjects; +using QSB.OwnershipSync; using QSB.Syncs.Unsectored.Rigidbodies; using QSB.Utility; using QSB.Utility.LinkedWorldObject; @@ -24,7 +24,7 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh { if (QSBCore.IsHost) { - netIdentity.RegisterAuthQueue(); + netIdentity.RegisterOwnerQueue(); } base.OnStartClient(); @@ -34,7 +34,7 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh { if (QSBCore.IsHost) { - netIdentity.UnregisterAuthQueue(); + netIdentity.UnregisterOwnerQueue(); } base.OnStopClient(); @@ -50,7 +50,7 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh AttachedRigidbody.OnUnsuspendOWRigidbody += OnUnsuspend; AttachedRigidbody.OnSuspendOWRigidbody += OnSuspend; - netIdentity.UpdateAuthQueue(AttachedRigidbody.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add); + netIdentity.UpdateOwnerQueue(AttachedRigidbody.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add); } protected override void Uninit() @@ -61,8 +61,8 @@ public class JellyfishTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBeh AttachedRigidbody.OnSuspendOWRigidbody -= OnSuspend; } - private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add); - private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove); + private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add); + private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove); protected override void Serialize(NetworkWriter writer) { diff --git a/QSB/JellyfishSync/WorldObjects/QSBJellyfish.cs b/QSB/JellyfishSync/WorldObjects/QSBJellyfish.cs index 515c1dfd..a8e809b5 100644 --- a/QSB/JellyfishSync/WorldObjects/QSBJellyfish.cs +++ b/QSB/JellyfishSync/WorldObjects/QSBJellyfish.cs @@ -11,7 +11,7 @@ public class QSBJellyfish : LinkedWorldObject false; protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.JellyfishPrefab; - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; public override void SendInitialState(uint to) => this.SendMessage(new JellyfishRisingMessage(AttachedObject._isRising) { To = to }); diff --git a/QSB/Localization/Translation.cs b/QSB/Localization/Translation.cs index 4ed59efe..b47014a8 100644 --- a/QSB/Localization/Translation.cs +++ b/QSB/Localization/Translation.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Mirror; +using System.Collections.Generic; namespace QSB.Localization; @@ -28,6 +29,7 @@ public class Translation public string OK; public string ServerRefusedConnection; public string ClientDisconnectWithError; + public Dictionary TransportErrors; public string QSBVersionMismatch; public string OWVersionMismatch; public string DLCMismatch; diff --git a/QSB/Menus/MenuManager.cs b/QSB/Menus/MenuManager.cs index 55166f55..0bb1bd42 100644 --- a/QSB/Menus/MenuManager.cs +++ b/QSB/Menus/MenuManager.cs @@ -736,7 +736,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart } }; - OpenInfoPopup(string.Format(QSBLocalization.Current.ClientDisconnectWithError, reason), QSBLocalization.Current.OK); + OpenInfoPopup(string.Format(QSBLocalization.Current.ClientDisconnectWithError, QSBLocalization.Current.TransportErrors[error], reason), QSBLocalization.Current.OK); } SetButtonActive(DisconnectButton, false); diff --git a/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs b/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs index f4abfe95..cf3a4e2f 100644 --- a/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs +++ b/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs @@ -1,6 +1,6 @@ -using QSB.AuthoritySync; -using QSB.Messaging; +using QSB.Messaging; using QSB.ModelShip.TransformSync; +using QSB.OwnershipSync; using QSB.Player; using QSB.Player.TransformSync; using QSB.Utility; @@ -66,9 +66,9 @@ internal class UseFlightConsoleMessage : QSBMessage if (QSBCore.IsHost) { - ModelShipTransformSync.LocalInstance.netIdentity.SetAuthority(isFlying + ModelShipTransformSync.LocalInstance.netIdentity.SetOwner(isFlying ? flyer - : QSBPlayerManager.LocalPlayerId); // Host gets authority when its not in use + : QSBPlayerManager.LocalPlayerId); // Host gets ownership when its not in use } // Client messes up its position when they start flying it diff --git a/QSB/ModelShip/ModelShipManager.cs b/QSB/ModelShip/ModelShipManager.cs index 4caae0ff..9561475e 100644 --- a/QSB/ModelShip/ModelShipManager.cs +++ b/QSB/ModelShip/ModelShipManager.cs @@ -46,7 +46,7 @@ internal class ModelShipManager : WorldObjectManager if (QSBCore.IsHost) { - Instantiate(QSBNetworkManager.singleton.ModelShipPrefab).SpawnWithServerAuthority(); + Instantiate(QSBNetworkManager.singleton.ModelShipPrefab).SpawnWithServerOwnership(); } // Is 0 by default -> 2D (bad) diff --git a/QSB/OrbSync/Patches/OrbPatches.cs b/QSB/OrbSync/Patches/OrbPatches.cs index 0566beae..6935dfe2 100644 --- a/QSB/OrbSync/Patches/OrbPatches.cs +++ b/QSB/OrbSync/Patches/OrbPatches.cs @@ -1,8 +1,8 @@ using HarmonyLib; -using QSB.AuthoritySync; using QSB.Messaging; using QSB.OrbSync.Messages; using QSB.OrbSync.WorldObjects; +using QSB.OwnershipSync; using QSB.Patches; using QSB.WorldSync; using UnityEngine; @@ -48,7 +48,7 @@ public class OrbPatches : QSBPatch var qsbOrb = __instance.GetWorldObject(); qsbOrb.SendMessage(new OrbDragMessage(true)); - qsbOrb.NetworkBehaviour.netIdentity.UpdateAuthQueue(AuthQueueAction.Force); + qsbOrb.NetworkBehaviour.netIdentity.UpdateOwnerQueue(OwnerQueueAction.Force); } } else @@ -75,7 +75,7 @@ public class OrbPatches : QSBPatch } var qsbOrb = __instance.GetWorldObject(); - if (!qsbOrb.NetworkBehaviour.hasAuthority) + if (!qsbOrb.NetworkBehaviour.isOwned) { return false; } @@ -95,7 +95,7 @@ public class OrbPatches : QSBPatch } var qsbOrb = __instance.GetWorldObject(); - if (qsbOrb.NetworkBehaviour.hasAuthority) + if (qsbOrb.NetworkBehaviour.isOwned) { if (__instance._occupiedSlot == null) { diff --git a/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs b/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs index e3b092fd..fb6f1d8a 100644 --- a/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs +++ b/QSB/OrbSync/TransformSync/NomaiOrbTransformSync.cs @@ -1,5 +1,5 @@ -using QSB.AuthoritySync; -using QSB.OrbSync.WorldObjects; +using QSB.OrbSync.WorldObjects; +using QSB.OwnershipSync; using QSB.Syncs.Unsectored.Transforms; using QSB.Utility.LinkedWorldObject; using QSB.WorldSync; @@ -28,7 +28,7 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha { if (QSBCore.IsHost) { - netIdentity.RegisterAuthQueue(); + netIdentity.RegisterOwnerQueue(); } base.OnStartClient(); @@ -38,7 +38,7 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha { if (QSBCore.IsHost) { - netIdentity.UnregisterAuthQueue(); + netIdentity.UnregisterOwnerQueue(); } base.OnStopClient(); @@ -52,7 +52,7 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha body.OnUnsuspendOWRigidbody += OnUnsuspend; body.OnSuspendOWRigidbody += OnSuspend; - netIdentity.UpdateAuthQueue(body.IsSuspended() ? AuthQueueAction.Remove : AuthQueueAction.Add); + netIdentity.UpdateOwnerQueue(body.IsSuspended() ? OwnerQueueAction.Remove : OwnerQueueAction.Add); } protected override void Uninit() @@ -64,8 +64,8 @@ public class NomaiOrbTransformSync : UnsectoredTransformSync, ILinkedNetworkBeha body.OnSuspendOWRigidbody -= OnSuspend; } - private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Add); - private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateAuthQueue(AuthQueueAction.Remove); + private void OnUnsuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Add); + private void OnSuspend(OWRigidbody suspendedBody) => netIdentity.UpdateOwnerQueue(OwnerQueueAction.Remove); protected override void ApplyToAttached() { diff --git a/QSB/OrbSync/WorldObjects/QSBOrb.cs b/QSB/OrbSync/WorldObjects/QSBOrb.cs index 57e531d9..17cb102d 100644 --- a/QSB/OrbSync/WorldObjects/QSBOrb.cs +++ b/QSB/OrbSync/WorldObjects/QSBOrb.cs @@ -13,7 +13,7 @@ public class QSBOrb : LinkedWorldObject false; protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.OrbPrefab; - protected override bool SpawnWithServerAuthority => false; + protected override bool SpawnWithServerOwnership => false; public override void SendInitialState(uint to) { diff --git a/QSB/AuthoritySync/IAuthWorldObject.cs b/QSB/OwnershipSync/IOwnedWorldObject.cs similarity index 65% rename from QSB/AuthoritySync/IAuthWorldObject.cs rename to QSB/OwnershipSync/IOwnedWorldObject.cs index 7d706feb..de547d32 100644 --- a/QSB/AuthoritySync/IAuthWorldObject.cs +++ b/QSB/OwnershipSync/IOwnedWorldObject.cs @@ -1,18 +1,18 @@ using QSB.WorldSync; -namespace QSB.AuthoritySync; +namespace QSB.OwnershipSync; /// /// a world object that has an owner /// -public interface IAuthWorldObject : IWorldObject +public interface IOwnedWorldObject : IWorldObject { /// /// 0 = owned by no one /// public uint Owner { get; set; } /// - /// can the world object have authority + /// can the world object be owned by this client /// public bool CanOwn { get; } } diff --git a/QSB/OwnershipSync/IOwnedWorldObject_Extensions.cs b/QSB/OwnershipSync/IOwnedWorldObject_Extensions.cs new file mode 100644 index 00000000..56ca2220 --- /dev/null +++ b/QSB/OwnershipSync/IOwnedWorldObject_Extensions.cs @@ -0,0 +1,32 @@ +using QSB.Messaging; +using QSB.Player; + +namespace QSB.OwnershipSync; + +public static class IOwnedWorldObject_Extensions +{ + /// + /// try and gain ownership over the object + /// + public static void RequestOwnership(this IOwnedWorldObject @this) + { + if (@this.Owner != 0) + { + return; + } + @this.SendMessage(new OwnedWorldObjectMessage(QSBPlayerManager.LocalPlayerId)); + } + + /// + /// release ownership over the object, + /// potentially to giving it to someone else + /// + public static void ReleaseOwnership(this IOwnedWorldObject @this) + { + if (@this.Owner != QSBPlayerManager.LocalPlayerId) + { + return; + } + @this.SendMessage(new OwnedWorldObjectMessage(0)); + } +} diff --git a/QSB/AuthoritySync/AuthWorldObject.cs b/QSB/OwnershipSync/OwnedWorldObject.cs similarity index 69% rename from QSB/AuthoritySync/AuthWorldObject.cs rename to QSB/OwnershipSync/OwnedWorldObject.cs index f70d64c7..31147978 100644 --- a/QSB/AuthoritySync/AuthWorldObject.cs +++ b/QSB/OwnershipSync/OwnedWorldObject.cs @@ -5,19 +5,19 @@ using QSB.WorldSync; using System.Threading; using UnityEngine; -namespace QSB.AuthoritySync; +namespace QSB.OwnershipSync; /// /// helper implementation of the interface /// -public abstract class AuthWorldObject : WorldObject, IAuthWorldObject +public abstract class OwnedWorldObject : WorldObject, IOwnedWorldObject where T : MonoBehaviour { public uint Owner { get; set; } public abstract bool CanOwn { get; } public override void SendInitialState(uint to) => - ((IAuthWorldObject)this).SendMessage(new AuthWorldObjectMessage(Owner) { To = to }); + ((IOwnedWorldObject)this).SendMessage(new OwnedWorldObjectMessage(Owner) { To = to }); public override async UniTask Init(CancellationToken ct) => QSBPlayerManager.OnRemovePlayer += OnPlayerLeave; @@ -33,7 +33,7 @@ public abstract class AuthWorldObject : WorldObject, IAuthWorldObject } if (Owner == player.PlayerId) { - ((IAuthWorldObject)this).SendMessage(new AuthWorldObjectMessage(CanOwn ? QSBPlayerManager.LocalPlayerId : 0)); + ((IOwnedWorldObject)this).SendMessage(new OwnedWorldObjectMessage(CanOwn ? QSBPlayerManager.LocalPlayerId : 0)); } } } diff --git a/QSB/AuthoritySync/AuthWorldObjectMessage.cs b/QSB/OwnershipSync/OwnedWorldObjectMessage.cs similarity index 74% rename from QSB/AuthoritySync/AuthWorldObjectMessage.cs rename to QSB/OwnershipSync/OwnedWorldObjectMessage.cs index 08f9cb95..85b87d36 100644 --- a/QSB/AuthoritySync/AuthWorldObjectMessage.cs +++ b/QSB/OwnershipSync/OwnedWorldObjectMessage.cs @@ -1,14 +1,14 @@ using QSB.Messaging; using QSB.Player; -namespace QSB.AuthoritySync; +namespace QSB.OwnershipSync; /// /// request or release ownership of a world object /// -public class AuthWorldObjectMessage : QSBWorldObjectMessage +public class OwnedWorldObjectMessage : QSBWorldObjectMessage { - public AuthWorldObjectMessage(uint owner) : base(owner) { } + public OwnedWorldObjectMessage(uint owner) : base(owner) { } public override bool ShouldReceive { @@ -39,7 +39,7 @@ public class AuthWorldObjectMessage : QSBWorldObjectMessage /// always sent to host /// -public class AuthQueueMessage : QSBMessage<(uint NetId, AuthQueueAction Action)> +public class OwnerQueueMessage : QSBMessage<(uint NetId, OwnerQueueAction Action)> { - public AuthQueueMessage(uint netId, AuthQueueAction action) : base((netId, action)) => + public OwnerQueueMessage(uint netId, OwnerQueueAction action) : base((netId, action)) => To = 0; public override bool ShouldReceive => QSBWorldSync.AllObjectsReady; public override void OnReceiveLocal() => OnReceiveRemote(); - public override void OnReceiveRemote() => NetworkServer.spawned[Data.NetId].ServerUpdateAuthQueue(From, Data.Action); + public override void OnReceiveRemote() => NetworkServer.spawned[Data.NetId].ServerUpdateOwnerQueue(From, Data.Action); } -public enum AuthQueueAction +public enum OwnerQueueAction { /// /// add player to the queue diff --git a/QSB/OwnershipSync/OwnershipManager.cs b/QSB/OwnershipSync/OwnershipManager.cs new file mode 100644 index 00000000..2cb52de4 --- /dev/null +++ b/QSB/OwnershipSync/OwnershipManager.cs @@ -0,0 +1,93 @@ +using Mirror; +using QSB.Messaging; +using QSB.Utility; +using System.Collections.Generic; + +namespace QSB.OwnershipSync; + +public static class OwnershipManager +{ + #region host only + + /// + /// whoever is first gets ownership + /// + private static readonly Dictionary> _ownerQueue = new(); + + public static void RegisterOwnerQueue(this NetworkIdentity identity) => _ownerQueue.Add(identity, new List()); + public static void UnregisterOwnerQueue(this NetworkIdentity identity) => _ownerQueue.Remove(identity); + + public static void ServerUpdateOwnerQueue(this NetworkIdentity identity, uint id, OwnerQueueAction action) + { + var ownerQueue = _ownerQueue[identity]; + var oldOwner = ownerQueue.Count != 0 ? ownerQueue[0] : uint.MaxValue; + + switch (action) + { + case OwnerQueueAction.Add: + ownerQueue.SafeAdd(id); + break; + + case OwnerQueueAction.Remove: + ownerQueue.Remove(id); + break; + + case OwnerQueueAction.Force: + ownerQueue.Remove(id); + ownerQueue.Insert(0, id); + break; + } + + var newOwner = ownerQueue.Count != 0 ? ownerQueue[0] : uint.MaxValue; + if (oldOwner != newOwner) + { + SetOwner(identity, newOwner); + } + } + + /// + /// transfer ownership to a different client + /// + public static void OnDisconnect(NetworkConnectionToClient conn) + { + var id = conn.GetPlayerId(); + foreach (var identity in _ownerQueue.Keys) + { + identity.ServerUpdateOwnerQueue(id, OwnerQueueAction.Remove); + } + } + + public static void SetOwner(this NetworkIdentity identity, uint id) + { + var oldConn = identity.connectionToClient; + var newConn = id != uint.MaxValue ? id.GetNetworkConnection() : null; + + if (oldConn == newConn) + { + return; + } + + identity.RemoveClientAuthority(); + + if (newConn != null) + { + identity.AssignClientAuthority(newConn); + } + } + + #endregion + + #region any client + + public static void UpdateOwnerQueue(this NetworkIdentity identity, OwnerQueueAction action) + { + if (action == OwnerQueueAction.Force && identity.isOwned) + { + return; + } + + new OwnerQueueMessage(identity.netId, action).Send(); + } + + #endregion +} diff --git a/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs b/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs index a0883377..0ad8f976 100644 --- a/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs +++ b/QSB/PoolSync/CustomNomaiRemoteCameraPlatform.cs @@ -516,6 +516,9 @@ internal class CustomNomaiRemoteCameraPlatform : NomaiShared private void SwitchToPlayerCamera() { + // does nothing except run CCU's prefix + _oldPlatform.SwitchToPlayerCamera(); + if (_slavePlatform._visualSector != null) { if (!_alreadyOccupiedSectors.Contains(_slavePlatform._visualSector)) diff --git a/QSB/PoolSync/Patches/PoolPatches.cs b/QSB/PoolSync/Patches/PoolPatches.cs index b5fa122b..1c3ed4f4 100644 --- a/QSB/PoolSync/Patches/PoolPatches.cs +++ b/QSB/PoolSync/Patches/PoolPatches.cs @@ -28,6 +28,10 @@ internal class PoolPatches : QSBPatch [HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.OnPedestalContact))] public static bool NomaiRemoteCameraPlatform_OnPedestalContact() => false; + [HarmonyPrefix] + [HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.SwitchToPlayerCamera))] + public static bool NomaiRemoteCameraPlatform_SwitchToPlayerCamera() => false; + [HarmonyPrefix] [HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.FixedUpdate))] public static bool NomaiRemoteCameraStreaming_FixedUpdate() => false; diff --git a/QSB/QSBCore.cs b/QSB/QSBCore.cs index 995e1ec8..1e54438c 100644 --- a/QSB/QSBCore.cs +++ b/QSB/QSBCore.cs @@ -63,6 +63,7 @@ public class QSBCore : ModBehaviour public static bool ShowPlayerNames { get; private set; } public static bool ShipDamage { get; private set; } public static bool ShowExtraHUDElements { get; private set; } + public static bool TextChatInput { get; private set; } public static GameVendor GameVendor { get; private set; } = GameVendor.None; public static bool IsStandalone => GameVendor is GameVendor.Epic or GameVendor.Steam; public static IProfileManager ProfileManager => IsStandalone @@ -263,6 +264,7 @@ public class QSBCore : ModBehaviour ShowPlayerNames = config.GetSettingsValue("showPlayerNames"); ShipDamage = config.GetSettingsValue("shipDamage"); ShowExtraHUDElements = config.GetSettingsValue("showExtraHud"); + TextChatInput = config.GetSettingsValue("textChatInput"); if (IsHost) { diff --git a/QSB/QSBNetworkManager.cs b/QSB/QSBNetworkManager.cs index fb6156ff..735c08b7 100644 --- a/QSB/QSBNetworkManager.cs +++ b/QSB/QSBNetworkManager.cs @@ -4,7 +4,6 @@ using Mirror; using OWML.Common; using OWML.Utils; using QSB.Anglerfish.TransformSync; -using QSB.AuthoritySync; using QSB.ClientServerStateSync; using QSB.DeathSync; using QSB.EchoesOfTheEye.AirlockSync.VariableSync; @@ -19,6 +18,7 @@ using QSB.ModelShip.TransformSync; using QSB.OrbSync.Messages; using QSB.OrbSync.TransformSync; using QSB.OrbSync.WorldObjects; +using QSB.OwnershipSync; using QSB.Patches; using QSB.Player; using QSB.Player.Messages; @@ -354,27 +354,27 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart // local conn = we are host, so skip if (conn is not LocalConnectionToClient) { - // revert authority from ship + // revert ownership from ship if (ShipTransformSync.LocalInstance != null) { var identity = ShipTransformSync.LocalInstance.netIdentity; if (identity != null && identity.connectionToClient == conn) { - identity.SetAuthority(QSBPlayerManager.LocalPlayerId); + identity.SetOwner(QSBPlayerManager.LocalPlayerId); } } - // revert authority from model ship + // revert ownership from model ship if (ModelShipTransformSync.LocalInstance != null) { var identity = ModelShipTransformSync.LocalInstance.netIdentity; if (identity != null && identity.connectionToClient == conn) { - identity.SetAuthority(QSBPlayerManager.LocalPlayerId); + identity.SetOwner(QSBPlayerManager.LocalPlayerId); } } // stop dragging for the orbs this player was dragging - // i THINK this is here because orb authority is in network behavior, which may not work properly in OnPlayerLeave + // i THINK this is here because orb ownership is in network behavior, which may not work properly in OnPlayerLeave foreach (var qsbOrb in QSBWorldSync.GetWorldObjects()) { if (qsbOrb.NetworkBehaviour == null) @@ -391,7 +391,7 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart } } - AuthorityManager.OnDisconnect(conn); + OwnershipManager.OnDisconnect(conn); } base.OnServerDisconnect(conn); diff --git a/QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs b/QSB/QuantumSync/Messages/QuantumOwnershipMessage.cs similarity index 81% rename from QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs rename to QSB/QuantumSync/Messages/QuantumOwnershipMessage.cs index 1d86499d..fad777d9 100644 --- a/QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs +++ b/QSB/QuantumSync/Messages/QuantumOwnershipMessage.cs @@ -4,9 +4,9 @@ using QSB.QuantumSync.WorldObjects; namespace QSB.QuantumSync.Messages; -public class QuantumAuthorityMessage : QSBWorldObjectMessage +public class QuantumOwnershipMessage : QSBWorldObjectMessage { - public QuantumAuthorityMessage(uint authorityOwner) : base(authorityOwner) { } + public QuantumOwnershipMessage(uint owner) : base(owner) { } public override bool ShouldReceive { @@ -38,7 +38,7 @@ public class QuantumAuthorityMessage : QSBWorldObjectMessage(); + // TODO: this should just be equal to _visibleinprobesnapshot. check if theyre in sync and just go back to using that like we did before var visibleToProbePlayers = worldObject.GetVisibleToProbePlayers(); __result = visibleToProbePlayers.Any(); return false; diff --git a/QSB/QuantumSync/QuantumManager.cs b/QSB/QuantumSync/QuantumManager.cs index 237bc3eb..00058393 100644 --- a/QSB/QuantumSync/QuantumManager.cs +++ b/QSB/QuantumSync/QuantumManager.cs @@ -51,7 +51,7 @@ internal class QuantumManager : WorldObjectManager { if (obj.ControllingPlayer == player.PlayerId) { - obj.SendMessage(new QuantumAuthorityMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : 0u)); + obj.SendMessage(new QuantumOwnershipMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : 0u)); } } } diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs index e1f28d97..326896f8 100644 --- a/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs @@ -88,7 +88,7 @@ internal abstract class QSBQuantumObject : WorldObject, IQSBQuantumObject } public override void SendInitialState(uint to) => - ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(ControllingPlayer) { To = to }); + ((IQSBQuantumObject)this).SendMessage(new QuantumOwnershipMessage(ControllingPlayer) { To = to }); public List GetAttachedShapes() { @@ -149,8 +149,8 @@ internal abstract class QSBQuantumObject : WorldObject, IQSBQuantumObject return; } - // no one is controlling this object right now, request authority - ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId)); + // no one is controlling this object right now, request ownership + ((IQSBQuantumObject)this).SendMessage(new QuantumOwnershipMessage(QSBPlayerManager.LocalPlayerId)); } private void OnDisable(Shape s) => @@ -179,8 +179,8 @@ internal abstract class QSBQuantumObject : WorldObject, IQSBQuantumObject return; } - // send event to other players that we're releasing authority - ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(0u)); + // send event to other players that we're releasing ownership + ((IQSBQuantumObject)this).SendMessage(new QuantumOwnershipMessage(0u)); }); public void OnTakeProbeSnapshot(PlayerInfo player, ProbeCamera.ID cameraId) diff --git a/QSB/SectorSync/QSBSectorManager.cs b/QSB/SectorSync/QSBSectorManager.cs index 389060ff..c7025685 100644 --- a/QSB/SectorSync/QSBSectorManager.cs +++ b/QSB/SectorSync/QSBSectorManager.cs @@ -44,7 +44,7 @@ public class QSBSectorManager : WorldObjectManager foreach (var sync in SectoredSyncs) { - if (sync.hasAuthority + if (sync.isOwned && sync.IsValid && sync.AttachedTransform.gameObject.activeInHierarchy) { diff --git a/QSB/ShipSync/Messages/FlyShipMessage.cs b/QSB/ShipSync/Messages/FlyShipMessage.cs index e1083c13..3b3adf11 100644 --- a/QSB/ShipSync/Messages/FlyShipMessage.cs +++ b/QSB/ShipSync/Messages/FlyShipMessage.cs @@ -1,5 +1,5 @@ -using QSB.AuthoritySync; -using QSB.Messaging; +using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Player; using QSB.Player.TransformSync; using QSB.ShipSync.TransformSync; @@ -57,7 +57,7 @@ internal class FlyShipMessage : QSBMessage if (QSBCore.IsHost) { - ShipTransformSync.LocalInstance.netIdentity.SetAuthority(isFlying + ShipTransformSync.LocalInstance.netIdentity.SetOwner(isFlying ? id : QSBPlayerManager.LocalPlayerId); } diff --git a/QSB/ShipSync/Patches/ShipPatches.cs b/QSB/ShipSync/Patches/ShipPatches.cs index e062e3c0..5780d389 100644 --- a/QSB/ShipSync/Patches/ShipPatches.cs +++ b/QSB/ShipSync/Patches/ShipPatches.cs @@ -215,7 +215,7 @@ internal class ShipPatches : QSBPatch [HarmonyPrefix] [HarmonyPatch(typeof(ShipDamageController), nameof(ShipDamageController.OnImpact))] public static bool ShipDamageController_OnImpact() - => ShipTransformSync.LocalInstance == null || ShipTransformSync.LocalInstance.hasAuthority; + => ShipTransformSync.LocalInstance == null || ShipTransformSync.LocalInstance.isOwned; [HarmonyPostfix] [HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.RepairTick))] diff --git a/QSB/ShipSync/ShipManager.cs b/QSB/ShipSync/ShipManager.cs index e345db14..6d7017a2 100644 --- a/QSB/ShipSync/ShipManager.cs +++ b/QSB/ShipSync/ShipManager.cs @@ -114,7 +114,7 @@ internal class ShipManager : WorldObjectManager DebugLog.ToConsole($"Error - Tried to spawn ship, but LocalPlayer's TransformSync is null!", MessageType.Error); } - Instantiate(QSBNetworkManager.singleton.ShipPrefab).SpawnWithServerAuthority(); + Instantiate(QSBNetworkManager.singleton.ShipPrefab).SpawnWithServerOwnership(); } QSBWorldSync.Init(); diff --git a/QSB/ShipSync/WorldObjects/QSBShipDetachableLeg.cs b/QSB/ShipSync/WorldObjects/QSBShipDetachableLeg.cs index e75b0c01..d0355e18 100644 --- a/QSB/ShipSync/WorldObjects/QSBShipDetachableLeg.cs +++ b/QSB/ShipSync/WorldObjects/QSBShipDetachableLeg.cs @@ -12,7 +12,7 @@ namespace QSB.ShipSync.WorldObjects; internal class QSBShipDetachableLeg : LinkedWorldObject { protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.ShipLegPrefab; - protected override bool SpawnWithServerAuthority => true; + protected override bool SpawnWithServerOwnership => true; public override void SendInitialState(uint to) { diff --git a/QSB/ShipSync/WorldObjects/QSBShipDetachableModule.cs b/QSB/ShipSync/WorldObjects/QSBShipDetachableModule.cs index 444b8034..f3de6892 100644 --- a/QSB/ShipSync/WorldObjects/QSBShipDetachableModule.cs +++ b/QSB/ShipSync/WorldObjects/QSBShipDetachableModule.cs @@ -12,7 +12,7 @@ namespace QSB.ShipSync.WorldObjects; internal class QSBShipDetachableModule : LinkedWorldObject { protected override GameObject NetworkObjectPrefab => QSBNetworkManager.singleton.ShipModulePrefab; - protected override bool SpawnWithServerAuthority => true; + protected override bool SpawnWithServerOwnership => true; public override void SendInitialState(uint to) { diff --git a/QSB/Syncs/Occasional/OccasionalManager.cs b/QSB/Syncs/Occasional/OccasionalManager.cs index f36a1369..a9aa2361 100644 --- a/QSB/Syncs/Occasional/OccasionalManager.cs +++ b/QSB/Syncs/Occasional/OccasionalManager.cs @@ -48,7 +48,7 @@ internal class OccasionalManager : WorldObjectManager if (QSBCore.IsHost) { - Instantiate(QSBNetworkManager.singleton.OccasionalPrefab).SpawnWithServerAuthority(); + Instantiate(QSBNetworkManager.singleton.OccasionalPrefab).SpawnWithServerOwnership(); } } diff --git a/QSB/Syncs/QSBNetworkTransformChild.cs b/QSB/Syncs/QSBNetworkTransformChild.cs index b3336e01..7a76f412 100644 --- a/QSB/Syncs/QSBNetworkTransformChild.cs +++ b/QSB/Syncs/QSBNetworkTransformChild.cs @@ -49,7 +49,7 @@ public class QSBNetworkTransformChild : QSBNetworkBehaviour { if (AttachedTransform) { - if (hasAuthority) + if (isOwned) { Target.localPosition = AttachedTransform.localPosition; Target.localRotation = AttachedTransform.localRotation; diff --git a/QSB/Syncs/Sectored/BaseSectoredSync.cs b/QSB/Syncs/Sectored/BaseSectoredSync.cs index 09ebbf81..c135e9aa 100644 --- a/QSB/Syncs/Sectored/BaseSectoredSync.cs +++ b/QSB/Syncs/Sectored/BaseSectoredSync.cs @@ -63,7 +63,7 @@ public abstract class BaseSectoredSync : SyncBase /// /// use this instead of SetReferenceTransform /// - /// called by QSBSectorManager (authority) and ApplyToSector (non authority) + /// called by QSBSectorManager (owner) and ApplyToSector (non owner) /// public void SetReferenceSector(QSBSector sector) { diff --git a/QSB/Syncs/Sectored/Transforms/SectoredTransformSync.cs b/QSB/Syncs/Sectored/Transforms/SectoredTransformSync.cs index e612ead2..e5a8dc81 100644 --- a/QSB/Syncs/Sectored/Transforms/SectoredTransformSync.cs +++ b/QSB/Syncs/Sectored/Transforms/SectoredTransformSync.cs @@ -9,7 +9,7 @@ public abstract class SectoredTransformSync : BaseSectoredSync protected abstract Transform InitRemoteTransform(); protected sealed override Transform InitAttachedTransform() - => hasAuthority ? InitLocalTransform() : InitRemoteTransform(); + => isOwned ? InitLocalTransform() : InitRemoteTransform(); protected override void GetFromAttached() { diff --git a/QSB/Syncs/SyncBase.cs b/QSB/Syncs/SyncBase.cs index 64e31720..c024455f 100644 --- a/QSB/Syncs/SyncBase.cs +++ b/QSB/Syncs/SyncBase.cs @@ -189,7 +189,7 @@ public abstract class SyncBase : QSBNetworkTransform protected virtual void Uninit() { - if (IsPlayerObject && !hasAuthority && AttachedTransform) + if (IsPlayerObject && !isOwned && AttachedTransform) { Destroy(AttachedTransform.gameObject); } @@ -255,7 +255,7 @@ public abstract class SyncBase : QSBNetworkTransform if (IsValid && _interpolating) { - if (hasAuthority) + if (isOwned) { _interpolating = false; return; @@ -294,13 +294,13 @@ public abstract class SyncBase : QSBNetworkTransform } ReferenceTransform = referenceTransform; - if (IsPlayerObject && !hasAuthority && AttachedTransform) + if (IsPlayerObject && !isOwned && AttachedTransform) { AttachedTransform.parent = ReferenceTransform; AttachedTransform.localScale = Vector3.one; } - if (UseInterpolation && !hasAuthority && AttachedTransform && ReferenceTransform) + if (UseInterpolation && !isOwned && AttachedTransform && ReferenceTransform) { SmoothPosition = ReferenceTransform.ToRelPos(AttachedTransform.position); SmoothRotation = ReferenceTransform.ToRelRot(AttachedTransform.rotation); diff --git a/QSB/Syncs/Unsectored/Transforms/UnsectoredTransformSync.cs b/QSB/Syncs/Unsectored/Transforms/UnsectoredTransformSync.cs index 6016a83a..3c49e020 100644 --- a/QSB/Syncs/Unsectored/Transforms/UnsectoredTransformSync.cs +++ b/QSB/Syncs/Unsectored/Transforms/UnsectoredTransformSync.cs @@ -9,7 +9,7 @@ public abstract class UnsectoredTransformSync : BaseUnsectoredSync protected abstract Transform InitRemoteTransform(); protected sealed override Transform InitAttachedTransform() - => hasAuthority ? InitLocalTransform() : InitRemoteTransform(); + => isOwned ? InitLocalTransform() : InitRemoteTransform(); protected override void GetFromAttached() { diff --git a/QSB/Tools/ProbeLauncherTool/WorldObjects/QSBStationaryProbeLauncher.cs b/QSB/Tools/ProbeLauncherTool/WorldObjects/QSBStationaryProbeLauncher.cs index e170e4a0..4940e789 100644 --- a/QSB/Tools/ProbeLauncherTool/WorldObjects/QSBStationaryProbeLauncher.cs +++ b/QSB/Tools/ProbeLauncherTool/WorldObjects/QSBStationaryProbeLauncher.cs @@ -1,7 +1,7 @@ using Cysharp.Threading.Tasks; using Mirror; -using QSB.AuthoritySync; using QSB.Messaging; +using QSB.OwnershipSync; using QSB.Player; using QSB.Tools.ProbeLauncherTool.Messages; using QSB.Tools.ProbeLauncherTool.VariableSync; @@ -74,10 +74,10 @@ public class QSBStationaryProbeLauncher : QSBProbeLauncher, ILinkedWorldObject QSBPatchTypes.OnClientConnect; - /* - * This patch is just to avoid error spam when testing probe destruction in SolarSystem - */ - - [HarmonyPrefix] - [HarmonyPatch(typeof(NomaiWarpStreaming), nameof(NomaiWarpStreaming.FixedUpdate))] - public static bool FixedUpdateOverride(NomaiWarpStreaming __instance) - { - if (__instance._warpTransmitter != null) - { - var ableToBeWarped = __instance._warpTransmitter.GetViewAngleToTarget() < __instance._streamingAngle; - var probeAbove = __instance._probe != null && __instance._probe.IsLaunched() && (!__instance._probe.IsAnchored() || __instance._warpTransmitter.IsProbeOnPlatform()); - - var shouldBeLoadingRequiredAssets = ableToBeWarped && (__instance._playerInVolume || (__instance._probeInVolume && probeAbove)); - var shouldBeLoadingGeneralAssets = ableToBeWarped && __instance._warpTransmitter.IsPlayerOnPlatform(); - __instance.UpdatePreloadingState(shouldBeLoadingRequiredAssets, shouldBeLoadingGeneralAssets); - } - - if (__instance._warpReceiver != null) - { - var ableToBeWarped = __instance._warpReceiver.IsReturnWarpEnabled() || __instance._warpReceiver.IsBlackHoleOpen(); - var probeAbove = __instance._probe != null && __instance._probe.IsLaunched() && (!__instance._probe.IsAnchored() || __instance._warpReceiver.IsProbeOnPlatform()); - - var shouldBeLoadingRequiredAssets = ableToBeWarped && (__instance._playerInVolume || (__instance._probeInVolume && probeAbove)); - var shouldBeLoadingGeneralAssets = ableToBeWarped && __instance._playerInVolume; - __instance.UpdatePreloadingState(shouldBeLoadingRequiredAssets, shouldBeLoadingGeneralAssets); - } - - return false; - } - [HarmonyPrefix] [HarmonyPatch(typeof(ProbeCamera), nameof(ProbeCamera.RotateHorizontal))] public static bool RotateHorizontal(ProbeCamera __instance, float degrees) diff --git a/QSB/Translations/en.json b/QSB/Translations/en.json index a0430021..f3ad1b60 100644 --- a/QSB/Translations/en.json +++ b/QSB/Translations/en.json @@ -22,7 +22,17 @@ "Connecting": "CONNECTING...", "OK": "OK", "ServerRefusedConnection": "Server refused connection.\n{0}", - "ClientDisconnectWithError": "Client disconnected with error!\n{0}", + "ClientDisconnectWithError": "Client disconnected with error!\n{0}\nMore info: {1}", + "TransportErrors": { + "DnsResolve": "Failed to resolve host name.", + "Refused": "Connection refused.", + "Timeout": "Connection timed out.", + "Congestion": "Congestion on transport.", + "InvalidReceive": "Error receiving message.", + "InvalidSend": "Error sending message.", + "ConnectionClosed": "Connection closed.", + "Unexpected": "Unexpected error." + }, "QSBVersionMismatch": "QSB version does not match. (Client:{0}, Server:{1})", "OWVersionMismatch": "Outer Wilds version does not match. (Client:{0}, Server:{1})", "DLCMismatch": "DLC installation state does not match. (Client:{0}, Server:{1})", diff --git a/QSB/Translations/tr.json b/QSB/Translations/tr.json new file mode 100644 index 00000000..86b6876c --- /dev/null +++ b/QSB/Translations/tr.json @@ -0,0 +1,127 @@ +{ + "Language": "TURKISH", + "MainMenuHost": "ÇOK OYUNCULU PAYLAŞ", + "MainMenuConnect": "ÇOK OYUNCULU BAĞLAN", + "PauseMenuDisconnect": "BAGLANTIYI KES", + "PauseMenuStopHosting": "PAYLAŞMAYI DURDUR", + "PublicIPAddress": "Genel IP Adresi\n\n(ÇOK OYUNCULU İLERLEMENİZ SİLİNECEKTİR)", + "ProductUserID": "Kullanıcı Kimliği\n\n(ÇOK OYUNCULU İLERLEMENİZ SİLİNECEKTİR)", + "Connect": "BAĞLAN", + "Cancel": "İPTAL", + "HostExistingOrNewOrCopy": "Mevcut bir tek oyunculu keşfi çok oyunculu olarak mı paylaşmak (çok oyunculuya kopyalamak), yoksa mevcut olan veya yeni bir çok oyunculu keşfi mi paylaşmak istiyorsun?", + "HostNewOrCopy": "Mevcut bir tek oyunculu keşfi çok oyunculu olarak mı paylaşmak, yoksa yeni bir çok oyunculu keşif mi paylaşmak istiyorsun?", + "HostExistingOrNew": "Yeni bir çok oyunculu keşif mi, yoksa mevcut olan bir çok oyunculu keşif mi paylaşmak istiyorsun?", + "ExistingSave": "MEVCUT KEŞİF", + "NewSave": "YENİ KEŞİF", + "CopySave": "KEŞFİ KOPYALA", + "DisconnectAreYouSure": "Baglantıyı kesmek istediginden emin misin?\nBu seni ana menüye döndürecektir.", + "Yes": "EVET", + "No": "HAYIR", + "StopHostingAreYouSure": "Paylaşmayı durdurmak istediğinden emin misin?\nBu tüm oyuncuların bağlantısını kesip onları ana menüye döndürecektir.", + "CopyProductUserIDToClipboard": "Keşif paylaşılıyor\nDiğer oyuncular senin aşağıdaki kullanıcı kimliğini girerek bağlanabilirler.\n{0}\nBunu panoya kopyalamak ister misin?", + "Connecting": "BAĞLANIYOR...", + "OK": "TAMAM", + "ServerRefusedConnection": "Sunucu bağlantıyı reddetti.\n{0}", + "ClientDisconnectWithError": "Bir hata nedeniyle istemcinin bağlantısı kesildi!\n{0}", + "QSBVersionMismatch": "QSB sürümü uyumlu değil. (İstemci:{0}, Sunucu:{1})", + "OWVersionMismatch": "Outer Wilds sürümü uyumlu değil. (İstemci:{0}, Sunucu:{1})", + "DLCMismatch": "DLC yüklenme durumu uyumlu değil. (İstemci:{0}, Sunucu:{1})", + "GameProgressLimit": "Oyun çok fazla ilerlemiş.", + "AddonMismatch": "Yüklü eklentiler uyumsuz. (İstemci:{0} eklentileri, Sunucu:{1} eklentileri)", + "IncompatibleMod": "İzin verilmeyen veya uyumsuz mod kullanılıyor. İlk bulunan mod {0}", + "PlayerJoinedTheGame": "{0} katıldı!", + "PlayerLeftTheGame": "{0} ayrıldı.", + "PlayerWasKicked": "{0} atıldı.", + "KickedFromServer": "Sunucudan atıldın. Sebep : {0}", + "RespawnPlayer": "Oyuncuyu yeniden canlandır", + "TimeSyncTooFarBehind": "{0}\nSunucu vaktine uymak için ileri sarılıyor...", + "TimeSyncWaitingForStartOfServer": "Sunucunun başlaması bekleniyor...", + "TimeSyncTooFarAhead": "{0}\nSunucu vaktine uymak için duraklatılıyor...", + "TimeSyncWaitForAllToReady": "Döngünün başlaması bekleniyor...", + "TimeSyncWaitForAllToDie": "Döngünün bitmesi bekleniyor...", + "GalaxyMapEveryoneNotPresent": "Henüz vakti değil. Buna şahitlik etmesi için herkesin burda olması gerek.", + "YouAreDead": "Öldün.", + "WaitingForRespawn": "Birinin seni yeniden canlandırması bekleniyor...", + "WaitingForAllToDie": "{0} oyuncunun daha ölmesi bekleniyor...", + "AttachToShip": "Gemiye tutun", + "DetachFromShip": "Gemiyi bırak", + "DeathMessages": { + "Default": [ + "{0} öldü", + "{0} öldürüldü" + ], + "Impact": [ + "{0} retro-iticilerini kullanmayı unuttu", + "{0} yere yapıştı", + "{0} yere çakıldı", + "{0} çok sert bir iniş yaptı", + "{0} çarpışma nedeniyle öldü", + "{0} kütleçekimini keşfetti" + ], + "Asphyxiation": [ + "{0} nefes almayı unuttu", + "{0} boğuldu", + "{0} boğularak öldü", + "{0} nasıl nefes alınacağını unuttu", + "{0} oksijenini kontrol etmeyi unuttu", + "{0} nefessiz kaldı", + "{0} oksijensiz kaldı", + "{0} için zaten nefes almaya gerek yoktu" + ], + "Energy": [ + "{0} pişirildi" + ], + "Supernova": [ + "{0} için vakit doldu", + "{0} yandı", + "{0} pişti", + "{0} buharlaştı", + "{0} zamanın akışında kayboldu" + ], + "Digestion": [ + "{0} canlı canlı yenildi", + "{0} balık buldu", + "{0} kötü bir yaratıkla karşılaştı", + "{0} yanlış balığa bulaştı", + "{0} sindirildi", + "{0} sindirilerek öldü" + ], + "Crushed": [ + "{0} ezildi", + "{0} sıkıştırıldı", + "{0} gömüldü", + "{0} zamanında çıkamadı", + "{0} kumda yüzmeye gitti", + "{0} kumu hafife aldı", + "{0} kumun altında sıkıştı" + ], + "Lava": [ + "{0} lavın içinde öldü", + "{0} eritildi", + "{0} lavda yüzmeye çalıştı", + "{0} lava düştü", + "{0} lava düşerek öldü", + "{0} lavda yüzdü", + "{0} lavda kızartıldı" + ], + "BlackHole": [ + "{0} anılarını kovaladı" + ], + "DreamExplosion": [ + "{0} patladı", + "{0} ilk kullanıcı oldu", + "{0} bom diye patladı", + "{0} kızartıldı", + "{0} patlama nedeniyle öldü", + "{0} yanlış eseri kullandı" + ], + "CrushedByElevator": [ + "{0} ezildi", + "{0} sıkıştırıldı", + "{0} asansör tarafından ezildi", + "{0} asansör altında durdu", + "{0} dümdüz oldu", + "{0} asansör tarafından sıkıştırıldı" + ] + } +} diff --git a/QSB/Utility/Extensions.cs b/QSB/Utility/Extensions.cs index 41d4e8c7..68efc695 100644 --- a/QSB/Utility/Extensions.cs +++ b/QSB/Utility/Extensions.cs @@ -62,7 +62,7 @@ public static class Extensions return conn; } - public static void SpawnWithServerAuthority(this GameObject go) => + public static void SpawnWithServerOwnership(this GameObject go) => NetworkServer.Spawn(go, NetworkServer.localConnection); #endregion diff --git a/QSB/Utility/LinkedWorldObject/ILinkedWorldObject_Extensions.cs b/QSB/Utility/LinkedWorldObject/ILinkedWorldObject_Extensions.cs index c3ab2893..2e40919a 100644 --- a/QSB/Utility/LinkedWorldObject/ILinkedWorldObject_Extensions.cs +++ b/QSB/Utility/LinkedWorldObject/ILinkedWorldObject_Extensions.cs @@ -20,16 +20,16 @@ public static class ILinkedWorldObject_Extensions /// link a world object and network object, then spawn it. /// (host only) /// - public static void SpawnLinked(this ILinkedWorldObject @this, GameObject prefab, bool spawnWithServerAuthority) + public static void SpawnLinked(this ILinkedWorldObject @this, GameObject prefab, bool spawnWithServerOwnership) { var go = Object.Instantiate(prefab); var networkBehaviour = go.GetComponent(); @this.LinkTo(networkBehaviour); - if (spawnWithServerAuthority) + if (spawnWithServerOwnership) { - go.SpawnWithServerAuthority(); + go.SpawnWithServerOwnership(); } else { diff --git a/QSB/Utility/LinkedWorldObject/LinkedWorldObject.cs b/QSB/Utility/LinkedWorldObject/LinkedWorldObject.cs index 1c31a246..132a5608 100644 --- a/QSB/Utility/LinkedWorldObject/LinkedWorldObject.cs +++ b/QSB/Utility/LinkedWorldObject/LinkedWorldObject.cs @@ -17,13 +17,13 @@ public abstract class LinkedWorldObject : WorldObject, public void SetNetworkBehaviour(NetworkBehaviour networkBehaviour) => NetworkBehaviour = (TNetworkBehaviour)networkBehaviour; protected abstract GameObject NetworkObjectPrefab { get; } - protected abstract bool SpawnWithServerAuthority { get; } + protected abstract bool SpawnWithServerOwnership { get; } public override async UniTask Init(CancellationToken ct) { if (QSBCore.IsHost) { - this.SpawnLinked(NetworkObjectPrefab, SpawnWithServerAuthority); + this.SpawnLinked(NetworkObjectPrefab, SpawnWithServerOwnership); } else { diff --git a/QSB/Utility/QSBNetworkBehaviour.cs b/QSB/Utility/QSBNetworkBehaviour.cs index 53de8c4d..542dd5a6 100644 --- a/QSB/Utility/QSBNetworkBehaviour.cs +++ b/QSB/Utility/QSBNetworkBehaviour.cs @@ -45,7 +45,7 @@ public abstract class QSBNetworkBehaviour : NetworkBehaviour return; } - if (!hasAuthority) + if (!isOwned) { return; } @@ -116,7 +116,7 @@ public abstract class QSBNetworkBehaviour : NetworkBehaviour return; } - if (hasAuthority) + if (isOwned) { return; } diff --git a/QSB/default-config.json b/QSB/default-config.json index 99f11d5f..c80d77fc 100644 --- a/QSB/default-config.json +++ b/QSB/default-config.json @@ -37,6 +37,12 @@ "type": "toggle", "value": true, "tooltip": "Show extra HUD elements, like player status and minimap icons." + }, + "textChatInput": { + "title": "Text Chat Input", + "type": "toggle", + "value": true, + "tooltip": "Disable this if using NomaiVR, or any other mod with conflicting inputs." } } } \ No newline at end of file diff --git a/QSB/manifest.json b/QSB/manifest.json index 43a6dbda..d81b0959 100644 --- a/QSB/manifest.json +++ b/QSB/manifest.json @@ -7,7 +7,7 @@ "body": "- Disable *all* other mods. (Can heavily affect performance)\n- Make sure you are not running any other network-intensive applications." }, "uniqueName": "Raicuparta.QuantumSpaceBuddies", - "version": "0.28.0", + "version": "0.28.1", "owmlVersion": "2.9.0", "dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ], "pathsToPreserve": [ "debugsettings.json" ],