quantum-space-buddies/QSB/Messaging/QSBMessageManager.cs

176 lines
4.2 KiB
C#
Raw Normal View History

2022-01-13 20:52:04 -08:00
using Mirror;
using OWML.Common;
using QSB.ClientServerStateSync;
2021-12-23 13:57:33 -08:00
using QSB.ClientServerStateSync.Messages;
2022-08-28 22:22:19 -07:00
using QSB.Patches;
using QSB.Player;
2021-12-23 13:49:47 -08:00
using QSB.Player.Messages;
using QSB.Player.TransformSync;
using QSB.Utility;
using QSB.WorldSync;
2021-12-23 17:07:29 -08:00
using System;
2022-01-14 02:29:42 -08:00
using System.Collections.Generic;
2021-12-23 17:07:29 -08:00
using System.Runtime.CompilerServices;
2022-01-14 02:29:42 -08:00
using System.Runtime.Serialization;
2022-03-02 19:46:33 -08:00
namespace QSB.Messaging;
public static class QSBMessageManager
{
2022-03-02 19:46:33 -08:00
#region inner workings
internal static readonly Dictionary<int, Type> _types = new();
2022-03-02 19:46:33 -08:00
static QSBMessageManager()
{
2023-08-03 14:40:47 -07:00
foreach (var type in typeof(QSBMessage).GetDerivedTypes())
2022-03-02 19:46:33 -08:00
{
var hash = type.FullName.GetStableHashCode();
_types.Add(hash, type);
2022-03-02 19:46:33 -08:00
// call static constructor of message if needed
2023-08-03 14:40:47 -07:00
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
2022-03-02 19:46:33 -08:00
}
}
2022-03-02 19:46:33 -08:00
public static void Init()
{
NetworkServer.RegisterHandler<Wrapper>((_, wrapper) => OnServerReceive(wrapper));
NetworkClient.RegisterHandler<Wrapper>(wrapper => OnClientReceive(wrapper));
}
2022-03-02 19:46:33 -08:00
private static void OnServerReceive(QSBMessage msg)
{
2023-08-03 14:40:47 -07:00
if (msg == null)
{
return;
}
2022-03-02 19:46:33 -08:00
if (msg.To == uint.MaxValue)
{
2022-03-02 19:46:33 -08:00
NetworkServer.SendToAll<Wrapper>(msg);
}
else if (msg.To == 0)
{
NetworkServer.localConnection.Send<Wrapper>(msg);
}
else
{
2023-03-08 23:16:07 +00:00
var connection = msg.To.GetNetworkConnection();
if (connection == default)
{
DebugLog.ToConsole($"Warning - Tried to handle message from disconnected(?) player.", MessageType.Warning);
return;
}
connection.Send<Wrapper>(msg);
}
2022-03-02 19:46:33 -08:00
}
2022-03-02 19:46:33 -08:00
private static void OnClientReceive(QSBMessage msg)
{
2023-08-08 16:29:24 -07:00
if (msg == null)
{
return;
}
2022-03-02 19:46:33 -08:00
if (PlayerTransformSync.LocalInstance == null)
{
2022-03-02 19:46:33 -08:00
DebugLog.ToConsole($"Warning - Tried to handle message {msg} before local player was established.", MessageType.Warning);
return;
2021-12-21 12:38:43 -08:00
}
2022-03-02 19:46:33 -08:00
if (QSBPlayerManager.PlayerExists(msg.From))
2021-12-21 12:38:43 -08:00
{
2022-03-02 19:46:33 -08:00
var player = QSBPlayerManager.GetPlayer(msg.From);
if (!player.IsReady
2023-08-03 14:40:47 -07:00
&& player.PlayerId != QSBPlayerManager.LocalPlayerId
&& player.State is ClientState.AliveInSolarSystem or ClientState.AliveInEye or ClientState.DeadInSolarSystem
&& msg is not (PlayerInformationMessage or PlayerReadyMessage or RequestStateResyncMessage or ServerStateMessage))
{
2022-08-13 11:52:26 +01:00
//DebugLog.ToConsole($"Warning - Got message {msg} from player {msg.From}, but they were not ready. Asking for state resync, just in case.", MessageType.Warning);
2022-03-02 19:46:33 -08:00
new RequestStateResyncMessage().Send();
}
}
2022-03-02 19:46:33 -08:00
try
{
2022-03-02 19:46:33 -08:00
if (!msg.ShouldReceive)
{
2021-12-11 18:40:20 -08:00
return;
}
2022-03-02 19:46:33 -08:00
if (msg.From != QSBPlayerManager.LocalPlayerId)
{
2022-08-28 22:22:19 -07:00
QSBPatch.Remote = true;
2022-03-02 19:46:33 -08:00
msg.OnReceiveRemote();
2022-08-28 22:22:19 -07:00
QSBPatch.Remote = false;
}
2022-03-02 19:46:33 -08:00
else
{
2022-03-02 19:46:33 -08:00
msg.OnReceiveLocal();
}
}
2022-03-02 19:46:33 -08:00
catch (Exception ex)
{
2022-03-02 19:46:33 -08:00
DebugLog.ToConsole($"Error - Exception handling message {msg} : {ex}", MessageType.Error);
}
2022-03-02 19:46:33 -08:00
}
#endregion
2022-03-02 19:46:33 -08:00
public static void Send<M>(this M msg)
where M : QSBMessage
{
if (PlayerTransformSync.LocalInstance == null)
{
2022-03-02 19:46:33 -08:00
DebugLog.ToConsole($"Warning - Tried to send message {msg} before local player was established.", MessageType.Warning);
return;
}
2022-03-02 19:46:33 -08:00
msg.From = QSBPlayerManager.LocalPlayerId;
NetworkClient.Send<Wrapper>(msg);
}
2022-03-02 19:46:33 -08:00
public static void SendMessage<T, M>(this T worldObject, M msg)
where T : IWorldObject
where M : QSBWorldObjectMessage<T>
{
2022-03-02 19:46:33 -08:00
msg.ObjectId = worldObject.ObjectId;
Send(msg);
}
2022-03-02 19:46:33 -08:00
}
internal struct Wrapper : NetworkMessage
{
public QSBMessage Msg;
public static implicit operator QSBMessage(Wrapper wrapper) => wrapper.Msg;
public static implicit operator Wrapper(QSBMessage msg) => new() { Msg = msg };
}
2022-01-14 02:29:42 -08:00
2023-07-28 19:49:30 +01:00
public static class ReaderWriterExtensions
2022-03-02 19:46:33 -08:00
{
private static QSBMessage ReadQSBMessage(this NetworkReader reader)
{
var hash = reader.ReadInt();
if (!QSBMessageManager._types.TryGetValue(hash, out var type))
2023-08-03 14:40:47 -07:00
{
DebugLog.DebugWrite($"unknown QSBMessage type with hash {hash}", MessageType.Error);
2023-08-03 14:40:47 -07:00
return null;
}
2022-03-02 19:46:33 -08:00
var msg = (QSBMessage)FormatterServices.GetUninitializedObject(type);
msg.Deserialize(reader);
return msg;
}
2022-03-02 19:46:33 -08:00
private static void WriteQSBMessage(this NetworkWriter writer, QSBMessage msg)
{
var type = msg.GetType();
var hash = type.FullName.GetStableHashCode();
writer.WriteInt(hash);
2022-03-02 19:46:33 -08:00
msg.Serialize(writer);
}
2023-08-03 14:40:47 -07:00
}