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 ;
2021-12-10 20:41:56 -08:00
using QSB.ClientServerStateSync.Events ;
2021-12-11 00:15:59 -08:00
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 ) ;
2021-12-20 15:39:50 -08:00
if ( msg . To = = uint . MaxValue )
2021-12-10 23:28:42 -08:00
{
2021-12-20 15:39:50 -08:00
QNetworkServer . SendToAll ( msgType , msg ) ;
2021-12-10 23:28:42 -08:00
}
2021-12-20 15:39:50 -08:00
else if ( msg . To = = 0 )
2021-12-10 23:28:42 -08:00
{
2021-12-20 15:39:50 -08:00
OnReceive ( msg ) ;
2021-12-10 23:28:42 -08:00
}
else
{
var conn = QNetworkServer . connections . FirstOrDefault ( x = > msg . To = = x . GetPlayerId ( ) ) ;
if ( conn = = null )
{
2021-12-11 19:02:34 -08:00
DebugLog . ToConsole ( $"SendTo unknown player! id: {msg.To}, message: {msg}" , MessageType . Error ) ;
2021-12-10 23:28:42 -08:00
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 ) ;
2021-12-20 15:39:50 -08:00
OnReceive ( msg ) ;
}
private static void OnReceive ( QSBMessage msg )
{
2021-12-11 18:40:20 -08:00
if ( PlayerTransformSync . LocalInstance = = null )
2021-12-10 23:28:42 -08:00
{
2021-12-11 19:02:34 -08:00
DebugLog . ToConsole ( $"Warning - Tried to handle message {msg} before localplayer was established." , MessageType . Warning ) ;
2021-12-11 18:40:20 -08:00
return ;
}
if ( QSBPlayerManager . PlayerExists ( msg . From ) )
{
var player = QSBPlayerManager . GetPlayer ( msg . From ) ;
2021-12-10 23:28:42 -08:00
2021-12-11 18:40:20 -08:00
if ( ! player . IsReady
2021-12-20 15:39:50 -08:00
& & player . PlayerId ! = QSBPlayerManager . LocalPlayerId
& & player . State is ClientState . AliveInSolarSystem or ClientState . AliveInEye or ClientState . DeadInSolarSystem
& & msg is not QSBEventRelay { Event : PlayerInformationEvent or PlayerReadyEvent or RequestStateResyncEvent or ServerStateEvent } )
2021-12-11 00:15:59 -08:00
{
2021-12-11 19:02:34 -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-11 18:40:20 -08:00
QSBEventManager . FireEvent ( EventNames . QSBRequestStateResync ) ;
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
{
if ( ! msg . ShouldReceive )
2021-12-11 00:15:59 -08:00
{
2021-12-11 18:40:20 -08:00
return ;
2021-12-11 00:15:59 -08:00
}
2021-12-10 23:28:42 -08:00
if ( msg . From ! = QSBPlayerManager . LocalPlayerId )
{
msg . OnReceiveRemote ( ) ;
}
else
{
msg . OnReceiveLocal ( ) ;
}
}
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-20 15:39:50 -08:00
public static void Send < M > ( this M msg )
2021-12-10 23:28:42 -08:00
where M : QSBMessage , new ( )
{
2021-12-11 19:02:34 -08:00
if ( ! QSBCore . IsInMultiplayer )
{
2021-12-20 15:39:50 -08:00
DebugLog . ToConsole ( $"Warning - Tried to send message {msg} while not connected to/hosting server." , MessageType . Warning ) ;
2021-12-11 19:02:34 -08:00
return ;
}
2021-12-20 15:39:50 -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
}
}
}