Skip to content

Commit

Permalink
feat: simplify listeners code
Browse files Browse the repository at this point in the history
  • Loading branch information
roflmuffin committed Oct 14, 2023
1 parent c99845d commit 82495fa
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 176 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace CounterStrikeSharp.API.Core.Attributes;

[AttributeUsage(AttributeTargets.Delegate, Inherited = false)]
public class ListenerNameAttribute : Attribute
{
public string Name { get; init; }

public ListenerNameAttribute(string name)
{
Name = name;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using CounterStrikeSharp.API.Modules.Events;

namespace CounterStrikeSharp.API.Core.Attributes;
namespace CounterStrikeSharp.API.Core.Attributes.Registration;

[AttributeUsage(AttributeTargets.Method)]
public class ConsoleCommandAttribute : Attribute
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using CounterStrikeSharp.API.Modules.Events;

namespace CounterStrikeSharp.API.Core.Attributes;
namespace CounterStrikeSharp.API.Core.Attributes.Registration;

[AttributeUsage(AttributeTargets.Method)]
public class GameEventHandlerAttribute : Attribute
Expand Down
141 changes: 26 additions & 115 deletions managed/CounterStrikeSharp.API/Core/BasePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Events;
using CounterStrikeSharp.API.Modules.Listeners;
Expand Down Expand Up @@ -187,41 +189,38 @@ public void UnhookConVarChange(ConVar convar, ConVar.ConVarChangedCallback handl
CommandHandlers.Remove(handler);
}
}*/

private void AddListener<T>(string name, Listeners.SourceEventHandler<T> handler,
Action<T, ScriptContext> input = null, Action<T, ScriptContext> output = null) where T : EventArgs, new()
// Adds global listener, e.g. OnTick, OnClientConnect
protected void RegisterListener<T>(T handler) where T : Delegate
{
var wrappedHandler = new Action<ScriptContext>(context =>
var listenerName = typeof(T).GetCustomAttribute<ListenerNameAttribute>()?.Name;
if (string.IsNullOrEmpty(listenerName))
{
var eventArgs = new T();

// Before crossing the border, gets all the correct data from the context
input?.Invoke(eventArgs, context);
throw new Exception("Listener of type T is invalid and does not have a name attribute");
}

var parameterTypes = typeof(T).GetMethod("Invoke").GetParameters().Select(p => p.ParameterType).ToArray();

// Invoke the actual event.
handler?.Invoke(eventArgs);
Console.WriteLine($"Registering listener for {listenerName} with {parameterTypes.Length}");

var wrappedHandler = new Action<ScriptContext>(context =>
{
var args = new object[parameterTypes.Length];
for (int i = 0; i < parameterTypes.Length; i++)
{
args[i] = context.GetArgument(parameterTypes[i], i);
}

// After crossing the border, puts all the correct "return" data back onto the context
output?.Invoke(eventArgs, context);
handler.DynamicInvoke(args);
});

var subscriber = new CallbackSubscriber(handler, wrappedHandler, () => { RemoveListener(listenerName, handler); });

var subscriber = new CallbackSubscriber(handler, wrappedHandler, () => { RemoveListener(name, handler); });

NativeAPI.AddListener(name, subscriber.GetInputArgument());
NativeAPI.AddListener(listenerName, subscriber.GetInputArgument());
Listeners[handler] = subscriber;
}

public void RemoveListener<T>(string name, Listeners.SourceEventHandler<T> handler)
where T : EventArgs, new()
{
if (!Listeners.TryGetValue(handler, out var subscriber)) return;

NativeAPI.RemoveListener(name, subscriber.GetInputArgument());
FunctionReference.Remove(subscriber.GetReferenceIdentifier());
Listeners.Remove(handler);
}

public void RemoveListener(string name, Delegate handler)
protected void RemoveListener(string name, Delegate handler)
{
if (!Listeners.TryGetValue(handler, out var subscriber)) return;

Expand All @@ -236,95 +235,7 @@ public Timer AddTimer(float interval, Action callback, TimerFlags? flags = null)
Timers.Add(timer);
return timer;
}

public event Listeners.SourceEventHandler<Listeners.PlayerConnectArgs> OnClientConnect
{
add => AddListener("OnClientConnect", value,
(args, context) =>
{
args.PlayerIndex = context.GetArgument<int>(0);
args.Name = context.GetArgument<string>(1);
args.Address = context.GetArgument<string>(2);
}
);
remove => RemoveListener("OnClientConnect", value);
}

public event Listeners.SourceEventHandler<Listeners.PlayerArgs> OnClientConnected
{
add => AddListener("OnClientConnected", value,
(args, context) => args.PlayerSlot = context.GetArgument<int>(0));
remove => RemoveListener("OnClientConnected", value);
}

public event Listeners.SourceEventHandler<Listeners.PlayerArgs> OnClientDisconnect
{
add => AddListener("OnClientDisconnect", value,
(args, context) => args.PlayerSlot = context.GetArgument<int>(0));
remove => RemoveListener("OnClientDisconnect", value);
}

public event Listeners.SourceEventHandler<Listeners.MapStartArgs> OnMapStart
{
add => AddListener("OnMapStart", value,
(args, context) => args.MapName = context.GetArgument<string>(0));
remove => RemoveListener("OnMapStart", value);
}

public event Listeners.SourceEventHandler<EventArgs> OnTick
{
add => AddListener("OnTick", value);
remove => RemoveListener("OnTick", value);
}

public event Listeners.SourceEventHandler<EventArgs> OnMapEnd
{
add => AddListener("OnMapEnd", value);
remove => RemoveListener("OnMapEnd", value);
}

public event Listeners.SourceEventHandler<Listeners.PlayerArgs> OnClientDisconnectPost
{
add => AddListener("OnClientDisconnectPost", value,
(args, context) => args.PlayerSlot = context.GetArgument<int>(0));
remove => RemoveListener("OnClientDisconnectPost", value);
}

public event Listeners.SourceEventHandler<Listeners.PlayerArgs> OnClientPutInServer
{
add => AddListener("OnClientPutInServer", value,
(args, context) => args.PlayerSlot = context.GetArgument<int>(0));
remove => RemoveListener("OnClientPutInServer", value);
}

public event Listeners.SourceEventHandler<Listeners.EntityArgs> OnEntityCreated
{
add => AddListener("OnEntityCreated", value,
(args, context) =>
{
args.EntityIndex = context.GetArgument<int>(0);
args.Classname = context.GetArgument<string>(1);
});
remove => RemoveListener("OnEntityCreated", value);
}

public event Listeners.SourceEventHandler<Listeners.EntityArgs> OnEntitySpawned
{
add => AddListener("OnEntitySpawned", value,
(args, context) =>
{
args.EntityIndex = context.GetArgument<int>(0);
args.Classname = context.GetArgument<string>(1);
});
remove => RemoveListener("OnEntitySpawned", value);
}

public event Listeners.SourceEventHandler<Listeners.EntityArgs> OnEntityDeleted
{
add => AddListener("OnEntityDeleted", value,
(args, context) => { args.EntityIndex = context.GetArgument<int>(0); });
remove => RemoveListener("OnEntityDeleted", value);
}


public void RegisterAllAttributes(object instance)
{
Expand Down
33 changes: 33 additions & 0 deletions managed/CounterStrikeSharp.API/Core/Listeners.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

using System;
using CounterStrikeSharp.API.Core.Attributes;

namespace CounterStrikeSharp.API.Core
{
public partial class Listeners {

[ListenerName("OnTick")]
public delegate void OnTick();

[ListenerName("OnMapStart")]
public delegate void OnMapStart(string mapName);

[ListenerName("OnMapEnd")]
public delegate void OnMapEnd();

[ListenerName("OnClientConnect")]
public delegate void OnClientConnect(int index, string name, string ipAddress);

[ListenerName("OnClientConnected")]
public delegate void OnClientConnected(int index);

[ListenerName("OnClientPutInServer")]
public delegate void OnClientPutInServer(int index);

[ListenerName("OnClientDisconnect")]
public delegate void OnClientDisconnect(int index);

[ListenerName("OnClientDisconnectPost")]
public delegate void OnClientDisconnectPost(int index);
}
}
54 changes: 0 additions & 54 deletions managed/CounterStrikeSharp.API/Modules/Listeners/Listeners.cs

This file was deleted.

13 changes: 10 additions & 3 deletions managed/TestPlugin/TestPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Events;
using CounterStrikeSharp.API.Modules.Memory;
Expand All @@ -43,10 +44,16 @@ public override void Load(bool hotReload)
{
Log($"{@event.Userid}, {@event.X},{@event.Y},{@event.Z}");
});

// Hook global listeners defined by CounterStrikeSharp
OnMapStart += args => { Log($"Map {args.MapName} has started!"); };
OnClientConnect += args => { Log($"Client {args.Name} from {args.Address} has connected!"); };
RegisterListener<Listeners.OnMapStart>(mapName =>
{
Log($"Map {mapName} has started!");
});
RegisterListener<Listeners.OnClientConnect>((index, name, ip) =>
{
Log($"Client {name} from {ip} has connected!");
});

// You can use `ModuleDirectory` to get the directory of the plugin (for storing config files, saving database files etc.)
File.WriteAllText(Path.Join(ModuleDirectory, "example.txt"),
Expand Down
3 changes: 3 additions & 0 deletions src/scripting/listeners/general.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
OnTick:
OnMapStart: mapName:string
OnMapEnd:
5 changes: 5 additions & 0 deletions src/scripting/listeners/players.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
OnClientConnect: index:int, name:string, ipAddress:string
OnClientConnected: index:int
OnClientPutInServer: index:int
OnClientDisconnect: index:int
OnClientDisconnectPost: index:int
1 change: 1 addition & 0 deletions tooling/CodeGen.Natives/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static void Main(string[] args)
{
Generators.GenerateNatives();
Generators.GenerateGameEvents();
Generators.GenerateListeners();
}
}
}
Loading

0 comments on commit 82495fa

Please sign in to comment.