mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-05 23:58:24 -08:00
Game Event Broadcast Manipulation & Cancellation (#10)
This commit is contained in:
@@ -1,19 +1,21 @@
|
|||||||
---
|
BasedOnStyle: LLVM
|
||||||
Language: Cpp
|
|
||||||
BasedOnStyle: Google
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
Standard: c++11
|
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
TabWidth: 4
|
|
||||||
UseTab: Never
|
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Left
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
BinPackParameters: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
AlignEscapedNewlines: Left
|
SortIncludes: false
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
SpaceBeforeParens: ControlStatements
|
||||||
PackConstructorInitializers: Never
|
AllowAllArgumentsOnNextLine: true
|
||||||
BreakConstructorInitializersBeforeComma: false
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
IndentPPDirectives: BeforeHash
|
IndentCaseLabels: false
|
||||||
SortIncludes: Never
|
BreakBeforeBraces: Custom
|
||||||
...
|
BraceWrapping:
|
||||||
|
AfterClass: true
|
||||||
|
AfterStruct: true
|
||||||
|
AfterEnum: true
|
||||||
|
AfterUnion: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterFunction: true
|
||||||
|
IndentBraces: false
|
||||||
|
|||||||
45
.clang-tidy
45
.clang-tidy
@@ -83,6 +83,7 @@ Checks: >
|
|||||||
-readability-redundant-declaration,
|
-readability-redundant-declaration,
|
||||||
-readability-function-cognitive-complexity,
|
-readability-function-cognitive-complexity,
|
||||||
-readability-convert-member-functions-to-static,
|
-readability-convert-member-functions-to-static,
|
||||||
|
-readability-implicit-bool-conversion,
|
||||||
-bugprone-narrowing-conversions,
|
-bugprone-narrowing-conversions,
|
||||||
-bugprone-easily-swappable-parameters,
|
-bugprone-easily-swappable-parameters,
|
||||||
-bugprone-implicit-widening-of-multiplication-result,
|
-bugprone-implicit-widening-of-multiplication-result,
|
||||||
@@ -92,25 +93,25 @@ Checks: >
|
|||||||
WarningsAsErrors: "*"
|
WarningsAsErrors: "*"
|
||||||
|
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: google-readability-braces-around-statements.ShortStatementLines
|
google-readability-braces-around-statements.ShortStatementLines: '1'
|
||||||
value: '1'
|
google-readability-function-size.StatementThreshold: '800'
|
||||||
- key: google-readability-function-size.StatementThreshold
|
google-readability-namespace-comments.ShortNamespaceLines: '10'
|
||||||
value: '800'
|
google-readability-namespace-comments.SpacesBeforeComments: '2'
|
||||||
- key: google-readability-namespace-comments.ShortNamespaceLines
|
readability-identifier-naming.PrivateMemberPrefix: 'm_'
|
||||||
value: '10'
|
readability-identifier-naming.ProtectedMemberPrefix: 'm_'
|
||||||
- key: google-readability-namespace-comments.SpacesBeforeComments
|
readability-identifier-naming.MemberPrefix: 'm_'
|
||||||
value: '2'
|
readability-identifier-naming.ClassCase: CamelCase
|
||||||
- key: readability-identifier-naming.ClassCase
|
readability-identifier-naming.MemberCase: CamelCase
|
||||||
value: CamelCase
|
readability-identifier-naming.EnumCase: CamelCase
|
||||||
- key: readability-identifier-naming.MemberCase
|
readability-identifier-naming.FunctionCase: CamelCase
|
||||||
value: camelBack
|
readability-identifier-naming.ParameterCase: CamelCase
|
||||||
- key: readability-identifier-naming.EnumCase
|
readability-identifier-naming.UnionCase: CamelCase
|
||||||
value: CamelCase
|
readability-identifier-naming.VariableCase: CamelCase
|
||||||
- key: readability-identifier-naming.FunctionCase
|
readability-identifier-naming.LocalConstantPointerPrefix: 'p'
|
||||||
value: CamelCase
|
readability-identifier-naming.VariableHungarianPrefix: On
|
||||||
- key: readability-identifier-naming.ParameterCase
|
readability-identifier-naming.ParameterHungarianPrefix: On
|
||||||
value: camelBack
|
readability-identifier-naming.MemberHungarianPrefix: On
|
||||||
- key: readability-identifier-naming.UnionCase
|
readability-identifier-naming.PointerParameterHungarianPrefix: On
|
||||||
value: CamelCase
|
readability-identifier-naming.PointerParameterCase: CamelCase
|
||||||
- key: readability-identifier-naming.VariableCase
|
readability-identifier-naming.HungarianNotation.UserDefinedType.std::string: s
|
||||||
value: camelBack
|
|
||||||
|
|||||||
@@ -15,10 +15,12 @@ The first parameter type must be a subclass of the `GameEvent` class. The names
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
[GameEventHandler]
|
[GameEventHandler]
|
||||||
public void OnPlayerConnect(EventPlayerConnect @event)
|
public HookResult OnPlayerConnect(EventPlayerConnect @event, GameEventInfo info)
|
||||||
{
|
{
|
||||||
// Userid will give you a reference to a CCSPlayerController class
|
// Userid will give you a reference to a CCSPlayerController class
|
||||||
Log($"Player {@event.Userid.PlayerName} has connected!");
|
Log($"Player {@event.Userid.PlayerName} has connected!");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -29,9 +31,11 @@ It is also possible to bind event listeners in the `OnLoad` (or anywhere you hav
|
|||||||
```csharp
|
```csharp
|
||||||
public override void Load(bool hotReload)
|
public override void Load(bool hotReload)
|
||||||
{
|
{
|
||||||
RegisterEventHandler<EventRoundStart>(@event =>
|
RegisterEventHandler<EventRoundStart>((@event, info) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Round has started with time limit of {@event.Timelimit}");
|
Console.WriteLine($"Round has started with time limit of {@event.Timelimit}");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -41,3 +45,11 @@ public override void Load(bool hotReload)
|
|||||||
The specific subclass of `GameEvent` will provide strongly typed parameters from the event definition. e.g. `event.Timelimit` will be a `long` value, `event.UserId` will be a `CCSPlayerController` and so-on.
|
The specific subclass of `GameEvent` will provide strongly typed parameters from the event definition. e.g. `event.Timelimit` will be a `long` value, `event.UserId` will be a `CCSPlayerController` and so-on.
|
||||||
|
|
||||||
These event properties are mutable so you can update them as normal and they will update in the event instance.
|
These event properties are mutable so you can update them as normal and they will update in the event instance.
|
||||||
|
|
||||||
|
## Preventing Broadcast
|
||||||
|
|
||||||
|
You can modify a game event so that it does not get broadcast to clients by modifying the `bool info.DontBroadcast` property. e.g.
|
||||||
|
|
||||||
|
## Cancelling an Event
|
||||||
|
|
||||||
|
In a pre-event hook, you can prevent the event from continuing to other plugins by returning `HookResult.Handled` or `HookResult.Stop`.
|
||||||
|
|||||||
@@ -31,10 +31,12 @@ public class HelloWorldPlugin : BasePlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[GameEventHandler]
|
[GameEventHandler]
|
||||||
public void OnPlayerConnect(EventPlayerConnect @event)
|
public HookResult OnPlayerConnect(EventPlayerConnect @event, GameEventInfo info)
|
||||||
{
|
{
|
||||||
// Userid will give you a reference to a CCSPlayerController class
|
// Userid will give you a reference to a CCSPlayerController class
|
||||||
Log($"Player {@event.Userid.PlayerName} has connected!");
|
Log($"Player {@event.Userid.PlayerName} has connected!");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConsoleCommand("issue_warning", "Issue warning to player")]
|
[ConsoleCommand("issue_warning", "Issue warning to player")]
|
||||||
|
|||||||
@@ -30,5 +30,5 @@ SET(
|
|||||||
dynload_s
|
dynload_s
|
||||||
dyncall_s
|
dyncall_s
|
||||||
distorm
|
distorm
|
||||||
funchook-shared
|
funchook-static
|
||||||
)
|
)
|
||||||
@@ -103,26 +103,19 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
|
|
||||||
public readonly List<Timer> Timers = new List<Timer>();
|
public readonly List<Timer> Timers = new List<Timer>();
|
||||||
|
|
||||||
private void RegisterEventHandlerInternal<T>(string name, Action<T> handler, bool post = false)
|
public delegate HookResult GameEventHandler<T>(T @event, GameEventInfo info) where T : GameEvent;
|
||||||
where T : GameEvent, new()
|
|
||||||
{
|
|
||||||
var wrappedHandler = new Action<IntPtr>(pointer =>
|
|
||||||
{
|
|
||||||
var @event = new T
|
|
||||||
{
|
|
||||||
Handle = pointer
|
|
||||||
};
|
|
||||||
handler.Invoke(@event);
|
|
||||||
});
|
|
||||||
|
|
||||||
var subscriber = new CallbackSubscriber(handler, wrappedHandler,
|
private void RegisterEventHandlerInternal<T>(string name, GameEventHandler<T> handler, bool post = false)
|
||||||
|
where T : GameEvent
|
||||||
|
{
|
||||||
|
var subscriber = new CallbackSubscriber(handler, handler,
|
||||||
() => DeregisterEventHandler(name, handler, post));
|
() => DeregisterEventHandler(name, handler, post));
|
||||||
|
|
||||||
NativeAPI.HookEvent(name, subscriber.GetInputArgument(), post);
|
NativeAPI.HookEvent(name, subscriber.GetInputArgument(), post);
|
||||||
Handlers[handler] = subscriber;
|
Handlers[handler] = subscriber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterEventHandler<T>(Action<T> handler, bool post = false) where T : GameEvent, new()
|
public void RegisterEventHandler<T>(GameEventHandler<T> handler, bool post = false) where T : GameEvent
|
||||||
{
|
{
|
||||||
var name = typeof(T).GetCustomAttribute<EventNameAttribute>()?.Name;
|
var name = typeof(T).GetCustomAttribute<EventNameAttribute>()?.Name;
|
||||||
RegisterEventHandlerInternal(name, handler, post);
|
RegisterEventHandlerInternal(name, handler, post);
|
||||||
@@ -276,8 +269,8 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
var parameterType = eventHandler.GetParameters().First().ParameterType;
|
var parameterType = eventHandler.GetParameters().First().ParameterType;
|
||||||
var eventName = parameterType.GetCustomAttribute<EventNameAttribute>()?.Name;
|
var eventName = parameterType.GetCustomAttribute<EventNameAttribute>()?.Name;
|
||||||
|
|
||||||
var actionType = typeof(Action<>).MakeGenericType(parameterType);
|
var actionType = typeof(GameEventHandler<>).MakeGenericType(parameterType);
|
||||||
var action = eventHandler.CreateDelegate(actionType, instance);
|
var action = Delegate.CreateDelegate(actionType, instance, eventHandler);
|
||||||
|
|
||||||
var generic = method.MakeGenericMethod(parameterType);
|
var generic = method.MakeGenericMethod(parameterType);
|
||||||
generic.Invoke(this, new object[] { eventName, action, false });
|
generic.Invoke(this, new object[] { eventName, action, false });
|
||||||
|
|||||||
13
managed/CounterStrikeSharp.API/Core/GameEventInfo.cs
Normal file
13
managed/CounterStrikeSharp.API/Core/GameEventInfo.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace CounterStrikeSharp.API.Core;
|
||||||
|
|
||||||
|
public class GameEventInfo : NativeObject
|
||||||
|
{
|
||||||
|
public GameEventInfo(IntPtr pointer) : base(pointer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe ref bool DontBroadcast => ref Unsafe.AsRef<bool>((void*)Handle);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
9
managed/CounterStrikeSharp.API/Core/HookResult.cs
Normal file
9
managed/CounterStrikeSharp.API/Core/HookResult.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace CounterStrikeSharp.API.Core;
|
||||||
|
|
||||||
|
public enum HookResult
|
||||||
|
{
|
||||||
|
Continue = 0,
|
||||||
|
Changed = 1,
|
||||||
|
Handled = 3,
|
||||||
|
Stop = 4,
|
||||||
|
}
|
||||||
@@ -30,11 +30,9 @@ namespace CounterStrikeSharp.API.Modules.Events
|
|||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GameEvent
|
public class GameEvent : NativeObject
|
||||||
{
|
{
|
||||||
public IntPtr Handle { get; internal set; }
|
public GameEvent(IntPtr pointer) : base(pointer)
|
||||||
|
|
||||||
protected GameEvent()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,11 +40,6 @@ namespace CounterStrikeSharp.API.Modules.Events
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal GameEvent(IntPtr pointer)
|
|
||||||
{
|
|
||||||
Handle = pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EventName => NativeAPI.GetEventName(Handle);
|
public string EventName => NativeAPI.GetEventName(Handle);
|
||||||
|
|
||||||
public T Get<T>(string name)
|
public T Get<T>(string name)
|
||||||
|
|||||||
@@ -54,19 +54,34 @@ namespace TestPlugin
|
|||||||
VirtualFunction.CreateVoid<IntPtr, int>(GameData.GetSignature("CCSPlayerController_SwitchTeam"));
|
VirtualFunction.CreateVoid<IntPtr, int>(GameData.GetSignature("CCSPlayerController_SwitchTeam"));
|
||||||
// Register Game Event Handlers
|
// Register Game Event Handlers
|
||||||
RegisterEventHandler<EventPlayerConnect>(GenericEventHandler);
|
RegisterEventHandler<EventPlayerConnect>(GenericEventHandler);
|
||||||
RegisterEventHandler<EventPlayerJump>(@event =>
|
RegisterEventHandler<EventPlayerDeath>((@event, info) =>
|
||||||
|
{
|
||||||
|
// You can use `info.DontBroadcast` to set the dont broadcast flag on the event.
|
||||||
|
if (new Random().NextSingle() > 0.5f)
|
||||||
|
{
|
||||||
|
@event.Attacker.PrintToChat($"Skipping player_death broadcast at {Server.CurrentTime}");
|
||||||
|
info.DontBroadcast = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
|
});
|
||||||
|
RegisterEventHandler<EventPlayerJump>((@event, info) =>
|
||||||
{
|
{
|
||||||
sigVirtualFunc(@event.Userid.Handle, 2, "Test", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
sigVirtualFunc(@event.Userid.Handle, 2, "Test", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
});
|
});
|
||||||
RegisterEventHandler<EventPlayerSpawn>(@event =>
|
RegisterEventHandler<EventPlayerSpawn>((@event, info) =>
|
||||||
{
|
{
|
||||||
if (!@event.Userid.IsValid) return;
|
if (!@event.Userid.IsValid) return 0;
|
||||||
if (!@event.Userid.PlayerPawn.IsValid) return;
|
if (!@event.Userid.PlayerPawn.IsValid) return 0;
|
||||||
|
|
||||||
Log($"Player spawned with entity index: {@event.Userid.EntityIndex} & User ID: {@event.Userid.UserId}");
|
Log($"Player spawned with entity index: {@event.Userid.EntityIndex} & User ID: {@event.Userid.UserId}");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
});
|
});
|
||||||
RegisterEventHandler<EventPlayerBlind>(GenericEventHandler);
|
RegisterEventHandler<EventPlayerBlind>(GenericEventHandler);
|
||||||
RegisterEventHandler<EventBulletImpact>(@event =>
|
RegisterEventHandler<EventBulletImpact>((@event, info) =>
|
||||||
{
|
{
|
||||||
var player = @event.Userid;
|
var player = @event.Userid;
|
||||||
var pawn = player.PlayerPawn.Value;
|
var pawn = player.PlayerPawn.Value;
|
||||||
@@ -83,21 +98,26 @@ namespace TestPlugin
|
|||||||
|
|
||||||
VirtualFunctions.GiveNamedItem(pawn.ItemServices.Handle, "weapon_ak47", 0, 0, 0, 0);
|
VirtualFunctions.GiveNamedItem(pawn.ItemServices.Handle, "weapon_ak47", 0, 0, 0, 0);
|
||||||
|
|
||||||
Log($"Pawn Position: {pawn.CBodyComponent?.SceneNode?.AbsOrigin} @{pawn.CBodyComponent?.SceneNode.Rotation}");
|
Log(
|
||||||
|
$"Pawn Position: {pawn.CBodyComponent?.SceneNode?.AbsOrigin} @{pawn.CBodyComponent?.SceneNode.Rotation}");
|
||||||
|
|
||||||
char randomColourChar = (char)new Random().Next(0, 16);
|
char randomColourChar = (char)new Random().Next(0, 16);
|
||||||
printAllFunc(3, $"Random String with Random Colour: {randomColourChar}{new Random().Next()}", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
printAllFunc(3, $"Random String with Random Colour: {randomColourChar}{new Random().Next()}",
|
||||||
|
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
||||||
|
|
||||||
pawn.Health += 5;
|
pawn.Health += 5;
|
||||||
|
|
||||||
Log(
|
Log(
|
||||||
$"Found steamID {new SteamID(player.SteamID)} for player {player.PlayerName}:{pawn.Health}|{pawn.InBuyZone}");
|
$"Found steamID {new SteamID(player.SteamID)} for player {player.PlayerName}:{pawn.Health}|{pawn.InBuyZone}");
|
||||||
Log($"{@event.Userid}, {@event.X},{@event.Y},{@event.Z}");
|
Log($"{@event.Userid}, {@event.X},{@event.Y},{@event.Z}");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
});
|
});
|
||||||
RegisterEventHandler<EventRoundStart>(@event =>
|
RegisterEventHandler<EventRoundStart>((@event, info) =>
|
||||||
{
|
{
|
||||||
// Grab all cs_player_controller entities and set their cash value to $1337.
|
// Grab all cs_player_controller entities and set their cash value to $1337.
|
||||||
var playerEntities = Utilities.FindAllEntitiesByDesignerName<CCSPlayerController>("cs_player_controller");
|
var playerEntities =
|
||||||
|
Utilities.FindAllEntitiesByDesignerName<CCSPlayerController>("cs_player_controller");
|
||||||
Log($"cs_player_controller count: {playerEntities.Count<CCSPlayerController>()}");
|
Log($"cs_player_controller count: {playerEntities.Count<CCSPlayerController>()}");
|
||||||
|
|
||||||
foreach (var player in playerEntities)
|
foreach (var player in playerEntities)
|
||||||
@@ -116,6 +136,8 @@ namespace TestPlugin
|
|||||||
var gamerulesEnt = new CCSGameRules(entity.Handle);
|
var gamerulesEnt = new CCSGameRules(entity.Handle);
|
||||||
gamerulesEnt.CTTimeOutActive = true;
|
gamerulesEnt.CTTimeOutActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hook global listeners defined by CounterStrikeSharp
|
// Hook global listeners defined by CounterStrikeSharp
|
||||||
@@ -131,7 +153,6 @@ namespace TestPlugin
|
|||||||
|
|
||||||
RegisterListener<Listeners.OnEntitySpawned>(entity =>
|
RegisterListener<Listeners.OnEntitySpawned>(entity =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var designerName = entity.DesignerName;
|
var designerName = entity.DesignerName;
|
||||||
if (designerName != "smokegrenade_projectile") return;
|
if (designerName != "smokegrenade_projectile") return;
|
||||||
|
|
||||||
@@ -151,7 +172,6 @@ namespace TestPlugin
|
|||||||
$"Test file created by TestPlugin at {DateTime.Now}");
|
$"Test file created by TestPlugin at {DateTime.Now}");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Execute a server command as if typed into the server console.
|
// Execute a server command as if typed into the server console.
|
||||||
Server.ExecuteCommand("find \"cssharp\"");
|
Server.ExecuteCommand("find \"cssharp\"");
|
||||||
|
|
||||||
@@ -160,7 +180,8 @@ namespace TestPlugin
|
|||||||
(player, info) =>
|
(player, info) =>
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
Log($"CounterStrikeSharp - a test command was called by {new SteamID(player.SteamID).SteamId2} with {info.ArgString}");
|
Log(
|
||||||
|
$"CounterStrikeSharp - a test command was called by {new SteamID(player.SteamID).SteamId2} with {info.ArgString}");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Example vfunc call that usually gets the game event manager pointer
|
// Example vfunc call that usually gets the game event manager pointer
|
||||||
@@ -169,14 +190,14 @@ namespace TestPlugin
|
|||||||
var virtualFunc = VirtualFunction.Create<IntPtr>(server.Pointer, 91);
|
var virtualFunc = VirtualFunction.Create<IntPtr>(server.Pointer, 91);
|
||||||
var result = virtualFunc() - 8;
|
var result = virtualFunc() - 8;
|
||||||
Log($"Result of virtual func call is {result:X}");
|
Log($"Result of virtual func call is {result:X}");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[GameEventHandler]
|
[GameEventHandler]
|
||||||
public void OnPlayerConnect(EventPlayerConnect @event)
|
public HookResult OnPlayerConnect(EventPlayerConnect @event, GameEventInfo info)
|
||||||
{
|
{
|
||||||
Log($"Player {@event.Name} has connected!");
|
Log($"Player {@event.Name} has connected!");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConsoleCommand("cssharp_attribute", "This is a custom attribute event")]
|
[ConsoleCommand("cssharp_attribute", "This is a custom attribute event")]
|
||||||
@@ -185,9 +206,11 @@ namespace TestPlugin
|
|||||||
Log("cssharp_attribute called!");
|
Log("cssharp_attribute called!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenericEventHandler<T>(T @event) where T : GameEvent
|
private HookResult GenericEventHandler<T>(T @event, GameEventInfo info) where T : GameEvent
|
||||||
{
|
{
|
||||||
Log($"Event found {@event.Handle:X}, event name: {@event.EventName}");
|
Log($"Event found {@event.Handle:X}, event name: {@event.EventName} dont broadcast: {info.DontBroadcast}");
|
||||||
|
|
||||||
|
return HookResult.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Log(string message)
|
private void Log(string message)
|
||||||
|
|||||||
@@ -34,147 +34,173 @@
|
|||||||
#include "core/log.h"
|
#include "core/log.h"
|
||||||
#include "scripting/callback_manager.h"
|
#include "scripting/callback_manager.h"
|
||||||
|
|
||||||
SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool);
|
SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent*, bool);
|
||||||
|
|
||||||
namespace counterstrikesharp {
|
namespace counterstrikesharp {
|
||||||
|
|
||||||
EventManager::EventManager() {}
|
EventManager::EventManager() = default;
|
||||||
|
|
||||||
EventManager::~EventManager() {}
|
EventManager::~EventManager() = default;
|
||||||
|
|
||||||
void EventManager::OnStartup() {}
|
void EventManager::OnStartup() {}
|
||||||
|
|
||||||
void EventManager::OnAllInitialized() {
|
void EventManager::OnAllInitialized()
|
||||||
|
{
|
||||||
SH_ADD_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
SH_ADD_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
||||||
SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
||||||
SH_ADD_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
SH_ADD_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
||||||
SH_MEMBER(this, &EventManager::OnFireEvent_Post), true);
|
SH_MEMBER(this, &EventManager::OnFireEventPost), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::OnShutdown() {
|
void EventManager::OnShutdown()
|
||||||
|
{
|
||||||
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
||||||
SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
||||||
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, globals::gameEventManager,
|
||||||
SH_MEMBER(this, &EventManager::OnFireEvent_Post), true);
|
SH_MEMBER(this, &EventManager::OnFireEventPost), true);
|
||||||
|
|
||||||
globals::gameEventManager->RemoveListener(this);
|
globals::gameEventManager->RemoveListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::FireGameEvent(IGameEvent *event) {}
|
void EventManager::FireGameEvent(IGameEvent* pEvent) {}
|
||||||
|
|
||||||
bool EventManager::HookEvent(const char *name, CallbackT callback, bool post) {
|
bool EventManager::HookEvent(const char* szName, CallbackT fnCallback, bool bPost)
|
||||||
EventHook *p_hook;
|
{
|
||||||
|
EventHook* pHook;
|
||||||
|
|
||||||
if (!globals::gameEventManager->FindListener(this, name)) {
|
if (!globals::gameEventManager->FindListener(this, szName)) {
|
||||||
globals::gameEventManager->AddListener(this, name, true);
|
globals::gameEventManager->AddListener(this, szName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSSHARP_CORE_INFO("Hooking event: {0} with callback pointer: {1}", name, (void *)callback);
|
CSSHARP_CORE_INFO("Hooking event: {0} with callback pointer: {1}", szName, (void*)fnCallback);
|
||||||
|
|
||||||
auto search = m_hooks.find(name);
|
auto search = m_hooksMap.find(szName);
|
||||||
// If hook struct is not found
|
// If hook struct is not found
|
||||||
if (search == m_hooks.end()) {
|
if (search == m_hooksMap.end()) {
|
||||||
p_hook = new EventHook();
|
pHook = new EventHook();
|
||||||
|
|
||||||
if (post) {
|
if (bPost) {
|
||||||
p_hook->PostHook = globals::callbackManager.CreateCallback(name);
|
pHook->m_pPostHook = globals::callbackManager.CreateCallback(szName);
|
||||||
p_hook->PostHook->AddListener(callback);
|
pHook->m_pPostHook->AddListener(fnCallback);
|
||||||
} else {
|
} else {
|
||||||
p_hook->PreHook = globals::callbackManager.CreateCallback(name);
|
pHook->m_pPreHook = globals::callbackManager.CreateCallback(szName);
|
||||||
p_hook->PreHook->AddListener(callback);
|
pHook->m_pPreHook->AddListener(fnCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_hook->name = std::string(name);
|
pHook->m_Name = std::string(szName);
|
||||||
|
|
||||||
m_hooks[name] = p_hook;
|
m_hooksMap[szName] = pHook;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
p_hook = search->second;
|
pHook = search->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (post) {
|
if (bPost) {
|
||||||
if (!p_hook->PostHook) {
|
if (!pHook->m_pPostHook) {
|
||||||
p_hook->PostHook = globals::callbackManager.CreateCallback("");
|
pHook->m_pPostHook = globals::callbackManager.CreateCallback("");
|
||||||
}
|
}
|
||||||
|
|
||||||
p_hook->PostHook->AddListener(callback);
|
pHook->m_pPostHook->AddListener(fnCallback);
|
||||||
} else {
|
} else {
|
||||||
if (!p_hook->PreHook) {
|
if (!pHook->m_pPreHook) {
|
||||||
p_hook->PreHook = globals::callbackManager.CreateCallback("");
|
pHook->m_pPreHook = globals::callbackManager.CreateCallback("");
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_hook->PreHook->AddListener(callback);
|
pHook->m_pPreHook->AddListener(fnCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventManager::UnhookEvent(const char *name, CallbackT callback, bool post) {
|
bool EventManager::UnhookEvent(const char* szName, CallbackT fnCallback, bool bPost)
|
||||||
EventHook *p_hook;
|
{
|
||||||
ScriptCallback *p_callback;
|
EventHook* pHook;
|
||||||
|
ScriptCallback* pCallback;
|
||||||
|
|
||||||
auto search = m_hooks.find(name);
|
auto search = m_hooksMap.find(szName);
|
||||||
if (search == m_hooks.end()) {
|
if (search == m_hooksMap.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_hook = search->second;
|
pHook = search->second;
|
||||||
|
|
||||||
if (post) {
|
if (bPost) {
|
||||||
p_callback = p_hook->PostHook;
|
pCallback = pHook->m_pPostHook;
|
||||||
} else {
|
} else {
|
||||||
p_callback = p_hook->PreHook;
|
pCallback = pHook->m_pPreHook;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from function list
|
// Remove from function list
|
||||||
if (p_callback == nullptr) {
|
if (pCallback == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_callback = nullptr;
|
if (bPost) {
|
||||||
if (post) {
|
pHook->m_pPostHook = nullptr;
|
||||||
p_hook->PostHook = nullptr;
|
|
||||||
} else {
|
} else {
|
||||||
p_hook->PreHook = nullptr;
|
pHook->m_pPreHook = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Clean up callback if theres noone left attached.
|
// TODO: Clean up callback if theres noone left attached.
|
||||||
|
|
||||||
CSSHARP_CORE_INFO("Unhooking event: {0} with callback pointer: {1}", name, (void *)callback);
|
CSSHARP_CORE_INFO("Unhooking event: {0} with callback pointer: {1}", szName, (void*)fnCallback);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) {
|
bool EventManager::OnFireEvent(IGameEvent* pEvent, bool bDontBroadcast)
|
||||||
EventHook *p_hook;
|
{
|
||||||
const char *name;
|
const char* szName;
|
||||||
|
bool bLocalDontBroadcast = bDontBroadcast;
|
||||||
|
|
||||||
if (!pEvent) {
|
if (!pEvent) {
|
||||||
RETURN_META_VALUE(MRES_IGNORED, false);
|
RETURN_META_VALUE(MRES_IGNORED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
name = pEvent->GetName();
|
szName = pEvent->GetName();
|
||||||
|
|
||||||
auto search = m_hooks.find(name);
|
CSSHARP_CORE_TRACE("OnFireEvent {}", szName);
|
||||||
if (search != m_hooks.end()) {
|
|
||||||
auto p_callback = search->second->PreHook;
|
|
||||||
|
|
||||||
if (p_callback) {
|
auto I = m_hooksMap.find(szName);
|
||||||
CSSHARP_CORE_INFO("Pushing event `{0}` pointer: {1}", name, (void *)pEvent);
|
if (I != m_hooksMap.end()) {
|
||||||
p_callback->ScriptContext().Reset();
|
auto* pCallback = I->second->m_pPreHook;
|
||||||
p_callback->ScriptContext().SetArgument(0, pEvent);
|
|
||||||
p_callback->Execute();
|
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, false);
|
if (pCallback) {
|
||||||
|
CSSHARP_CORE_INFO("Pushing event `{0}` pointer: {1}, dont broadcast: {2}", szName,
|
||||||
|
(void*)pEvent, bDontBroadcast);
|
||||||
|
EventOverride override = {bDontBroadcast};
|
||||||
|
pCallback->Reset();
|
||||||
|
pCallback->ScriptContext().Push(pEvent);
|
||||||
|
pCallback->ScriptContext().Push(&override);
|
||||||
|
|
||||||
|
for (auto fnMethodToCall : pCallback->GetFunctions()) {
|
||||||
|
if (!fnMethodToCall)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fnMethodToCall(&pCallback->ScriptContextStruct());
|
||||||
|
auto result = pCallback->ScriptContext().GetResult<HookResult>();
|
||||||
|
|
||||||
|
bLocalDontBroadcast = override.m_bDontBroadcast;
|
||||||
|
|
||||||
|
if (result >= HookResult::Handled) {
|
||||||
|
globals::gameEventManager->FreeEvent(pEvent);
|
||||||
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bLocalDontBroadcast != bDontBroadcast)
|
||||||
|
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent,
|
||||||
|
(pEvent, bLocalDontBroadcast));
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) {
|
bool EventManager::OnFireEventPost(IGameEvent* pEvent, bool bDontBroadcast)
|
||||||
|
{
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
} // namespace counterstrikesharp
|
} // namespace counterstrikesharp
|
||||||
@@ -46,43 +46,48 @@ class CUtlString;
|
|||||||
namespace counterstrikesharp {
|
namespace counterstrikesharp {
|
||||||
class ScriptCallback;
|
class ScriptCallback;
|
||||||
class PluginFunction;
|
class PluginFunction;
|
||||||
} // namespace counterstrikesharp
|
} // namespace counterstrikesharp
|
||||||
|
|
||||||
struct EventHook {
|
struct EventHook
|
||||||
EventHook() {
|
{
|
||||||
PreHook = nullptr;
|
EventHook()
|
||||||
PostHook = nullptr;
|
{
|
||||||
|
m_pPreHook = nullptr;
|
||||||
|
m_pPostHook = nullptr;
|
||||||
}
|
}
|
||||||
counterstrikesharp::ScriptCallback *PreHook;
|
counterstrikesharp::ScriptCallback* m_pPreHook;
|
||||||
counterstrikesharp::ScriptCallback *PostHook;
|
counterstrikesharp::ScriptCallback* m_pPostHook;
|
||||||
std::string name;
|
std::string m_Name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventOverride {
|
||||||
|
bool m_bDontBroadcast;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace counterstrikesharp {
|
namespace counterstrikesharp {
|
||||||
|
|
||||||
class EventManager : public IGameEventListener2, public GlobalClass {
|
class EventManager : public IGameEventListener2, public GlobalClass
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
EventManager();
|
EventManager();
|
||||||
~EventManager();
|
~EventManager() override;
|
||||||
|
|
||||||
public: // GlobalClass
|
// GlobalClass
|
||||||
void OnShutdown() override;
|
void OnShutdown() override;
|
||||||
void OnAllInitialized() override;
|
void OnAllInitialized() override;
|
||||||
void OnStartup() override;
|
void OnStartup() override;
|
||||||
|
|
||||||
public: // IGameEventListener2
|
// IGameEventListener2
|
||||||
void FireGameEvent(IGameEvent *event) override;
|
void FireGameEvent(IGameEvent* pEvent) override;
|
||||||
|
|
||||||
public:
|
bool UnhookEvent(const char* szName, CallbackT fnCallback, bool bPost);
|
||||||
bool UnhookEvent(const char *name, CallbackT callback, bool post);
|
bool HookEvent(const char* szName, CallbackT fnCallback, bool bPost);
|
||||||
bool HookEvent(const char *name, CallbackT callback, bool post);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);
|
bool OnFireEvent(IGameEvent* pEvent, bool bDontBroadcast);
|
||||||
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
|
bool OnFireEventPost(IGameEvent* pEvent, bool bDontBroadcast);
|
||||||
|
|
||||||
private:
|
std::map<std::string, EventHook*> m_hooksMap;
|
||||||
std::map<std::string, EventHook *> m_hooks;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace counterstrikesharp
|
} // namespace counterstrikesharp
|
||||||
|
|||||||
@@ -20,95 +20,102 @@
|
|||||||
|
|
||||||
namespace counterstrikesharp {
|
namespace counterstrikesharp {
|
||||||
|
|
||||||
ScriptCallback::ScriptCallback(const char *name)
|
ScriptCallback::ScriptCallback(const char* szName) : m_root_context(fxNativeContext{})
|
||||||
: m_root_context(fxNativeContext{}) {
|
{
|
||||||
m_script_context_raw = ScriptContextRaw(m_root_context);
|
m_script_context_raw = ScriptContextRaw(m_root_context);
|
||||||
m_name = std::string(name);
|
m_name = std::string(szName);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptCallback::~ScriptCallback() { m_functions.clear(); }
|
ScriptCallback::~ScriptCallback() { m_functions.clear(); }
|
||||||
|
|
||||||
void ScriptCallback::AddListener(CallbackT plugin_function) {
|
void ScriptCallback::AddListener(CallbackT fnPluginFunction)
|
||||||
m_functions.push_back(plugin_function);
|
{
|
||||||
|
m_functions.push_back(fnPluginFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptCallback::RemoveListener(CallbackT pluginFunction) {
|
bool ScriptCallback::RemoveListener(CallbackT fnPluginFunction)
|
||||||
bool success;
|
{
|
||||||
|
bool bSuccess;
|
||||||
|
|
||||||
m_functions.erase(std::remove(m_functions.begin(), m_functions.end(), pluginFunction),
|
m_functions.erase(std::remove(m_functions.begin(), m_functions.end(), fnPluginFunction),
|
||||||
m_functions.end());
|
m_functions.end());
|
||||||
|
|
||||||
return success;
|
return bSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptCallback::Execute(bool resetContext) {
|
void ScriptCallback::Execute(bool bResetContext)
|
||||||
for (auto method_to_call : m_functions) {
|
{
|
||||||
if (method_to_call) {
|
for (auto fnMethodToCall : m_functions) {
|
||||||
method_to_call(&ScriptContextStruct());
|
if (fnMethodToCall) {
|
||||||
|
fnMethodToCall(&ScriptContextStruct());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resetContext) {
|
if (bResetContext) {
|
||||||
ResetContext();
|
Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptCallback::ResetContext() { ScriptContext().Reset(); }
|
void ScriptCallback::Reset() { ScriptContext().Reset(); }
|
||||||
|
|
||||||
CallbackManager::CallbackManager() {}
|
CallbackManager::CallbackManager() = default;
|
||||||
|
|
||||||
ScriptCallback *CallbackManager::CreateCallback(const char *name) {
|
ScriptCallback* CallbackManager::CreateCallback(const char* szName)
|
||||||
CSSHARP_CORE_TRACE("Creating callback {0}", name);
|
{
|
||||||
auto *callback = new ScriptCallback(name);
|
CSSHARP_CORE_TRACE("Creating callback {0}", szName);
|
||||||
m_managed.push_back(callback);
|
auto* pCallback = new ScriptCallback(szName);
|
||||||
|
m_managed.push_back(pCallback);
|
||||||
|
|
||||||
return callback;
|
return pCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptCallback *CallbackManager::FindCallback(const char *name) {
|
ScriptCallback* CallbackManager::FindCallback(const char* szName)
|
||||||
for (auto it = m_managed.begin(); it != m_managed.end(); ++it) {
|
{
|
||||||
ScriptCallback *marshal = *it;
|
for (auto* pMarshal : m_managed) {
|
||||||
if (strcmp(marshal->GetName().c_str(), name) == 0) {
|
if (strcmp(pMarshal->GetName().c_str(), szName) == 0) {
|
||||||
return marshal;
|
return pMarshal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallbackManager::ReleaseCallback(ScriptCallback *callback) {
|
void CallbackManager::ReleaseCallback(ScriptCallback* pCallback)
|
||||||
bool success;
|
{
|
||||||
auto it = std::remove_if(m_managed.begin(), m_managed.end(),
|
auto I = std::remove_if(m_managed.begin(), m_managed.end(),
|
||||||
[callback](ScriptCallback *i) { return callback == i; });
|
[pCallback](ScriptCallback* pI) { return pCallback == pI; });
|
||||||
|
|
||||||
if ((success = it != m_managed.end())) m_managed.erase(it, m_managed.end());
|
if (I != m_managed.end())
|
||||||
delete callback;
|
m_managed.erase(I, m_managed.end());
|
||||||
|
delete pCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallbackManager::TryAddFunction(const char *name, CallbackT pCallable) {
|
bool CallbackManager::TryAddFunction(const char* szName, CallbackT fnCallable)
|
||||||
auto *fwd = FindCallback(name);
|
{
|
||||||
if (fwd) {
|
auto* pCallback = FindCallback(szName);
|
||||||
fwd->AddListener(pCallable);
|
if (pCallback) {
|
||||||
|
pCallback->AddListener(fnCallable);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallbackManager::TryRemoveFunction(const char *name, CallbackT pCallable) {
|
bool CallbackManager::TryRemoveFunction(const char* szName, CallbackT fnCallable)
|
||||||
auto *fwd = FindCallback(name);
|
{
|
||||||
if (fwd) {
|
auto* pCallback = FindCallback(szName);
|
||||||
bool success = fwd->RemoveListener(pCallable);
|
if (pCallback) {
|
||||||
return success;
|
return pCallback->RemoveListener(fnCallable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallbackManager::PrintCallbackDebug() {
|
void CallbackManager::PrintCallbackDebug()
|
||||||
|
{
|
||||||
CSSHARP_CORE_INFO("----CALLBACKS----");
|
CSSHARP_CORE_INFO("----CALLBACKS----");
|
||||||
for (auto it : m_managed) {
|
for (auto* pCallback : m_managed) {
|
||||||
CSSHARP_CORE_INFO("{0} ({0})\n", it->GetName().c_str(), 1);
|
CSSHARP_CORE_INFO("{0} ({0})\n", pCallback->GetName().c_str(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace counterstrikesharp
|
} // namespace counterstrikesharp
|
||||||
@@ -24,40 +24,44 @@
|
|||||||
|
|
||||||
namespace counterstrikesharp {
|
namespace counterstrikesharp {
|
||||||
|
|
||||||
class ScriptCallback {
|
class ScriptCallback
|
||||||
public:
|
{
|
||||||
ScriptCallback(const char *name);
|
public:
|
||||||
|
ScriptCallback(const char* szName);
|
||||||
~ScriptCallback();
|
~ScriptCallback();
|
||||||
void AddListener(CallbackT plugin_function);
|
void AddListener(CallbackT fnPluginFunction);
|
||||||
bool RemoveListener(CallbackT plugin_function);
|
bool RemoveListener(CallbackT fnPluginFunction);
|
||||||
std::string GetName() { return m_name; }
|
std::string GetName() { return m_name; }
|
||||||
unsigned int GetFunctionCount() { return m_functions.size(); }
|
unsigned int GetFunctionCount() { return m_functions.size(); }
|
||||||
void Execute(bool resetContext = true);
|
std::vector<CallbackT> GetFunctions() { return m_functions; }
|
||||||
void ResetContext();
|
|
||||||
ScriptContextRaw &ScriptContext() { return m_script_context_raw; }
|
|
||||||
fxNativeContext &ScriptContextStruct() { return m_root_context; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
void Execute(bool bResetContext = true);
|
||||||
|
void Reset();
|
||||||
|
ScriptContextRaw& ScriptContext() { return m_script_context_raw; }
|
||||||
|
fxNativeContext& ScriptContextStruct() { return m_root_context; }
|
||||||
|
|
||||||
|
private:
|
||||||
std::vector<CallbackT> m_functions;
|
std::vector<CallbackT> m_functions;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
ScriptContextRaw m_script_context_raw;
|
ScriptContextRaw m_script_context_raw;
|
||||||
fxNativeContext m_root_context;
|
fxNativeContext m_root_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CallbackManager : public GlobalClass {
|
class CallbackManager : public GlobalClass
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
CallbackManager();
|
CallbackManager();
|
||||||
|
|
||||||
public:
|
ScriptCallback* CreateCallback(const char* szName);
|
||||||
ScriptCallback *CreateCallback(const char *name);
|
ScriptCallback* FindCallback(const char* szName);
|
||||||
ScriptCallback *FindCallback(const char *name);
|
void ReleaseCallback(ScriptCallback* pCallback);
|
||||||
void ReleaseCallback(ScriptCallback *callback);
|
bool TryAddFunction(const char* szName, CallbackT fnCallable);
|
||||||
bool TryAddFunction(const char *name, CallbackT pCallable);
|
bool TryRemoveFunction(const char* szName, CallbackT fnCallable);
|
||||||
bool TryRemoveFunction(const char *name, CallbackT pCallable);
|
|
||||||
void PrintCallbackDebug();
|
void PrintCallbackDebug();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ScriptCallback *> m_managed;
|
std::vector<ScriptCallback*> m_managed;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace counterstrikesharp
|
} // namespace counterstrikesharp
|
||||||
@@ -33,6 +33,13 @@
|
|||||||
|
|
||||||
namespace counterstrikesharp {
|
namespace counterstrikesharp {
|
||||||
|
|
||||||
|
enum HookResult {
|
||||||
|
Continue = 0,
|
||||||
|
Changed = 1,
|
||||||
|
Handled = 3,
|
||||||
|
Stop = 4,
|
||||||
|
};
|
||||||
|
|
||||||
inline uint32_t hash_string(const char *string) {
|
inline uint32_t hash_string(const char *string) {
|
||||||
unsigned long result = 5381;
|
unsigned long result = 5381;
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public partial class Generators
|
|||||||
[EventName(""{gameEvent.Name}"")]
|
[EventName(""{gameEvent.Name}"")]
|
||||||
public class Event{gameEvent.NamePascalCase} : GameEvent
|
public class Event{gameEvent.NamePascalCase} : GameEvent
|
||||||
{{
|
{{
|
||||||
public Event{gameEvent.NamePascalCase}() : base(){{}}
|
public Event{gameEvent.NamePascalCase}(IntPtr pointer) : base(pointer){{}}
|
||||||
public Event{gameEvent.NamePascalCase}(bool force) : base(""{gameEvent.Name}"", force){{}}
|
public Event{gameEvent.NamePascalCase}(bool force) : base(""{gameEvent.Name}"", force){{}}
|
||||||
|
|
||||||
{string.Join("\n", propertyDefinition)}
|
{string.Join("\n", propertyDefinition)}
|
||||||
|
|||||||
Reference in New Issue
Block a user