From 5a8252374360dd9bf1660f2122da2c7118eea941 Mon Sep 17 00:00:00 2001 From: Rushaway Date: Tue, 29 Sep 2026 20:35:16 +0200 Subject: [PATCH] feat: use newest SourceMod decls and methodmaps - Replace LoadGameConfigFile/GameConfGetAddress with the GameData methodmap - Replace DHookCreateDetour/DHookAddParam/DHookEnableDetour with DynamicDetour - Use DHookParam.Get instead of DHookGetParam - Drop the FloatMod/operator% shim (native since SourceMod 1.12) - Bump version to 1.0.4 and update Copilot instructions Closes #28 Co-Authored-By: Claude Opus 5.5 --- .github/copilot-instructions.md | 27 ++++++------- addons/sourcemod/scripting/FixFuncRotating.sp | 40 +++++++------------ 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 7a86f67..66bddf1 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -61,7 +61,7 @@ To trigger builds: - **Remove trailing whitespace** ### Memory Management -- Use `Handle` for DHooks detours (current pattern in codebase) +- Use the `DynamicDetour` methodmap for DHooks detours and the `GameData` methodmap for gamedata - **Important**: Use `delete` instead of `CloseHandle()` for newer SourceMod versions - Never check for null before `delete` - it's safe to call on null handles - For StringMap/ArrayList: Use `delete` instead of `.Clear()` to prevent memory leaks @@ -71,33 +71,37 @@ When working with DHooks in this codebase: ```sourcepawn // 1. Load gamedata -Handle hGameConf = LoadGameConfigFile("FixFuncRotating.games"); -if(hGameConf == INVALID_HANDLE) { +GameData hGameConf = new GameData("FixFuncRotating.games"); +if(hGameConf == null) { LogError("Couldn't load gamedata!"); return; } // 2. Get function address -Address pFunction = GameConfGetAddress(hGameConf, "FunctionName"); +Address pFunction = hGameConf.GetAddress("FunctionName"); if(!pFunction) { LogError("Could not find function address"); + delete hGameConf; return; } // 3. Create detour -Handle detour = DHookCreateDetour(pFunction, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity); +DynamicDetour detour = new DynamicDetour(pFunction, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity); // 4. Add parameters if needed -DHookAddParam(detour, HookParamType_Float); +detour.AddParam(HookParamType_Float); // 5. Enable detour -if(!DHookEnableDetour(detour, false, CallbackFunction)) { +if(!detour.Enable(Hook_Pre, CallbackFunction)) { LogError("Could not enable detour"); } + +// 6. Free gamedata +delete hGameConf; ``` ### Error Handling -- Always check gamedata loading with `INVALID_HANDLE` +- Always check gamedata loading against `null` - Validate all function addresses before creating detours - Log meaningful error messages using `LogError()` - Use proper return values (`MRES_Ignored`, etc.) @@ -188,12 +192,7 @@ The GitHub Actions pipeline validates: - `sm_dump_classes CFuncRotating`: Show entity properties (if available) ### Backward Compatibility -The plugin includes compatibility code for SourceMod < 1.13: -```sourcepawn -#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR < 13 -// FloatMod implementation for older versions -#endif -``` +The plugin targets SourceMod 1.12+ and relies on the native float `%` operator and the `GameData` / `DynamicDetour` methodmaps; no compatibility shims are kept for older versions. ## Performance Considerations - DHooks detours add minimal overhead when functions are called diff --git a/addons/sourcemod/scripting/FixFuncRotating.sp b/addons/sourcemod/scripting/FixFuncRotating.sp index 6fc05ff..ff38e01 100644 --- a/addons/sourcemod/scripting/FixFuncRotating.sp +++ b/addons/sourcemod/scripting/FixFuncRotating.sp @@ -11,24 +11,12 @@ public Plugin myinfo = name = "FixFuncRotating", author = "Cloud Strife", description = "Fixes func_rotating`s StartForward and StopAtStartPos inputs", - version = "1.0.3", + version = "1.0.4", url = "" }; -Handle g_CFuncRotating_StartForward = null; -Handle g_CFuncRotating_UpdateSpeed = null; - -#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR < 12 -stock float FloatMod(float num, float denom) -{ - return num - denom * RoundToFloor(num / denom); -} - -stock float operator%(float oper1, float oper2) -{ - return FloatMod(oper1, oper2); -} -#endif +DynamicDetour g_CFuncRotating_StartForward = null; +DynamicDetour g_CFuncRotating_UpdateSpeed = null; // Set m_bStopAtStartPos to false public MRESReturn CFuncRotating_InputStartForward(int entity) @@ -37,11 +25,11 @@ public MRESReturn CFuncRotating_InputStartForward(int entity) return MRES_Ignored; } -public MRESReturn CFuncRotating_UpdateSpeed(int entity, Handle hParams) +public MRESReturn CFuncRotating_UpdateSpeed(int entity, DHookParam hParams) { if(GetEntProp(entity, Prop_Data, "m_bStopAtStartPos", 1)) { - float flNewSpeed = view_as(DHookGetParam(hParams, 1)); + float flNewSpeed = hParams.Get(1); if(flNewSpeed <= 25) { float vecMoveAng[3], angStart[3], angRotation[3], avelpertick[3]; @@ -71,26 +59,26 @@ public MRESReturn CFuncRotating_UpdateSpeed(int entity, Handle hParams) public void OnPluginStart() { - Handle hGameConf = LoadGameConfigFile("FixFuncRotating.games"); - if(hGameConf == INVALID_HANDLE) + GameData hGameConf = new GameData("FixFuncRotating.games"); + if(hGameConf == null) { LogError("Couldn't load FixFuncRotating.games game config!"); return; } - Address pStartForward = GameConfGetAddress(hGameConf, "CFuncRotating::InputStartForward"); + Address pStartForward = hGameConf.GetAddress("CFuncRotating::InputStartForward"); if(pStartForward) { - g_CFuncRotating_StartForward = DHookCreateDetour(pStartForward, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity); + g_CFuncRotating_StartForward = new DynamicDetour(pStartForward, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity); - if(!DHookEnableDetour(g_CFuncRotating_StartForward, false, CFuncRotating_InputStartForward)) + if(!g_CFuncRotating_StartForward.Enable(Hook_Pre, CFuncRotating_InputStartForward)) { LogError("Could not enable detour for CFuncRotating::InputStartForward"); } } else LogError("Could not find CFuncRotating::InputStartForward address"); - Address pUpdateSpeed = GameConfGetAddress(hGameConf, "CFuncRotating::UpdateSpeed"); + Address pUpdateSpeed = hGameConf.GetAddress("CFuncRotating::UpdateSpeed"); if(!pUpdateSpeed) { LogError("Could not find CFuncRotating::UpdateSpeed address"); @@ -98,10 +86,10 @@ public void OnPluginStart() return; } - g_CFuncRotating_UpdateSpeed = DHookCreateDetour(pUpdateSpeed, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity); - DHookAddParam(g_CFuncRotating_UpdateSpeed, HookParamType_Float); + g_CFuncRotating_UpdateSpeed = new DynamicDetour(pUpdateSpeed, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity); + g_CFuncRotating_UpdateSpeed.AddParam(HookParamType_Float); - if(!DHookEnableDetour(g_CFuncRotating_UpdateSpeed, false, CFuncRotating_UpdateSpeed)) + if(!g_CFuncRotating_UpdateSpeed.Enable(Hook_Pre, CFuncRotating_UpdateSpeed)) { LogError("Could not enable detour for CFuncRotating::UpdateSpeed"); }