diff --git a/QSB/Player/Messages/RequestStateResyncMessage.cs b/QSB/Player/Messages/RequestStateResyncMessage.cs index 8c927f12..828bb4e4 100644 --- a/QSB/Player/Messages/RequestStateResyncMessage.cs +++ b/QSB/Player/Messages/RequestStateResyncMessage.cs @@ -16,6 +16,7 @@ using QSB.Tools.TranslatorTool.TranslationSync.Messages; using QSB.Tools.TranslatorTool.TranslationSync.WorldObjects; using QSB.TornadoSync.Messages; using QSB.TornadoSync.WorldObjects; +using QSB.TriggerSync; using QSB.Utility; using QSB.WorldSync; using System.Linq; @@ -126,6 +127,9 @@ namespace QSB.Player.Messages QSBWorldSync.GetWorldObjects().ForEach(tornado => tornado.SendMessage(new TornadoFormStateMessage(tornado.FormState) { To = From })); + + QSBWorldSync.GetWorldObjects().ForEach(trigger + => trigger.SendMessage(new TriggerResyncMessage(trigger.Players))); } /// diff --git a/QSB/TriggerSync/QSBTrigger.cs b/QSB/TriggerSync/QSBTrigger.cs new file mode 100644 index 00000000..ac4de97a --- /dev/null +++ b/QSB/TriggerSync/QSBTrigger.cs @@ -0,0 +1,105 @@ +using OWML.Common; +using QSB.Messaging; +using QSB.Player; +using QSB.Utility; +using QSB.WorldSync; +using System.Collections.Generic; +using UnityEngine; + +namespace QSB.TriggerSync +{ + public abstract class QSBTrigger : WorldObject + { + public readonly List Players = new(); + + public override void Init() + { + AttachedObject.OnEntry += OnEntry; + AttachedObject.OnExit += OnExit; + + QSBPlayerManager.OnRemovePlayer += OnPlayerLeave; + + QSBCore.UnityEvents.RunWhen(() => WorldObjectManager.AllObjectsReady, () => + { + if (AttachedObject._trackedObjects == null) + { + DebugLog.DebugWrite($"{LogName} tracked objects == null", MessageType.Warning); + } + else if (AttachedObject._trackedObjects.Contains(Locator.GetPlayerDetector())) + { + this.SendMessage(new TriggerMessage(true)); + } + }); + } + + public override void OnRemoval() + { + AttachedObject.OnEntry -= OnEntry; + AttachedObject.OnExit -= OnExit; + + QSBPlayerManager.OnRemovePlayer -= OnPlayerLeave; + } + + private void OnPlayerLeave(PlayerInfo player) + { + if (Players.Contains(player)) + { + Exit(player); + } + } + + private void OnEntry(GameObject hitObj) + { + if (hitObj.CompareTag("PlayerDetector")) + { + this.SendMessage(new TriggerMessage(true)); + } + } + + private void OnExit(GameObject hitObj) + { + if (hitObj.CompareTag("PlayerDetector")) + { + this.SendMessage(new TriggerMessage(false)); + } + } + + public void Enter(PlayerInfo player) + { + if (!Players.SafeAdd(player)) + { + DebugLog.DebugWrite($"{LogName} + {player.PlayerId}", MessageType.Warning); + return; + } + + DebugLog.DebugWrite($"{LogName} + {player.PlayerId}"); + } + + public void Exit(PlayerInfo player) + { + if (!Players.QuickRemove(player)) + { + DebugLog.DebugWrite($"{LogName} - {player.PlayerId}", MessageType.Warning); + return; + } + + DebugLog.DebugWrite($"{LogName} - {player.PlayerId}"); + } + } + + public class QSBCharacterTrigger : QSBTrigger + { + } + + public class QSBSolanumTrigger : QSBTrigger + { + } + + public class QSBVesselCageTrigger : QSBTrigger + { + } + + public class QSBMaskZoneTrigger : QSBTrigger + { + } +} diff --git a/QSB/TriggerSync/TriggerLink.cs b/QSB/TriggerSync/TriggerLink.cs deleted file mode 100644 index 6d093dd6..00000000 --- a/QSB/TriggerSync/TriggerLink.cs +++ /dev/null @@ -1,83 +0,0 @@ -using OWML.Common; -using QSB.Messaging; -using QSB.Player; -using QSB.Utility; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace QSB.TriggerSync -{ - public class TriggerLink : IDisposable - { - public string LogName => - $"trigger {QSBPlayerManager.LocalPlayerId}.{_id}.{(_trigger ? _trigger.name : "null")}"; - - public readonly List Players = new(); - - private readonly int _id; - private readonly OWTriggerVolume _trigger; - - public TriggerLink(int id, OWTriggerVolume trigger) - { - _id = id; - _trigger = trigger; - - _trigger.OnEntry += OnEntry; - _trigger.OnExit += OnExit; - - if (_trigger._trackedObjects != null && _trigger.IsTrackingObject(Locator.GetPlayerDetector())) - { - OnEntry(Locator.GetPlayerDetector()); - } - - DebugLog.DebugWrite($"{LogName} created"); - } - - public void Dispose() - { - _trigger.OnEntry -= OnEntry; - _trigger.OnExit -= OnExit; - - DebugLog.DebugWrite($"{LogName} disposed"); - } - - private void OnEntry(GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - new TriggerMessage(_id, true).Send(); - } - } - - private void OnExit(GameObject hitObj) - { - if (hitObj.CompareTag("PlayerDetector")) - { - new TriggerMessage(_id, false).Send(); - } - } - - public void Enter(PlayerInfo player) - { - if (!Players.SafeAdd(player)) - { - DebugLog.DebugWrite($"{LogName} already added {player.PlayerId}", MessageType.Warning); - return; - } - - DebugLog.DebugWrite($"{LogName} + {player.PlayerId}"); - } - - public void Exit(PlayerInfo player) - { - if (!Players.QuickRemove(player)) - { - DebugLog.DebugWrite($"{LogName} already removed {player.PlayerId}", MessageType.Warning); - return; - } - - DebugLog.DebugWrite($"{LogName} - {player.PlayerId}"); - } - } -} diff --git a/QSB/TriggerSync/TriggerManager.cs b/QSB/TriggerSync/TriggerManager.cs index 7ba745c8..5c2fd473 100644 --- a/QSB/TriggerSync/TriggerManager.cs +++ b/QSB/TriggerSync/TriggerManager.cs @@ -1,6 +1,4 @@ -using OWML.Common; -using QSB.Utility; -using QSB.WorldSync; +using QSB.WorldSync; using System.Linq; namespace QSB.TriggerSync @@ -9,24 +7,28 @@ namespace QSB.TriggerSync { public override WorldObjectType WorldObjectType => WorldObjectType.Both; - private static TriggerLink[] _triggerLinks; - protected override void RebuildWorldObjects(OWScene scene) { - _triggerLinks?.ForEach(x => x.Dispose()); - _triggerLinks = QSBWorldSync.GetUnityObjects() - .Select((x, i) => new TriggerLink(i, x)) - .ToArray(); - } + QSBWorldSync.Init( + QSBWorldSync.GetUnityObjects() + .Where(x => x.playerTrackingZone) + .Select(x => x.playerTrackingZone) + ); - public static TriggerLink GetTriggerLink(int id) - { - if (!_triggerLinks.TryGet(id, out var triggerLink)) - { - DebugLog.ToConsole($"no trigger link with id {id}", MessageType.Error); - } + QSBWorldSync.Init( + QSBWorldSync.GetUnityObjects() + .Select(x => x._watchPlayerVolume) + ); - return triggerLink; + QSBWorldSync.Init( + QSBWorldSync.GetUnityObjects() + .Select(x => x._cageTrigger) + ); + + QSBWorldSync.Init( + QSBWorldSync.GetUnityObjects() + .Select(x => x._maskZoneTrigger) + ); } } } diff --git a/QSB/TriggerSync/TriggerMessage.cs b/QSB/TriggerSync/TriggerMessage.cs index e4435657..8f349dc2 100644 --- a/QSB/TriggerSync/TriggerMessage.cs +++ b/QSB/TriggerSync/TriggerMessage.cs @@ -1,47 +1,24 @@ using QSB.Messaging; using QSB.Player; -using QSB.WorldSync; -using QuantumUNET.Transport; namespace QSB.TriggerSync { - public class TriggerMessage : QSBBoolMessage + public class TriggerMessage : QSBBoolWorldObjectMessage { - private int _id; - - public TriggerMessage(int id, bool entered) - { - _id = id; - Value = entered; - } - - public override void Serialize(QNetworkWriter writer) - { - base.Serialize(writer); - writer.Write(_id); - } - - public override void Deserialize(QNetworkReader reader) - { - base.Deserialize(reader); - _id = reader.ReadInt32(); - } - - public override bool ShouldReceive => WorldObjectManager.AllObjectsReady; + public TriggerMessage(bool entered) => Value = entered; public override void OnReceiveLocal() => OnReceiveRemote(); public override void OnReceiveRemote() { var player = QSBPlayerManager.GetPlayer(From); - var triggerLink = TriggerManager.GetTriggerLink(_id); if (Value) { - triggerLink.Enter(player); + WorldObject.Enter(player); } else { - triggerLink.Exit(player); + WorldObject.Exit(player); } } } diff --git a/QSB/TriggerSync/TriggerResyncMessage.cs b/QSB/TriggerSync/TriggerResyncMessage.cs new file mode 100644 index 00000000..5c005553 --- /dev/null +++ b/QSB/TriggerSync/TriggerResyncMessage.cs @@ -0,0 +1,51 @@ +using QSB.Messaging; +using QSB.Player; +using QSB.Utility; +using QuantumUNET.Transport; +using System.Collections.Generic; +using System.Linq; + +namespace QSB.TriggerSync +{ + /// + /// always sent by host + /// + public class TriggerResyncMessage : QSBWorldObjectMessage + { + private uint[] _playerIds; + + public TriggerResyncMessage(IEnumerable players) => + _playerIds = players.Select(x => x.PlayerId).ToArray(); + + public override void Serialize(QNetworkWriter writer) + { + base.Serialize(writer); + writer.Write(_playerIds.Length); + _playerIds.ForEach(writer.Write); + } + + public override void Deserialize(QNetworkReader reader) + { + base.Deserialize(reader); + _playerIds = new uint[reader.ReadInt32()]; + for (var i = 0; i < _playerIds.Length; i++) + { + _playerIds[i] = reader.ReadUInt32(); + } + } + + public override void OnReceiveRemote() + { + var serverPlayers = _playerIds.Select(QSBPlayerManager.GetPlayer).ToList(); + foreach (var added in serverPlayers.Except(WorldObject.Players)) + { + WorldObject.Enter(added); + } + + foreach (var removed in WorldObject.Players.Except(serverPlayers)) + { + WorldObject.Exit(removed); + } + } + } +}