Use implicit operator for CustomEventHash, add CustomEventFlags

Resource rebuild will be required, but no code change is needed
This commit is contained in:
sardelka9515
2022-10-05 15:53:57 +08:00
parent 3f3b5fd2d0
commit 71f7f4b257
15 changed files with 500 additions and 445 deletions

View File

@ -25,6 +25,7 @@ namespace RageCoop.Client
static Networking() static Networking()
{ {
Security = new Security(Main.Logger); Security = new Security(Main.Logger);
Packets.CustomEvent.ResolveHandle = _resolveHandle;
} }
public static void ToggleConnection(string address, string username = null, string password = null, PublicKey publicKey = null) public static void ToggleConnection(string address, string username = null, string password = null, PublicKey publicKey = null)

View File

@ -259,16 +259,11 @@ namespace RageCoop.Client
case PacketType.CustomEvent: case PacketType.CustomEvent:
{ {
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle); Packets.CustomEvent packet = new Packets.CustomEvent();
packet.Deserialize(msg); packet.Deserialize(msg);
Scripting.API.Events.InvokeCustomEventReceived(packet); if (packet.Flags.HasEventFlag(Core.Scripting.CustomEventFlags.Queued))
}
break;
case PacketType.CustomEventQueued:
{ {
recycle = false; recycle = false;
Packets.CustomEvent packet = new Packets.CustomEvent(_resolveHandle);
Main.QueueAction(() => Main.QueueAction(() =>
{ {
packet.Deserialize(msg); packet.Deserialize(msg);
@ -276,6 +271,11 @@ namespace RageCoop.Client
Peer.Recycle(msg); Peer.Recycle(msg);
}); });
} }
else
{
Scripting.API.Events.InvokeCustomEventReceived(packet);
}
}
break; break;
case PacketType.FileTransferChunk: case PacketType.FileTransferChunk:

View File

@ -16,7 +16,7 @@ using System.Resources;
// Version informationr( // Version informationr(
[assembly: AssemblyVersion("1.5.4.3")] [assembly: AssemblyVersion("1.5.4.7")]
[assembly: AssemblyFileVersion("1.5.4.3")] [assembly: AssemblyFileVersion("1.5.4.7")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )] [assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -3,6 +3,7 @@
<Import Project="..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" /> <Import Project="..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}</ProjectGuid> <ProjectGuid>{EF56D109-1F22-43E0-9DFF-CFCFB94E0681}</ProjectGuid>
@ -22,6 +23,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>DEBUG</DefineConstants> <DefineConstants>DEBUG</DefineConstants>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<NoWarn>1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
<OutPutPath>..\bin\Release\Client</OutPutPath> <OutPutPath>..\bin\Release\Client</OutPutPath>

View File

@ -2,6 +2,7 @@
using GTA; using GTA;
using Newtonsoft.Json; using Newtonsoft.Json;
using RageCoop.Core; using RageCoop.Core;
using RageCoop.Core.Scripting;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
@ -280,7 +281,7 @@ namespace RageCoop.Client.Scripting
/// </summary> /// </summary>
/// <param name="eventHash">An unique identifier of the event</param> /// <param name="eventHash">An unique identifier of the event</param>
/// <param name="args">The objects conataing your data, see <see cref="CustomEventReceivedArgs"/> for a list of supported types</param> /// <param name="args">The objects conataing your data, see <see cref="CustomEventReceivedArgs"/> for a list of supported types</param>
public static void SendCustomEvent(int eventHash, params object[] args) public static void SendCustomEvent(CustomEventHash eventHash, params object[] args)
{ {
Networking.Peer.SendTo(new Packets.CustomEvent() Networking.Peer.SendTo(new Packets.CustomEvent()
@ -289,13 +290,27 @@ namespace RageCoop.Client.Scripting
Hash = eventHash Hash = eventHash
}, Networking.ServerConnection, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered); }, Networking.ServerConnection, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
} }
/// <summary>
/// Send an event and data to the server
/// </summary>
/// <param name="flags"></param>
/// <param name="eventHash">An unique identifier of the event</param>
/// <param name="args">The objects conataing your data, see <see cref="CustomEventReceivedArgs"/> for a list of supported types</param>
public static void SendCustomEvent(CustomEventFlags flags,CustomEventHash eventHash, params object[] args)
{
Networking.Peer.SendTo(new Packets.CustomEvent(flags)
{
Args = args,
Hash = eventHash
}, Networking.ServerConnection, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
}
/// <summary> /// <summary>
/// Register an handler to the specifed event hash, one event can have multiple handlers. This will be invoked from backgound thread, use <see cref="QueueAction(Action)"/> in the handler to dispatch code to script thread. /// Register an handler to the specifed event hash, one event can have multiple handlers. This will be invoked from backgound thread, use <see cref="QueueAction(Action)"/> in the handler to dispatch code to script thread.
/// </summary> /// </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="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. </param> /// <param name="handler">An handler to be invoked when the event is received from the server. </param>
public static void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler) public static void RegisterCustomEventHandler(CustomEventHash hash, Action<CustomEventReceivedArgs> handler)
{ {
lock (CustomEventHandlers) lock (CustomEventHandlers)
{ {

View File

@ -1,6 +1,7 @@
using GTA.Math; using GTA.Math;
using Lidgren.Network; using Lidgren.Network;
using Newtonsoft.Json; using Newtonsoft.Json;
using RageCoop.Core.Scripting;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -13,6 +14,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using static ICSharpCode.SharpZipLib.Zip.ExtendedUnixData;
[assembly: InternalsVisibleTo("RageCoop.Server")] [assembly: InternalsVisibleTo("RageCoop.Server")]
[assembly: InternalsVisibleTo("RageCoop.Client")] [assembly: InternalsVisibleTo("RageCoop.Client")]
@ -272,22 +274,27 @@ namespace RageCoop.Core
p.Deserialize(msg); p.Deserialize(msg);
return p; return p;
} }
public static bool HasPedFlag(this PedDataFlags flagToCheck, PedDataFlags flag) public static bool HasPedFlag(this PedDataFlags flags, PedDataFlags flag)
{ {
return (flagToCheck & flag) != 0; return (flags & flag) != 0;
} }
public static bool HasProjDataFlag(this ProjectileDataFlags flagToCheck, ProjectileDataFlags flag) public static bool HasProjDataFlag(this ProjectileDataFlags flags, ProjectileDataFlags flag)
{ {
return (flagToCheck & flag) != 0; return (flags & flag) != 0;
} }
public static bool HasVehFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag) public static bool HasVehFlag(this VehicleDataFlags flags, VehicleDataFlags flag)
{ {
return (flagToCheck & flag) != 0; return (flags & flag) != 0;
} }
public static bool HasConfigFlag(this PlayerConfigFlags flagToCheck, PlayerConfigFlags flag) public static bool HasConfigFlag(this PlayerConfigFlags flags, PlayerConfigFlags flag)
{ {
return (flagToCheck & flag) != 0; return (flags & flag) != 0;
}
public static bool HasEventFlag(this CustomEventFlags flags,CustomEventFlags flag)
{
return (flags & flag) != 0;
} }
public static Type GetActualType(this TypeCode code) public static Type GetActualType(this TypeCode code)
{ {

View File

@ -1,4 +1,5 @@
using Lidgren.Network; using Lidgren.Network;
using RageCoop.Core.Scripting;
using System; using System;
namespace RageCoop.Core namespace RageCoop.Core
{ {
@ -7,21 +8,20 @@ namespace RageCoop.Core
internal class CustomEvent : Packet internal class CustomEvent : Packet
{ {
public override PacketType Type => (_queued ? PacketType.CustomEventQueued : PacketType.CustomEvent); public static Func<byte, NetIncomingMessage, object> ResolveHandle = null;
public CustomEvent(Func<byte, NetIncomingMessage, object> onResolve = null, bool queued = false) public CustomEventFlags Flags;
public override PacketType Type => PacketType.CustomEvent;
public CustomEvent(CustomEventFlags flags = CustomEventFlags.None)
{ {
_resolve = onResolve; Flags = flags;
_queued = queued;
} }
private readonly bool _queued;
private Func<byte, NetIncomingMessage, object> _resolve { get; set; }
public int Hash { get; set; } public int Hash { get; set; }
public object[] Args { get; set; } public object[] Args { get; set; }
protected override void Serialize(NetOutgoingMessage m) protected override void Serialize(NetOutgoingMessage m)
{ {
Args = Args ?? new object[] { }; Args = Args ?? new object[] { };
m.Write((byte)Flags);
m.Write(Hash); m.Write(Hash);
m.Write(Args.Length); m.Write(Args.Length);
foreach (var arg in Args) foreach (var arg in Args)
@ -33,7 +33,7 @@ namespace RageCoop.Core
public override void Deserialize(NetIncomingMessage m) public override void Deserialize(NetIncomingMessage m)
{ {
Flags = (CustomEventFlags)m.ReadByte();
Hash = m.ReadInt32(); Hash = m.ReadInt32();
var len = m.ReadInt32(); var len = m.ReadInt32();
Args = new object[len]; Args = new object[len];
@ -73,13 +73,13 @@ namespace RageCoop.Core
case 0x15: case 0x15:
Args[i] = m.ReadByteArray(); break; Args[i] = m.ReadByteArray(); break;
default: default:
if (_resolve == null) if (ResolveHandle == null)
{ {
throw new InvalidOperationException($"Unexpected type: {type}"); throw new InvalidOperationException($"Unexpected type: {type}");
} }
else else
{ {
Args[i] = _resolve(type, m); break; Args[i] = ResolveHandle(type, m); break;
} }
} }
} }

View File

@ -24,7 +24,6 @@ namespace RageCoop.Core
AllResourcesSent = 15, AllResourcesSent = 15,
CustomEvent = 16, CustomEvent = 16,
CustomEventQueued = 17,
ConnectionRequest = 18, ConnectionRequest = 18,
P2PConnect = 19, P2PConnect = 19,

View File

@ -24,6 +24,14 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Costura.Fody" Version="5.7.0"> <PackageReference Include="Costura.Fody" Version="5.7.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@ -1,4 +1,5 @@
using System; using GTA.Native;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
@ -6,38 +7,59 @@ using System.Text;
namespace RageCoop.Core.Scripting namespace RageCoop.Core.Scripting
{ {
/// <summary> /// <summary>
/// /// Describes how the event should be sent or processed
/// </summary> /// </summary>
public static class CustomEvents public enum CustomEventFlags : byte
{
None=0,
/// <summary>
/// Data will be encrypted and decrypted on target client
/// </summary>
Encrypted=1,
/// <summary>
/// Event will be queued and fired in script thread, specify this flag if your handler will call native functions.
/// </summary>
Queued=2,
}
/// <summary>
/// Struct to identify different event using hash
/// </summary>
public struct CustomEventHash
{ {
private static readonly MD5 Hasher = MD5.Create(); private static readonly MD5 Hasher = MD5.Create();
private static readonly Dictionary<int, string> Hashed = new Dictionary<int, string>(); private static readonly Dictionary<int, string> Hashed = new Dictionary<int, string>();
internal static readonly int OnPlayerDied = Hash("RageCoop.OnPlayerDied"); /// <summary>
internal static readonly int SetWeather = Hash("RageCoop.SetWeather"); /// Hash value
internal static readonly int OnPedDeleted = Hash("RageCoop.OnPedDeleted"); /// </summary>
internal static readonly int OnVehicleDeleted = Hash("RageCoop.OnVehicleDeleted"); public int Hash;
internal static readonly int SetAutoRespawn = Hash("RageCoop.SetAutoRespawn"); /// <summary>
internal static readonly int SetDisplayNameTag = Hash("RageCoop.SetDisplayNameTag"); /// Create from hash
internal static readonly int NativeCall = Hash("RageCoop.NativeCall"); /// </summary>
internal static readonly int NativeResponse = Hash("RageCoop.NativeResponse"); /// <param name="hash"></param>
internal static readonly int AllResourcesSent = Hash("RageCoop.AllResourcesSent"); public static implicit operator CustomEventHash(int hash)
internal static readonly int ServerPropSync = Hash("RageCoop.ServerPropSync"); {
internal static readonly int ServerBlipSync = Hash("RageCoop.ServerBlipSync"); return new CustomEventHash() { Hash = hash };
internal static readonly int SetEntity = Hash("RageCoop.SetEntity"); }
internal static readonly int DeleteServerProp = Hash("RageCoop.DeleteServerProp"); /// <summary>
internal static readonly int UpdatePedBlip = Hash("RageCoop.UpdatePedBlip"); /// Create from string
internal static readonly int DeleteEntity = Hash("RageCoop.DeleteEntity"); /// </summary>
internal static readonly int DeleteServerBlip = Hash("RageCoop.DeleteServerBlip"); /// <param name="name"></param>
internal static readonly int CreateVehicle = Hash("RageCoop.CreateVehicle"); public static implicit operator CustomEventHash(string name)
internal static readonly int WeatherTimeSync = Hash("RageCoop.WeatherTimeSync"); {
internal static readonly int IsHost = Hash("RageCoop.IsHost"); return new CustomEventHash() { Hash = FromString(name) };
}
/// <summary> /// <summary>
/// Get a Int32 hash of a string. /// Get a Int32 hash of a string.
/// </summary> /// </summary>
/// <param name="s"></param> /// <param name="s"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="ArgumentException">The exception is thrown when the name did not match a previously computed one and the hash was the same.</exception> /// <exception cref="ArgumentException">The exception is thrown when the name did not match a previously computed one and the hash was the same.</exception>
public static int Hash(string s) public static int FromString(string s)
{ {
var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0); var hash = BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0);
lock (Hashed) lock (Hashed)
@ -56,5 +78,39 @@ namespace RageCoop.Core.Scripting
return hash; return hash;
} }
} }
/// <summary>
/// To int
/// </summary>
/// <param name="h"></param>
public static implicit operator int(CustomEventHash h)
{
return h.Hash;
}
}
/// <summary>
///
/// </summary>
public static class CustomEvents
{
internal static readonly CustomEventHash OnPlayerDied = "RageCoop.OnPlayerDied";
internal static readonly CustomEventHash SetWeather = "RageCoop.SetWeather";
internal static readonly CustomEventHash OnPedDeleted = "RageCoop.OnPedDeleted";
internal static readonly CustomEventHash OnVehicleDeleted = "RageCoop.OnVehicleDeleted";
internal static readonly CustomEventHash SetAutoRespawn = "RageCoop.SetAutoRespawn";
internal static readonly CustomEventHash SetDisplayNameTag = "RageCoop.SetDisplayNameTag";
internal static readonly CustomEventHash NativeCall = "RageCoop.NativeCall";
internal static readonly CustomEventHash NativeResponse = "RageCoop.NativeResponse";
internal static readonly CustomEventHash AllResourcesSent = "RageCoop.AllResourcesSent";
internal static readonly CustomEventHash ServerPropSync = "RageCoop.ServerPropSync";
internal static readonly CustomEventHash ServerBlipSync = "RageCoop.ServerBlipSync";
internal static readonly CustomEventHash SetEntity = "RageCoop.SetEntity";
internal static readonly CustomEventHash DeleteServerProp = "RageCoop.DeleteServerProp";
internal static readonly CustomEventHash UpdatePedBlip = "RageCoop.UpdatePedBlip";
internal static readonly CustomEventHash DeleteEntity = "RageCoop.DeleteEntity";
internal static readonly CustomEventHash DeleteServerBlip = "RageCoop.DeleteServerBlip";
internal static readonly CustomEventHash CreateVehicle = "RageCoop.CreateVehicle";
internal static readonly CustomEventHash WeatherTimeSync = "RageCoop.WeatherTimeSync";
internal static readonly CustomEventHash IsHost = "RageCoop.IsHost";
} }
} }

View File

@ -170,9 +170,10 @@ namespace RageCoop.Server
/// <summary> /// <summary>
/// Trigger a CustomEvent for this client /// Trigger a CustomEvent for this client
/// </summary> /// </summary>
/// <param name="hash">An unique identifier of the event, you can use <see cref="CustomEvents.Hash(string)"/> to get it from a string</param> /// <param name="flags"></param>
/// <param name="hash">An unique identifier of the event</param>
/// <param name="args">Arguments</param> /// <param name="args">Arguments</param>
public void SendCustomEvent(int hash, params object[] args) public void SendCustomEvent(CustomEventFlags flags,CustomEventHash hash, params object[] args)
{ {
if (!IsReady) if (!IsReady)
{ {
@ -183,7 +184,7 @@ namespace RageCoop.Server
{ {
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.CustomEvent() new Packets.CustomEvent(flags)
{ {
Hash = hash, Hash = hash,
Args = args Args = args
@ -196,37 +197,13 @@ namespace RageCoop.Server
Server.Logger?.Error(ex); Server.Logger?.Error(ex);
} }
} }
public void SendCustomEventQueued(CustomEventHash hash, params object[] args) {
/// <summary> SendCustomEvent(CustomEventFlags.Queued, hash, args);
/// Send a CustomEvent that'll be queued at client side and invoked from script thread
/// </summary>
/// <param name="hash"></param>
/// <param name="args"></param>
public void SendCustomEventQueued(int hash, params object[] args)
{
if (!IsReady)
{
Server.Logger?.Warning($"Player \"{Username}\" is not ready!");
} }
public void SendCustomEvent(CustomEventHash hash, params object[] args)
try
{ {
SendCustomEvent(CustomEventFlags.None, hash, args);
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.CustomEvent(null, true)
{
Hash = hash,
Args = args
}.Pack(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);
} }
catch (Exception ex)
{
Server.Logger?.Error(ex);
}
}
#endregion #endregion
} }
} }

View File

@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Version information // Version information
[assembly: AssemblyVersion("1.5.4.2")] [assembly: AssemblyVersion("1.5.4.5")]
[assembly: AssemblyFileVersion("1.5.4.2")] [assembly: AssemblyFileVersion("1.5.4.5")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )] [assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -28,6 +28,12 @@
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
<OutDir>..\bin\Release\Server</OutDir> <OutDir>..\bin\Release\Server</OutDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="icon.ico" /> <Content Include="icon.ico" />
</ItemGroup> </ItemGroup>

View File

@ -302,57 +302,50 @@ namespace RageCoop.Server.Scripting
{ {
var argsList = new List<object>(args); var argsList = new List<object>(args);
argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty, (ulong)hash }); argsList.InsertRange(0, new object[] { (byte)TypeCode.Empty, (ulong)hash });
SendCustomEventQueued(clients, CustomEvents.NativeCall, argsList.ToArray()); SendCustomEvent(CustomEventFlags.Queued, clients, CustomEvents.NativeCall, argsList.ToArray());
} }
/// <summary> /// <summary>
/// Send an event and data to the specified clients. Use <see cref="Client.SendCustomEvent(int,object[])"/> if you want to send event to individual client. /// Send an event and data to the specified clients.
/// </summary> /// </summary>
/// <param name="eventHash">An unique identifier of the event, you can use <see cref="CustomEvents.Hash(string)"/> to get it from a string</param> /// <param name="flags"></param>
/// <param name="eventHash">An unique identifier of the event/> to get it from a string</param>
/// <param name="args">The objects conataing your data, see <see cref="Scripting.CustomEventReceivedArgs.Args"/> for supported types.</param> /// <param name="args">The objects conataing your data, see <see cref="Scripting.CustomEventReceivedArgs.Args"/> for supported types.</param>
/// <param name="targets">The target clients to send. Leave it null to send to all clients</param> /// <param name="targets">The target clients to send. Leave it null to send to all clients</param>
public void SendCustomEvent(List<Client> targets, int eventHash, params object[] args) public void SendCustomEvent(CustomEventFlags flags, List<Client> targets, CustomEventHash eventHash, params object[] args)
{ {
var p = new Packets.CustomEvent(flags)
targets ??= new(Server.ClientsByNetHandle.Values);
var p = new Packets.CustomEvent()
{ {
Args = args, Args = args,
Hash = eventHash Hash = eventHash
}; };
if (targets == null)
{
Server.SendToAll(p, ConnectionChannel.Event, NetDeliveryMethod.ReliableOrdered);
}
else
{
foreach (var c in targets) foreach (var c in targets)
{ {
Server.Send(p, c, ConnectionChannel.Event, NetDeliveryMethod.ReliableOrdered); Server.Send(p, c, ConnectionChannel.Event, NetDeliveryMethod.ReliableOrdered);
} }
} }
/// <summary>
/// Send a CustomEvent that'll be queued at client side and invoked from script thread
/// </summary>
/// <param name="targets"></param>
/// <param name="eventHash"></param>
/// <param name="args"></param>
public void SendCustomEventQueued(List<Client> targets, int eventHash, params object[] args)
{
targets ??= new(Server.ClientsByNetHandle.Values);
var p = new Packets.CustomEvent(null, true)
{
Args = args,
Hash = eventHash
};
foreach (var c in targets)
{
Server.Send(p, c, ConnectionChannel.Event, NetDeliveryMethod.ReliableOrdered);
} }
public void SendCustomEvent(List<Client> targets, CustomEventHash eventHash, params object[] args)
{
SendCustomEvent(CustomEventFlags.None, targets, eventHash, args);
}
public void SendCustomEventQueued(List<Client> targets, CustomEventHash eventHash, params object[] args)
{
SendCustomEvent(CustomEventFlags.Queued, targets, eventHash, args);
} }
/// <summary> /// <summary>
/// Register an handler to the specifed event hash, one event can have multiple handlers. /// Register an handler to the specifed event hash, one event can have multiple handlers.
/// </summary> /// </summary>
/// <param name="hash">An unique identifier of the event, you can hash your event name with <see cref="CustomEvents.Hash(string)"/></param> /// <param name="hash">An unique identifier of the event></param>
/// <param name="handler">An handler to be invoked when the event is received from the server.</param> /// <param name="handler">An handler to be invoked when the event is received from the server.</param>
public void RegisterCustomEventHandler(int hash, Action<CustomEventReceivedArgs> handler) public void RegisterCustomEventHandler(CustomEventHash hash, Action<CustomEventReceivedArgs> handler)
{ {
lock (Events.CustomEventHandlers) lock (Events.CustomEventHandlers)
{ {
@ -363,15 +356,6 @@ namespace RageCoop.Server.Scripting
handlers.Add(handler); handlers.Add(handler);
} }
} }
/// <summary>
/// Register an event handler for specified event name.
/// </summary>
/// <param name="name">This value will be hashed to an int to reduce overhead</param>
/// <param name="handler">The handler to be invoked when the event is received</param>
public void RegisterCustomEventHandler(string name, Action<CustomEventReceivedArgs> handler)
{
RegisterCustomEventHandler(CustomEvents.Hash(name), handler);
}
/// <summary> /// <summary>

View File

@ -92,7 +92,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public virtual void Delete() public virtual void Delete()
{ {
Owner?.SendCustomEventQueued(CustomEvents.DeleteEntity, Handle); Owner?.SendCustomEvent(CustomEventFlags.Queued, CustomEvents.DeleteEntity, Handle);
} }
/// <summary> /// <summary>
@ -125,7 +125,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public override void Delete() public override void Delete()
{ {
Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerProp, ID); Server.API.SendCustomEvent(CustomEventFlags.Queued, null, CustomEvents.DeleteServerProp, ID);
Server.API.Entities.RemoveProp(ID); Server.API.Entities.RemoveProp(ID);
} }
@ -322,7 +322,7 @@ namespace RageCoop.Server.Scripting
/// </summary> /// </summary>
public void Delete() public void Delete()
{ {
Server.API.SendCustomEventQueued(null, CustomEvents.DeleteServerBlip, ID); Server.API.SendCustomEvent(CustomEventFlags.Queued, null, CustomEvents.DeleteServerBlip, ID);
Server.Entities.RemoveServerBlip(ID); Server.Entities.RemoveServerBlip(ID);
} }
@ -413,7 +413,7 @@ namespace RageCoop.Server.Scripting
} }
private void DoUpdate() private void DoUpdate()
{ {
Ped.Owner.SendCustomEventQueued(CustomEvents.UpdatePedBlip, Ped.Handle, (byte)Color, (ushort)Sprite, Scale); Ped.Owner.SendCustomEvent(CustomEventFlags.Queued, CustomEvents.UpdatePedBlip, Ped.Handle, (byte)Color, (ushort)Sprite, Scale);
} }
} }