mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-08 08:56:34 -08:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d1891a3a8 | ||
|
|
6bc43444f7 | ||
|
|
f0c7869f4a | ||
|
|
3e38ed3c77 | ||
|
|
7e9e7c6665 | ||
|
|
9a018f295b | ||
|
|
8b725d435f |
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -17,3 +17,9 @@
|
||||
[submodule "libraries/GameTracking-CS2"]
|
||||
path = libraries/GameTracking-CS2
|
||||
url = https://github.com/SteamDatabase/GameTracking-CS2
|
||||
[submodule "libraries/DynoHook"]
|
||||
path = libraries/DynoHook
|
||||
url = git@github.com:qubka/DynoHook.git
|
||||
[submodule "libraries/asmjit"]
|
||||
path = libraries/asmjit
|
||||
url = git@github.com:asmjit/asmjit.git
|
||||
|
||||
@@ -8,7 +8,9 @@ include("makefiles/shared.cmake")
|
||||
add_subdirectory(libraries/spdlog)
|
||||
add_subdirectory(libraries/dyncall)
|
||||
add_subdirectory(libraries/funchook)
|
||||
add_subdirectory(libraries/DynoHook)
|
||||
|
||||
set_property(TARGET dynohook PROPERTY DYNO_ARCH_X86 64)
|
||||
set_property(TARGET funchook-static PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
SET(SOURCE_FILES
|
||||
@@ -81,6 +83,7 @@ SET(SOURCE_FILES
|
||||
src/core/managers/server_manager.h
|
||||
src/scripting/natives/natives_server.cpp
|
||||
libraries/nlohmann/json.hpp
|
||||
src/scripting/natives/natives_dynamichooks.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@
|
||||
"linux": "\\x8B\\x8F\\x40\\x0E\\x00\\x00\\x83\\xF9\\xFF\\x0F\\x84\\xD9\\x01"
|
||||
}
|
||||
},
|
||||
"CCSPlayerPawnBase_PostThink": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x8B\\xC4\\x48\\x89\\x48\\x08\\x55\\x53\\x56\\x57\\x41\\x56\\x48\\x8D\\xA8\\xD8\\xFE\\xFF\\xFF",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x49\\x89\\xFF\\x41\\x56\\x41\\x55\\x41\\x54\\x53\\x48\\x81\\xEC\\x2A\\x2A\\x2A\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x4C"
|
||||
}
|
||||
},
|
||||
"GiveNamedItem": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
@@ -125,6 +132,27 @@
|
||||
"linux": 147
|
||||
}
|
||||
},
|
||||
"CBaseEntity_TakeDamageOld": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x56\\x57\\x48\\x83\\xEC\\x58\\x48\\x8B\\x41\\x10",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x83\\xEC\\x38\\x4C\\x8D\\x2D\\x2A\\x2A\\x2A\\x2A\\x49\\x8B\\x7D\\x00\\x48\\x85\\xFF\\x0F\\x84\\x2A\\x2A\\x2A\\x2A"
|
||||
}
|
||||
},
|
||||
"CBaseTrigger_StartTouch": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x41\\x56\\x41\\x57\\x48\\x83\\xEC\\x58\\x48\\x8B\\x01",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x49\\x89\\xFD\\x41\\x54\\x53\\xBB"
|
||||
}
|
||||
},
|
||||
"CBaseTrigger_EndTouch": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x53\\x57\\x41\\x55\\x48\\x83\\xEC\\x40",
|
||||
"linux": "\\x55\\xBA\\xFF\\xFF\\xFF\\xFF\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x49"
|
||||
}
|
||||
},
|
||||
"GameEntitySystem": {
|
||||
"offsets": {
|
||||
"windows": 88,
|
||||
|
||||
@@ -17,8 +17,13 @@ The first parameter type must be a subclass of the `GameEvent` class. The names
|
||||
[GameEventHandler]
|
||||
public HookResult OnPlayerConnect(EventPlayerConnect @event, GameEventInfo info)
|
||||
{
|
||||
// Userid will give you a reference to a CCSPlayerController class
|
||||
Logger.LogInformation("Player {Name} has connected!", @event.Userid.PlayerName);
|
||||
// Userid will give you a reference to a CCSPlayerController class.
|
||||
// Before accessing any of its fields, you must first check if the Userid
|
||||
// handle is actually valid, otherwise you may run into runtime exceptions.
|
||||
// See the documentation section on Referencing Players for details.
|
||||
if (@event.Userid.IsValid) {
|
||||
Logger.LogInformation("Player {Name} has connected!", @event.Userid.PlayerName);
|
||||
}
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
1
libraries/DynoHook
Submodule
1
libraries/DynoHook
Submodule
Submodule libraries/DynoHook added at d7f8ebb059
1
libraries/asmjit
Submodule
1
libraries/asmjit
Submodule
Submodule libraries/asmjit added at 0dd16b0a98
@@ -16,14 +16,16 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -Wno-reorder")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse -msse -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics -v -fvisibility=default")
|
||||
|
||||
set(COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
${SOURCESDK_LIB}/linux64/libtier0.so
|
||||
${SOURCESDK_LIB}/linux64/tier1.a
|
||||
${SOURCESDK_LIB}/linux64/interfaces.a
|
||||
${SOURCESDK_LIB}/linux64/mathlib.a
|
||||
spdlog
|
||||
dynload_s
|
||||
dyncall_s
|
||||
distorm
|
||||
funchook-static
|
||||
SET(
|
||||
COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
${SOURCESDK_LIB}/linux64/libtier0.so
|
||||
${SOURCESDK_LIB}/linux64/tier1.a
|
||||
${SOURCESDK_LIB}/linux64/interfaces.a
|
||||
${SOURCESDK_LIB}/linux64/mathlib.a
|
||||
spdlog
|
||||
dynload_s
|
||||
dyncall_s
|
||||
distorm
|
||||
funchook-static
|
||||
dynohook
|
||||
)
|
||||
@@ -14,6 +14,8 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING
|
||||
# TODO: Use C++20 instead.
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
Set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
Set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
|
||||
set(SOURCESDK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libraries/hl2sdk-cs2)
|
||||
@@ -45,6 +47,7 @@ include_directories(
|
||||
libraries/spdlog/include
|
||||
libraries/tl
|
||||
libraries/funchook/include
|
||||
libraries/DynoHook/src
|
||||
libraries
|
||||
)
|
||||
|
||||
|
||||
@@ -17,4 +17,5 @@ set(COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
dyncall_s
|
||||
distorm
|
||||
funchook-static
|
||||
dynohook
|
||||
)
|
||||
@@ -157,6 +157,56 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static T DynamicHookGetReturn<T>(IntPtr hook, int datatype){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(hook);
|
||||
ScriptContext.GlobalScriptContext.Push(datatype);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x4F5B80D0);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (T)ScriptContext.GlobalScriptContext.GetResult(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
public static void DynamicHookSetReturn<T>(IntPtr hook, int datatype, T value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(hook);
|
||||
ScriptContext.GlobalScriptContext.Push(datatype);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xDB297E44);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static T DynamicHookGetParam<T>(IntPtr hook, int datatype, int paramindex){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(hook);
|
||||
ScriptContext.GlobalScriptContext.Push(datatype);
|
||||
ScriptContext.GlobalScriptContext.Push(paramindex);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x5F5ABDD5);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (T)ScriptContext.GlobalScriptContext.GetResult(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
public static void DynamicHookSetParam<T>(IntPtr hook, int datatype, int paramindex, T value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(hook);
|
||||
ScriptContext.GlobalScriptContext.Push(datatype);
|
||||
ScriptContext.GlobalScriptContext.Push(paramindex);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xA96CFBC1);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetMapName(){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -803,6 +853,30 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void HookFunction(IntPtr function, InputArgument hook, bool post){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(function);
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)hook);
|
||||
ScriptContext.GlobalScriptContext.Push(post);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xA6C8BA9B);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnhookFunction(IntPtr function, InputArgument hook, bool post){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(function);
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)hook);
|
||||
ScriptContext.GlobalScriptContext.Push(post);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x2051B00);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static T ExecuteVirtualFunction<T>(IntPtr function, object[] arguments){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
@@ -24,6 +25,17 @@ public partial class CCSPlayerController
|
||||
return VirtualFunctions.GiveNamedItem(PlayerPawn.Value.ItemServices.Handle, item, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public IntPtr GiveNamedItem(CsItem item)
|
||||
{
|
||||
string? itemString = EnumUtils.GetEnumMemberAttributeValue(item);
|
||||
if (string.IsNullOrWhiteSpace(itemString))
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
return this.GiveNamedItem(itemString);
|
||||
}
|
||||
|
||||
public void PrintToConsole(string message)
|
||||
{
|
||||
NativeAPI.PrintToConsole((int)EntityIndex.Value.Value, $"{message}\n\0");
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CPlayerPawnComponent
|
||||
{
|
||||
public PointerTo<CBasePlayerPawn> Pawn => new PointerTo<CBasePlayerPawn>(this.Handle + 0x30);
|
||||
}
|
||||
@@ -19806,6 +19806,63 @@ public partial class CTablet : CCSWeaponBase
|
||||
|
||||
}
|
||||
|
||||
public partial class CTakeDamageInfo : NativeObject
|
||||
{
|
||||
public CTakeDamageInfo (IntPtr pointer) : base(pointer) {}
|
||||
|
||||
// m_vecDamageForce
|
||||
public Vector DamageForce => Schema.GetDeclaredClass<Vector>(this.Handle, "CTakeDamageInfo", "m_vecDamageForce");
|
||||
|
||||
// m_vecDamagePosition
|
||||
public Vector DamagePosition => Schema.GetDeclaredClass<Vector>(this.Handle, "CTakeDamageInfo", "m_vecDamagePosition");
|
||||
|
||||
// m_vecReportedPosition
|
||||
public Vector ReportedPosition => Schema.GetDeclaredClass<Vector>(this.Handle, "CTakeDamageInfo", "m_vecReportedPosition");
|
||||
|
||||
// m_vecDamageDirection
|
||||
public Vector DamageDirection => Schema.GetDeclaredClass<Vector>(this.Handle, "CTakeDamageInfo", "m_vecDamageDirection");
|
||||
|
||||
// m_hInflictor
|
||||
public CHandle<CBaseEntity> Inflictor => Schema.GetDeclaredClass<CHandle<CBaseEntity>>(this.Handle, "CTakeDamageInfo", "m_hInflictor");
|
||||
|
||||
// m_hAttacker
|
||||
public CHandle<CBaseEntity> Attacker => Schema.GetDeclaredClass<CHandle<CBaseEntity>>(this.Handle, "CTakeDamageInfo", "m_hAttacker");
|
||||
|
||||
// m_hAbility
|
||||
public CHandle<CBaseEntity> Ability => Schema.GetDeclaredClass<CHandle<CBaseEntity>>(this.Handle, "CTakeDamageInfo", "m_hAbility");
|
||||
|
||||
// m_flDamage
|
||||
public ref float Damage => ref Schema.GetRef<float>(this.Handle, "CTakeDamageInfo", "m_flDamage");
|
||||
|
||||
// m_bitsDamageType
|
||||
public ref Int32 BitsDamageType => ref Schema.GetRef<Int32>(this.Handle, "CTakeDamageInfo", "m_bitsDamageType");
|
||||
|
||||
// m_iDamageCustom
|
||||
public ref Int32 DamageCustom => ref Schema.GetRef<Int32>(this.Handle, "CTakeDamageInfo", "m_iDamageCustom");
|
||||
|
||||
// m_iAmmoType
|
||||
public ref byte AmmoType => ref Schema.GetRef<byte>(this.Handle, "CTakeDamageInfo", "m_iAmmoType");
|
||||
|
||||
// m_flOriginalDamage
|
||||
public ref float OriginalDamage => ref Schema.GetRef<float>(this.Handle, "CTakeDamageInfo", "m_flOriginalDamage");
|
||||
|
||||
// m_bShouldBleed
|
||||
public ref bool ShouldBleed => ref Schema.GetRef<bool>(this.Handle, "CTakeDamageInfo", "m_bShouldBleed");
|
||||
|
||||
// m_bShouldSpark
|
||||
public ref bool ShouldSpark => ref Schema.GetRef<bool>(this.Handle, "CTakeDamageInfo", "m_bShouldSpark");
|
||||
|
||||
// m_nDamageFlags
|
||||
public ref TakeDamageFlags_t DamageFlags => ref Schema.GetRef<TakeDamageFlags_t>(this.Handle, "CTakeDamageInfo", "m_nDamageFlags");
|
||||
|
||||
// m_nNumObjectsPenetrated
|
||||
public ref Int32 NumObjectsPenetrated => ref Schema.GetRef<Int32>(this.Handle, "CTakeDamageInfo", "m_nNumObjectsPenetrated");
|
||||
|
||||
// m_bInTakeDamageFlow
|
||||
public ref bool InTakeDamageFlow => ref Schema.GetRef<bool>(this.Handle, "CTakeDamageInfo", "m_bInTakeDamageFlow");
|
||||
|
||||
}
|
||||
|
||||
public partial class CTankTargetChange : CPointEntity
|
||||
{
|
||||
public CTankTargetChange (IntPtr pointer) : base(pointer) {}
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Entities.Constants
|
||||
{
|
||||
public enum CsItem
|
||||
{
|
||||
//-----------------------------------------
|
||||
//EQUIPMENT
|
||||
//-----------------------------------------
|
||||
[EnumMember(Value = "item_kevlar")]
|
||||
Kevlar = 000,
|
||||
|
||||
[EnumMember(Value = "item_assaultsuit")]
|
||||
AssaultSuit = 001,
|
||||
KevlarHelmet = AssaultSuit,
|
||||
|
||||
[EnumMember(Value = "weapon_taser")]
|
||||
Taser = 002,
|
||||
Zeus = Taser,
|
||||
|
||||
[EnumMember(Value = "weapon_snowball")]
|
||||
Snowball = 003,
|
||||
|
||||
[EnumMember(Value = "weapon_shield")]
|
||||
Shield = 004,
|
||||
|
||||
[EnumMember(Value = "weapon_c4")]
|
||||
C4 = 005,
|
||||
Bomb = C4,
|
||||
|
||||
[EnumMember(Value = "weapon_healthshot")]
|
||||
Healthshot = 006,
|
||||
|
||||
[EnumMember(Value = "weapon_breachcharge")]
|
||||
BreachCharge = 007,
|
||||
|
||||
[EnumMember(Value = "weapon_tablet")]
|
||||
Tablet = 008,
|
||||
|
||||
[EnumMember(Value = "weapon_bumpmine")]
|
||||
Bumpmine = 009,
|
||||
|
||||
//-----------------------------------------
|
||||
//GRENADES
|
||||
//-----------------------------------------
|
||||
[EnumMember(Value = "weapon_smokegrenade")]
|
||||
Smoke = 100,
|
||||
SmokeGrenade = Smoke,
|
||||
|
||||
[EnumMember(Value = "weapon_flashbang")]
|
||||
Flashbang = 101,
|
||||
FlashbangGrenade = Flashbang,
|
||||
|
||||
[EnumMember(Value = "weapon_hegrenade")]
|
||||
HighExplosive = 102,
|
||||
HE = HighExplosive,
|
||||
HighExplosiveGrenade = HighExplosive,
|
||||
HEGrenade = HighExplosive,
|
||||
|
||||
[EnumMember(Value = "weapon_molotov")]
|
||||
Molotov = 103,
|
||||
|
||||
[EnumMember(Value = "weapon_incgrenade")]
|
||||
Incendiary = 104,
|
||||
IncGrenade = Incendiary,
|
||||
IncendiaryGrenade = Incendiary,
|
||||
|
||||
[EnumMember(Value = "weapon_decoy")]
|
||||
Decoy = 105,
|
||||
DecoyGrenade = Decoy,
|
||||
|
||||
//XRay-Grenade
|
||||
[EnumMember(Value = "weapon_tagrenade")]
|
||||
TacticalAwareness = 106,
|
||||
TAGrenade = TacticalAwareness,
|
||||
XRayGrenade = TacticalAwareness,
|
||||
|
||||
//Dangerzone: Better HighExplosive
|
||||
[EnumMember(Value = "weapon_frag")]
|
||||
Frag = 107,
|
||||
FragGrenade = Frag,
|
||||
|
||||
//Dangerzone: Better Molotov
|
||||
[EnumMember(Value = "weapon_firebomb")]
|
||||
Firebomb = 108,
|
||||
|
||||
//Dangerzone: Decoy but Footsteps instead of gun sounds
|
||||
[EnumMember(Value = "weapon_diversion")]
|
||||
Diversion = 109,
|
||||
|
||||
//-----------------------------------------
|
||||
//PISTOLS
|
||||
//-----------------------------------------
|
||||
[EnumMember(Value = "weapon_deagle")]
|
||||
Deagle = 200,
|
||||
DesertEagle = Deagle,
|
||||
|
||||
[EnumMember(Value = "weapon_glock")]
|
||||
Glock = 201,
|
||||
Glock18 = Glock,
|
||||
|
||||
[EnumMember(Value = "weapon_usp_silencer")]
|
||||
USPS = 202,
|
||||
USP = USPS,
|
||||
|
||||
[EnumMember(Value = "weapon_hkp2000")]
|
||||
HKP2000 = 203,
|
||||
P2000 = HKP2000,
|
||||
P2K = HKP2000,
|
||||
|
||||
[EnumMember(Value = "weapon_elite")]
|
||||
Elite = 204,
|
||||
DualBerettas = Elite,
|
||||
Dualies = Elite,
|
||||
|
||||
[EnumMember(Value = "weapon_tec9")]
|
||||
Tec9 = 205,
|
||||
|
||||
[EnumMember(Value = "weapon_p250")]
|
||||
P250 = 206,
|
||||
|
||||
[EnumMember(Value = "weapon_cz75a")]
|
||||
CZ = 207,
|
||||
CZ75 = CZ,
|
||||
|
||||
[EnumMember(Value = "weapon_fiveseven")]
|
||||
FiveSeven = 208,
|
||||
|
||||
[EnumMember(Value = "weapon_revolver")]
|
||||
Revolver = 209,
|
||||
R8 = Revolver,
|
||||
|
||||
//-----------------------------------------
|
||||
//MID-TIER
|
||||
//-----------------------------------------
|
||||
[EnumMember(Value = "weapon_mac10")]
|
||||
Mac10 = 300,
|
||||
|
||||
[EnumMember(Value = "weapon_mp9")]
|
||||
MP9 = 301,
|
||||
|
||||
[EnumMember(Value = "weapon_mp7")]
|
||||
MP7 = 302,
|
||||
|
||||
[EnumMember(Value = "weapon_p90")]
|
||||
P90 = 303,
|
||||
|
||||
[EnumMember(Value = "weapon_mp5sd")]
|
||||
MP5SD = 304,
|
||||
MP5 = MP5SD,
|
||||
|
||||
[EnumMember(Value = "weapon_bizon")]
|
||||
Bizon = 305,
|
||||
PPBizon = Bizon,
|
||||
|
||||
[EnumMember(Value = "weapon_ump45")]
|
||||
UMP45 = 306,
|
||||
UMP = UMP45,
|
||||
|
||||
[EnumMember(Value = "weapon_xm1014")]
|
||||
XM1014 = 307,
|
||||
|
||||
[EnumMember(Value = "weapon_nova")]
|
||||
Nova = 308,
|
||||
|
||||
[EnumMember(Value = "weapon_mag7")]
|
||||
MAG7 = 309,
|
||||
|
||||
[EnumMember(Value = "weapon_sawedoff")]
|
||||
SawedOff = 310,
|
||||
|
||||
[EnumMember(Value = "weapon_m249")]
|
||||
M249 = 311,
|
||||
|
||||
[EnumMember(Value = "weapon_negev")]
|
||||
Negev = 312,
|
||||
|
||||
//-----------------------------------------
|
||||
//RIFLES
|
||||
//-----------------------------------------
|
||||
[EnumMember(Value = "weapon_ak47")]
|
||||
AK47 = 400,
|
||||
|
||||
[EnumMember(Value = "weapon_m4a1_silencer")]
|
||||
M4A1S = 401,
|
||||
SilencedM4 = M4A1S,
|
||||
|
||||
[EnumMember(Value = "weapon_m4a1")]
|
||||
M4A1 = 402,
|
||||
M4A4 = M4A1,
|
||||
|
||||
[EnumMember(Value = "weapon_galilar")]
|
||||
GalilAR = 403,
|
||||
Galil = GalilAR,
|
||||
|
||||
[EnumMember(Value = "weapon_famas")]
|
||||
Famas = 404,
|
||||
|
||||
[EnumMember(Value = "weapon_sg556")]
|
||||
SG556 = 405,
|
||||
SG553 = SG556,
|
||||
Krieg = SG556,
|
||||
|
||||
[EnumMember(Value = "weapon_awp")]
|
||||
AWP = 406,
|
||||
|
||||
[EnumMember(Value = "weapon_aug")]
|
||||
AUG = 407,
|
||||
|
||||
[EnumMember(Value = "weapon_ssg08")]
|
||||
SSG08 = 408,
|
||||
Scout = SSG08,
|
||||
|
||||
[EnumMember(Value = "weapon_scar20")]
|
||||
SCAR20 = 409,
|
||||
AutoSniperCT = SCAR20,
|
||||
|
||||
[EnumMember(Value = "weapon_g3sg1")]
|
||||
G3SG1 = 410,
|
||||
AutoSniperT = G3SG1,
|
||||
|
||||
//-----------------------------------------
|
||||
//KNIFE
|
||||
//-----------------------------------------
|
||||
[EnumMember(Value = "weapon_knife_t")]
|
||||
DefaultKnifeT = 500,
|
||||
KnifeT = DefaultKnifeT,
|
||||
|
||||
[EnumMember(Value = "weapon_knife")]
|
||||
DefaultKnifeCT = 501,
|
||||
KnifeCT = DefaultKnifeCT,
|
||||
Knife = DefaultKnifeCT,
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -77,5 +77,22 @@ namespace CounterStrikeSharp.API.Modules.Memory
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DataType ToValidDataType(this Type type)
|
||||
{
|
||||
if (types.ContainsKey(type)) return types[type];
|
||||
|
||||
if (typeof(NativeObject).IsAssignableFrom(type))
|
||||
{
|
||||
return DataType.DATA_TYPE_POINTER;
|
||||
}
|
||||
|
||||
if (type.IsEnum && types.ContainsKey(Enum.GetUnderlyingType(type)))
|
||||
{
|
||||
return types[Enum.GetUnderlyingType(type)];
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Data type not supported:" + type.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
|
||||
public abstract class BaseMemoryFunction : NativeObject
|
||||
{
|
||||
private static Dictionary<string, IntPtr> _createdFunctions = new();
|
||||
|
||||
private static IntPtr CreateValveFunctionBySignature(string signature, DataType returnType,
|
||||
DataType[] argumentTypes)
|
||||
{
|
||||
if (!_createdFunctions.TryGetValue(signature, out var function))
|
||||
{
|
||||
try
|
||||
{
|
||||
function = NativeAPI.CreateVirtualFunctionBySignature(IntPtr.Zero, Addresses.ServerPath, signature,
|
||||
argumentTypes.Length, (int)returnType, argumentTypes.Cast<object>().ToArray());
|
||||
_createdFunctions[signature] = function;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
public BaseMemoryFunction(string signature, DataType returnType, DataType[] parameters) : base(
|
||||
CreateValveFunctionBySignature(signature, returnType, parameters))
|
||||
{
|
||||
}
|
||||
|
||||
public void Hook(Func<DynamicHook, HookResult> handler, HookMode mode)
|
||||
{
|
||||
NativeAPI.HookFunction(Handle, handler, mode == HookMode.Post);
|
||||
}
|
||||
|
||||
public void Unhook(Func<DynamicHook, HookResult> handler, HookMode mode)
|
||||
{
|
||||
NativeAPI.UnhookFunction(Handle, handler, mode == HookMode.Post);
|
||||
}
|
||||
|
||||
protected T InvokeInternal<T>(params object[] args)
|
||||
{
|
||||
return NativeAPI.ExecuteVirtualFunction<T>(Handle, args);
|
||||
}
|
||||
|
||||
protected void InvokeInternalVoid(params object[] args)
|
||||
{
|
||||
NativeAPI.ExecuteVirtualFunction<object>(Handle, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
|
||||
public class DynamicHook : NativeObject
|
||||
{
|
||||
public DynamicHook(IntPtr pointer) : base(pointer)
|
||||
{
|
||||
}
|
||||
|
||||
public T GetParam<T>(int index)
|
||||
{
|
||||
return NativeAPI.DynamicHookGetParam<T>(Handle, (int)typeof(T).ToValidDataType(), index);
|
||||
}
|
||||
|
||||
public T GetReturn<T>(int index)
|
||||
{
|
||||
return NativeAPI.DynamicHookGetReturn<T>(Handle, (int)typeof(T).ToValidDataType());
|
||||
}
|
||||
|
||||
public void SetParam<T>(int index, T value)
|
||||
{
|
||||
NativeAPI.DynamicHookSetParam(Handle, (int)typeof(T).ToValidDataType(), index, value);
|
||||
}
|
||||
|
||||
public void SetReturn<T>(T value)
|
||||
{
|
||||
NativeAPI.DynamicHookSetReturn(Handle, (int)typeof(T).ToValidDataType(), value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
|
||||
public class MemoryFunctionVoid : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID, Array.Empty<DataType>())
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
InvokeInternalVoid();
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[] { typeof(T1).ToValidDataType() })
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1)
|
||||
{
|
||||
InvokeInternalVoid(arg1);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[] { typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType() })
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[] { typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType() })
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4, T5> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
|
||||
typeof(T5).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4, T5, T6> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
|
||||
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4, T5, T6, T7> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
|
||||
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4, T5, T6, T7, T8> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
|
||||
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4, T5, T6, T7, T8, T9> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
|
||||
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType(),
|
||||
typeof(T9).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionVoid<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionVoid(string signature) : base(signature, DataType.DATA_TYPE_VOID,
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(),
|
||||
typeof(T3).ToValidDataType(), typeof(T4).ToValidDataType(),
|
||||
typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType(),
|
||||
typeof(T9).ToValidDataType(), typeof(T10).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public void Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
|
||||
{
|
||||
InvokeInternalVoid(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
using System;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
|
||||
public class MemoryFunctionWithReturn<TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
Array.Empty<DataType>())
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke()
|
||||
{
|
||||
return InvokeInternal<TResult>();
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[] { typeof(T1).ToValidDataType() })
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[] { typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType() })
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[] { typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType() })
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, T5, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType(), typeof(T5).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, T5, T6, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType(), typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, T5, T6, T7, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType(), typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, T5, T6, T7, T8, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType(), typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType(), typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType(), typeof(T9).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
|
||||
}
|
||||
}
|
||||
|
||||
public class MemoryFunctionWithReturn<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> : BaseMemoryFunction
|
||||
{
|
||||
public MemoryFunctionWithReturn(string signature) : base(signature, typeof(TResult).ToValidDataType(),
|
||||
new[]
|
||||
{
|
||||
typeof(T1).ToValidDataType(), typeof(T2).ToValidDataType(), typeof(T3).ToValidDataType(),
|
||||
typeof(T4).ToValidDataType(), typeof(T5).ToValidDataType(), typeof(T6).ToValidDataType(),
|
||||
typeof(T7).ToValidDataType(), typeof(T8).ToValidDataType(), typeof(T9).ToValidDataType(),
|
||||
typeof(T10).ToValidDataType()
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
public TResult Invoke(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10)
|
||||
{
|
||||
return InvokeInternal<TResult>(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,79 @@
|
||||
using System;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Memory;
|
||||
|
||||
public static class VirtualFunctions
|
||||
{
|
||||
public static Action<IntPtr, HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr> ClientPrint =
|
||||
VirtualFunction.CreateVoid<IntPtr, HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr>(
|
||||
public static MemoryFunctionVoid<IntPtr, HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr> ClientPrintFunc =
|
||||
new(
|
||||
GameData.GetSignature("ClientPrint"));
|
||||
|
||||
public static Action<IntPtr, HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr> ClientPrint =
|
||||
ClientPrintFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr> ClientPrintAllFunc =
|
||||
new(GameData.GetSignature("UTIL_ClientPrintAll"));
|
||||
|
||||
public static Action<HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr> ClientPrintAll =
|
||||
VirtualFunction.CreateVoid<HudDestination, string, IntPtr, IntPtr, IntPtr, IntPtr>(
|
||||
GameData.GetSignature("UTIL_ClientPrintAll"));
|
||||
ClientPrintAllFunc.Invoke;
|
||||
|
||||
// void (*FnGiveNamedItem)(void* itemService,const char* pchName, void* iSubType,void* pScriptItem, void* a5,void* a6) = nullptr;
|
||||
public static Func<IntPtr, string, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr> GiveNamedItem =
|
||||
VirtualFunction.Create<IntPtr, string, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr>(
|
||||
GameData.GetSignature("GiveNamedItem"));
|
||||
public static MemoryFunctionWithReturn<IntPtr, string, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr> GiveNamedItemFunc =
|
||||
new(GameData.GetSignature("GiveNamedItem"));
|
||||
|
||||
public static Action<IntPtr, byte> SwitchTeam =
|
||||
VirtualFunction.CreateVoid<IntPtr, byte>(GameData.GetSignature("CCSPlayerController_SwitchTeam"));
|
||||
public static Func<IntPtr, string, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr> GiveNamedItem = GiveNamedItemFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<IntPtr, byte> SwitchTeamFunc =
|
||||
new(GameData.GetSignature("CCSPlayerController_SwitchTeam"));
|
||||
|
||||
public static Action<IntPtr, byte> SwitchTeam = SwitchTeamFunc.Invoke;
|
||||
|
||||
// void(*UTIL_Remove)(CEntityInstance*);
|
||||
public static Action<IntPtr> UTIL_Remove = VirtualFunction.CreateVoid<IntPtr>(GameData.GetSignature("UTIL_Remove"));
|
||||
public static MemoryFunctionVoid<IntPtr> UTIL_RemoveFunc =
|
||||
new(GameData.GetSignature("UTIL_Remove"));
|
||||
|
||||
public static Action<IntPtr> UTIL_Remove = UTIL_RemoveFunc.Invoke;
|
||||
|
||||
// void(*CBaseModelEntity_SetModel)(CBaseModelEntity*, const char*);
|
||||
public static Action<IntPtr, string> SetModel = VirtualFunction.CreateVoid<IntPtr, string>(GameData.GetSignature("CBaseModelEntity_SetModel"));
|
||||
public static MemoryFunctionVoid<IntPtr, string> SetModelFunc =
|
||||
new(GameData.GetSignature("CBaseModelEntity_SetModel"));
|
||||
|
||||
public static Action<IntPtr, RoundEndReason, float> TerminateRound = VirtualFunction.CreateVoid<nint, RoundEndReason, float>(GameData.GetSignature("CCSGameRules_TerminateRound"));
|
||||
public static Action<IntPtr, string> SetModel = SetModelFunc.Invoke;
|
||||
|
||||
public static Func<string, int, IntPtr> UTIL_CreateEntityByName = VirtualFunction.Create<string, int, IntPtr>(GameData.GetSignature("UTIL_CreateEntityByName"));
|
||||
public static MemoryFunctionVoid<nint, RoundEndReason, float> TerminateRoundFunc =
|
||||
new(GameData.GetSignature("CCSGameRules_TerminateRound"));
|
||||
|
||||
public static Action<IntPtr, IntPtr> CBaseEntity_DispatchSpawn = VirtualFunction.CreateVoid<IntPtr, IntPtr>(GameData.GetSignature("CBaseEntity_DispatchSpawn"));
|
||||
public static Action<IntPtr, RoundEndReason, float> TerminateRound = TerminateRoundFunc.Invoke;
|
||||
|
||||
public static Action<IntPtr> CCSPlayerPawn_Respawn = VirtualFunction.CreateVoid<IntPtr>(GameData.GetSignature("CCSPlayerPawn_Respawn"));
|
||||
public static MemoryFunctionWithReturn<string, int, IntPtr> UTIL_CreateEntityByNameFunc =
|
||||
new(GameData.GetSignature("UTIL_CreateEntityByName"));
|
||||
|
||||
public static Func<string, int, IntPtr> UTIL_CreateEntityByName = UTIL_CreateEntityByNameFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<IntPtr, IntPtr> CBaseEntity_DispatchSpawnFunc =
|
||||
new(GameData.GetSignature("CBaseEntity_DispatchSpawn"));
|
||||
|
||||
public static Action<IntPtr, IntPtr> CBaseEntity_DispatchSpawn = CBaseEntity_DispatchSpawnFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<IntPtr> CCSPlayerPawn_RespawnFunc = new(GameData.GetSignature("CCSPlayerPawn_Respawn"));
|
||||
|
||||
public static Action<IntPtr> CCSPlayerPawn_Respawn = CCSPlayerPawn_RespawnFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOldFunc = new (GameData.GetSignature("CBaseEntity_TakeDamageOld"));
|
||||
public static Action<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOld = CBaseEntity_TakeDamageOldFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThinkFunc = new (GameData.GetSignature("CCSPlayerPawnBase_PostThink"));
|
||||
public static Action<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThink = CCSPlayerPawnBase_PostThinkFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<CBaseTrigger, CBaseEntity> CBaseTrigger_StartTouchFunc = new (GameData.GetSignature("CBaseTrigger_StartTouch"));
|
||||
public static Action<CBaseTrigger, CBaseEntity> CBaseTrigger_StartTouch = CBaseTrigger_StartTouchFunc.Invoke;
|
||||
|
||||
public static MemoryFunctionVoid<CBaseTrigger, CBaseEntity> CBaseTrigger_EndTouchFunc = new (GameData.GetSignature("CBaseTrigger_EndTouch"));
|
||||
public static Action<CBaseTrigger, CBaseEntity> CBaseTrigger_EndTouch = CBaseTrigger_EndTouchFunc.Invoke;
|
||||
}
|
||||
@@ -22,19 +22,20 @@ namespace CounterStrikeSharp.API.Modules.Utils
|
||||
public static char White = '\x01';
|
||||
public static char Darkred = '\x02';
|
||||
public static char Green = '\x04';
|
||||
public static char LightYellow = '\x03';
|
||||
public static char LightBlue = '\x03';
|
||||
public static char LightYellow = '\x09';
|
||||
public static char LightBlue = '\x0B';
|
||||
public static char Olive = '\x05';
|
||||
public static char Lime = '\x06';
|
||||
public static char Red = '\x07';
|
||||
public static char Purple = '\x03';
|
||||
public static char LightPurple = '\x03';
|
||||
public static char Purple = '\x0E';
|
||||
public static char Grey = '\x08';
|
||||
public static char Yellow = '\x09';
|
||||
public static char Gold = '\x10';
|
||||
public static char Silver = '\x0A';
|
||||
public static char Blue = '\x0B';
|
||||
public static char DarkBlue = '\x0C';
|
||||
public static char BlueGrey = '\x0D';
|
||||
public static char BlueGrey = '\x0A';
|
||||
public static char Magenta = '\x0E';
|
||||
public static char LightRed = '\x0F';
|
||||
}
|
||||
|
||||
36
managed/CounterStrikeSharp.API/Modules/Utils/EnumUtils.cs
Normal file
36
managed/CounterStrikeSharp.API/Modules/Utils/EnumUtils.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Utils
|
||||
{
|
||||
public static class EnumUtils
|
||||
{
|
||||
public static string? GetEnumMemberAttributeValue<T>(T enumValue)
|
||||
{
|
||||
var enumType = typeof(T);
|
||||
|
||||
if(!enumType.IsEnum || enumValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var enumString = enumValue.ToString();
|
||||
|
||||
if(string.IsNullOrWhiteSpace(enumString))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var memberInfo = enumType.GetMember(enumString);
|
||||
var enumMemberAttribute = memberInfo.FirstOrDefault()?.GetCustomAttributes(false).OfType<EnumMemberAttribute>().FirstOrDefault();
|
||||
if (enumMemberAttribute != null)
|
||||
{
|
||||
return enumMemberAttribute.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,9 @@ internal static partial class Program
|
||||
WriteEnum(builder, enumName, schemaEnum);
|
||||
}
|
||||
|
||||
// Manually whitelist some classes
|
||||
visited.Add("CTakeDamageInfo");
|
||||
|
||||
var visitedClassNames = new HashSet<string>();
|
||||
foreach (var (className, schemaClass) in allClasses)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,11 @@ public record SchemaFieldType
|
||||
this.Category = SchemaTypeCategory.Builtin;
|
||||
this.Name = "int32";
|
||||
}
|
||||
else if (this.Name == "AmmoIndex_t")
|
||||
{
|
||||
this.Category = SchemaTypeCategory.Builtin;
|
||||
this.Name = "uint8";
|
||||
}
|
||||
else if (this.Name == "CBitVec< 64 >")
|
||||
{
|
||||
this.Category = SchemaTypeCategory.FixedArray;
|
||||
@@ -68,6 +73,7 @@ public record SchemaFieldType
|
||||
"uint32" => "UInt32",
|
||||
"uint64" => "UInt64",
|
||||
"bool" => "bool",
|
||||
"char" => "char",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(name), name, $"Unknown built-in: {name}")
|
||||
};
|
||||
|
||||
@@ -85,6 +91,7 @@ public record SchemaFieldType
|
||||
SchemaAtomicCategory.T => $"{name.Split('<')[0]}<{inner!.CsTypeName}>",
|
||||
SchemaAtomicCategory.Collection => $"NetworkedVector<{inner!.CsTypeName}>",
|
||||
SchemaAtomicCategory.Unknown => "CBitVec",
|
||||
SchemaAtomicCategory.TT => "Unknown",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(atomic), atomic, $"Unsupported atomic: {atomic}")
|
||||
};
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Events;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Menu;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -74,6 +74,12 @@ namespace TestPlugin
|
||||
$"Test Plugin has been loaded, and the hot reload flag was {hotReload}, path is {ModulePath}");
|
||||
|
||||
Logger.LogWarning($"Max Players: {Server.MaxPlayers}");
|
||||
|
||||
VirtualFunctions.SwitchTeamFunc.Hook(hook =>
|
||||
{
|
||||
Logger.LogInformation("Switch team func called");
|
||||
return HookResult.Continue;
|
||||
}, HookMode.Pre);
|
||||
|
||||
SetupConvars();
|
||||
SetupGameEvents();
|
||||
@@ -98,6 +104,57 @@ namespace TestPlugin
|
||||
var virtualFunc = VirtualFunction.Create<IntPtr>(server.Pointer, 91);
|
||||
var result = virtualFunc() - 8;
|
||||
Logger.LogInformation("Result of virtual func call is {Pointer:X}", result);
|
||||
|
||||
VirtualFunctions.CBaseTrigger_StartTouchFunc.Hook(h =>
|
||||
{
|
||||
var trigger = h.GetParam<CBaseTrigger>(0);
|
||||
var entity = h.GetParam<CBaseEntity>(1);
|
||||
|
||||
Logger.LogInformation("Trigger {Trigger} touched by {Entity}", trigger.DesignerName, entity.DesignerName);
|
||||
|
||||
return HookResult.Continue;
|
||||
}, HookMode.Post);
|
||||
|
||||
VirtualFunctions.CBaseTrigger_EndTouchFunc.Hook(h =>
|
||||
{
|
||||
var trigger = h.GetParam<CBaseTrigger>(0);
|
||||
var entity = h.GetParam<CBaseEntity>(1);
|
||||
|
||||
Logger.LogInformation("Trigger left {Trigger} by {Entity}", trigger.DesignerName, entity.DesignerName);
|
||||
|
||||
return HookResult.Continue;
|
||||
}, HookMode.Post);
|
||||
|
||||
VirtualFunctions.UTIL_RemoveFunc.Hook(hook =>
|
||||
{
|
||||
var entityInstance = hook.GetParam<CEntityInstance>(0);
|
||||
Logger.LogInformation("Removed entity {EntityIndex}", entityInstance.EntityIndex.Value.Value);
|
||||
|
||||
return HookResult.Continue;
|
||||
}, HookMode.Post);
|
||||
|
||||
VirtualFunctions.CBaseEntity_TakeDamageOldFunc.Hook((h =>
|
||||
{
|
||||
var victim = h.GetParam<CEntityInstance>(0);
|
||||
var damageInfo = h.GetParam<CTakeDamageInfo>(1);
|
||||
|
||||
if (damageInfo.Inflictor.Value.DesignerName == "inferno")
|
||||
{
|
||||
var inferno = new CInferno(damageInfo.Inflictor.Value.Handle);
|
||||
Logger.LogInformation("Owner of inferno is {Owner}", inferno.OwnerEntity);
|
||||
|
||||
if (victim == inferno.OwnerEntity.Value)
|
||||
{
|
||||
damageInfo.Damage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
damageInfo.Damage = 150;
|
||||
}
|
||||
}
|
||||
|
||||
return HookResult.Continue;
|
||||
}), HookMode.Pre);
|
||||
}
|
||||
|
||||
private void SetupConvars()
|
||||
@@ -385,6 +442,18 @@ namespace TestPlugin
|
||||
command.ReplyToCommand(weapon.Value.DesignerName);
|
||||
}
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_colors", "List Chat Colors")]
|
||||
public void OnCommandColors(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
if (player == null) return;
|
||||
if (!player.PlayerPawn.IsValid) return;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
command.ReplyToCommand($" {(char)i}Color 0x{i:x}");
|
||||
}
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_pause", "Pause Game")]
|
||||
public void OnCommandPause(CCSPlayerController? player, CommandInfo command)
|
||||
@@ -400,6 +469,30 @@ namespace TestPlugin
|
||||
player.GiveNamedItem(command.ArgByIndex(1));
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_giveenum", "giveenum")]
|
||||
public void OnCommandGiveEnum(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
if (player == null) return;
|
||||
if (!player.IsValid) return;
|
||||
|
||||
player.GiveNamedItem(CsItem.M4A1);
|
||||
player.GiveNamedItem(CsItem.HEGrenade);
|
||||
player.GiveNamedItem(CsItem.Kevlar);
|
||||
player.GiveNamedItem(CsItem.Tec9);
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_give", "give")]
|
||||
public void OnCommandGiveItems(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
if (player == null) return;
|
||||
if (!player.IsValid) return;
|
||||
|
||||
player.GiveNamedItem("weapon_m4a1");
|
||||
player.GiveNamedItem("weapon_hegrenade");
|
||||
player.GiveNamedItem("item_kevlar");
|
||||
player.GiveNamedItem("weapon_tec9");
|
||||
}
|
||||
|
||||
private HookResult GenericEventHandler<T>(T @event, GameEventInfo info) where T : GameEvent
|
||||
{
|
||||
Logger.LogInformation("Event found {Pointer:X}, event name: {EventName}, dont broadcast: {DontBroadcast}",
|
||||
|
||||
@@ -32,41 +32,47 @@
|
||||
#include "core/log.h"
|
||||
#include "dyncall/dyncall/dyncall.h"
|
||||
|
||||
#include "pch.h"
|
||||
#include "dynohook/core.h"
|
||||
#include "dynohook/manager.h"
|
||||
#include "dynohook/conventions/x64/x64SystemVcall.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
DCCallVM* g_pCallVM = dcNewCallVM(4096);
|
||||
std::map<dyno::Hook*, ValveFunction*> g_HookMap;
|
||||
|
||||
// ============================================================================
|
||||
// >> GetDynCallConvention
|
||||
// ============================================================================
|
||||
int GetDynCallConvention(Convention_t eConv) {
|
||||
int GetDynCallConvention(Convention_t eConv)
|
||||
{
|
||||
switch (eConv) {
|
||||
case CONV_CUSTOM:
|
||||
return -1;
|
||||
case CONV_CDECL:
|
||||
return DC_CALL_C_DEFAULT;
|
||||
case CONV_THISCALL:
|
||||
case CONV_CUSTOM:
|
||||
return -1;
|
||||
case CONV_CDECL:
|
||||
return DC_CALL_C_DEFAULT;
|
||||
case CONV_THISCALL:
|
||||
#ifdef _WIN32
|
||||
return DC_CALL_C_X86_WIN32_THIS_MS;
|
||||
return DC_CALL_C_X86_WIN32_THIS_MS;
|
||||
#else
|
||||
return DC_CALL_C_X86_WIN32_THIS_GNU;
|
||||
return DC_CALL_C_X86_WIN32_THIS_GNU;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
case CONV_STDCALL:
|
||||
return DC_CALL_C_X86_WIN32_STD;
|
||||
case CONV_FASTCALL:
|
||||
return DC_CALL_C_X86_WIN32_FAST_MS;
|
||||
case CONV_STDCALL:
|
||||
return DC_CALL_C_X86_WIN32_STD;
|
||||
case CONV_FASTCALL:
|
||||
return DC_CALL_C_X86_WIN32_FAST_MS;
|
||||
#endif
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ValveFunction::ValveFunction(void* ulAddr,
|
||||
Convention_t callingConvention,
|
||||
std::vector<DataType_t> args,
|
||||
DataType_t returnType)
|
||||
: m_ulAddr(ulAddr) {
|
||||
ValveFunction::ValveFunction(void* ulAddr, Convention_t callingConvention,
|
||||
std::vector<DataType_t> args, DataType_t returnType)
|
||||
: m_ulAddr(ulAddr)
|
||||
{
|
||||
m_Args = args;
|
||||
|
||||
m_eReturnType = returnType;
|
||||
@@ -76,11 +82,8 @@ ValveFunction::ValveFunction(void* ulAddr,
|
||||
m_iCallingConvention = GetDynCallConvention(m_eCallingConvention);
|
||||
}
|
||||
|
||||
ValveFunction::ValveFunction(void* ulAddr,
|
||||
Convention_t callingConvention,
|
||||
DataType_t* args,
|
||||
int argCount,
|
||||
DataType_t returnType)
|
||||
ValveFunction::ValveFunction(void* ulAddr, Convention_t callingConvention, DataType_t* args,
|
||||
int argCount, DataType_t returnType)
|
||||
: m_ulAddr(ulAddr)
|
||||
|
||||
{
|
||||
@@ -93,26 +96,14 @@ ValveFunction::ValveFunction(void* ulAddr,
|
||||
|
||||
ValveFunction::~ValveFunction() {}
|
||||
|
||||
bool ValveFunction::IsCallable() {
|
||||
bool ValveFunction::IsCallable()
|
||||
{
|
||||
return (m_eCallingConvention != CONV_CUSTOM) && (m_iCallingConvention != -1);
|
||||
}
|
||||
|
||||
// bool ValveFunction::IsHookable() { return m_pCallingConvention != NULL; }
|
||||
//
|
||||
// bool ValveFunction::IsHooked() { return GetHookManager()->FindHook((void*)m_ulAddr) != NULL; }
|
||||
//
|
||||
// CHook* ValveFunction::GetHook() { return GetHookManager()->FindHook((void*)m_ulAddr); }
|
||||
|
||||
// ValveFunction* ValveFunction::GetTrampoline() {
|
||||
// CHook* pHook = GetHookManager()->FindHook((void*)m_ulAddr);
|
||||
// if (!pHook) return nullptr;
|
||||
//
|
||||
// return new ValveFunction((unsigned long)pHook->m_pTrampoline, m_eCallingConvention, m_Args,
|
||||
// m_eReturnType);
|
||||
// }
|
||||
|
||||
template <class ReturnType, class Function>
|
||||
ReturnType CallHelper(Function func, DCCallVM* vm, void* addr) {
|
||||
ReturnType CallHelper(Function func, DCCallVM* vm, void* addr)
|
||||
{
|
||||
ReturnType result;
|
||||
result = (ReturnType)func(vm, (void*)addr);
|
||||
return result;
|
||||
@@ -120,8 +111,10 @@ ReturnType CallHelper(Function func, DCCallVM* vm, void* addr) {
|
||||
|
||||
void CallHelperVoid(DCCallVM* vm, void* addr) { dcCallVoid(vm, (void*)addr); }
|
||||
|
||||
void ValveFunction::Call(ScriptContext& script_context, int offset) {
|
||||
if (!IsCallable()) return;
|
||||
void ValveFunction::Call(ScriptContext& script_context, int offset)
|
||||
{
|
||||
if (!IsCallable())
|
||||
return;
|
||||
|
||||
dcReset(g_pCallVM);
|
||||
dcMode(g_pCallVM, m_iCallingConvention);
|
||||
@@ -129,148 +122,195 @@ void ValveFunction::Call(ScriptContext& script_context, int offset) {
|
||||
for (size_t i = 0; i < m_Args.size(); i++) {
|
||||
int contextIndex = i + offset;
|
||||
switch (m_Args[i]) {
|
||||
case DATA_TYPE_BOOL:
|
||||
dcArgBool(g_pCallVM, script_context.GetArgument<bool>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
dcArgChar(g_pCallVM, script_context.GetArgument<char>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
dcArgChar(g_pCallVM, script_context.GetArgument<unsigned char>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
dcArgShort(g_pCallVM, script_context.GetArgument<short>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
dcArgShort(g_pCallVM, script_context.GetArgument<unsigned short>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
dcArgInt(g_pCallVM, script_context.GetArgument<int>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
dcArgInt(g_pCallVM, script_context.GetArgument<unsigned int>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
dcArgLong(g_pCallVM, script_context.GetArgument<long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
dcArgLong(g_pCallVM, script_context.GetArgument<unsigned long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
dcArgLongLong(g_pCallVM, script_context.GetArgument<long long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
dcArgLongLong(g_pCallVM,
|
||||
script_context.GetArgument<unsigned long long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
dcArgFloat(g_pCallVM, script_context.GetArgument<float>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
dcArgDouble(g_pCallVM, script_context.GetArgument<double>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
dcArgPointer(g_pCallVM, script_context.GetArgument<void*>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
dcArgPointer(g_pCallVM,
|
||||
(void*)script_context.GetArgument<const char*>(contextIndex));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function parameter type!");
|
||||
break;
|
||||
case DATA_TYPE_BOOL:
|
||||
dcArgBool(g_pCallVM, script_context.GetArgument<bool>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
dcArgChar(g_pCallVM, script_context.GetArgument<char>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
dcArgChar(g_pCallVM, script_context.GetArgument<unsigned char>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
dcArgShort(g_pCallVM, script_context.GetArgument<short>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
dcArgShort(g_pCallVM, script_context.GetArgument<unsigned short>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
dcArgInt(g_pCallVM, script_context.GetArgument<int>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
dcArgInt(g_pCallVM, script_context.GetArgument<unsigned int>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
dcArgLong(g_pCallVM, script_context.GetArgument<long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
dcArgLong(g_pCallVM, script_context.GetArgument<unsigned long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
dcArgLongLong(g_pCallVM, script_context.GetArgument<long long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
dcArgLongLong(g_pCallVM, script_context.GetArgument<unsigned long long>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
dcArgFloat(g_pCallVM, script_context.GetArgument<float>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
dcArgDouble(g_pCallVM, script_context.GetArgument<double>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
dcArgPointer(g_pCallVM, script_context.GetArgument<void*>(contextIndex));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
dcArgPointer(g_pCallVM, (void*)script_context.GetArgument<const char*>(contextIndex));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function parameter type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_eReturnType) {
|
||||
case DATA_TYPE_VOID:
|
||||
CallHelperVoid(g_pCallVM, m_ulAddr);
|
||||
break;
|
||||
case DATA_TYPE_BOOL:
|
||||
script_context.SetResult(CallHelper<bool>(dcCallBool, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
script_context.SetResult(CallHelper<char>(dcCallChar, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
script_context.SetResult(CallHelper<unsigned char>(dcCallChar, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
script_context.SetResult(CallHelper<short>(dcCallShort, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
script_context.SetResult(CallHelper<unsigned short>(dcCallShort, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
script_context.SetResult(CallHelper<int>(dcCallInt, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
script_context.SetResult(CallHelper<unsigned int>(dcCallInt, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
script_context.SetResult(CallHelper<long>(dcCallLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
script_context.SetResult(CallHelper<unsigned long>(dcCallLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
script_context.SetResult(CallHelper<long long>(dcCallLongLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
script_context.SetResult(
|
||||
CallHelper<unsigned long long>(dcCallLongLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
script_context.SetResult(CallHelper<float>(dcCallFloat, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
script_context.SetResult(CallHelper<double>(dcCallDouble, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
script_context.SetResult(CallHelper<void*>(dcCallPointer, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
script_context.SetResult(CallHelper<const char*>(dcCallPointer, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function return type!");
|
||||
break;
|
||||
case DATA_TYPE_VOID:
|
||||
CallHelperVoid(g_pCallVM, m_ulAddr);
|
||||
break;
|
||||
case DATA_TYPE_BOOL:
|
||||
script_context.SetResult(CallHelper<bool>(dcCallBool, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
script_context.SetResult(CallHelper<char>(dcCallChar, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
script_context.SetResult(CallHelper<unsigned char>(dcCallChar, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
script_context.SetResult(CallHelper<short>(dcCallShort, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
script_context.SetResult(CallHelper<unsigned short>(dcCallShort, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
script_context.SetResult(CallHelper<int>(dcCallInt, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
script_context.SetResult(CallHelper<unsigned int>(dcCallInt, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
script_context.SetResult(CallHelper<long>(dcCallLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
script_context.SetResult(CallHelper<unsigned long>(dcCallLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
script_context.SetResult(CallHelper<long long>(dcCallLongLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
script_context.SetResult(
|
||||
CallHelper<unsigned long long>(dcCallLongLong, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
script_context.SetResult(CallHelper<float>(dcCallFloat, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
script_context.SetResult(CallHelper<double>(dcCallDouble, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
script_context.SetResult(CallHelper<void*>(dcCallPointer, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
script_context.SetResult(CallHelper<const char*>(dcCallPointer, g_pCallVM, m_ulAddr));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function return type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
// CHook* HookFunctionHelper(void* addr, ICallingConvention* pConv) {
|
||||
// CHook* result;
|
||||
// result = GetHookManager()->HookFunction(addr, pConv);
|
||||
// return result;
|
||||
//}
|
||||
//
|
||||
// void ValveFunction::DeleteHook() {
|
||||
// CHook* pHook = GetHookManager()->FindHook((void*)m_ulAddr);
|
||||
// if (!pHook) return;
|
||||
//
|
||||
// // Set the calling convention to NULL, because DynamicHooks will delete it
|
||||
// // otherwise.
|
||||
// pHook->m_pCallingConvention = NULL;
|
||||
// GetHookManager()->UnhookFunction((void*)m_ulAddr);
|
||||
//}
|
||||
//
|
||||
// CHook* ValveFunction::AddHook(HookType_t eType, void* callable) {
|
||||
// if (!IsHookable()) return nullptr;
|
||||
//
|
||||
// CHook* pHook = GetHookManager()->FindHook((void*)m_ulAddr);
|
||||
//
|
||||
// if (!pHook) {
|
||||
// pHook = HookFunctionHelper((void*)m_ulAddr, m_pCallingConvention);
|
||||
//
|
||||
// // DynamicHooks will handle our convention from there, regardless if we
|
||||
// // allocated it or not.
|
||||
// m_bAllocatedCallingConvention = false;
|
||||
// }
|
||||
//
|
||||
// // Add the hook handler. If it's already added, it won't be added twice
|
||||
// pHook->AddCallback(eType, (HookHandlerFn*)(void*)callable);
|
||||
//
|
||||
// return pHook;
|
||||
//}
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
dyno::ReturnAction HookHandler(dyno::HookType hookType, dyno::Hook& hook)
|
||||
{
|
||||
auto vf = g_HookMap[&hook];
|
||||
|
||||
auto callback = hookType == dyno::HookType::Pre ? vf->m_precallback : vf->m_postcallback;
|
||||
|
||||
if (callback == nullptr) {
|
||||
return dyno::ReturnAction::Ignored;
|
||||
}
|
||||
|
||||
callback->Reset();
|
||||
callback->ScriptContext().Push(&hook);
|
||||
|
||||
for (auto fnMethodToCall : callback->GetFunctions()) {
|
||||
if (!fnMethodToCall)
|
||||
continue;
|
||||
fnMethodToCall(&callback->ScriptContextStruct());
|
||||
|
||||
auto result = callback->ScriptContext().GetResult<HookResult>();
|
||||
CSSHARP_CORE_TRACE("Received hook callback result of {}, hook mode {}", result,
|
||||
(int)hookType);
|
||||
|
||||
if (result >= HookResult::Handled) {
|
||||
return dyno::ReturnAction::Supercede;
|
||||
}
|
||||
}
|
||||
|
||||
return dyno::ReturnAction::Ignored;
|
||||
}
|
||||
|
||||
std::vector<dyno::DataObject> ConvertArgsToDynoHook(const std::vector<DataType_t>& dataTypes)
|
||||
{
|
||||
std::vector<dyno::DataObject> converted;
|
||||
converted.reserve(dataTypes.size());
|
||||
|
||||
for (DataType_t dt : dataTypes) {
|
||||
converted.push_back(dyno::DataObject(static_cast<dyno::DataType>(dt)));
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
void ValveFunction::AddHook(CallbackT callable, bool post)
|
||||
{
|
||||
dyno::HookManager& manager = dyno::HookManager::Get();
|
||||
dyno::Hook* hook = manager.hook((void*)m_ulAddr, [this] {
|
||||
return new dyno::x64SystemVcall(ConvertArgsToDynoHook(m_Args),
|
||||
static_cast<dyno::DataType>(this->m_eReturnType));
|
||||
});
|
||||
g_HookMap[hook] = this;
|
||||
hook->addCallback(dyno::HookType::Post, (dyno::HookHandler*)&HookHandler);
|
||||
hook->addCallback(dyno::HookType::Pre, (dyno::HookHandler*)&HookHandler);
|
||||
|
||||
if (post) {
|
||||
if (m_postcallback == nullptr) {
|
||||
m_postcallback = globals::callbackManager.CreateCallback("");
|
||||
}
|
||||
m_postcallback->AddListener(callable);
|
||||
} else {
|
||||
if (m_precallback == nullptr) {
|
||||
m_precallback = globals::callbackManager.CreateCallback("");
|
||||
}
|
||||
m_precallback->AddListener(callable);
|
||||
}
|
||||
}
|
||||
void ValveFunction::RemoveHook(CallbackT callable, bool post) {
|
||||
dyno::HookManager& manager = dyno::HookManager::Get();
|
||||
dyno::Hook* hook = manager.hook((void*)m_ulAddr, [this] {
|
||||
return new dyno::x64SystemVcall(ConvertArgsToDynoHook(m_Args),
|
||||
static_cast<dyno::DataType>(this->m_eReturnType));
|
||||
});
|
||||
g_HookMap[hook] = this;
|
||||
|
||||
if (post) {
|
||||
if (m_postcallback != nullptr) {
|
||||
m_postcallback->RemoveListener(callable);
|
||||
}
|
||||
} else {
|
||||
if (m_precallback != nullptr) {
|
||||
m_precallback->RemoveListener(callable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
@@ -32,6 +32,11 @@
|
||||
|
||||
#include "scripting/callback_manager.h"
|
||||
#include "scripting/script_engine.h"
|
||||
#include <map>
|
||||
|
||||
namespace dyno {
|
||||
class Hook;
|
||||
}
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
@@ -81,19 +86,13 @@ public:
|
||||
~ValveFunction();
|
||||
|
||||
bool IsCallable();
|
||||
// bool IsHookable();
|
||||
|
||||
// bool IsHooked();
|
||||
// CHook* GetHook();
|
||||
|
||||
// ValveFunction* GetTrampoline();
|
||||
|
||||
void SetOffset(int offset) { m_offset = offset; }
|
||||
void SetSignature(const char* signature) { m_signature = signature; }
|
||||
|
||||
void Call(ScriptContext& args, int offset = 0);
|
||||
// CHook* AddHook(HookType_t eType, void* callable);
|
||||
// void DeleteHook();
|
||||
void AddHook(CallbackT callable, bool post);
|
||||
void RemoveHook(CallbackT callable, bool post);
|
||||
|
||||
void* m_ulAddr;
|
||||
std::vector<DataType_t> m_Args;
|
||||
@@ -107,6 +106,8 @@ public:
|
||||
|
||||
int m_offset;
|
||||
const char* m_signature;
|
||||
ScriptCallback* m_precallback = nullptr;
|
||||
ScriptCallback* m_postcallback = nullptr;
|
||||
};
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
283
src/scripting/natives/natives_dynamichooks.cpp
Normal file
283
src/scripting/natives/natives_dynamichooks.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
#include "mm_plugin.h"
|
||||
#include "core/timer_system.h"
|
||||
#include "scripting/autonative.h"
|
||||
#include "scripting/script_engine.h"
|
||||
#include "core/function.h"
|
||||
#include "pch.h"
|
||||
#include "dynohook/core.h"
|
||||
#include "dynohook/manager.h"
|
||||
|
||||
// clang-format on
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
void DHookGetReturn(ScriptContext& script_context)
|
||||
{
|
||||
auto hook = script_context.GetArgument<dyno::Hook*>(0);
|
||||
auto dataType = script_context.GetArgument<DataType_t>(1);
|
||||
if (hook == nullptr) {
|
||||
script_context.ThrowNativeError("Invalid hook");
|
||||
}
|
||||
|
||||
switch (dataType) {
|
||||
case DATA_TYPE_BOOL:
|
||||
script_context.SetResult(hook->getReturnValue<bool>());
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
script_context.SetResult(hook->getReturnValue<char>());
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
script_context.SetResult(hook->getReturnValue<unsigned char>());
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
script_context.SetResult(hook->getReturnValue<short>());
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
script_context.SetResult(hook->getReturnValue<unsigned short>());
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
script_context.SetResult(hook->getReturnValue<int>());
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
script_context.SetResult(hook->getReturnValue<unsigned int>());
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
script_context.SetResult(hook->getReturnValue<long>());
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
script_context.SetResult(hook->getReturnValue<unsigned long>());
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
script_context.SetResult(hook->getReturnValue<long long>());
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
script_context.SetResult(hook->getReturnValue<unsigned long long>());
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
script_context.SetResult(hook->getReturnValue<float>());
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
script_context.SetResult(hook->getReturnValue<double>());
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
script_context.SetResult(hook->getReturnValue<void*>());
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
script_context.SetResult(hook->getReturnValue<const char*>());
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function parameter type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DHookSetReturn(ScriptContext& script_context)
|
||||
{
|
||||
auto hook = script_context.GetArgument<dyno::Hook*>(0);
|
||||
auto dataType = script_context.GetArgument<DataType_t>(1);
|
||||
if (hook == nullptr) {
|
||||
script_context.ThrowNativeError("Invalid hook");
|
||||
}
|
||||
|
||||
auto valueIndex = 2;
|
||||
|
||||
switch (dataType) {
|
||||
case DATA_TYPE_BOOL:
|
||||
hook->setReturnValue(script_context.GetArgument<bool>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
hook->setReturnValue(script_context.GetArgument<char>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
hook->setReturnValue(script_context.GetArgument<unsigned char>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
hook->setReturnValue(script_context.GetArgument<short>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
hook->setReturnValue(script_context.GetArgument<unsigned short>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
hook->setReturnValue(script_context.GetArgument<int>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
hook->setReturnValue(script_context.GetArgument<unsigned int>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
hook->setReturnValue(script_context.GetArgument<long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
hook->setReturnValue(script_context.GetArgument<unsigned long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
hook->setReturnValue(script_context.GetArgument<long long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
hook->setReturnValue(script_context.GetArgument<unsigned long long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
hook->setReturnValue(script_context.GetArgument<float>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
hook->setReturnValue(script_context.GetArgument<double>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
hook->setReturnValue(script_context.GetArgument<void*>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
hook->setReturnValue(script_context.GetArgument<const char*>(valueIndex));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function parameter type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DHookGetParam(ScriptContext& script_context)
|
||||
{
|
||||
auto hook = script_context.GetArgument<dyno::Hook*>(0);
|
||||
auto dataType = script_context.GetArgument<DataType_t>(1);
|
||||
auto paramIndex = script_context.GetArgument<int>(2);
|
||||
if (hook == nullptr) {
|
||||
script_context.ThrowNativeError("Invalid hook");
|
||||
}
|
||||
|
||||
switch (dataType) {
|
||||
case DATA_TYPE_BOOL:
|
||||
script_context.SetResult(hook->getArgument<bool>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
script_context.SetResult(hook->getArgument<char>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
script_context.SetResult(hook->getArgument<unsigned char>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
script_context.SetResult(hook->getArgument<short>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
script_context.SetResult(hook->getArgument<unsigned short>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
script_context.SetResult(hook->getArgument<int>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
script_context.SetResult(hook->getArgument<unsigned int>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
script_context.SetResult(hook->getArgument<long>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
script_context.SetResult(hook->getArgument<unsigned long>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
script_context.SetResult(hook->getArgument<long long>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
script_context.SetResult(hook->getArgument<unsigned long long>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
script_context.SetResult(hook->getArgument<float>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
script_context.SetResult(hook->getArgument<double>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
script_context.SetResult(hook->getArgument<void*>(paramIndex));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
script_context.SetResult(hook->getArgument<const char*>(paramIndex));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function parameter type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DHookSetParam(ScriptContext& script_context)
|
||||
{
|
||||
auto hook = script_context.GetArgument<dyno::Hook*>(0);
|
||||
auto dataType = script_context.GetArgument<DataType_t>(1);
|
||||
auto paramIndex = script_context.GetArgument<int>(2);
|
||||
if (hook == nullptr) {
|
||||
script_context.ThrowNativeError("Invalid hook");
|
||||
}
|
||||
|
||||
auto valueIndex = 3;
|
||||
|
||||
switch (dataType) {
|
||||
case DATA_TYPE_BOOL:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<bool>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_CHAR:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<char>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_UCHAR:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<unsigned char>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_SHORT:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<short>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_USHORT:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<unsigned short>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_INT:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<int>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_UINT:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<unsigned int>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<unsigned long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_LONG_LONG:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<long long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_ULONG_LONG:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<unsigned long long>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_FLOAT:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<float>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_DOUBLE:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<double>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_POINTER:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<void*>(valueIndex));
|
||||
break;
|
||||
case DATA_TYPE_STRING:
|
||||
hook->setArgument(paramIndex, script_context.GetArgument<const char*>(valueIndex));
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown function parameter type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(dynamichooks, {
|
||||
ScriptEngine::RegisterNativeHandler("DYNAMIC_HOOK_GET_RETURN", DHookGetReturn);
|
||||
ScriptEngine::RegisterNativeHandler("DYNAMIC_HOOK_SET_RETURN", DHookSetReturn);
|
||||
ScriptEngine::RegisterNativeHandler("DYNAMIC_HOOK_GET_PARAM", DHookGetParam);
|
||||
ScriptEngine::RegisterNativeHandler("DYNAMIC_HOOK_SET_PARAM", DHookSetParam);
|
||||
})
|
||||
} // namespace counterstrikesharp
|
||||
4
src/scripting/natives/natives_dynamichooks.yaml
Normal file
4
src/scripting/natives/natives_dynamichooks.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
DYNAMIC_HOOK_GET_RETURN: hook:pointer, datatype:int -> any
|
||||
DYNAMIC_HOOK_SET_RETURN: hook:pointer, datatype:int, value:any -> void
|
||||
DYNAMIC_HOOK_GET_PARAM: hook:pointer, datatype:int, paramIndex:int -> any
|
||||
DYNAMIC_HOOK_SET_PARAM: hook:pointer, datatype:int, paramIndex:int, value:any -> void
|
||||
@@ -24,11 +24,12 @@
|
||||
#include "core/log.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
std::vector<ValveFunction *> m_managed_ptrs;
|
||||
std::vector<ValveFunction*> m_managed_ptrs;
|
||||
|
||||
byte *ConvertToByteArray(const char *str, size_t *outLength) {
|
||||
size_t len = strlen(str) / 4; // Every byte is represented as \xHH
|
||||
byte *result = (byte *)malloc(len);
|
||||
byte* ConvertToByteArray(const char* str, size_t* outLength)
|
||||
{
|
||||
size_t len = strlen(str) / 4; // Every byte is represented as \xHH
|
||||
byte* result = (byte*)malloc(len);
|
||||
|
||||
for (size_t i = 0, j = 0; i < len; ++i, j += 4) {
|
||||
sscanf(str + j, "\\x%2hhx", &result[i]);
|
||||
@@ -38,24 +39,26 @@ byte *ConvertToByteArray(const char *str, size_t *outLength) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void *FindSignatureNative(ScriptContext &scriptContext) {
|
||||
auto moduleName = scriptContext.GetArgument<const char *>(0);
|
||||
auto bytesStr = scriptContext.GetArgument<const char *>(1);
|
||||
void* FindSignatureNative(ScriptContext& scriptContext)
|
||||
{
|
||||
auto moduleName = scriptContext.GetArgument<const char*>(0);
|
||||
auto bytesStr = scriptContext.GetArgument<const char*>(1);
|
||||
|
||||
return FindSignature(moduleName, bytesStr);
|
||||
}
|
||||
|
||||
ValveFunction *CreateVirtualFunctionBySignature(ScriptContext &script_context) {
|
||||
ValveFunction* CreateVirtualFunctionBySignature(ScriptContext& script_context)
|
||||
{
|
||||
auto ptr = script_context.GetArgument<unsigned long>(0);
|
||||
auto binary_name = script_context.GetArgument<const char *>(1);
|
||||
auto signature_hex_string = script_context.GetArgument<const char *>(2);
|
||||
auto binary_name = script_context.GetArgument<const char*>(1);
|
||||
auto signature_hex_string = script_context.GetArgument<const char*>(2);
|
||||
auto num_arguments = script_context.GetArgument<int>(3);
|
||||
auto return_type = script_context.GetArgument<DataType_t>(4);
|
||||
|
||||
auto* function_addr = FindSignature(binary_name, signature_hex_string);
|
||||
|
||||
if (function_addr == nullptr) {
|
||||
script_context.ThrowNativeError("Could not find signature");
|
||||
script_context.ThrowNativeError("Could not find signature %s", signature_hex_string);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -67,19 +70,21 @@ ValveFunction *CreateVirtualFunctionBySignature(ScriptContext &script_context) {
|
||||
auto function = new ValveFunction(function_addr, CONV_CDECL, args, return_type);
|
||||
function->SetSignature(signature_hex_string);
|
||||
|
||||
CSSHARP_CORE_TRACE("Created virtual function, pointer found at {}, signature {}", function_addr, signature_hex_string);
|
||||
CSSHARP_CORE_TRACE("Created virtual function, pointer found at {}, signature {}", function_addr,
|
||||
signature_hex_string);
|
||||
|
||||
m_managed_ptrs.push_back(function);
|
||||
return function;
|
||||
}
|
||||
|
||||
ValveFunction *CreateVirtualFunction(ScriptContext &script_context) {
|
||||
auto ptr = script_context.GetArgument<void *>(0);
|
||||
ValveFunction* CreateVirtualFunction(ScriptContext& script_context)
|
||||
{
|
||||
auto ptr = script_context.GetArgument<void*>(0);
|
||||
auto vtable_offset = script_context.GetArgument<int>(1);
|
||||
auto num_arguments = script_context.GetArgument<int>(2);
|
||||
auto return_type = script_context.GetArgument<DataType_t>(3);
|
||||
|
||||
void **vtable = *(void ***)ptr;
|
||||
void** vtable = *(void***)ptr;
|
||||
if (!vtable) {
|
||||
script_context.ThrowNativeError("Failed to get the virtual function table.");
|
||||
return nullptr;
|
||||
@@ -99,8 +104,37 @@ ValveFunction *CreateVirtualFunction(ScriptContext &script_context) {
|
||||
return function;
|
||||
}
|
||||
|
||||
void ExecuteVirtualFunction(ScriptContext &script_context) {
|
||||
auto function = script_context.GetArgument<ValveFunction *>(0);
|
||||
void HookFunction(ScriptContext& script_context)
|
||||
{
|
||||
auto function = script_context.GetArgument<ValveFunction*>(0);
|
||||
auto callback = script_context.GetArgument<CallbackT>(1);
|
||||
auto post = script_context.GetArgument<bool>(2);
|
||||
|
||||
if (!function) {
|
||||
script_context.ThrowNativeError("Invalid function pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
function->AddHook(callback, post);
|
||||
}
|
||||
|
||||
void UnhookFunction(ScriptContext& script_context)
|
||||
{
|
||||
auto function = script_context.GetArgument<ValveFunction*>(0);
|
||||
auto callback = script_context.GetArgument<CallbackT>(1);
|
||||
auto post = script_context.GetArgument<bool>(2);
|
||||
|
||||
if (!function) {
|
||||
script_context.ThrowNativeError("Invalid function pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
function->RemoveHook(callback, post);
|
||||
}
|
||||
|
||||
void ExecuteVirtualFunction(ScriptContext& script_context)
|
||||
{
|
||||
auto function = script_context.GetArgument<ValveFunction*>(0);
|
||||
|
||||
if (!function) {
|
||||
script_context.ThrowNativeError("Invalid function pointer");
|
||||
@@ -110,41 +144,15 @@ void ExecuteVirtualFunction(ScriptContext &script_context) {
|
||||
function->Call(script_context, 1);
|
||||
}
|
||||
|
||||
// void HookFunction(ScriptContext& script_context) {
|
||||
// auto function = script_context.GetArgument<ValveFunction*>(0);
|
||||
// auto entity_index = script_context.GetArgument<int>(1);
|
||||
// auto post = script_context.GetArgument<bool>(2);
|
||||
// auto callback = script_context.GetArgument<CallbackT>(3);
|
||||
//
|
||||
// if (!function) {
|
||||
// script_context.ThrowNativeError("Invalid function pointer");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// globals::hook_manager.AddHook(function, entity_index, callback, post);
|
||||
// }
|
||||
//
|
||||
// void UnhookFunction(ScriptContext& script_context) {
|
||||
// auto function = script_context.GetArgument<ValveFunction*>(0);
|
||||
// auto entity_index = script_context.GetArgument<int>(1);
|
||||
// auto post = script_context.GetArgument<bool>(2);
|
||||
// auto callback = script_context.GetArgument<CallbackT>(3);
|
||||
//
|
||||
// if (!function) {
|
||||
// script_context.ThrowNativeError("Invalid function pointer");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// globals::hook_manager.Unhook(function, entity_index, callback, post);
|
||||
// }
|
||||
|
||||
int GetNetworkVectorSize(ScriptContext &script_context) {
|
||||
int GetNetworkVectorSize(ScriptContext& script_context)
|
||||
{
|
||||
auto vec = script_context.GetArgument<CUtlVector<void*>*>(0);
|
||||
|
||||
return vec->Count();
|
||||
}
|
||||
|
||||
void* GetNetworkVectorElementAt(ScriptContext &script_context) {
|
||||
void* GetNetworkVectorElementAt(ScriptContext& script_context)
|
||||
{
|
||||
auto vec = script_context.GetArgument<CUtlVector<CEntityHandle>*>(0);
|
||||
auto index = script_context.GetArgument<int>(1);
|
||||
|
||||
@@ -156,10 +164,10 @@ REGISTER_NATIVES(memory, {
|
||||
ScriptEngine::RegisterNativeHandler("CREATE_VIRTUAL_FUNCTION_BY_SIGNATURE",
|
||||
CreateVirtualFunctionBySignature);
|
||||
ScriptEngine::RegisterNativeHandler("EXECUTE_VIRTUAL_FUNCTION", ExecuteVirtualFunction);
|
||||
// ScriptEngine::RegisterNativeHandler("HOOK_FUNCTION", HookFunction);
|
||||
// ScriptEngine::RegisterNativeHandler("UNHOOK_FUNCTION", UnhookFunction);
|
||||
ScriptEngine::RegisterNativeHandler("HOOK_FUNCTION", HookFunction);
|
||||
ScriptEngine::RegisterNativeHandler("UNHOOK_FUNCTION", UnhookFunction);
|
||||
ScriptEngine::RegisterNativeHandler("FIND_SIGNATURE", FindSignatureNative);
|
||||
ScriptEngine::RegisterNativeHandler("GET_NETWORK_VECTOR_SIZE", GetNetworkVectorSize);
|
||||
ScriptEngine::RegisterNativeHandler("GET_NETWORK_VECTOR_ELEMENT_AT", GetNetworkVectorElementAt);
|
||||
})
|
||||
} // namespace counterstrikesharp
|
||||
} // namespace counterstrikesharp
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
CREATE_VIRTUAL_FUNCTION: pointer:pointer,vtableOffset:int,numArguments:int,returnType:int,arguments:object[] -> pointer
|
||||
CREATE_VIRTUAL_FUNCTION_BY_SIGNATURE: pointer:pointer,binaryName:string,signature:string,numArguments:int,returnType:int,arguments:object[] -> pointer
|
||||
HOOK_FUNCTION: function:pointer, hook:callback, post:bool -> void
|
||||
UNHOOK_FUNCTION: function:pointer, hook:callback, post:bool -> void
|
||||
EXECUTE_VIRTUAL_FUNCTION: function:pointer,arguments:object[] -> any
|
||||
FIND_SIGNATURE: modulePath:string, signature:string -> pointer
|
||||
GET_NETWORK_VECTOR_SIZE: vec:pointer -> int
|
||||
|
||||
Reference in New Issue
Block a user