2021-12-10 23:28:42 -08:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using OWML.Common ;
2021-12-11 00:15:59 -08:00
using QSB.ClientServerStateSync ;
using QSB.Events ;
2021-12-10 23:28:42 -08:00
using QSB.Player ;
2021-12-11 00:15:59 -08:00
using QSB.Player.Events ;
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 ;
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 ( )
{
var types = typeof ( QSBMessage ) . GetDerivedTypes ( ) . ToArray ( ) ;
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-10 23:28:42 -08:00
}
}
public static void Init ( )
{
2021-12-11 00:19:24 -08:00
foreach ( var msgType in _msgTypeToType . Keys )
2021-12-10 23:28:42 -08:00
{
QNetworkServer . RegisterHandlerSafe ( msgType , OnServerReceive ) ;
QNetworkManager . singleton . client . RegisterHandlerSafe ( msgType , OnClientReceive ) ;
}
}
private static void OnServerReceive ( QNetworkMessage netMsg )
{
var msgType = netMsg . MsgType ;
2021-12-11 00:19:24 -08:00
var msg = ( QSBMessage ) Activator . CreateInstance ( _msgTypeToType [ msgType ] ) ;
2021-12-10 23:28:42 -08:00
netMsg . ReadMessage ( msg ) ;
if ( msg . To = = 0 )
{
QNetworkServer . SendToClient ( 0 , msgType , msg ) ;
}
else if ( msg . To = = uint . MaxValue )
{
QNetworkServer . SendToAll ( msgType , msg ) ;
}
else
{
var conn = QNetworkServer . connections . FirstOrDefault ( x = > msg . To = = x . GetPlayerId ( ) ) ;
if ( conn = = null )
{
DebugLog . ToConsole ( $"SendTo unknown player! id: {msg.To}, message: {msg.GetType().Name}" , MessageType . Error ) ;
return ;
}
conn . Send ( msgType , msg ) ;
}
}
private static void OnClientReceive ( QNetworkMessage netMsg )
{
var msgType = netMsg . MsgType ;
2021-12-11 00:19:24 -08:00
var msg = ( QSBMessage ) Activator . CreateInstance ( _msgTypeToType [ msgType ] ) ;
2021-12-10 23:28:42 -08:00
netMsg . ReadMessage ( msg ) ;
try
{
if ( ! msg . ShouldReceive )
{
return ;
}
2021-12-11 00:15:59 -08:00
if ( PlayerTransformSync . LocalInstance = = null )
{
DebugLog . ToConsole ( $"Warning - Tried to handle message of type <{msg.GetType().Name}> before localplayer was established." , MessageType . Warning ) ;
return ;
}
if ( QSBPlayerManager . PlayerExists ( msg . From ) )
{
var player = QSBPlayerManager . GetPlayer ( msg . From ) ;
if ( ! player . IsReady
& & player . PlayerId ! = QSBPlayerManager . LocalPlayerId
& & player . State is ClientState . AliveInSolarSystem or ClientState . AliveInEye or ClientState . DeadInSolarSystem
& & msg is not QSBEventRelay { Event : PlayerInformationEvent or PlayerReadyEvent } )
{
DebugLog . ToConsole ( $"Warning - Got message from player {msg.From}, but they were not ready. Asking for state resync, just in case." , MessageType . Warning ) ;
QSBEventManager . FireEvent ( EventNames . QSBRequestStateResync ) ;
}
}
2021-12-10 23:28:42 -08:00
if ( msg . From ! = QSBPlayerManager . LocalPlayerId )
{
msg . OnReceiveRemote ( ) ;
}
else
{
msg . OnReceiveLocal ( ) ;
}
}
catch ( Exception ex )
{
DebugLog . ToConsole ( $"Error - Exception handling message {msg.GetType().Name} : {ex}" , MessageType . Error ) ;
}
}
#endregion
2021-12-11 00:06:09 -08:00
public static void Send < M > ( this M message )
2021-12-10 23:28:42 -08:00
where M : QSBMessage , new ( )
{
var msgType = _typeToMsgType [ typeof ( M ) ] ;
message . From = QSBPlayerManager . LocalPlayerId ;
QNetworkManager . singleton . client . Send ( msgType , message ) ;
}
2021-12-11 00:06:09 -08:00
public static void SendMessage < T , M > ( this T worldObject , M message )
2021-12-10 23:28:42 -08:00
where M : QSBWorldObjectMessage < T > , new ( )
where T : IWorldObject
{
message . ObjectId = worldObject . ObjectId ;
2021-12-11 00:06:09 -08:00
Send ( message ) ;
2021-12-10 23:28:42 -08:00
}
}
}