diff --git a/QSB/Player/Messages/RequestStateResyncMessage.cs b/QSB/Player/Messages/RequestStateResyncMessage.cs index 8c927f12..e05578af 100644 --- a/QSB/Player/Messages/RequestStateResyncMessage.cs +++ b/QSB/Player/Messages/RequestStateResyncMessage.cs @@ -99,7 +99,7 @@ namespace QSB.Player.Messages QSBWorldSync.GetWorldObjects<IQSBQuantumObject>().ForEach(x => { - x.SendMessage(new QuantumAuthorityMessage(x.ControllingPlayer) { To = From }); + x.SendMessage(new QuantumAuthorityMessage(x.ControllingPlayer, true) { To = From }); if (x is QSBQuantumMoon qsbQuantumMoon) { diff --git a/QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs b/QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs index cf75e73d..ae6f8779 100644 --- a/QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs +++ b/QSB/QuantumSync/Messages/QuantumAuthorityMessage.cs @@ -7,20 +7,32 @@ namespace QSB.QuantumSync.Messages { public class QuantumAuthorityMessage : QSBWorldObjectMessage<IQSBQuantumObject> { - private uint AuthorityOwner; + private uint ControllingPlayer; + /// <summary> + /// if true, force sets controlling player, + /// without checking current controlling player + /// or checking for other potential controllers + /// </summary> + private bool Force; - public QuantumAuthorityMessage(uint authorityOwner) => AuthorityOwner = authorityOwner; + public QuantumAuthorityMessage(uint controllingPlayer, bool force) + { + ControllingPlayer = controllingPlayer; + Force = force; + } public override void Serialize(QNetworkWriter writer) { base.Serialize(writer); - writer.Write(AuthorityOwner); + writer.Write(ControllingPlayer); + writer.Write(Force); } public override void Deserialize(QNetworkReader reader) { base.Deserialize(reader); - AuthorityOwner = reader.ReadUInt32(); + ControllingPlayer = reader.ReadUInt32(); + Force = reader.ReadBoolean(); } public override bool ShouldReceive @@ -32,28 +44,34 @@ namespace QSB.QuantumSync.Messages return false; } - // Deciding if to change the object's owner - // Message - // | = 0 | > 0 | - // = 0 | No | Yes | - // > 0 | Yes | No | - // if Obj==Message then No - // Obj + if (WorldObject.ControllingPlayer == ControllingPlayer) + { + return false; + } - return (WorldObject.ControllingPlayer == 0 || AuthorityOwner == 0) - && WorldObject.ControllingPlayer != AuthorityOwner; + if (Force) + { + return true; + } + + if (ControllingPlayer == uint.MaxValue) + { + return true; + } + + return WorldObject.ControllingPlayer == uint.MaxValue; } } - public override void OnReceiveLocal() => WorldObject.ControllingPlayer = AuthorityOwner; + public override void OnReceiveLocal() => WorldObject.ControllingPlayer = ControllingPlayer; public override void OnReceiveRemote() { - WorldObject.ControllingPlayer = AuthorityOwner; - if (WorldObject.ControllingPlayer == 00 && WorldObject.IsEnabled) + WorldObject.ControllingPlayer = ControllingPlayer; + if (!Force && ControllingPlayer == uint.MaxValue && WorldObject.IsEnabled) { // object has no owner, but is still active for this player. request ownership - WorldObject.SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId)); + WorldObject.SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId, false)); } } } diff --git a/QSB/QuantumSync/Patches/QuantumPatches.cs b/QSB/QuantumSync/Patches/QuantumPatches.cs index f1b99f60..70b8387d 100644 --- a/QSB/QuantumSync/Patches/QuantumPatches.cs +++ b/QSB/QuantumSync/Patches/QuantumPatches.cs @@ -23,7 +23,12 @@ namespace QSB.QuantumSync.Patches [HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.IsLockedByPlayerContact))] public static bool QuantumObject_IsLockedByPlayerContact(ref bool __result, QuantumObject __instance) { - var playersEntangled = QuantumManager.GetEntangledPlayers(__instance); + if (!WorldObjectManager.AllObjectsReady) + { + return true; + } + + var playersEntangled = QuantumManager.GetEntangledPlayers(__instance.GetWorldObject<IQSBQuantumObject>()); __result = playersEntangled.Count() != 0 && __instance.IsIlluminated(); return false; } @@ -35,13 +40,15 @@ namespace QSB.QuantumSync.Patches ref bool __result, bool skipInstantVisibilityCheck) { - if (WorldObjectManager.AllObjectsReady) + if (!WorldObjectManager.AllObjectsReady) { - var socketedWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>(); - if (socketedWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId) - { - return false; - } + return true; + } + + var socketedQuantumObject = __instance.GetWorldObject<QSBSocketedQuantumObject>(); + if (socketedQuantumObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId) + { + return false; } foreach (var socket in __instance._childSockets) @@ -97,7 +104,7 @@ namespace QSB.QuantumSync.Patches bool socketNotSuitable; var isSocketIlluminated = __instance.CheckIllumination(); - var playersEntangled = QuantumManager.GetEntangledPlayers(__instance); + var playersEntangled = QuantumManager.GetEntangledPlayers(socketedQuantumObject); if (playersEntangled.Count() != 0) { // socket not suitable if illuminated @@ -176,14 +183,15 @@ namespace QSB.QuantumSync.Patches QuantumShuffleObject __instance, ref bool __result) { - QSBQuantumShuffleObject shuffleWorldObject = default; - if (WorldObjectManager.AllObjectsReady) + if (!WorldObjectManager.AllObjectsReady) { - shuffleWorldObject = __instance.GetWorldObject<QSBQuantumShuffleObject>(); - if (shuffleWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId) - { - return false; - } + return true; + } + + var shuffleWorldObject = __instance.GetWorldObject<QSBQuantumShuffleObject>(); + if (shuffleWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId) + { + return false; } __instance._indexList.Clear(); @@ -201,11 +209,8 @@ namespace QSB.QuantumSync.Patches __instance._shuffledObjects[j].localPosition = __instance._localPositions[__instance._indexList[j]]; } - if (WorldObjectManager.AllObjectsReady) - { - shuffleWorldObject.SendMessage(new QuantumShuffleMessage(__instance._indexList.ToArray())); - __result = true; - } + shuffleWorldObject.SendMessage(new QuantumShuffleMessage(__instance._indexList.ToArray())); + __result = true; return false; } @@ -220,7 +225,7 @@ namespace QSB.QuantumSync.Patches } var qsbObj = __instance.GetWorldObject<QSBMultiStateQuantumObject>(); - if (qsbObj.ControllingPlayer == 0) + if (qsbObj.ControllingPlayer == uint.MaxValue) { return true; } @@ -256,7 +261,7 @@ namespace QSB.QuantumSync.Patches } var qsbObj = __instance.GetWorldObject<QSBMultiStateQuantumObject>(); - if (qsbObj.ControllingPlayer == 0 && qsbObj.CurrentState == -1) + if (qsbObj.ControllingPlayer == uint.MaxValue && qsbObj.CurrentState == -1) { return true; } @@ -331,8 +336,8 @@ namespace QSB.QuantumSync.Patches } if (QSBPlayerManager.LocalPlayer != null - && QSBPlayerManager.LocalPlayer.IsInShrine - && PlayerState.IsFlashlightOn()) + && QSBPlayerManager.LocalPlayer.IsInShrine + && PlayerState.IsFlashlightOn()) { __result = false; return false; diff --git a/QSB/QuantumSync/QuantumManager.cs b/QSB/QuantumSync/QuantumManager.cs index 30501ae4..78de4134 100644 --- a/QSB/QuantumSync/QuantumManager.cs +++ b/QSB/QuantumSync/QuantumManager.cs @@ -57,7 +57,7 @@ namespace QSB.QuantumSync { if (obj.ControllingPlayer == playerId) { - obj.SendMessage(new QuantumAuthorityMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : 0u)); + obj.SendMessage(new QuantumAuthorityMessage(obj.IsEnabled ? QSBPlayerManager.LocalPlayerId : uint.MaxValue, false)); } } } @@ -76,7 +76,7 @@ namespace QSB.QuantumSync foreach (var quantumObject in QSBWorldSync.GetWorldObjects<IQSBQuantumObject>()) { - if (quantumObject.ControllingPlayer == 0) + if (quantumObject.ControllingPlayer == uint.MaxValue) { if (quantumObject.IsEnabled) { @@ -139,15 +139,7 @@ namespace QSB.QuantumSync && QSBPlayerManager.GetPlayersWithCameras(!ignoreLocalCamera) .Any(x => VisibilityOccluder.CanYouSee(tracker, x.Camera.mainCamera.transform.position)); - public static IEnumerable<PlayerInfo> GetEntangledPlayers(QuantumObject obj) - { - if (!AllObjectsReady) - { - return Enumerable.Empty<PlayerInfo>(); - } - - var worldObj = obj.GetWorldObject<IQSBQuantumObject>(); - return QSBPlayerManager.PlayerList.Where(x => x.EntangledObject == worldObj); - } + public static IEnumerable<PlayerInfo> GetEntangledPlayers(IQSBQuantumObject obj) => + QSBPlayerManager.PlayerList.Where(x => x.EntangledObject == obj); } } \ No newline at end of file diff --git a/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs b/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs index f13c2bf1..fdb1f31a 100644 --- a/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs +++ b/QSB/QuantumSync/WorldObjects/QSBQuantumObject.cs @@ -13,7 +13,7 @@ namespace QSB.QuantumSync.WorldObjects internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject where T : QuantumObject { - public uint ControllingPlayer { get; set; } + public uint ControllingPlayer { get; set; } = uint.MaxValue; public bool IsEnabled { get; set; } public override void OnRemoval() @@ -25,7 +25,7 @@ namespace QSB.QuantumSync.WorldObjects } } - public override bool ShouldDisplayLabel() => ControllingPlayer != 0; + public override bool ShouldDisplayLabel() => ControllingPlayer != uint.MaxValue; public override void Init() { @@ -60,7 +60,7 @@ namespace QSB.QuantumSync.WorldObjects { if (shape is BoxShape boxShape) { - var newCube = UnityEngine.Object.Instantiate(cube); + var newCube = Object.Instantiate(cube); newCube.transform.parent = shape.transform; newCube.transform.localPosition = Vector3.zero; newCube.transform.localRotation = Quaternion.Euler(0, 0, 0); @@ -68,7 +68,7 @@ namespace QSB.QuantumSync.WorldObjects } else if (shape is SphereShape sphereShape) { - var newSphere = UnityEngine.Object.Instantiate(sphere); + var newSphere = Object.Instantiate(sphere); newSphere.transform.parent = shape.transform; newSphere.transform.localPosition = Vector3.zero; newSphere.transform.localRotation = Quaternion.Euler(0, 0, 0); @@ -92,28 +92,23 @@ namespace QSB.QuantumSync.WorldObjects private void LateInit() { FinishDelayedReady(); - foreach (var shape in GetAttachedShapes()) + var attachedShapes = GetAttachedShapes(); + foreach (var shape in attachedShapes) { shape.OnShapeActivated += OnEnable; shape.OnShapeDeactivated += OnDisable; } - var attachedShapes = GetAttachedShapes(); + var enable = attachedShapes.Count != 0 && + attachedShapes.All(x => x.enabled && x.gameObject.activeInHierarchy && x.active); - if (attachedShapes.Count == 0) + if (enable) { - IsEnabled = false; - return; - } - - if (attachedShapes.All(x => x.enabled && x.gameObject.activeInHierarchy && x.active)) - { - IsEnabled = true; + OnEnable(null); } else { - ControllingPlayer = 0u; - IsEnabled = false; + OnDisable(null); } } @@ -165,19 +160,15 @@ namespace QSB.QuantumSync.WorldObjects } IsEnabled = true; - if (!WorldObjectManager.AllObjectsReady && !QSBCore.IsHost) - { - return; - } - if (ControllingPlayer != 0) + if (ControllingPlayer != uint.MaxValue) { // controlled by another player, dont care that we activate it return; } // no one is controlling this object right now, request authority - ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId)); + ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(QSBPlayerManager.LocalPlayerId, false)); } private void OnDisable(Shape s) @@ -193,10 +184,6 @@ namespace QSB.QuantumSync.WorldObjects } IsEnabled = false; - if (!WorldObjectManager.AllObjectsReady && !QSBCore.IsHost) - { - return; - } if (ControllingPlayer != QSBPlayerManager.LocalPlayerId) { @@ -204,9 +191,8 @@ namespace QSB.QuantumSync.WorldObjects return; } - var id = ObjectId; // send event to other players that we're releasing authority - ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(0u)); + ((IQSBQuantumObject)this).SendMessage(new QuantumAuthorityMessage(uint.MaxValue, false)); } } } diff --git a/QSB/Utility/DebugGUI.cs b/QSB/Utility/DebugGUI.cs index 60e34f24..8a3a46f5 100644 --- a/QSB/Utility/DebugGUI.cs +++ b/QSB/Utility/DebugGUI.cs @@ -247,7 +247,7 @@ namespace QSB.Utility WriteLine(4, $"Enabled QuantumObjects :"); foreach (var qo in QSBWorldSync.GetWorldObjects<IQSBQuantumObject>()) { - if (qo.ControllingPlayer != 0) + if (qo.ControllingPlayer != uint.MaxValue) { continue; }