using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Lidgren.Network; using RageCoop.Core; using System.Net; namespace RageCoop.Server.Scripting { public static class API { #region INTERNAL internal static Dictionary>>> CustomEventHandlers = new(); #endregion public static class Events { #region DELEGATES public delegate void EmptyEvent(); public delegate void PlayerConnect(Client client); public delegate void PlayerDisconnect(Client client); #endregion public static event EventHandler OnChatMessage; public static event EventHandler OnPlayerHandshake; public static event PlayerConnect OnPlayerConnected; public static event PlayerDisconnect OnPlayerDisconnected; /// /// Will be invoked before registered handlers /// public static event EventHandler OnCommandReceived; /// /// Invoked everytime a player's main ped has been updated /// public static event EventHandler OnPlayerUpdate; /// /// This will be invoked when a CustomEvent is received from one client. /// public static event EventHandler OnCustomEventReceived; internal static void ClearHandlers() { OnChatMessage=null; OnPlayerHandshake=null; OnPlayerConnected=null; OnPlayerDisconnected=null; OnCustomEventReceived=null; OnCommandReceived=null; } #region INVOKE internal static void InvokeOnChatMessage(Packets.ChatMessage p,Client sender) { OnChatMessage?.Invoke(null,new ChatEventArgs() { Sender=sender, Message=p.Message }); } internal static void InvokePlayerConnected(Client client) { OnPlayerConnected?.Invoke(client); } internal static void InvokePlayerDisconnected(Client client) { OnPlayerDisconnected?.Invoke(client); } internal static void InvokePlayerHandshake(HandshakeEventArgs args) { OnPlayerHandshake?.Invoke(null, args); } internal static void InvokeCustomEventReceived(Packets.CustomEvent p,Client sender) { OnCustomEventReceived?.Invoke(null, new CustomEventReceivedArgs() { Hash=p.Hash, Args=p.Args,Sender=sender }); } 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; } internal static void InvokePlayerUpdate(Client client) { OnPlayerUpdate?.Invoke(null,client); } #endregion } #region FUNCTIONS /// /// Send a native call (Function.Call) to all players. /// Keys = int, float, bool, string and lvector3 /// /// The hash (Example: 0x25223CA6B4D20B7F = GET_CLOCK_HOURS) /// The arguments (Example: string = int, object = 5) 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(args) ?? new List() }; 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} <<"); } } /// /// Get a list of all Clients /// /// All clients as a dictionary indexed by NetID public static Dictionary GetAllClients() { return Server.Clients; } /// /// Get the client by its username /// /// The username to search for (non case-sensitive) /// The Client from this user or null public static Client GetClientByUsername(string username) { return Server.Clients.Values.FirstOrDefault(x => x.Username.ToLower() == username.ToLower()); } /// /// Send a chat message to all players /// /// The chat message /// The username which send this message (default = "Server") public static void SendChatMessage(string message, List targets = null, string username = "Server") { try { if (Server.MainNetServer.ConnectionsCount == 0) { return; } 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); } catch (Exception e) { Program.Logger.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<"); } } /// /// Send CleanUpWorld to all players to delete all objects created by the server /// public static void SendCleanUpWorldToAll(List netHandleList = null) { if (Server.MainNetServer.ConnectionsCount == 0) { return; } List 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); } /// /// Register a new command chat command (Example: "/test") /// /// The name of the command (Example: "test" for "/test") /// How to use this message (argsLength required!) /// The length of args (Example: "/message USERNAME MESSAGE" = 2) (usage required!) /// Create a new function! public static void RegisterCommand(string name, string usage, short argsLength, Action callback) { Server.RegisterCommand(name, usage, argsLength, callback); } /// /// Register a new command chat command (Example: "/test") /// /// The name of the command (Example: "test" for "/test") /// Create a new function! public static void RegisterCommand(string name, Action callback) { Server.RegisterCommand(name, callback); } /// /// Register a class of commands /// /// The name of your class with functions public static void RegisterCommands() { Server.RegisterCommands(); } /// /// Send an event and data to the specified clients. /// /// An unique identifier of the event /// The objects conataing your data, supported types: byte, short, ushort, int, uint, long, ulong, float, bool, string. /// The target clients to send. public static void SendCustomEvent(int eventHash,List args,List targets=null) { targets ??= new(Server.Clients.Values); var p = new Packets.CustomEvent() { Args=args, Hash=eventHash }; foreach(var c in targets) { Server.Send(p,c,ConnectionChannel.Event,NetDeliveryMethod.ReliableOrdered); } } public static void RegisterCustomEventHandler(int hash,Action> handler) { List>> handlers; lock (CustomEventHandlers) { if (!CustomEventHandlers.TryGetValue(hash,out handlers)) { CustomEventHandlers.Add(hash, handlers = new List>>()); } handlers.Add(handler); } } public static Core.Logging.Logger GetLogger() { return Program.Logger; } #endregion } }