better trigger

This commit is contained in:
JohnCorby 2022-01-12 18:43:18 -08:00
parent 066df2ff3f
commit fafe7617c5
6 changed files with 183 additions and 127 deletions

View File

@ -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<QSBTornado>().ForEach(tornado
=> tornado.SendMessage(new TornadoFormStateMessage(tornado.FormState) { To = From }));
QSBWorldSync.GetWorldObjects<QSBTrigger>().ForEach(trigger
=> trigger.SendMessage(new TriggerResyncMessage(trigger.Players)));
}
/// <summary>

View File

@ -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<OWTriggerVolume>
{
public readonly List<PlayerInfo> 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
{
}
}

View File

@ -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<PlayerInfo> 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}");
}
}
}

View File

@ -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<OWTriggerVolume>()
.Select((x, i) => new TriggerLink(i, x))
.ToArray();
}
QSBWorldSync.Init<QSBCharacterTrigger, OWTriggerVolume>(
QSBWorldSync.GetUnityObjects<CharacterAnimController>()
.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<QSBSolanumTrigger, OWTriggerVolume>(
QSBWorldSync.GetUnityObjects<NomaiConversationManager>()
.Select(x => x._watchPlayerVolume)
);
return triggerLink;
QSBWorldSync.Init<QSBVesselCageTrigger, OWTriggerVolume>(
QSBWorldSync.GetUnityObjects<VesselWarpController>()
.Select(x => x._cageTrigger)
);
QSBWorldSync.Init<QSBMaskZoneTrigger, OWTriggerVolume>(
QSBWorldSync.GetUnityObjects<MaskZoneController>()
.Select(x => x._maskZoneTrigger)
);
}
}
}

View File

@ -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<QSBTrigger>
{
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);
}
}
}

View File

@ -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
{
/// <summary>
/// always sent by host
/// </summary>
public class TriggerResyncMessage : QSBWorldObjectMessage<QSBTrigger>
{
private uint[] _playerIds;
public TriggerResyncMessage(IEnumerable<PlayerInfo> 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);
}
}
}
}