diff --git a/QSB/Events/QSBEvent.cs b/QSB/Events/QSBEvent.cs
index 5194bf7c..ad4f0243 100644
--- a/QSB/Events/QSBEvent.cs
+++ b/QSB/Events/QSBEvent.cs
@@ -34,19 +34,26 @@ namespace QSB.Events
public abstract bool RequireWorldObjectsReady { get; }
- public void SendEvent(T message)
- {
- message.FromId = QSBPlayerManager.LocalPlayerId;
- QSBCore.UnityEvents.RunWhen(
- () => PlayerTransformSync.LocalInstance != null,
- () => _eventHandler.SendToServer(message));
- }
+ /// used to force set ForId for every sent event
+ protected static uint ForIdOverride = uint.MaxValue;
+
+ public void SendEvent(T message) => QSBCore.UnityEvents.RunWhen(
+ () => PlayerTransformSync.LocalInstance != null,
+ () =>
+ {
+ message.FromId = LocalPlayerId;
+ if (ForIdOverride != uint.MaxValue)
+ {
+ message.ForId = ForIdOverride;
+ }
+ _eventHandler.SendToServer(message);
+ });
///
- /// Checks whether the message should be processed by the executing client/server.
+ /// Checks whether the message should be processed by the executing client.
///
/// True if the message should be processed.
- public virtual bool CheckMessage(bool isServer, T message)
+ public virtual bool CheckMessage(T message)
=> !RequireWorldObjectsReady || WorldObjectManager.AllObjectsReady;
private void OnReceive(bool isServer, T message)
@@ -59,18 +66,24 @@ namespace QSB.Events
* hub for all events.
*/
- if (!CheckMessage(isServer, message))
- {
- return;
- }
-
if (isServer)
{
- _eventHandler.SendToAll(message);
+ if (message.OnlySendToHost)
+ {
+ _eventHandler.SendToHost(message);
+ }
+ else if (message.ForId != uint.MaxValue)
+ {
+ _eventHandler.SendTo(message.ForId, message);
+ }
+ else
+ {
+ _eventHandler.SendToAll(message);
+ }
return;
}
- if (message.OnlySendToHost && !QSBCore.IsHost)
+ if (!CheckMessage(message))
{
return;
}
@@ -87,8 +100,8 @@ namespace QSB.Events
if (!player.IsReady
&& player.PlayerId != LocalPlayerId
- && (player.State is ClientState.AliveInSolarSystem or ClientState.AliveInEye or ClientState.DeadInSolarSystem)
- && (message is not PlayerInformationEvent or PlayerReadyEvent))
+ && player.State is ClientState.AliveInSolarSystem or ClientState.AliveInEye or ClientState.DeadInSolarSystem
+ && this is not PlayerInformationEvent or PlayerReadyEvent)
{
DebugLog.ToConsole($"Warning - Got message from player {message.FromId}, but they were not ready. Asking for state resync, just in case.", MessageType.Warning);
QSBEventManager.FireEvent(EventNames.QSBRequestStateResync);
@@ -97,14 +110,14 @@ namespace QSB.Events
try
{
- if (message.FromId == QSBPlayerManager.LocalPlayerId ||
- QSBPlayerManager.IsBelongingToLocalPlayer(message.FromId))
+ if (QSBPlayerManager.IsBelongingToLocalPlayer(message.FromId))
{
OnReceiveLocal(QSBCore.IsHost, message);
- return;
}
-
- OnReceiveRemote(QSBCore.IsHost, message);
+ else
+ {
+ OnReceiveRemote(QSBCore.IsHost, message);
+ }
}
catch (Exception ex)
{
diff --git a/QSB/Messaging/MessageHandler.cs b/QSB/Messaging/MessageHandler.cs
index a66bf53b..545f6607 100644
--- a/QSB/Messaging/MessageHandler.cs
+++ b/QSB/Messaging/MessageHandler.cs
@@ -1,5 +1,4 @@
-using QSB.Events;
-using QSB.Utility;
+using QSB.Utility;
using QuantumUNET;
using QuantumUNET.Components;
using QuantumUNET.Messages;
@@ -58,6 +57,32 @@ namespace QSB.Messaging
QNetworkServer.SendToAll(_eventType, message);
}
+ public void SendToHost(T message)
+ {
+ if (!QSBNetworkManager.Instance.IsReady)
+ {
+ return;
+ }
+
+ QNetworkServer.SendToClient(0, _eventType, message);
+ }
+
+ public void SendTo(uint id, T message)
+ {
+ if (!QSBNetworkManager.Instance.IsReady)
+ {
+ return;
+ }
+
+ var conn = QNetworkServer.connections.FirstOrDefault(x => x.GetPlayerId() == id);
+ if (conn == null)
+ {
+ DebugLog.ToConsole($"SendTo unknown player! id: {id}, message: {message.GetType().Name}", OWML.Common.MessageType.Error);
+ return;
+ }
+ QNetworkServer.SendToClient(conn.connectionId, _eventType, message);
+ }
+
public void SendToServer(T message)
{
if (!QSBNetworkManager.Instance.IsReady)
diff --git a/QSB/Messaging/PlayerMessage.cs b/QSB/Messaging/PlayerMessage.cs
index dc22a948..b14eb553 100644
--- a/QSB/Messaging/PlayerMessage.cs
+++ b/QSB/Messaging/PlayerMessage.cs
@@ -16,16 +16,27 @@ namespace QSB.Messaging
public uint AboutId { get; set; }
///
- /// If true, only send this message to the host of the current session
+ /// If true, only send this message to the host of the current session
/// (OnReceiveLocal/Remote is not called on any other client)
///
public bool OnlySendToHost { get; set; }
+ ///
+ /// The Player ID that this message is for.
+ /// By default, this is uint.MaxValue,
+ /// which means this is ignored and the message is sent to all clients
+ ///
+ public uint ForId { get; set; } = uint.MaxValue;
+
public override void Deserialize(QNetworkReader reader)
{
FromId = reader.ReadUInt32();
AboutId = reader.ReadUInt32();
OnlySendToHost = reader.ReadBoolean();
+ if (!OnlySendToHost)
+ {
+ reader.ReadUInt32();
+ }
}
public override void Serialize(QNetworkWriter writer)
@@ -33,6 +44,10 @@ namespace QSB.Messaging
writer.Write(FromId);
writer.Write(AboutId);
writer.Write(OnlySendToHost);
+ if (!OnlySendToHost)
+ {
+ writer.Write(ForId);
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/QSB/Player/Events/RequestStateResyncEvent.cs b/QSB/Player/Events/RequestStateResyncEvent.cs
index ab1f32f1..26750419 100644
--- a/QSB/Player/Events/RequestStateResyncEvent.cs
+++ b/QSB/Player/Events/RequestStateResyncEvent.cs
@@ -30,20 +30,31 @@ namespace QSB.Player.Events
public override void OnReceiveRemote(bool isHost, PlayerMessage message)
{
- // if host, send worldobject and server states
-
- if (isHost)
+ // send response only to the requesting client
+ ForIdOverride = message.FromId;
+ try
{
- QSBEventManager.FireEvent(EventNames.QSBServerState, ServerStateManager.Instance.GetServerState());
- QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
+ // if host, send worldobject and server states
+ if (isHost)
+ {
+ QSBEventManager.FireEvent(EventNames.QSBServerState, ServerStateManager.Instance.GetServerState());
+ QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
- SendWorldObjectInfo();
-
- return;
+ if (WorldObjectManager.AllObjectsReady)
+ {
+ SendWorldObjectInfo();
+ }
+ }
+ // if client, send player and client states
+ else
+ {
+ QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
+ }
+ }
+ finally
+ {
+ ForIdOverride = uint.MaxValue;
}
-
- // if client, send player and client states
- QSBEventManager.FireEvent(EventNames.QSBPlayerInformation);
}
private void SendWorldObjectInfo()
diff --git a/QSB/QuantumSync/Events/QuantumAuthorityEvent.cs b/QSB/QuantumSync/Events/QuantumAuthorityEvent.cs
index c1749fb2..a52e02d5 100644
--- a/QSB/QuantumSync/Events/QuantumAuthorityEvent.cs
+++ b/QSB/QuantumSync/Events/QuantumAuthorityEvent.cs
@@ -20,9 +20,9 @@ namespace QSB.QuantumSync.Events
AuthorityOwner = authorityOwner
};
- public override bool CheckMessage(bool isServer, QuantumAuthorityMessage message)
+ public override bool CheckMessage(QuantumAuthorityMessage message)
{
- if (!base.CheckMessage(isServer, message))
+ if (!base.CheckMessage(message))
{
return false;
}