2021-12-23 17:07:29 -08:00
using OWML.Common ;
2021-12-11 00:15:59 -08:00
using QSB.ClientServerStateSync ;
2021-12-23 13:57:33 -08:00
using QSB.ClientServerStateSync.Messages ;
2021-12-10 23:28:42 -08:00
using QSB.Player ;
2021-12-23 13:49:47 -08:00
using QSB.Player.Messages ;
2021-12-11 00:15:59 -08:00
using QSB.Player.TransformSync ;
2021-12-10 23:28:42 -08:00
using QSB.Utility ;
using QSB.WorldSync ;
using QuantumUNET ;
using QuantumUNET.Components ;
using QuantumUNET.Messages ;
2021-12-23 17:07:29 -08:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Runtime.CompilerServices ;
2021-12-10 23:28:42 -08:00
namespace QSB.Messaging
{
public static class QSBMessageManager
{
#region inner workings
2021-12-11 00:19:24 -08:00
private static readonly Dictionary < short , Type > _msgTypeToType = new ( ) ;
2021-12-10 23:28:42 -08:00
private static readonly Dictionary < Type , short > _typeToMsgType = new ( ) ;
static QSBMessageManager ( )
{
2021-12-21 12:38:43 -08:00
var types = typeof ( QSBMessageRaw ) . GetDerivedTypes ( )
. Concat ( typeof ( QSBMessage ) . GetDerivedTypes ( ) )
. ToArray ( ) ;
2021-12-10 23:28:42 -08:00
for ( var i = 0 ; i < types . Length ; i + + )
{
var msgType = ( short ) ( QMsgType . Highest + 1 + i ) ;
if ( msgType > = short . MaxValue )
{
DebugLog . ToConsole ( "Hey, uh, maybe don't create 32,767 events? You really should never be seeing this." +
"If you are, something has either gone terrible wrong or QSB somehow needs more events that classes in Outer Wilds." +
"In either case, I guess something has gone terribly wrong..." , MessageType . Error ) ;
}
2021-12-11 00:19:24 -08:00
_msgTypeToType . Add ( msgType , types [ i ] ) ;
_typeToMsgType . Add ( types [ i ] , msgType ) ;
2021-12-23 13:06:18 -08:00
// call static constructor of message if needed
RuntimeHelpers . RunClassConstructor ( types [ i ] . TypeHandle ) ;
2021-12-10 23:28:42 -08:00
}
}
public static void Init ( )
{
2021-12-21 12:38:43 -08:00
foreach ( var ( msgType , type ) in _msgTypeToType )
2021-12-10 23:28:42 -08:00
{
2021-12-21 12:38:43 -08:00
if ( typeof ( QSBMessageRaw ) . IsAssignableFrom ( type ) )
{
QNetworkServer . RegisterHandlerSafe ( msgType , OnServerReceiveRaw ) ;
QNetworkManager . singleton . client . RegisterHandlerSafe ( msgType , OnClientReceiveRaw ) ;
}
else
{
QNetworkServer . RegisterHandlerSafe ( msgType , OnServerReceive ) ;
QNetworkManager . singleton . client . RegisterHandlerSafe ( msgType , OnClientReceive ) ;
}
2021-12-10 23:28:42 -08:00
}
}
2021-12-21 12:38:43 -08:00
private static void OnServerReceiveRaw ( QNetworkMessage netMsg )
{
var msgType = netMsg . MsgType ;
var msg = ( QSBMessageRaw ) Activator . CreateInstance ( _msgTypeToType [ msgType ] ) ;
netMsg . ReadMessage ( msg ) ;
QNetworkServer . SendToAll ( msgType , msg ) ;
}
private static void OnClientReceiveRaw ( QNetworkMessage netMsg )
2021-12-10 23:28:42 -08:00
{
var msgType = netMsg . MsgType ;
2021-12-20 16:35:12 -08:00
var msg = ( QSBMessageRaw ) Activator . CreateInstance ( _msgTypeToType [ msgType ] ) ;
2021-12-10 23:28:42 -08:00
netMsg . ReadMessage ( msg ) ;
2021-12-21 12:38:43 -08:00
msg . OnReceive ( ) ;
}
private static void OnServerReceive ( QNetworkMessage netMsg )
{
var msgType = netMsg . MsgType ;
var msg = ( QSBMessage ) Activator . CreateInstance ( _msgTypeToType [ msgType ] ) ;
netMsg . ReadMessage ( msg ) ;
if ( msg . To = = uint . MaxValue )
2021-12-10 23:28:42 -08:00
{
2021-12-21 12:38:43 -08:00
QNetworkServer . SendToAll ( msgType , msg ) ;
}
else if ( msg . To = = 0 )
{
QNetworkServer . localConnection . Send ( msgType , msg ) ;
2021-12-10 23:28:42 -08:00
}
else
{
2021-12-21 12:38:43 -08:00
var conn = QNetworkServer . connections . FirstOrDefault ( x = > msg . To = = x . GetPlayerId ( ) ) ;
if ( conn = = null )
{
DebugLog . ToConsole ( $"SendTo unknown player! id: {msg.To}, message: {msg}" , MessageType . Error ) ;
return ;
}
conn . Send ( msgType , msg ) ;
2021-12-10 23:28:42 -08:00
}
}
private static void OnClientReceive ( QNetworkMessage netMsg )
{
var msgType = netMsg . MsgType ;
2021-12-21 12:38:43 -08:00
var msg = ( QSBMessage ) Activator . CreateInstance ( _msgTypeToType [ msgType ] ) ;
2021-12-10 23:28:42 -08:00
netMsg . ReadMessage ( msg ) ;
2021-12-11 18:40:20 -08:00
if ( PlayerTransformSync . LocalInstance = = null )
2021-12-10 23:28:42 -08:00
{
2021-12-20 16:35:12 -08:00
DebugLog . ToConsole ( $"Warning - Tried to handle message {msg} before local player was established." , MessageType . Warning ) ;
2021-12-11 18:40:20 -08:00
return ;
}
2021-12-21 12:38:43 -08:00
if ( QSBPlayerManager . PlayerExists ( msg . From ) )
2021-12-11 18:40:20 -08:00
{
2021-12-21 12:38:43 -08:00
var player = QSBPlayerManager . GetPlayer ( msg . From ) ;
if ( ! player . IsReady
& & player . PlayerId ! = QSBPlayerManager . LocalPlayerId
& & player . State is ClientState . AliveInSolarSystem or ClientState . AliveInEye or ClientState . DeadInSolarSystem
2021-12-22 18:27:12 -08:00
& & msg is not ( PlayerInformationMessage or PlayerReadyMessage or RequestStateResyncMessage or ServerStateMessage ) )
2021-12-11 00:15:59 -08:00
{
2021-12-21 12:38:43 -08: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 ) ;
2021-12-22 18:20:53 -08:00
new RequestStateResyncMessage ( ) . Send ( ) ;
2021-12-11 00:15:59 -08:00
}
2021-12-11 18:40:20 -08:00
}
2021-12-11 00:15:59 -08:00
2021-12-11 18:40:20 -08:00
try
{
2021-12-21 12:38:43 -08:00
if ( ! msg . ShouldReceive )
{
return ;
}
if ( msg . From ! = QSBPlayerManager . LocalPlayerId )
{
msg . OnReceiveRemote ( ) ;
}
else
{
msg . OnReceiveLocal ( ) ;
}
2021-12-10 23:28:42 -08:00
}
catch ( Exception ex )
{
2021-12-11 19:02:34 -08:00
DebugLog . ToConsole ( $"Error - Exception handling message {msg} : {ex}" , MessageType . Error ) ;
2021-12-10 23:28:42 -08:00
}
}
#endregion
2021-12-21 12:38:43 -08:00
public static void SendRaw < M > ( this M msg )
2021-12-20 16:35:12 -08:00
where M : QSBMessageRaw , new ( )
2021-12-21 12:38:43 -08:00
{
var msgType = _typeToMsgType [ typeof ( M ) ] ;
QNetworkManager . singleton . client . Send ( msgType , msg ) ;
}
2021-12-22 14:32:11 -08:00
public static void ServerSendRaw < M > ( this M msg , QNetworkConnection conn )
where M : QSBMessageRaw , new ( )
{
var msgType = _typeToMsgType [ typeof ( M ) ] ;
conn . Send ( msgType , msg ) ;
}
2021-12-21 12:38:43 -08:00
public static void Send < M > ( this M msg )
where M : QSBMessage , new ( )
2021-12-10 23:28:42 -08:00
{
2021-12-20 16:35:12 -08:00
if ( PlayerTransformSync . LocalInstance = = null )
2021-12-11 19:02:34 -08:00
{
2021-12-20 16:35:12 -08:00
DebugLog . ToConsole ( $"Warning - Tried to send message {msg} before local player was established." , MessageType . Warning ) ;
2021-12-11 19:02:34 -08:00
return ;
}
2021-12-21 12:38:43 -08:00
msg . From = QSBPlayerManager . LocalPlayerId ;
2021-12-10 23:28:42 -08:00
var msgType = _typeToMsgType [ typeof ( M ) ] ;
2021-12-20 15:39:50 -08:00
QNetworkManager . singleton . client . Send ( msgType , msg ) ;
2021-12-10 23:28:42 -08:00
}
2021-12-20 15:39:50 -08:00
public static void SendMessage < T , M > ( this T worldObject , M msg )
2021-12-10 23:28:42 -08:00
where T : IWorldObject
2021-12-20 15:39:50 -08:00
where M : QSBWorldObjectMessage < T > , new ( )
2021-12-10 23:28:42 -08:00
{
2021-12-20 15:39:50 -08:00
msg . ObjectId = worldObject . ObjectId ;
Send ( msg ) ;
2021-12-10 23:28:42 -08:00
}
}
2021-12-20 16:35:12 -08:00
/// <summary>
2021-12-21 12:38:43 -08:00
/// message that will be sent to every client. <br/>
/// no checks are performed on the message. it is just sent and received.
2021-12-20 16:35:12 -08:00
/// </summary>
public abstract class QSBMessageRaw : QMessageBase
{
public abstract void OnReceive ( ) ;
public override string ToString ( ) = > GetType ( ) . Name ;
}
2021-12-10 23:28:42 -08:00
}