2022-06-04 18:09:42 +08:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using Lidgren.Network ;
using RageCoop.Core ;
2022-06-23 09:46:38 +08:00
using RageCoop.Core.Scripting ;
2022-06-04 18:09:42 +08:00
using System.Net ;
namespace RageCoop.Server.Scripting
{
public static class API
{
2022-06-19 11:12:20 +08:00
#region INTERNAL
2022-06-22 14:18:20 +08:00
internal static Dictionary < int , List < Action < CustomEventReceivedArgs > > > CustomEventHandlers = new ( ) ;
2022-06-19 11:12:20 +08:00
#endregion
2022-06-04 18:09:42 +08:00
public static class Events
{
#region DELEGATES
public delegate void EmptyEvent ( ) ;
2022-06-11 18:41:10 +08:00
public delegate void PlayerConnect ( Client client ) ;
public delegate void PlayerDisconnect ( Client client ) ;
2022-06-04 18:09:42 +08:00
#endregion
public static event EventHandler < ChatEventArgs > OnChatMessage ;
public static event EventHandler < HandshakeEventArgs > OnPlayerHandshake ;
public static event PlayerConnect OnPlayerConnected ;
public static event PlayerDisconnect OnPlayerDisconnected ;
2022-06-21 19:06:50 +08:00
/// <summary>
/// Will be invoked before registered handlers
/// </summary>
2022-06-21 18:13:30 +08:00
public static event EventHandler < OnCommandEventArgs > OnCommandReceived ;
2022-06-21 19:06:50 +08:00
/// <summary>
/// Invoked everytime a player's main ped has been updated
/// </summary>
public static event EventHandler < Client > OnPlayerUpdate ;
2022-06-22 14:18:20 +08:00
/ *
2022-06-21 18:13:30 +08:00
/// <summary>
/// This will be invoked when a CustomEvent is received from one client.
/// </summary>
public static event EventHandler < CustomEventReceivedArgs > OnCustomEventReceived ;
2022-06-22 14:18:20 +08:00
* /
2022-06-21 18:13:30 +08:00
internal static void ClearHandlers ( )
2022-06-11 18:41:10 +08:00
{
2022-06-21 18:13:30 +08:00
OnChatMessage = null ;
OnPlayerHandshake = null ;
OnPlayerConnected = null ;
OnPlayerDisconnected = null ;
2022-06-22 14:18:20 +08:00
// OnCustomEventReceived=null;
2022-06-21 18:13:30 +08:00
OnCommandReceived = null ;
2022-06-22 08:28:08 +08:00
OnPlayerUpdate = null ;
2022-06-11 18:41:10 +08:00
}
2022-06-04 18:09:42 +08:00
#region INVOKE
2022-06-21 18:13:30 +08:00
internal static void InvokeOnChatMessage ( Packets . ChatMessage p , Client sender )
2022-06-04 18:09:42 +08:00
{
OnChatMessage ? . Invoke ( null , new ChatEventArgs ( ) {
2022-06-21 18:13:30 +08:00
Sender = sender ,
2022-06-04 18:09:42 +08:00
Message = p . Message
} ) ;
}
internal static void InvokePlayerConnected ( Client client )
2022-06-11 18:41:10 +08:00
{ OnPlayerConnected ? . Invoke ( client ) ; }
2022-06-04 18:09:42 +08:00
internal static void InvokePlayerDisconnected ( Client client )
2022-06-11 18:41:10 +08:00
{ OnPlayerDisconnected ? . Invoke ( client ) ; }
2022-06-04 18:09:42 +08:00
internal static void InvokePlayerHandshake ( HandshakeEventArgs args )
2022-06-12 15:39:32 +08:00
{ OnPlayerHandshake ? . Invoke ( null , args ) ; }
2022-06-21 18:13:30 +08:00
internal static void InvokeCustomEventReceived ( Packets . CustomEvent p , Client sender )
{
2022-06-22 14:18:20 +08:00
var args = new CustomEventReceivedArgs ( ) { Hash = p . Hash , Args = p . Args , Sender = sender } ;
List < Action < CustomEventReceivedArgs > > handlers ;
if ( CustomEventHandlers . TryGetValue ( p . Hash , out handlers ) )
{
handlers . ForEach ( ( x ) = > { x . Invoke ( args ) ; } ) ;
}
2022-06-21 18:13:30 +08:00
}
internal static bool InvokeOnCommandReceived ( string cname , string [ ] cargs , Client sender )
{
var args = new OnCommandEventArgs ( )
{
Name = cname ,
Args = cargs ,
Sender = sender
} ;
OnCommandReceived ? . Invoke ( null , args ) ;
return args . Cancel ;
}
2022-06-21 19:06:50 +08:00
internal static void InvokePlayerUpdate ( Client client )
{
2022-06-21 23:52:30 +08:00
OnPlayerUpdate ? . Invoke ( null , client ) ;
2022-06-21 19:06:50 +08:00
}
2022-06-04 18:09:42 +08:00
#endregion
}
#region FUNCTIONS
2022-06-23 09:46:38 +08:00
/ *
2022-06-04 18:09:42 +08:00
/// <summary>
/// Send a native call (Function.Call) to all players.
/// Keys = int, float, bool, string and lvector3
/// </summary>
/// <param name="hash">The hash (Example: 0x25223CA6B4D20B7F = GET_CLOCK_HOURS)</param>
/// <param name="args">The arguments (Example: string = int, object = 5)</param>
public static void SendNativeCallToAll ( GTA . Native . Hash hash , params object [ ] args )
{
try
{
if ( Server . MainNetServer . ConnectionsCount = = 0 )
{
return ;
}
if ( args ! = null & & args . Length = = 0 )
{
Program . Logger . Error ( $"[ServerScript->SendNativeCallToAll(ulong hash, params object[] args)]: args is not null!" ) ;
return ;
}
Packets . NativeCall packet = new ( )
{
Hash = ( ulong ) hash ,
Args = new List < object > ( args ) ? ? new List < object > ( )
} ;
NetOutgoingMessage outgoingMessage = Server . MainNetServer . CreateMessage ( ) ;
packet . Pack ( outgoingMessage ) ;
Server . MainNetServer . SendMessage ( outgoingMessage , Server . MainNetServer . Connections , NetDeliveryMethod . ReliableOrdered , ( byte ) ConnectionChannel . Native ) ;
}
catch ( Exception e )
{
Program . Logger . Error ( $">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<" ) ;
}
}
2022-06-23 09:46:38 +08:00
* /
2022-06-04 18:09:42 +08:00
/// <summary>
/// Get a list of all Clients
/// </summary>
/// <returns>All clients as a dictionary indexed by NetID</returns>
public static Dictionary < long , Client > GetAllClients ( )
{
2022-06-23 09:46:38 +08:00
return new ( Server . Clients ) ;
2022-06-04 18:09:42 +08:00
}
/// <summary>
/// Get the client by its username
/// </summary>
/// <param name="username">The username to search for (non case-sensitive)</param>
/// <returns>The Client from this user or null</returns>
public static Client GetClientByUsername ( string username )
{
2022-06-21 18:13:30 +08:00
return Server . Clients . Values . FirstOrDefault ( x = > x . Username . ToLower ( ) = = username . ToLower ( ) ) ;
2022-06-04 18:09:42 +08:00
}
/// <summary>
/// Send a chat message to all players
/// </summary>
/// <param name="message">The chat message</param>
/// <param name="username">The username which send this message (default = "Server")</param>
2022-06-21 18:13:30 +08:00
public static void SendChatMessage ( string message , List < Client > targets = null , string username = "Server" )
2022-06-04 18:09:42 +08:00
{
try
{
if ( Server . MainNetServer . ConnectionsCount = = 0 )
{
return ;
}
2022-06-21 18:13:30 +08:00
targets ? ? = new ( Server . Clients . Values ) ;
foreach ( Client client in targets )
{
Server . SendChatMessage ( username , message , client . Connection ) ;
}
}
catch ( Exception e )
{
Program . Logger . Error ( $">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<" ) ;
}
}
public static void SendChatMessage ( string message , Client target , string username = "Server" )
{
try
{
Server . SendChatMessage ( username , message , target . Connection ) ;
2022-06-04 18:09:42 +08:00
}
catch ( Exception e )
{
Program . Logger . Error ( $">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<" ) ;
}
}
/// <summary>
/// Send CleanUpWorld to all players to delete all objects created by the server
/// </summary>
public static void SendCleanUpWorldToAll ( List < long > netHandleList = null )
{
if ( Server . MainNetServer . ConnectionsCount = = 0 )
{
return ;
}
2022-06-23 09:46:38 +08:00
2022-06-04 18:09:42 +08:00
List < NetConnection > connections = netHandleList = = null
? Server . MainNetServer . Connections
: Server . MainNetServer . Connections . FindAll ( c = > netHandleList . Contains ( c . RemoteUniqueIdentifier ) ) ;
NetOutgoingMessage outgoingMessage = Server . MainNetServer . CreateMessage ( ) ;
outgoingMessage . Write ( ( byte ) PacketTypes . CleanUpWorld ) ;
Server . MainNetServer . SendMessage ( outgoingMessage , connections , NetDeliveryMethod . ReliableOrdered , ( byte ) ConnectionChannel . Default ) ;
}
/// <summary>
/// Register a new command chat command (Example: "/test")
/// </summary>
/// <param name="name">The name of the command (Example: "test" for "/test")</param>
/// <param name="usage">How to use this message (argsLength required!)</param>
/// <param name="argsLength">The length of args (Example: "/message USERNAME MESSAGE" = 2) (usage required!)</param>
/// <param name="callback">Create a new function!</param>
public static void RegisterCommand ( string name , string usage , short argsLength , Action < CommandContext > callback )
{
Server . RegisterCommand ( name , usage , argsLength , callback ) ;
}
/// <summary>
/// Register a new command chat command (Example: "/test")
/// </summary>
/// <param name="name">The name of the command (Example: "test" for "/test")</param>
/// <param name="callback">Create a new function!</param>
public static void RegisterCommand ( string name , Action < CommandContext > callback )
{
Server . RegisterCommand ( name , callback ) ;
}
/// <summary>
/// Register a class of commands
/// </summary>
/// <typeparam name="T">The name of your class with functions</typeparam>
public static void RegisterCommands < T > ( )
{
Server . RegisterCommands < T > ( ) ;
}
2022-06-21 18:13:30 +08:00
/// <summary>
/// Send an event and data to the specified clients.
/// </summary>
/// <param name="eventHash">An unique identifier of the event</param>
/// <param name="args">The objects conataing your data, supported types: byte, short, ushort, int, uint, long, ulong, float, bool, string.</param>
/// <param name="targets">The target clients to send.</param>
public static void SendCustomEvent ( int eventHash , List < object > args , List < Client > targets = null )
2022-06-12 15:39:32 +08:00
{
2022-06-19 11:12:20 +08:00
targets ? ? = new ( Server . Clients . Values ) ;
var p = new Packets . CustomEvent ( )
2022-06-12 15:39:32 +08:00
{
2022-06-19 11:12:20 +08:00
Args = args ,
Hash = eventHash
} ;
foreach ( var c in targets )
2022-06-12 15:39:32 +08:00
{
2022-06-19 11:12:20 +08:00
Server . Send ( p , c , ConnectionChannel . Event , NetDeliveryMethod . ReliableOrdered ) ;
2022-06-12 15:39:32 +08:00
}
2022-06-04 18:09:42 +08:00
}
2022-06-22 14:18:20 +08:00
/// <summary>
/// Register an handler to the specifed event hash, one event can have multiple handlers.
/// </summary>
/// <param name="hash">An unique identifier of the event, you can hash your event name with <see cref="Core.Scripting.CustomEvents.Hash(string)"/></param>
/// <param name="handler">An handler to be invoked when the event is received from the server. This will be invoked from main thread.
public static void RegisterCustomEventHandler ( int hash , Action < CustomEventReceivedArgs > handler )
2022-06-21 18:13:30 +08:00
{
2022-06-22 14:18:20 +08:00
List < Action < CustomEventReceivedArgs > > handlers ;
2022-06-21 18:13:30 +08:00
lock ( CustomEventHandlers )
{
if ( ! CustomEventHandlers . TryGetValue ( hash , out handlers ) )
{
2022-06-22 14:18:20 +08:00
CustomEventHandlers . Add ( hash , handlers = new List < Action < CustomEventReceivedArgs > > ( ) ) ;
2022-06-21 18:13:30 +08:00
}
handlers . Add ( handler ) ;
}
}
2022-06-23 09:46:38 +08:00
public static void RegisterCustomEventHandler ( string name , Action < CustomEventReceivedArgs > handler )
{
RegisterCustomEventHandler ( CustomEvents . Hash ( name ) , handler ) ;
}
2022-06-22 08:58:36 +08:00
public static Logger GetLogger ( )
2022-06-21 18:13:30 +08:00
{
return Program . Logger ;
}
2022-06-04 18:09:42 +08:00
#endregion
}
}