diff --git a/Forward-event-code-example/Config.cs b/Forward-event-code-example/Config.cs new file mode 100644 index 0000000..43d6c20 --- /dev/null +++ b/Forward-event-code-example/Config.cs @@ -0,0 +1,10 @@ +namespace Module +{ + internal static class ModuleConfig + { + public const string Name = "AmxmodxModule"; + public const string Version = ""; + public const string Author = ""; + public const string Url = ""; + } +} \ No newline at end of file diff --git a/Forward-event-code-example/Forward-event-code-example.csproj b/Forward-event-code-example/Forward-event-code-example.csproj new file mode 100644 index 0000000..5bf2bcf --- /dev/null +++ b/Forward-event-code-example/Forward-event-code-example.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + true + true + Module + $(MSBuildProjectName.Replace(".", ""))_amxx + + + + + + + + + + + + + + diff --git a/Forward-event-code-example/Global.cs b/Forward-event-code-example/Global.cs new file mode 100644 index 0000000..73cb467 --- /dev/null +++ b/Forward-event-code-example/Global.cs @@ -0,0 +1,171 @@ +using GoldSrc.Amxmodx.Native; +using GoldSrc.HLSDK; +using GoldSrc.HLSDK.Native; +using GoldSrc.MetaMod; +using GoldSrc.MetaMod.Native; + +using System.Runtime.InteropServices; + +#pragma warning disable CS8981 +using cell = int; +#pragma warning restore CS8981 +using size_t = uint; + +namespace Module +{ + public unsafe static class Global + { + public static DLL_FUNCTIONS g_EntityAPI_Table; + public static DLL_FUNCTIONS* g_pFunctionTable; + + public static DLL_FUNCTIONS g_EntityAPI_Post_Table; + public static DLL_FUNCTIONS* g_pFunctionTable_Post; + + public static NEW_DLL_FUNCTIONS g_NewFuncs_Table; + public static NEW_DLL_FUNCTIONS* g_pNewFunctionsTable; + + public static NEW_DLL_FUNCTIONS g_NewFuncs_Post_Table; + public static NEW_DLL_FUNCTIONS* g_pNewFunctionsTable_Post; + + public static enginefuncs_t g_EngineFuncs_Table; + public static enginefuncs_t* g_pengfuncsTable; + + public static enginefuncs_t g_EngineFuncs_Post_Table; + public static enginefuncs_t* g_pEngineFuncs_Post; + + public static enginefuncs_t g_engfuncs; + public static globalvars_t* gpGlobals; + + public static meta_globals_t* gpMetaGlobals; // metamod globals + public static gamedll_funcs_t* gpGamedllFuncs; // gameDLL function tables + public static mutil_funcs_t* gpMetaUtilFuncs; + + public static plugin_info_t* Plugin_info; + public static META_FUNCTIONS g_MetaFunctions_Table; + + public static amxx_module_info_t g_ModuleInfo; + + public static delegate* unmanaged[Cdecl] g_fn_RequestFunction; + + + static Global() + { + Plugin_info = (plugin_info_t*)Marshal.AllocHGlobal(sizeof(mutil_funcs_t)); + Plugin_info->ifvers = MetaModInfo.META_INTERFACE_VERSION.GetNativeString(); + Plugin_info->name = ModuleConfig.Name.GetNativeString(); + Plugin_info->version = ModuleConfig.Name.GetNativeString(); + Plugin_info->date = DateTime.Now.ToString().GetNativeString(); + Plugin_info->author = ModuleConfig.Author.GetNativeString(); + Plugin_info->url = ModuleConfig.Url.GetNativeString(); + Plugin_info->logtag = ModuleConfig.Name.GetNativeString(); + Plugin_info->loadable = PLUG_LOADTIME.PT_ANYTIME; + Plugin_info->unloadable = PLUG_LOADTIME.PT_ANYTIME; + + g_ModuleInfo.name = Plugin_info->name; + g_ModuleInfo.author = Plugin_info->author; + g_ModuleInfo.version = Plugin_info->version; + g_ModuleInfo.reload = 1; + g_ModuleInfo.library = ModuleConfig.Name.GetNativeString(); + g_ModuleInfo.libclass = "".GetNativeString(); + + } + + + public const int False = 0; + public const int True = 1; + + public const int AMXX_OK = 0; /* no error */ + public const int AMXX_IFVERS = 1; /* interface version */ + public const int AMXX_PARAM = 2; /* Invalid parameter */ + public const int AMXX_FUNC_NOT_PRESENT = 3; /* Function not present */ + + + public const int AMXX_GAME_OK = 0; /* This module can load on the current game mod. */ + public const int AMXX_GAME_BAD = 1; /* This module can not load on the current game mod. */ + + + #region 隐藏多余的API接口 + // amxx api + public static delegate* unmanaged[Cdecl] g_fn_AddNatives; + public static delegate* unmanaged[Cdecl] g_fn_AddNewNatives; + public static delegate* unmanaged[Cdecl] g_fn_BuildPathname; + public static delegate* unmanaged[Cdecl] g_fn_BuildPathnameR; + public static delegate* unmanaged[Cdecl] g_fn_GetAmxAddr; + public static delegate* unmanaged[Cdecl] g_fn_PrintSrvConsole; + public static delegate* unmanaged[Cdecl] g_fn_GetModname; + public static delegate* unmanaged[Cdecl] g_fn_GetAmxScriptName; + public static delegate* unmanaged[Cdecl] g_fn_GetAmxScript; + public static delegate* unmanaged[Cdecl] g_fn_FindAmxScriptByAmx; + public static delegate* unmanaged[Cdecl] g_fn_FindAmxScriptByName; + public static delegate* unmanaged[Cdecl] g_fn_SetAmxString; + public static delegate* unmanaged[Cdecl] g_fn_GetAmxString; + public static delegate* unmanaged[Cdecl] g_fn_GetAmxStringLen; + public static delegate* unmanaged[Cdecl] g_fn_FormatAmxString; + public static delegate* unmanaged[Cdecl] g_fn_CopyAmxMemory; + public static delegate* unmanaged[Cdecl] g_fn_Log; + public static delegate* unmanaged[Cdecl] g_fn_LogErrorFunc; + public static delegate* unmanaged[Cdecl] g_fn_RaiseAmxError; + public static delegate* unmanaged[Cdecl] g_fn_RegisterForward; + public static delegate* unmanaged[Cdecl] g_fn_ExecuteForward; + public static delegate* unmanaged[Cdecl] g_fn_PrepareCellArray; + public static delegate* unmanaged[Cdecl] g_fn_PrepareCharArray; + public static delegate* unmanaged[Cdecl] g_fn_PrepareCellArrayA; + public static delegate* unmanaged[Cdecl] g_fn_PrepareCharArrayA; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerValid; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerName; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerIP; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerIngame; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerBot; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerAuthorized; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerTime; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerPlayTime; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerFlags; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerCurweapon; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerTeam; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerTeamID; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerDeaths; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerMenu; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerKeys; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerAlive; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerFrags; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerConnecting; + public static delegate* unmanaged[Cdecl] g_fn_IsPlayerHLTV; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerArmor; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerHealth; + public static delegate* unmanaged[Cdecl] g_fn_AmxExec; + public static delegate* unmanaged[Cdecl] g_fn_AmxExecv; + public static delegate* unmanaged[Cdecl] g_fn_AmxAllot; + public static delegate* unmanaged[Cdecl] g_fn_AmxFindPublic; + public static delegate* unmanaged[Cdecl] g_fn_AmxFindNative; + public static delegate* unmanaged[Cdecl] g_fn_LoadAmxScript; + public static delegate* unmanaged[Cdecl] g_fn_UnloadAmxScript; + public static delegate* unmanaged[Cdecl] g_fn_RealToCell; + public static delegate* unmanaged[Cdecl] g_fn_CellToReal; + public static delegate* unmanaged[Cdecl] g_fn_RegisterSPForward; + public static delegate* unmanaged[Cdecl] g_fn_RegisterSPForwardByName; + public static delegate* unmanaged[Cdecl] g_fn_UnregisterSPForward; + public static delegate* unmanaged[Cdecl] g_fn_MergeDefinition_File; + public static delegate* unmanaged[Cdecl] g_fn_Format; + public static delegate* unmanaged[Cdecl] g_fn_RegisterFunction; + public static delegate* unmanaged[Cdecl] g_fn_AmxPush; + public static delegate* unmanaged[Cdecl] g_fn_SetTeamInfo; + public static delegate* unmanaged[Cdecl], void> g_fn_RegAuthFunc; + public static delegate* unmanaged[Cdecl], void> g_fn_UnregAuthFunc; + public static delegate* unmanaged[Cdecl] g_fn_FindLibrary; + public static delegate* unmanaged[Cdecl] g_fn_AddLibraries; + public static delegate* unmanaged[Cdecl] g_fn_RemoveLibraries; + public static delegate* unmanaged[Cdecl] g_fn_OverrideNatives; + public static delegate* unmanaged[Cdecl] g_fn_GetLocalInfo; + public static delegate* unmanaged[Cdecl] g_fn_AmxReRegister; + public static delegate* unmanaged[Cdecl] g_fn_RegisterFunctionEx; + public static delegate* unmanaged[Cdecl] g_fn_MessageBlock; + public static delegate* unmanaged[Cdecl] g_fn_GetPlayerEdict; + public static delegate* unmanaged[Cdecl] g_fn_PlayerPropAddr; + #endregion + + + + //添加amxx接口镜像 + public static delegate* unmanaged[Cdecl] g_fn_skill_get_skill_level; + } +} diff --git a/Forward-event-code-example/Module.cs b/Forward-event-code-example/Module.cs new file mode 100644 index 0000000..4b841c8 --- /dev/null +++ b/Forward-event-code-example/Module.cs @@ -0,0 +1,510 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using GoldSrc.Amxmodx; +using GoldSrc.Amxmodx.Native; +using GoldSrc.HLSDK; +using GoldSrc.HLSDK.Native; +using GoldSrc.MetaMod; +using GoldSrc.MetaMod.Native; + +using static Module.Global; + +namespace Module +{ + public unsafe static class Module + { + static Module() + { + g_MetaFunctions_Table.pfnGetEntityAPI2 = &GetEntityAPI2; + g_MetaFunctions_Table.pfnGetEntityAPI2_Post = &GetEntityAPI2_Post; + g_MetaFunctions_Table.pfnGetNewDLLFunctions = &GetNewDLLFunctions; + g_MetaFunctions_Table.pfnGetNewDLLFunctions_Post = &GetNewDLLFunctions_Post; + g_MetaFunctions_Table.pfnGetEngineFunctions = &GetEngineFunctions; + g_MetaFunctions_Table.pfnGetEngineFunctions_Post = &GetEngineFunctions_Post; + } + + [UnmanagedCallersOnly(EntryPoint = "GetEntityAPI2", CallConvs = [typeof(CallConvCdecl)])] + public static int GetEntityAPI2(DLL_FUNCTIONS* pFunctionTable, int* interfaceVersion) + { + if (pFunctionTable == null) + return False; + if (*interfaceVersion != HLSDKInfo.INTERFACE_VERSION) + { + *interfaceVersion = HLSDKInfo.INTERFACE_VERSION; + return False; + } + *pFunctionTable = g_EntityAPI_Table; + g_pFunctionTable = pFunctionTable; + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "GetEntityAPI2_Post", CallConvs = [typeof(CallConvCdecl)])] + public static int GetEntityAPI2_Post(DLL_FUNCTIONS* pFunctionTable, int* interfaceVersion) + { + if (pFunctionTable == null) + return False; + if (*interfaceVersion != HLSDKInfo.INTERFACE_VERSION) + { + *interfaceVersion = HLSDKInfo.INTERFACE_VERSION; + return False; + } + *pFunctionTable = g_EntityAPI_Post_Table; + g_pFunctionTable_Post = pFunctionTable; + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "GetEngineFunctions", CallConvs = [typeof(CallConvCdecl)])] + public static int GetEngineFunctions(enginefuncs_t* pengfuncsFromEngine, int* interfaceVersion) + { + if (pengfuncsFromEngine == null) + return False; + if (*interfaceVersion != MetaModInfo.ENGINE_INTERFACE_VERSION) + { + *interfaceVersion = MetaModInfo.ENGINE_INTERFACE_VERSION; + return False; + } + *pengfuncsFromEngine = g_EngineFuncs_Table; + g_pengfuncsTable = pengfuncsFromEngine; + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "GetEngineFunctions_Post", CallConvs = [typeof(CallConvCdecl)])] + public static int GetEngineFunctions_Post(enginefuncs_t* pengfuncsFromEngine, int* interfaceVersion) + { + if (pengfuncsFromEngine == null) + return False; + if (*interfaceVersion != MetaModInfo.ENGINE_INTERFACE_VERSION) + { + *interfaceVersion = MetaModInfo.ENGINE_INTERFACE_VERSION; + return False; + } + *pengfuncsFromEngine = g_EngineFuncs_Post_Table; + g_pEngineFuncs_Post = pengfuncsFromEngine; + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "GetNewDLLFunctions", CallConvs = [typeof(CallConvCdecl)])] + public static int GetNewDLLFunctions(NEW_DLL_FUNCTIONS* pNewFunctionTable, int* interfaceVersion) + { + if (pNewFunctionTable == null) + return False; + if (*interfaceVersion != HLSDKInfo.NEW_DLL_FUNCTIONS_VERSION) + { + *interfaceVersion = HLSDKInfo.NEW_DLL_FUNCTIONS_VERSION; + return False; + } + *pNewFunctionTable = g_NewFuncs_Table; + g_pNewFunctionsTable = pNewFunctionTable; + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "GetNewDLLFunctions_Post", CallConvs = [typeof(CallConvCdecl)])] + public static int GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS* pNewFunctionTable, int* interfaceVersion) + { + if (pNewFunctionTable == null) + return False; + if (*interfaceVersion != HLSDKInfo.NEW_DLL_FUNCTIONS_VERSION) + { + *interfaceVersion = HLSDKInfo.NEW_DLL_FUNCTIONS_VERSION; + return False; + } + *pNewFunctionTable = g_NewFuncs_Post_Table; + g_pNewFunctionsTable_Post = pNewFunctionTable; + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "Meta_Query", CallConvs = [typeof(CallConvCdecl)])] + public static int Meta_Query(sbyte* ifvers, plugin_info_t** pPlugInfo, mutil_funcs_t* pMetaUtilFuncs) + { + if (pMetaUtilFuncs == null) + { + return False; + } + gpMetaUtilFuncs = pMetaUtilFuncs; + *pPlugInfo = Plugin_info; + + var frameVersion = Marshal.PtrToStringAnsi((nint)ifvers)!; + var list = frameVersion.Split(":"); + var mmajor = int.Parse(list[0]); + var mminor = int.Parse(list[1]); + + list = MetaModInfo.META_INTERFACE_VERSION.Split(":"); + var pmajor = int.Parse(list[0]); + var pminor = int.Parse(list[1]); + + if (pmajor > mmajor || (pmajor == mmajor && pminor > mminor)) + return False; + else if (pmajor < mmajor) + return False; + return True; + } + + + [UnmanagedCallersOnly(EntryPoint = "Meta_Attach", CallConvs = [typeof(CallConvCdecl)])] + public static int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS* pFunctionTable, meta_globals_t* pMGlobals, gamedll_funcs_t* pGamedllFuncs) + { + if ((int)now > (int)Plugin_info->loadable) + return False; + if (pMGlobals == null) + return False; + gpMetaGlobals = pMGlobals; + if (pFunctionTable == null) + return False; + *pFunctionTable = g_MetaFunctions_Table; + gpGamedllFuncs = pGamedllFuncs; + Plugin.FN_META_ATTACH(); + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "Meta_Detach", CallConvs = [typeof(CallConvCdecl)])] + public static int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) + { + if (now > Plugin_info->unloadable && reason != PL_UNLOAD_REASON.PNL_CMD_FORCED) + return False; + Plugin.FN_META_DETACH(); + return True; + } + + [UnmanagedCallersOnly(EntryPoint = "GiveFnptrsToDll", CallConvs = [typeof(CallConvStdcall)])] + public static void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t* pGlobals) + { + g_engfuncs = *pengfuncsFromEngine; + gpGlobals = pGlobals; + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_Query", CallConvs = [typeof(CallConvCdecl)])] + public static int AMXX_Query(int* interfaceVersion, amxx_module_info_t* moduleInfo) + { + if (interfaceVersion == null || moduleInfo == null) + return AMXX_PARAM; + if (*interfaceVersion != AmxxInfo.AMXX_INTERFACE_VERSION) + { + *interfaceVersion = AmxxInfo.AMXX_INTERFACE_VERSION; + return AMXX_IFVERS; + } + *moduleInfo = g_ModuleInfo; + Plugin.FN_AMXX_QUERY(); + return AMXX_OK; + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_CheckGame", CallConvs = [typeof(CallConvCdecl)])] + public static int AMXX_CheckGame(nint game) + { + Plugin.FN_AMXX_CHECKGAME((sbyte*)game); + return AMXX_GAME_OK; + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_Attach", CallConvs = [typeof(CallConvCdecl)])] + public static int AMXX_Attach(delegate* unmanaged[Cdecl] reqFnptrFunc) + { + if (reqFnptrFunc == null) + return AMXX_PARAM; + var size = sizeof(AMX); + g_fn_RequestFunction = reqFnptrFunc; + #region 隐藏多余的API映射 + using (var funName = "BuildPathname".GetNativeString()) + { + g_fn_BuildPathname = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "BuildPathnameR".GetNativeString()) + { + g_fn_BuildPathnameR = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "PrintSrvConsole".GetNativeString()) + { + g_fn_PrintSrvConsole = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetModname".GetNativeString()) + { + g_fn_GetModname = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "Log".GetNativeString()) + { + g_fn_Log = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "LogError".GetNativeString()) + { + g_fn_LogErrorFunc = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "MergeDefinitionFile".GetNativeString()) + { + g_fn_MergeDefinition_File = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "Format".GetNativeString()) + { + g_fn_Format = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RegisterFunction".GetNativeString()) + { + g_fn_RegisterFunction = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RegisterFunctionEx".GetNativeString()) + { + g_fn_RegisterFunctionEx = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetAmxScript".GetNativeString()) + { + g_fn_GetAmxScript = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "FindAmxScriptByAmx".GetNativeString()) + { + g_fn_FindAmxScriptByAmx = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "FindAmxScriptByName".GetNativeString()) + { + g_fn_FindAmxScriptByName = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "LoadAmxScript".GetNativeString()) + { + g_fn_LoadAmxScript = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "UnloadAmxScript".GetNativeString()) + { + g_fn_UnloadAmxScript = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetAmxScriptName".GetNativeString()) + { + g_fn_GetAmxScriptName = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "SetAmxString".GetNativeString()) + { + g_fn_SetAmxString = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetAmxString".GetNativeString()) + { + g_fn_GetAmxString = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetAmxStringLen".GetNativeString()) + { + g_fn_GetAmxStringLen = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "FormatAmxString".GetNativeString()) + { + g_fn_FormatAmxString = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "CopyAmxMemory".GetNativeString()) + { + g_fn_CopyAmxMemory = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetAmxAddr".GetNativeString()) + { + g_fn_GetAmxAddr = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "AddNatives".GetNativeString()) + { + g_fn_AddNatives = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "AddNewNatives".GetNativeString()) + { + g_fn_AddNewNatives = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RaiseAmxError".GetNativeString()) + { + g_fn_RaiseAmxError = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RegisterForward".GetNativeString()) + { + g_fn_RegisterForward = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RegisterSPForward".GetNativeString()) + { + g_fn_RegisterSPForward = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RegisterSPForwardByName".GetNativeString()) + { + g_fn_RegisterSPForwardByName = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "UnregisterSPForward".GetNativeString()) + { + g_fn_UnregisterSPForward = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "ExecuteForward".GetNativeString()) + { + g_fn_ExecuteForward = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "PrepareCharArray".GetNativeString()) + { + g_fn_PrepareCharArray = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "PrepareCellArrayA".GetNativeString()) + { + g_fn_PrepareCellArrayA = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "PrepareCharArrayA".GetNativeString()) + { + g_fn_PrepareCharArrayA = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerValid".GetNativeString()) + { + g_fn_IsPlayerValid = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerName".GetNativeString()) + { + g_fn_GetPlayerName = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerIP".GetNativeString()) + { + g_fn_GetPlayerIP = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerInGame".GetNativeString()) + { + g_fn_IsPlayerIngame = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerBot".GetNativeString()) + { + g_fn_IsPlayerBot = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerAuthorized".GetNativeString()) + { + g_fn_IsPlayerAuthorized = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerTime".GetNativeString()) + { + g_fn_GetPlayerTime = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerPlayTime".GetNativeString()) + { + g_fn_GetPlayerPlayTime = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerCurweapon".GetNativeString()) + { + g_fn_GetPlayerCurweapon = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerTeam".GetNativeString()) + { + g_fn_GetPlayerTeam = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerDeaths".GetNativeString()) + { + g_fn_GetPlayerDeaths = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerMenu".GetNativeString()) + { + g_fn_GetPlayerMenu = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerKeys".GetNativeString()) + { + g_fn_GetPlayerKeys = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerAlive".GetNativeString()) + { + g_fn_IsPlayerAlive = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerFrags".GetNativeString()) + { + g_fn_GetPlayerFrags = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerConnecting".GetNativeString()) + { + g_fn_IsPlayerConnecting = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "IsPlayerHLTV".GetNativeString()) + { + g_fn_IsPlayerHLTV = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerArmor".GetNativeString()) + { + g_fn_GetPlayerArmor = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerHealth".GetNativeString()) + { + g_fn_GetPlayerHealth = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerFlags".GetNativeString()) + { + g_fn_GetPlayerFlags = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetPlayerEdict".GetNativeString()) + { + g_fn_GetPlayerEdict = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "amx_Push".GetNativeString()) + { + g_fn_AmxPush = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "SetPlayerTeamInfo".GetNativeString()) + { + g_fn_SetTeamInfo = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "PlayerPropAddr".GetNativeString()) + { + g_fn_PlayerPropAddr = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RegAuthFunc".GetNativeString()) + { + g_fn_RegAuthFunc = (delegate* unmanaged[Cdecl], void>)reqFnptrFunc(funName); + } + using (var funName = "UnregAuthFunc".GetNativeString()) + { + g_fn_UnregAuthFunc = (delegate* unmanaged[Cdecl], void>)reqFnptrFunc(funName); + } + using (var funName = "FindLibrary".GetNativeString()) + { + g_fn_FindLibrary = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "AddLibraries".GetNativeString()) + { + g_fn_AddLibraries = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "RemoveLibraries".GetNativeString()) + { + g_fn_RemoveLibraries = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "OverrideNatives".GetNativeString()) + { + g_fn_OverrideNatives = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "GetLocalInfo".GetNativeString()) + { + g_fn_GetLocalInfo = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "AmxReregister".GetNativeString()) + { + g_fn_AmxReRegister = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + using (var funName = "MessageBlock".GetNativeString()) + { + g_fn_MessageBlock = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + #endregion + // 在AMXX_Attach方法中其他函数指针获取之后添加 + using (var funName = "skill_get_skill_level".GetNativeString()) + { + g_fn_skill_get_skill_level = (delegate* unmanaged[Cdecl])reqFnptrFunc(funName); + } + + + + Plugin.FN_AMXX_ATTACH(); + return AMXX_OK; + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_Detach", CallConvs = [typeof(CallConvCdecl)])] + public static int AMXX_Detach() + { + Plugin.FN_AMXX_DETACH(); + return AMXX_OK; + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_PluginsLoaded", CallConvs = [typeof(CallConvCdecl)])] + public static int AMXX_PluginsLoaded() + { + Plugin.FN_AMXX_PLUGINSLOADED(); + return AMXX_OK; + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_PluginsUnloaded", CallConvs = [typeof(CallConvCdecl)])] + public static void AMXX_PluginsUnloaded() + { + Plugin.FN_AMXX_PLUGINSUNLOADED(); + } + + [UnmanagedCallersOnly(EntryPoint = "AMXX_PluginsUnloading", CallConvs = [typeof(CallConvCdecl)])] + public static void AMXX_PluginsUnloading() + { + Plugin.FN_AMXX_PLUGINSUNLOADING(); + } + + } +} diff --git a/Forward-event-code-example/Plugin.cs b/Forward-event-code-example/Plugin.cs new file mode 100644 index 0000000..e673af0 --- /dev/null +++ b/Forward-event-code-example/Plugin.cs @@ -0,0 +1,117 @@ +using GoldSrc.Amxmodx.Native; +using GoldSrc.HLSDK; +using GoldSrc.HLSDK.Native; + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using static Module.Global; + +#pragma warning disable CS8981 +using cell = int; + +#pragma warning restore CS8981 + + +using GoldSrc.Amxmodx.Framework.Attributes; + +namespace Module +{ + public unsafe class Plugin + { + public static AMX_NATIVE_INFO* nativeInfo = null; + static Plugin() + { + nativeInfo = (AMX_NATIVE_INFO*)Marshal.AllocHGlobal(sizeof(AMX_NATIVE_INFO) * 2); + + + + + nativeInfo[1].name = null; + nativeInfo[1].func = nint.Zero; + } + + public static void FN_META_QUERY() + { + + } + + public static void FN_META_ATTACH() + { + + } + + public static void FN_META_DETACH() + { + + } + + public static void FN_AMXX_QUERY() + { + + } + + public static int FN_AMXX_CHECKGAME(sbyte* game) + { + return AMXX_GAME_OK; + } + + public static void FN_AMXX_ATTACH() + { + // 注册forward监听 + using var forwardName = "skill_respawn_selected".GetNativeString(); + g_fwd_skill_respawn_selected = g_fn_RegisterForward(forwardName, ForwardExecType.ET_IGNORE); + } + + public static void FN_AMXX_DETACH() + { + } + + public static void FN_AMXX_PLUGINSLOADED() + { + } + + public static void FN_AMXX_PLUGINSUNLOADING() + { + + } + public static void FN_AMXX_PLUGINSUNLOADED() + { + + } + + + + // Forward句柄 + public static int g_fwd_skill_respawn_selected = -1; + + + + // 调用native函数 + public static int GetSkillLevel(int index, int itemid) + { + return g_fn_skill_get_skill_level(index, itemid); + } + + // 触发forward事件 + public static void TriggerSkillRespawnSelected(int id, int itemid) + { + if (g_fwd_skill_respawn_selected == -1) + return; + + g_fn_AmxPush(null, itemid); + g_fn_AmxPush(null, id); + g_fn_ExecuteForward(g_fwd_skill_respawn_selected); + } + + // Forward事件处理器 + [AmxxForward("skill_respawn_selected")] + public static int OnSkillRespawnSelected(int id, int itemid) + { + using var msg = $"Player {id} skill respawn: {itemid}\n".GetNativeString(); + g_engfuncs.pfnServerPrint(msg); + return 0; + } + } + +} diff --git a/Forward-event-code-example/amxScript/configs/plugins-LevelMenu.ini b/Forward-event-code-example/amxScript/configs/plugins-LevelMenu.ini new file mode 100644 index 0000000..b7e4266 --- /dev/null +++ b/Forward-event-code-example/amxScript/configs/plugins-LevelMenu.ini @@ -0,0 +1,4 @@ +//ģV1.2 +ZP_LevelBasic.amxx + +//-------- diff --git a/Forward-event-code-example/amxScript/plugins/ZP_LevelBasic.amxx b/Forward-event-code-example/amxScript/plugins/ZP_LevelBasic.amxx new file mode 100644 index 0000000..5bb3851 Binary files /dev/null and b/Forward-event-code-example/amxScript/plugins/ZP_LevelBasic.amxx differ diff --git a/Forward-event-code-example/amxScript/scripting/ZP_LevelBasic.sma b/Forward-event-code-example/amxScript/scripting/ZP_LevelBasic.sma new file mode 100644 index 0000000..6b9b614 --- /dev/null +++ b/Forward-event-code-example/amxScript/scripting/ZP_LevelBasic.sma @@ -0,0 +1,1197 @@ +/* 本插件由 AMXX-Studio 中文版自动生成*/ +/* UTF-8 func by www.DT-Club.net */ +/* +* 该技能添加系统游戏金钱版于3月14日完成 +* 添加技能,不用写技能提示类的文字,直接添加内容即可 +* 游戏中$是该升级菜单的升级菜单金钱,游戏中输入/shopmenu打开技能菜单 +* 4月13日修改V1.2beta:优化了数集增加还有介绍 +* 7月12号V1.3beta:进行大部分优化和全面修改,增加插件外添加技能的功能 +* 7月14号V1.31beta:严重BUG修复,修复只显示一个技能名称的BUG +* 7月15号V1.4正式版:修复inc的部分代码无法使用的bug和开局自动执行技能1的BUG +* V1.4:增加获取 技能点数,队伍,是否活着才可以升级 的inc代码 +* V1.41:添加限制技能升级次数及其限制技能升级时间时间等类型的inc代码 +* V1.42:添加技能升级的forward,即是client_shop(id,itemid) +* 注意:Forward内须执行skill_reset_item_hasbuy(id) +* V1.43:由测试得已知严重BUG。修复活着与死亡显示信息无法正常显示而且有时候报错的BUG。 +* V2.0:技能升级权限及其不用钱和验证直接给予指定玩家技能的inc代码添加 +* V2.1:添加返回指定技能升级所需的权限,添加每个inc函数的具体用法的例子 +* 及其更新inc中的介绍内容,全面让编写者了解此INC代码的用法 +* V2.2:限制开局后多少时间才能开启升级菜单 +* V2.3:技能编号名字的获取及其打开升级菜单无技能的提示 +* V2.31:修复关于开局的时间限制的一些BUG +* +* 改版自商场模版V2.31正式版本,Halo-QQ351642983 +* V1.2:添加重置技能点数的选项,头文件中增加获取总技能数的语句,修复少数的BUG,重置技能的Forward的添加 +* v1.21修复观察者BUG +* v1.22对少数测试所得bug进行修复,技能注册在非预缓存区域等级获取错误的修复,显示菜单的判断更加人性化 +*/ + +#include +#include +#include + + +#define PLUGIN_NAME "技能添加系统" +#define PLUGIN_VERSION "V1.22" +#define PLUGIN_AUTHOR "Halo-QQ351642983" + + +//所能支持的最多的技能个数 +#define ITEMNUM 64 + +//按键的绑定(不要绑定的话删除下面一行即可) +#define ANJIAN "l" + + +new bool:g_showtrue[33]; + +//判断需要显示什么东西的变量初始化 +new ItemSF[33]=0,IteamNums=0,ApackPD[33]=0,ITime[ITEMNUM][33],Limit[ITEMNUM][33] +new bool:g_ShopOpen=true + + +//技能变量初始化 +new g_levelexe[33],g_level[33],g_skilllevel[33][ITEMNUM],g_Maxlevel,g_leveltotalexe[33],g_levelpoint[33] + +//CVAR的储存值 +new g_sfOpenTime,g_sfHudChannel,g_sfShowMode,g_sfBasicNum,g_sfBasicExe,g_sfEasyGainexe,g_sfzExeGain,g_sfrMode,g_sfrExe,g_sfrPacks + +//Forward的储存id值 +new g_ForwardID,g_ForwardID1,g_ForwardID2,g_ForwardID3,g_ForwardID4,g_ForwardID5,g_ForwardID6,g_ForwardID7 + + +//定义死亡是否升级技能时显示的状态 +new const AliveShow[2][]= +{ + " 死亡 ", + " 活着 " +}; + + +new MenuItem[ITEMNUM][ITEMNUM] + +new ItemTeams[ITEMNUM] + +new ItemCost[ITEMNUM] + +new ItemIfaLive[ITEMNUM] + +new Float:TimeLimit[ITEMNUM] + +new TimesLimit[ITEMNUM] + +new ItemLevel[ITEMNUM] + +new ItemMaxLevel[ITEMNUM] + +new ItemRespawn[ITEMNUM] + +new ItemRestart[ITEMNUM] + +new ItemBuy[ITEMNUM] + +new ItemOpen[ITEMNUM] + +new ItemSkillDamage[ITEMNUM] + +new Array:AritemName + +new Arid[33] + + + + +public plugin_precache() +{ + AritemName=ArrayCreate(ITEMNUM,1) +} + +public plugin_init() +{ + register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR) + register_event("HLTV","resetlimit","a","1=0","2=0") + register_event("ResetHUD","Respawn","b") + register_logevent("resetRound",2,"1=Round_Start") + register_clcmd("say /skillmenu","IMenuShow") + + g_ForwardID=CreateMultiForward("skill_selected", ET_CONTINUE,FP_CELL,FP_CELL) + g_ForwardID1=CreateMultiForward("skill_damage_selected", ET_CONTINUE,FP_CELL,FP_CELL,FP_CELL,FP_CELL,FP_CELL,FP_CELL,FP_CELL) + g_ForwardID3=CreateMultiForward("skill_restart_selected_pre",ET_IGNORE,FP_CELL,FP_CELL) + g_ForwardID4=CreateMultiForward("skill_open_selected", ET_IGNORE,FP_CELL,FP_CELL) + g_ForwardID5=CreateMultiForward("skill_respawn_selected", ET_IGNORE,FP_CELL,FP_CELL) + g_ForwardID6=CreateMultiForward("skill_restart_selected_post", ET_IGNORE,FP_CELL,FP_CELL) + g_ForwardID2=CreateMultiForward("skill_levelup", ET_CONTINUE,FP_CELL) + g_ForwardID7=CreateMultiForward("skill_levelreset", ET_CONTINUE,FP_CELL) + + g_sfOpenTime=register_cvar("skill_start_open","0.0") + g_sfHudChannel=register_cvar("skill_hud_channel","3") + g_sfShowMode=register_cvar("skill_show_mode","3") + g_sfBasicNum=register_cvar("skill_basic_num","1.57") + g_sfBasicExe=register_cvar("skill_basic_exe","1000") + + //如果有装上保存经验这项建议设置为0.0 + g_sfEasyGainexe=register_cvar("skill_esaygain_exe","1.0") + + + g_sfzExeGain=register_cvar("skill_infector_exe","1000") + g_sfrMode=register_cvar("skill_reset_mode","1") + g_sfrExe=register_cvar("skill_reset_exe","2000") + g_sfrPacks=register_cvar("skill_reset_packs","20") + set_task(0.5,"getmaxlevel") + + +} +public getmaxlevel() +{ + g_Maxlevel=0 + for(new i=0;i<=IteamNums-1;i++) + g_Maxlevel+=ItemMaxLevel[i]*ItemCost[i] + g_Maxlevel++ +} +public client_putinserver(id) +{ + set_task(1.0,"InfoShow",id+1000,_,_,"b") +} +public client_connect(id) +{ + ApackPD[id]=0 + ItemSF[id]=0 + get_all(Limit,ITEMNUM-1,0,id) + get_all(ITime,ITEMNUM-1,0,id) + for(new i=0;i<=IteamNums-1;i++) + g_skilllevel[id][i]=0 + remove_task(id) + remove_task(id+1000) + + g_levelexe[id]=0 + g_leveltotalexe[id]=get_pcvar_num(g_sfBasicExe) + g_level[id]=1 + g_levelpoint[id]=0 + #if defined ANJIAN + client_cmd(id,"bind %s ^"say /skillmenu",ANJIAN) + #endif +} + +public InfoShow(pid) +{ + new id=pid-1000 + if(is_user_connected(id)) + { + if(is_user_alive(id)) + { + if(get_pcvar_num(g_sfShowMode)==1) + { + set_hudmessage(127, 255, 42, -1.0, 0.05, 0, 6.0, 1.1,_,_,get_pcvar_num(g_sfHudChannel)) + show_hudmessage(id, "等级:%d/%d^n经验:%d/%d^n技能点数:%d点",g_level[id],g_Maxlevel,g_levelexe[id],g_leveltotalexe[id],g_levelpoint[id]) + } + else if(get_pcvar_num(g_sfShowMode)==2) + { + client_print(id,print_center, "等级:%d/%d 经验:%d/%d 技能点数:%d点",g_level[id],g_Maxlevel,g_levelexe[id],g_leveltotalexe[id],g_levelpoint[id]) + } + else if(get_pcvar_num(g_sfShowMode)==3) + { + new szMsg[128] + format(szMsg,127,"等级:%d/%d 经验:%d/%d 技能点数:%d点",g_level[id],g_Maxlevel,g_levelexe[id],g_leveltotalexe[id],g_levelpoint[id]) + message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("StatusText"), _, id) + write_byte(0) + write_string(szMsg) + message_end() + } + } + else + { + new aid=pev(id,pev_iuser2) + if(is_user_alive(aid)) + { + + static opcion[64],name[33] + new hudinfo[1560] + get_user_name(aid,name,33) + formatex(hudinfo, charsmax(hudinfo),"玩家:^n=== %s ===^n^n等级:%d",name,g_level[aid]) + ItemSF[aid]=0 + for(new i=0;i<=(IteamNums-1);i++) + { + if((zp_get_user_zombie(aid)?1:2)==ItemTeams[i]||ItemTeams[i]==3) + { + if(ItemCost[i]>0&&ItemIfaLive[i]!=0) + { + ItemSF[aid]+=1 + if(ItemLevel[i]==0) + { + if(g_skilllevel[aid][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s %d级", MenuItem[i],g_skilllevel[aid][i]) + else formatex(opcion, charsmax(opcion),"%s MAX!", MenuItem[i]) + } + else{ + if(g_skilllevel[aid][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s MAX!", MenuItem[i]) + } + } + else if(ItemCost[i]==0&&ItemIfaLive[i]!=0) + { + ItemSF[aid]+=1 + if(ItemLevel[i]==0) + { + if(g_skilllevel[id][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s %d级", MenuItem[i],g_skilllevel[aid][i]) + else formatex(opcion, charsmax(opcion),"%s Max!", MenuItem[i]) + } + else{ + if(g_skilllevel[id][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s %d级", MenuItem[i],g_skilllevel[aid][i]) + else formatex(opcion, charsmax(opcion),"%s Max!", MenuItem[i]) + } + } + formatex(hudinfo, charsmax(hudinfo),"%s^n%s",hudinfo,opcion) + } + } + if(ItemSF[aid]==0) + { + formatex(hudinfo, charsmax(hudinfo)," (该队伍无技能菜单)") + } + set_hudmessage(127, 212, 255, 0.73, 0.12, 1, 6.0, 1.1,_,_,get_pcvar_num(g_sfHudChannel)) + show_hudmessage(id, "%s",hudinfo) + + } + } + } + else + { + remove_task(id+1000) + } +} + +public client_damage(attacker,victim,damage,weapon,hitplace,ta) +{ + if(is_user_connected(attacker)&&is_user_connected(victim)) + { + if(zp_get_user_zombie(attacker)!=zp_get_user_zombie(victim)) + g_levelexe[attacker]+=floatround(damage*get_pcvar_float(g_sfEasyGainexe)) + + for(new i=0;i<=IteamNums-1;i++) + { + if(ItemSkillDamage[i]==1&&g_skilllevel[attacker][i]>0) + { + new g_num + if(is_user_alive(attacker)&&ItemIfaLive[i]==1||ItemIfaLive[i]==3) + { + if(zp_get_user_zombie(attacker)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + else if((!zp_get_user_zombie(attacker))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + } + else if((!is_user_alive(attacker))&&(ItemIfaLive[i]==2)) + { + if(zp_get_user_zombie(attacker)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + else if((!zp_get_user_zombie(attacker))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + } + } + else if(ItemSkillDamage[i]==2&&g_skilllevel[victim][i]>0) + { + new g_num + if(is_user_alive(victim)&&ItemIfaLive[i]==1||ItemIfaLive[i]==3) + { + if(zp_get_user_zombie(victim)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + else if((!zp_get_user_zombie(victim))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + } + else if((!is_user_alive(victim))&&(ItemIfaLive[i]==2)) + { + if(zp_get_user_zombie(victim)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + else if((!zp_get_user_zombie(victim))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID1,g_num,i,attacker,victim,damage,weapon,hitplace,ta) + } + } + } + } +} + +public zp_user_infected_pre(id,infector) +{ + g_levelexe[infector]+=get_pcvar_num(g_sfzExeGain) +} + +public resetlimit() +{ + g_ShopOpen=false + for(new id=0;id<=get_maxplayers();id++) + { + if(is_user_connected(id)) + { + remove_task(id) + get_all(Limit,ITEMNUM-1,0,id) + get_all(ITime,ITEMNUM-1,0,id) + for(new i=0;i<=IteamNums-1;i++) + { + if(g_skilllevel[id][i]>0) + if(ItemRestart[i]==1) + { + new g_num + if(is_user_alive(id)&&ItemIfaLive[i]==1||ItemIfaLive[i]==3) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID3,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID3,g_num,id,i) + } + else if((!is_user_alive(id))&&(ItemIfaLive[i]==2)) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID3,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID3,g_num,id,i) + } + } + } + } + } + set_task(get_pcvar_float(g_sfOpenTime),"OpenShop") +} + +public Respawn(id) +{ + if(is_user_connected(id)) + { + for(new i=0;i<=IteamNums-1;i++) + { + if(g_skilllevel[id][i]>0) + if(ItemRespawn[i]==1) + { + new g_num + if(is_user_alive(id)&&ItemIfaLive[i]==1||ItemIfaLive[i]==3) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID5,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID5,g_num,id,i) + } + else if((!is_user_alive(id))&&(ItemIfaLive[i]==2)) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID5,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID5,g_num,id,i) + } + } + } + } +} + +public resetRound() +{ + for(new id=1;id<=get_maxplayers();id++) + { + if(is_user_connected(id)) + { + for(new i=0;i<=IteamNums-1;i++) + { + if(g_skilllevel[id][i]>0) + if(ItemRestart[i]==2) + { + new g_num + if(is_user_alive(id)&&ItemIfaLive[i]==1||ItemIfaLive[i]==3) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID6,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID6,g_num,id,i) + } + else if((!is_user_alive(id))&&(ItemIfaLive[i]==2)) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID6,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID6,g_num,id,i) + } + } + } + } + } +} + +public OpenShop() +{ + g_ShopOpen=true + for(new id=1;id<=get_maxplayers();id++) + { + if(is_user_connected(id)) + { + for(new i=0;i<=IteamNums-1;i++) + { + if(g_skilllevel[id][i]>0) + if(ItemOpen[i]==1) + { + new g_num + if(is_user_alive(id)&&ItemIfaLive[i]==1||ItemIfaLive[i]==3) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID4,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID4,g_num,id,i) + } + else if((!is_user_alive(id))&&(ItemIfaLive[i]==2)) + { + if(zp_get_user_zombie(id)&&ItemTeams[i]==1||ItemTeams[i]==3) + ExecuteForward(g_ForwardID4,g_num,id,i) + else if((!zp_get_user_zombie(id))&&ItemTeams[i]==2) + ExecuteForward(g_ForwardID4,g_num,id,i) + } + } + } + } + } +} + +public zp_round_started(gamemode,id) +{ + for(new i=1;i<=32&&is_user_connected(i);i++) + { + if(is_user_connected(i)) + g_showtrue[i]=true; + else g_showtrue[i]=false; + } + +} +public client_PreThink(id) +{ + if(is_user_connected(id)) + { + if(is_user_alive(id)) + { + if(g_levelexe[id]>=g_leveltotalexe[id]&&g_level[id]0) + g_levelpoint[id]-=1 + g_leveltotalexe[id]=floatround(get_pcvar_num(g_sfBasicExe)*g_level[id]*(g_level[id]==1?1.0:get_pcvar_float(g_sfBasicNum))) + } + if(g_levelexe[id]>g_leveltotalexe[id]&&g_level[id]==g_Maxlevel) + g_levelexe[id]=floatround(get_pcvar_num(g_sfBasicExe)*g_Maxlevel*get_pcvar_float(g_sfBasicNum)) + } + } + else if(g_showtrue[id]) + { + g_showtrue[id]=false + } +} + +public plugin_natives() +{ + register_native("skill_add_item","add_skillitem",1) //注册技能的基本信息并返回技能的ID值 + register_native("skill_get_item_id","get_skillitem",1) //搜索技能返回技能ID的值 + register_native("skill_reset_item","reset_skillitem",1) //删除升级菜单中指定技能 + register_native("skill_set_item","set_skillitem",1) //修改升级菜单中技能的基本属性 + register_native("skill_get_item_hasbuy","hasbuy",1) //技能是否被升级,是的话返回值1,否的话0,并保存在主插件 + register_native("skill_reset_item_hasbuy","resethasbuy",1) //把技能升级的返回值设置为0 + register_native("skill_get_item_cost","getmoney",1) //返回指定技能所需的技能点数 + register_native("skill_get_item_team","getteam",1) //返回指定技能所代表的队伍 + register_native("skill_is_item_alive","isalive",1) //返回指定技能是否需要活着才可以升级 + register_native("skill_limit_item","limititem",1) //限制技能的每局升级次数 + register_native("skill_limit_item_time","limittime",1) //限制技能的升级时间 + register_native("skill_remove_item_limit","removetimeslimit",1) //移除指定技能的限制的次数 + register_native("skill_remove_item_time","removetime",1) //移除指定技能的限制的时间 + register_native("skill_reset_item_limit","limitreset",1) //把玩家当前限定的次数清零 + register_native("skill_reset_item_time","timereset",1) //把玩家当前限制的时间清零 + register_native("skill_get_item_time","gettime",1) //返回技能限制的时间的值 + register_native("skill_get_item_limit","getlimit",1) //返回技能限制的次数的值 + register_native("skill_give_item","giveiditem",1) //不用钱和验证直接给予指定玩家技能 + register_native("skill_set_item_flag","limitlevel",1) //技能升级权限的限定 + register_native("skill_get_item_flag","getlimitlevel",1) //返回指定技能升级所需的权限 + register_native("skill_get_item_name","getitemidname",1) //技能名字的获取 + register_native("skill_get_item_maxlevel","getitemidmaxlevel",1) //技能的最高等级的获取 + register_native("skill_get_item_respawn","getitemidrespawn",1) //技能的重生所执行的模式的获取 + register_native("skill_get_item_restart","getitemidrestart",1) //技能的重新开始所执行的模式的获取 + register_native("skill_get_item_openmode","getitemidopenmode",1) //技能的升级菜单开放时所执行的模式的获取 + register_native("skill_get_item_buymode","getitemidbuymode",1) //技能的升级技能时所执行的模式的获取 + register_native("skill_set_item_mode","setmode",1) //设置技能的触发模式 + register_native("skill_get_item_damagemode","getdamagemode",1) //获取技能的攻击触发模式 + register_native("skill_set_level_exe","setlevelexe",1) //设置等级的经验值 + register_native("skill_get_level_exe","getlevelexe",1) //获取该等级的经验值 + register_native("skill_set_level","setlevel",1) //设置等级 + register_native("skill_get_level","getlevel",1) //获取等级 + register_native("skill_set_level_point","setlevelpoint",1) //设置技能点 + register_native("skill_get_level_point","getlevelpoint",1) //获取技能点 + register_native("skill_set_skill_level","setlevelskill",1) //设置技能的等级 + register_native("skill_get_skill_level","getlevelskill",1) //获取技能的等级 + register_native("skill_reset_skill_point","resetlevelskill",1) //重置技能点数 + register_native("skill_get_skill_num","getlevelskillnum",1) //获取技能的数目 + +} + +//native注册技能的基本信息并返回技能的ID值 +public add_skillitem(const itemname[],itemteam,itemcosts,itembuyalive,skillmaxlevel) +{ + param_convert(1) + ArrayPushString(AritemName,itemname) + ArrayGetString(AritemName,IteamNums,MenuItem[IteamNums],ITEMNUM-1) + ItemTeams[IteamNums]=itemteam + ItemCost[IteamNums]=itemcosts + ItemIfaLive[IteamNums]=itembuyalive + ItemMaxLevel[IteamNums]=skillmaxlevel + IteamNums+=1 + return IteamNums-1 +} + +//native技能的重生所执行的forward的模式的获取 +public getitemidrespawn(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemRespawn[itemid] +} + + +//native技能的重新开始所执行的forward的模式的获取 +public getitemidrestart(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemRestart[itemid] +} + + +//native搜索技能返回技能ID的值 +public get_skillitem(const itemname[]) +{ + param_convert(1) + static i, item_name[32] + for (i = 0; i < IteamNums; i++) + { + ArrayGetString(AritemName, i, item_name, charsmax(item_name)) + if (equali(itemname, item_name)) + return i; + } + + return -1; +} +//native删除升级菜单中指定技能 +public reset_skillitem(itemid) +{ + if(itemid>ITEMNUM) + return -1 + new item[]={""} + format(MenuItem[itemid],ITEMNUM-1,"%s",item) + ItemTeams[itemid]=0 + ItemCost[itemid]=0 + ItemIfaLive[itemid]=0 + ItemMaxLevel[itemid]=0 + ItemRespawn[itemid]=0 + ItemRestart[itemid]=0 + ItemBuy[itemid]=0 + ItemOpen[itemid]=0 + ItemSkillDamage[itemid]=0 + return 0 +} +//native修改升级菜单中技能的基本属性 +public set_skillitem(itemid,const itemname[],itemteam,itemcosts,itembuyalive,skillmaxlevel) +{ + if(itemid>ITEMNUM) + return -1 + + param_convert(2) + ArraySetString(AritemName,itemid,itemname) + ArrayGetString(AritemName,itemid,MenuItem[itemid],ITEMNUM-1) + ItemTeams[itemid]=itemteam + ItemCost[itemid]=itemcosts + return 0 +} +//native技能是否被升级,是的话返回值1,否的话0,并保存在本插件 +public hasbuy(id,itemid) +{ + if(itemid>ITEMNUM) + return -1 + if(itemid+1==ApackPD[id]) + return 1 + return 0 +} +//native把技能升级的返回值设置为0 +public resethasbuy(id) +{ + ApackPD[id]=0 +} +//native返回指定技能所需的技能点数 +public getmoney(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemCost[itemid] +} +//native返回指定技能所代表的队伍 +public getteam(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemTeams[itemid] +} +//native返回指定技能是否需要活着才可以升级 +public isalive(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemIfaLive[itemid] +} +//native限制技能的每局升级次数 +public limititem(itemid,times) +{ + if(itemid>ITEMNUM) + return -1 + + TimesLimit[itemid]=times + return 0 +} +//native限制技能的升级时间 +public limittime(itemid,Float:long) +{ + if(itemid>ITEMNUM) + return -1 + + TimeLimit[itemid]=long + return 0 +} +//native移除指定技能的限制的次数 +public removetimeslimit(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + TimesLimit[itemid]=0 + return 0 +} +//native移除指定技能的限制的时间 +public removetime(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + TimeLimit[itemid]=0.0 + return 0 +} +//native把玩家升级指定技能限定的次数清零 +public limitreset(id,itemid) +{ + if(itemid>ITEMNUM) + return -1 + Limit[itemid][id]=0 + return 0 +} +//native把玩家当前限制的时间清零 +public timereset(id,itemid) +{ + if(itemid>ITEMNUM) + return -1 + ITime[itemid][id]=0 + return 0 +} +//native返回技能限制的时间的值 +public Float:gettime(itemid) +{ + if(itemid>ITEMNUM) + return -1.0 + + return TimeLimit[itemid] +} +//native返回技能限制的次数的值 +public getlimit(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return TimesLimit[itemid] +} + +//native不用技能点数和验证直接升级指定玩家技能 +public giveiditem(id,itemid) +{ + if(itemid>ITEMNUM) + return -1 + new g_num + ApackPD[id]=itemid+1 + ExecuteForward(g_ForwardID,g_num,id,itemid) + + return 0 +} +//native技能升级权限的限定 +public limitlevel(itemid,level) +{ + if(itemid>ITEMNUM) + return -1 + + ItemLevel[itemid]=level + + return 0 +} +//native返回指定技能升级所需的权限 +public getlimitlevel(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemLevel[itemid] +} +//native技能名字的获取 +public getitemidname(itemid,itemname[],len) +{ + if(itemid>ITEMNUM) + return -1 + + format(itemname,len,"%s",MenuItem[itemid]) + + return 0 +} +//native技能的最高等级的获取 +public getitemidmaxlevel(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemMaxLevel[itemid] +} +//native设置技能的触发模式 +public setmode(itemid,Respawns,Restart,Buy,ShopOpen,Damage) +{ + if(itemid>ITEMNUM) + return -1 + ItemRespawn[itemid]=Respawns + ItemRestart[itemid]=Restart + ItemBuy[itemid]=Buy + ItemOpen[itemid]=ShopOpen + ItemSkillDamage[itemid]=Damage + + return 0 +} +//native技能的升级菜单开放时所执行的模式的获取 +public getitemidopenmode(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemOpen[itemid] +} +//native技能的升级技能时所执行的模式的获取 +public getitemidbuymode(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemBuy[itemid] +} +//native获取技能的攻击触发模式 +public getdamagemode(itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return ItemSkillDamage[itemid] +} +//native设置经验 +public setlevelexe(index,exe) +{ + new g_exe + if(g_level[index]>1) + { + for(new i=2;i<=g_level[index]-1;i++) + { + g_exe+=floatround(get_pcvar_num(g_sfBasicExe)*i*get_pcvar_float(g_sfBasicNum)) + } + g_exe+=get_pcvar_num(g_sfBasicExe) + g_exe+=g_levelexe[index] + } + else g_exe=g_levelexe[index] + g_levelexe[index]+=exe-g_exe +} +//native得到经验 +public getlevelexe(index) +{ + new g_exe + if(g_level[index]>1) + { + for(new i=2;i<=g_level[index]-1;i++) + { + g_exe+=floatround(get_pcvar_num(g_sfBasicExe)*i*get_pcvar_float(g_sfBasicNum)) + } + g_exe+=get_pcvar_num(g_sfBasicExe) + g_exe+=g_levelexe[index] + } + else g_exe=g_levelexe[index] + return g_exe +} +//native设置等级 +public setlevel(index,level) +{ + g_level[index]=level +} +//native获取等级 +public getlevel(index) +{ + return g_level[index] +} + +//native设置技能点数 +public setlevelpoint(index,point) +{ + g_levelpoint[index]=point +} +//native获取技能点数 +public getlevelpoint(index) +{ + return g_levelpoint[index] +} +//native设置技能的等级 +public setlevelskill(id,itemid,level) +{ + if(itemid>ITEMNUM) + return -1 + if(ItemMaxLevel[itemid]>=level) + { + g_skilllevel[id][itemid]=level + } + else return 1 + + return 0 +} +//native获取技能的等级 +public getlevelskill(id,itemid) +{ + if(itemid>ITEMNUM) + return -1 + + return g_skilllevel[id][itemid] +} +//native重置技能点数 +public resetlevelskill(id) +{ + new g_num + g_levelpoint[id]=g_level[id]-1 + for(new i=0;i<=IteamNums-1;i++) + g_skilllevel[id][i]=0 + ExecuteForward(g_ForwardID7,g_num,id) + + return 0 +} +//native获取技能的数目 +public getlevelskillnum(mode) +{ + new g_num=0 + if(mode!=3) + { + for(new i=0;i<=(IteamNums-1);i++) + { + if(mode==ItemTeams[i]||ItemTeams[i]==3) + { + g_num++ + } + } + return g_num + } + else return (IteamNums-1) + + return 0 +} + + + +public removelimits(id) +{ + ITime[Arid[id]][id]=0 + Arid[id]=0 +} + + +public Choose(id, menu, item) +{ + if(item==MENU_EXIT) + { + menu_destroy(menu) + return PLUGIN_HANDLED + } + new command[6], name[64], access, callback + menu_item_getinfo(menu, item, access, command, sizeof command - 1, name, sizeof name - 1, callback) + switch(item) + { + case 0..ITEMNUM: + { + if(g_ShopOpen) + { + new itemid=select_to_num(id,ItemTeams[0],ITEMNUM,item+1) + if(get_pcvar_num(g_sfrMode)!=0) + { + if(ItemSF[id]==item) + { + if((get_pcvar_num(g_sfrMode)==1)?getlevelexe(id)>=get_pcvar_num(g_sfrExe):zp_get_user_ammo_packs(id)>=get_pcvar_num(g_sfrPacks)) + { + new g_num + g_levelpoint[id]=g_level[id]-1 + for(new i=0;i<=IteamNums-1;i++) + g_skilllevel[id][i]=0 + if(get_pcvar_num(g_sfrMode)==1) + g_levelexe[id]-=get_pcvar_num(g_sfrExe) + + else zp_set_user_ammo_packs(id,zp_get_user_ammo_packs(id)-get_pcvar_num(g_sfrPacks)) + ExecuteForward(g_ForwardID7,g_num,id) + client_color(id,"/y恭喜你!技能点重置成功...") + } + else + { + client_color(id,"/y对不起,您的/g%s/y不够,无法重置技能点数",(get_pcvar_num(g_sfrMode)==1)?"经验":"弹药袋") + } + return PLUGIN_CONTINUE; + } + } + if(get_user_flags(id)&ItemLevel[itemid]||ItemLevel[itemid]==0) + { + if(is_user_alive(id)&&ItemIfaLive[itemid]==1||!is_user_alive(id)&&ItemIfaLive[itemid]==2||ItemIfaLive[itemid]==3) + { + if(Limit[itemid][id]=ItemCost[itemid]&&item0) + Limit[itemid][id]+=1 + if(TimeLimit[itemid]>0) + { + ITime[itemid][id]=1 + Arid[id]=itemid + set_task(TimeLimit[itemid],"removelimits",id) + } + } + else if(item0) + Limit[itemid][id]+=1 + if(TimeLimit[itemid]>0) + { + ITime[itemid][id]=1 + Arid[id]=itemid + set_task(TimeLimit[itemid],"removelimits",id) + } + } + + } + else client_color(id,"/ctr%s/y已经升到满级了,无法继续为您升级", MenuItem[itemid]) + if(g_levelpoint[id]>0) + IMenuShow(id) + } + else + { + client_color(id,"/ctr%s/y被限制/g每%.1f秒/y升级,请/g等待/y后再升级", MenuItem[itemid],TimeLimit[itemid]) + } + } + else + { + client_color(id,"/ctr%s/y被限制每局只能升级/g%d/y次,请/g下局/y再升级", MenuItem[itemid],TimesLimit[itemid]) + } + } + else + { + client_color(id,"/y你现在处于/g%s/y的状态,不能升级 /ctr%s/y",AliveShow[ItemIfaLive[itemid]-1],MenuItem[itemid]) + } + } + else + { + client_color(id,"/y你的/g权限/y不足以升级/ctr%s/y,请提升权限再行尝试",MenuItem[itemid]) + } + } + else + { + client_color(id,"/ctr技能/y被限制开局后/g%d/y秒才可以升级,请/g等待.",get_pcvar_num(g_sfOpenTime)) + } + } + } + + menu_destroy(menu) + + return PLUGIN_HANDLED +} + + +public IMenuShow(id) +{ + if(g_ShopOpen) + { + static opcion[64] + formatex(opcion, charsmax(opcion),"\w升级菜单\y||\w技能点数:\r%d",g_levelpoint[id]) + new iMenu=menu_create(opcion,"Choose") //执行菜单命令的目标 + new i,szTempid[10] + ItemSF[id]=0 + for(i=0;i<=(IteamNums-1);i++) + { + if(((zp_get_user_zombie(id)?1:2)==ItemTeams[i]||ItemTeams[i]==3)&&get_user_team(id)!=3) + { + if(ItemCost[i]>0&&ItemIfaLive[i]!=0) + { + ItemSF[id]+=1 + if(ItemLevel[i]==0) + { + if(g_skilllevel[id][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s \y(\r%d/%d/%d\y) ", MenuItem[i],ItemCost[i],g_skilllevel[id][i],ItemMaxLevel[i]) + else formatex(opcion, charsmax(opcion),"%s \rMAX!", MenuItem[i]) + } + else{ + if(g_skilllevel[id][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s \rMAX! \yADMIN", MenuItem[i]) + } + } + else if(ItemCost[i]==0&&ItemIfaLive[i]!=0) + { + ItemSF[id]+=1 + if(ItemLevel[i]==0) + { + if(g_skilllevel[id][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s \y(\r%d/%d\y)", MenuItem[i],g_skilllevel[id][i],ItemMaxLevel[i]) + else formatex(opcion, charsmax(opcion),"%s \rMax!", MenuItem[i]) + } + else{ + if(g_skilllevel[id][i]!=ItemMaxLevel[i]) + formatex(opcion, charsmax(opcion),"%s \y(\r%d/%d\y) \yADMIN", MenuItem[i],g_skilllevel[id][i],ItemMaxLevel[i]) + else formatex(opcion, charsmax(opcion),"%s \rMax! \yADMIN", MenuItem[i]) + } + } + menu_additem(iMenu, opcion, szTempid,0) + } + } + if(ItemSF[id]==0) + { + client_color(id,"/y该/ctr队伍/y的升级菜单/g无技能/y,/ctr无法打开/g升级菜单") + } + else if(get_pcvar_num(g_sfrMode)!=0) + { + formatex(opcion, charsmax(opcion),"\y重置技能点数\w(\r%d%s\w)",(get_pcvar_num(g_sfrMode)==1)?get_pcvar_num(g_sfrExe):get_pcvar_num(g_sfrPacks),(get_pcvar_num(g_sfrMode)==1)?"经验":"弹药袋") + menu_additem(iMenu, opcion, szTempid,0) + } + menu_setprop(iMenu, MPROP_EXIT, MEXIT_ALL) + formatex(opcion, charsmax(opcion),"\w返回") //返回菜单的名字 + menu_setprop(iMenu, MPROP_BACKNAME, opcion) + formatex(opcion, charsmax(opcion),"\w下一页") //下一页菜单的名字 + menu_setprop(iMenu, MPROP_NEXTNAME, opcion) + formatex(opcion, charsmax(opcion),"\w退出") //退出菜单的名字 + menu_setprop(iMenu, MPROP_EXITNAME, opcion) + menu_setprop(iMenu, MPROP_NUMBER_COLOR, "\r") //菜单前面颜色的数字 + menu_display(id, iMenu, 0) + } + else + { + client_color(id,"/ctr升级菜单/y被限制开局后/g%d/y秒才可以打开,请/g等待.",get_pcvar_num(g_sfOpenTime)) + } + + return PLUGIN_HANDLED +} + +public client_disconnect(id) +{ + ApackPD[id]=0 + ItemSF[id]=0 + get_all(Limit,ITEMNUM-1,0,id) + get_all(ITime,ITEMNUM-1,0,id) + for(new i=0;i<=IteamNums-1;i++) + g_skilllevel[id][i]=0 + remove_task(id) + remove_task(id+1000) + g_levelexe[id]=0 + g_leveltotalexe[id]=get_pcvar_num(g_sfBasicExe) + g_level[id]=1 + g_levelpoint[id]=0 +} + + + +/*============================华丽分割线===============================*/ + +stock client_color(id, const input[], any:...) +{ + static iPlayersNum[32], iCount; iCount = 1 + static szMsg[191] + + vformat(szMsg, charsmax(szMsg), input, 3) + + replace_all(szMsg, 190, "/g", "^4") // 绿色 + replace_all(szMsg, 190, "/y", "^1") // 橙色 + replace_all(szMsg, 190, "/ctr", "^3") // 队伍色 + replace_all(szMsg, 190, "/w", "^0") // 黄色 + + if(id) iPlayersNum[0] = id + else get_players(iPlayersNum, iCount, "ch") + + for (new i = 0; i < iCount; i++) + { + if (is_user_connected(iPlayersNum[i])) + { + message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SayText"), _, iPlayersNum[i]) + write_byte(iPlayersNum[i]) + write_string(szMsg) + message_end() + } + } +} + +//判断出当前选择的技能是否符合设置的队伍,符合的话返回该技能在队伍中所对应的位置 +stock select_to_num(index,numbers[],len,item) +{ + new empty=0 + for(new i=0;i - net9.0 + net8.0 enable enable true diff --git a/Source/Metahook.Plugin/Metahook.Plugin.csproj b/Source/Metahook.Plugin/Metahook.Plugin.csproj index d081498..5911da2 100644 --- a/Source/Metahook.Plugin/Metahook.Plugin.csproj +++ b/Source/Metahook.Plugin/Metahook.Plugin.csproj @@ -1,7 +1,7 @@  - net9.0 + net8.0 enable enable true diff --git a/Source/SourceGenerators/AmxxModuleSourceGenerator/Amxmodx.SourceGenerator.csproj b/Source/SourceGenerators/AmxxModuleSourceGenerator/Amxmodx.SourceGenerator.csproj index 6122a8b..61803fc 100644 --- a/Source/SourceGenerators/AmxxModuleSourceGenerator/Amxmodx.SourceGenerator.csproj +++ b/Source/SourceGenerators/AmxxModuleSourceGenerator/Amxmodx.SourceGenerator.csproj @@ -7,7 +7,7 @@ - + diff --git a/Template/Amxmodx.Module.Template/.template.config/template.json b/Template/Amxmodx.Module.Template/.template.config/template.json index a5c20e6..98d1aac 100644 --- a/Template/Amxmodx.Module.Template/.template.config/template.json +++ b/Template/Amxmodx.Module.Template/.template.config/template.json @@ -10,6 +10,17 @@ "type": "project" }, "sourceName": "Amxmodx.Module.Template", - "preferNameDirectory": true + "preferNameDirectory": true, + "sources": [ + { + "source": "./", + "target": "./", + "exclude": [".template.config/**/*"] + }, + { + "source": "Bridge", + "target": "Bridge" + } + ] } \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.csproj b/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.csproj index 4616131..0a48e67 100644 --- a/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.csproj +++ b/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.csproj @@ -10,8 +10,17 @@ $(MSBuildProjectName.Replace(".", ""))_amxx + + + + + + + + + diff --git a/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.sln b/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.sln new file mode 100644 index 0000000..7cfe4d7 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Amxmodx.Module.Template.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34227.203 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Amxmodx.Module.Template", "Amxmodx.Module.Template.csproj", "{01F1C56E-754E-41F2-8503-A9379E328F27}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {01F1C56E-754E-41F2-8503-A9379E328F27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01F1C56E-754E-41F2-8503-A9379E328F27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01F1C56E-754E-41F2-8503-A9379E328F27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01F1C56E-754E-41F2-8503-A9379E328F27}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0ED03508-EFF5-4811-98DC-E6E0936B23BA} + EndGlobalSection +EndGlobal diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Event.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Event.cs new file mode 100644 index 0000000..4c8623b --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Event.cs @@ -0,0 +1,223 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Event +{ + /// + /// 事件标志枚举 + /// + [Flags] + public enum EventFlags + { + /// + /// 无特殊标志 + /// + None = 0, + + /// + /// 包含世界事件 + /// + IncludeWorld = 1, + + /// + /// 包含客户端事件 + /// + IncludeClient = 2, + + /// + /// 只执行一次 + /// + Once = 4, + + /// + /// 只包含死亡玩家 + /// + DeadOnly = 8, + + /// + /// 只包含存活玩家 + /// + AliveOnly = 16, + + /// + /// 不包含机器人 + /// + NoBots = 32, + + /// + /// 不包含真实玩家 + /// + NoPlayers = 64 + } + + /// + /// 事件回调委托 + /// + /// 事件数据 + public delegate void EventCallback(EventData eventData); + + /// + /// 事件数据类 + /// + public class EventData + { + /// + /// 事件名称 + /// + public string EventName { get; set; } + + /// + /// 触发事件的玩家ID + /// + public int PlayerId { get; set; } + + /// + /// 事件参数 + /// + public object[] Parameters { get; set; } + } + + /// + /// 事件系统桥接接口 + /// + public static class EventBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 注册游戏事件 + /// + /// 事件名称 + /// 回调函数名 + /// 事件标志 + /// 事件条件数组 + /// 条件数量 + /// 事件句柄,失败返回0 + [DllImport(DllName, EntryPoint = "AmxModx_Bridge_RegisterEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern int RegisterEvent([MarshalAs(UnmanagedType.LPStr)] string eventName, + [MarshalAs(UnmanagedType.LPStr)] string callbackFunc, + int flags, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] conditions, + int conditionCount); + + /// + /// 扩展注册游戏事件 + /// + /// 事件名称 + /// 回调函数名 + /// 事件标志 + /// 事件条件数组 + /// 条件数量 + /// 事件句柄,失败返回0 + [DllImport(DllName, EntryPoint = "AmxModx_Bridge_RegisterEventEx", CallingConvention = CallingConvention.Cdecl)] + public static extern int RegisterEventEx([MarshalAs(UnmanagedType.LPStr)] string eventName, + [MarshalAs(UnmanagedType.LPStr)] string callbackFunc, + int flags, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] conditions, + int conditionCount); + + /// + /// 启用事件 + /// + /// 事件句柄 + /// 成功返回1,失败返回0 + [DllImport(DllName, EntryPoint = "AmxModx_Bridge_EnableEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern int EnableEvent(int eventHandle); + + /// + /// 禁用事件 + /// + /// 事件句柄 + /// 成功返回1,失败返回0 + [DllImport(DllName, EntryPoint = "AmxModx_Bridge_DisableEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern int DisableEvent(int eventHandle); + + /// + /// 获取事件ID + /// + /// 事件名称 + /// 事件ID,0表示无效事件 + [DllImport(DllName, EntryPoint = "AmxModx_Bridge_GetEventId", CallingConvention = CallingConvention.Cdecl)] + public static extern int GetEventId([MarshalAs(UnmanagedType.LPStr)] string eventName); + + /// + /// 检查事件是否有效 + /// + /// 事件句柄 + /// 有效返回1,无效返回0 + [DllImport(DllName, EntryPoint = "AmxModx_Bridge_IsEventValid", CallingConvention = CallingConvention.Cdecl)] + public static extern int IsEventValid(int eventHandle); + + /// + /// 注册事件并绑定回调 + /// + /// 事件名称 + /// 回调函数 + /// 事件标志 + /// 事件条件 + /// 事件句柄 + public static int RegisterEventWithCallback(string eventName, EventCallback callback, EventFlags flags = EventFlags.None, params string[] conditions) + { + // 注意:由于AMX Mod X的事件系统需要函数名, + // 这里需要实现一个映射机制来将C#委托映射到内部函数 + // 简化实现:返回句柄,实际回调需要通过其他机制处理 + return RegisterEvent(eventName, "EventCallbackProxy", (int)flags, conditions, conditions?.Length ?? 0); + } + + /// + /// 注册常见游戏事件 + /// + public static class GameEvents + { + /// + /// 玩家死亡事件 + /// + public const string PlayerDeath = "DeathMsg"; + + /// + /// 玩家连接事件 + /// + public const string PlayerConnect = "PlayerConnect"; + + /// + /// 玩家断开连接事件 + /// + public const string PlayerDisconnect = "PlayerDisconnect"; + + /// + /// 玩家重生事件 + /// + public const string PlayerSpawn = "Spawn"; + + /// + /// 回合开始事件 + /// + public const string RoundStart = "RoundStart"; + + /// + /// 回合结束事件 + /// + public const string RoundEnd = "RoundEnd"; + + /// + /// 炸弹安放事件 + /// + public const string BombPlanted = "BombPlanted"; + + /// + /// 炸弹爆炸事件 + /// + public const string BombExploded = "BombExploded"; + + /// + /// 炸弹拆除事件 + /// + public const string BombDefused = "BombDefused"; + + /// + /// 人质救援事件 + /// + public const string HostageRescued = "HostageRescued"; + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Forward.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Forward.cs new file mode 100644 index 0000000..6d5b00d --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Forward.cs @@ -0,0 +1,252 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge +{ + /// + /// 转发系统桥接接口 + /// 提供AMX Mod X转发器的C#封装 + /// + public static class Forward + { + /// + /// 参数类型枚举 + /// + public enum ForwardParamType + { + /// 普通整数 + Cell = 0, + /// 浮点数 + Float = 1, + /// 字符串 + String = 2, + /// 可更新字符串 + StringEx = 3, + /// 数组 + Array = 4, + /// 整数引用 + CellByRef = 5, + /// 浮点数引用 + FloatByRef = 6 + } + + /// + /// 执行类型枚举 + /// + public enum ForwardExecType + { + /// 忽略返回值 + Ignore = 0, + /// 遇到PLUGIN_HANDLED时停止 + Stop = 1, + /// 遇到PLUGIN_HANDLED时停止,其他值继续 + Stop2 = 2, + /// 继续执行,返回最大返回值 + Continue = 3 + } + + /// + /// 创建多插件转发器 + /// + /// 转发器名称 + /// 执行类型 + /// 参数类型数组 + /// 转发器ID,失败返回-1 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_CreateMultiForward( + [MarshalAs(UnmanagedType.LPStr)] string funcName, + ForwardExecType execType, + int numParams, + [In, MarshalAs(UnmanagedType.LPArray)] int[] paramTypes + ); + + /// + /// 创建单插件转发器 + /// + /// 插件ID + /// 函数名称 + /// 参数类型数组 + /// 转发器ID,失败返回-1 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_CreateOneForward( + int pluginId, + [MarshalAs(UnmanagedType.LPStr)] string funcName, + int numParams, + [In, MarshalAs(UnmanagedType.LPArray)] int[] paramTypes + ); + + /// + /// 销毁转发器 + /// + /// 转发器ID + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_DestroyForward(int forwardId); + + /// + /// 执行转发器 + /// + /// 转发器ID + /// 参数数组 + /// 执行结果 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteForward( + int forwardId, + [In, MarshalAs(UnmanagedType.LPArray)] int[] parameters, + int numParams + ); + + /// + /// 准备数组参数 + /// + /// 数组数据 + /// 数组大小 + /// 是否复制回数据 + /// 数组句柄 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_PrepareArray( + [In, MarshalAs(UnmanagedType.LPArray)] int[] arrayData, + int size, + int copyBack + ); + + /// + /// 获取转发器参数数量 + /// + /// 转发器ID + /// 参数数量,失败返回-1 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetForwardParamCount(int forwardId); + + /// + /// 获取转发器参数类型 + /// + /// 转发器ID + /// 参数索引 + /// 参数类型,失败返回-1 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetForwardParamType(int forwardId, int paramIndex); + + /// + /// 创建多插件转发器(简化版) + /// + /// 转发器名称 + /// 执行类型 + /// 参数类型数组 + /// 转发器ID + public static int CreateMultiForward(string funcName, ForwardExecType execType, params ForwardParamType[] paramTypes) + { + int[] types = Array.ConvertAll(paramTypes, x => (int)x); + return AmxModx_Bridge_CreateMultiForward(funcName, execType, types.Length, types); + } + + /// + /// 创建单插件转发器(简化版) + /// + /// 插件ID + /// 函数名称 + /// 参数类型数组 + /// 转发器ID + public static int CreateOneForward(int pluginId, string funcName, params ForwardParamType[] paramTypes) + { + int[] types = Array.ConvertAll(paramTypes, x => (int)x); + return AmxModx_Bridge_CreateOneForward(pluginId, funcName, types.Length, types); + } + + /// + /// 执行转发器(简化版) + /// + /// 转发器ID + /// 参数数组 + /// 执行结果 + public static int ExecuteForward(int forwardId, params int[] parameters) + { + return AmxModx_Bridge_ExecuteForward(forwardId, parameters, parameters.Length); + } + + /// + /// 准备数组参数(简化版) + /// + /// 数组数据 + /// 是否复制回数据 + /// 数组句柄 + public static int PrepareArray(int[] arrayData, bool copyBack = false) + { + return AmxModx_Bridge_PrepareArray(arrayData, arrayData.Length, copyBack ? 1 : 0); + } + + /// + /// 委托定义:转发回调函数 + /// + /// 参数数组 + /// 执行结果 + public delegate int ForwardCallback(params int[] parameters); + + /// + /// 事件管理器类 + /// + public static class ForwardManager + { + /// + /// 已注册的转发器字典 + /// + private static Dictionary forwards = + new Dictionary(); + + /// + /// 注册全局转发器 + /// + /// 转发器名称 + /// 执行类型 + /// 参数类型 + /// 转发器ID + public static int RegisterForward(string name, ForwardExecType execType, params ForwardParamType[] paramTypes) + { + if (forwards.ContainsKey(name)) + return forwards[name]; + + int forwardId = CreateMultiForward(name, execType, paramTypes); + if (forwardId >= 0) + forwards[name] = forwardId; + + return forwardId; + } + + /// + /// 获取转发器ID + /// + /// 转发器名称 + /// 转发器ID,不存在返回-1 + public static int GetForward(string name) + { + return forwards.ContainsKey(name) ? forwards[name] : -1; + } + + /// + /// 执行已注册的转发器 + /// + /// 转发器名称 + /// 参数 + /// 执行结果 + public static int ExecuteRegisteredForward(string name, params int[] parameters) + { + if (!forwards.ContainsKey(name)) + return 0; + + return ExecuteForward(forwards[name], parameters); + } + + /// + /// 清理所有转发器 + /// + public static void Clear() + { + foreach (var forwardId in forwards.Values) + { + AmxModx_Bridge_DestroyForward(forwardId); + } + forwards.Clear(); + } + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Messages.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Messages.cs new file mode 100644 index 0000000..3acdc9d --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Communication/AmxModx.Bridge.Messages.cs @@ -0,0 +1,319 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +namespace AmxModx.Bridge.Messages +{ + /// + /// 消息系统桥接接口 + /// + public static class MessageBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 消息目标类型 + /// + public enum MessageDestination + { + BROADCAST = 0, + ONE = 1, + ALL = 2, + INIT = 3, + PVS = 4, + PAS = 5, + PVS_R = 6, + PAS_R = 7, + ONE_UNRELIABLE = 8, + SPEC = 32 + } + + /// + /// 消息参数类型 + /// + public enum MessageArgType + { + BYTE = 1, + CHAR = 2, + SHORT = 3, + LONG = 4, + ANGLE = 5, + COORD = 6, + STRING = 7, + ENTITY = 8 + } + + /// + /// 开始发送消息 + /// + /// 消息目标 + /// 消息类型 + /// 消息原点坐标 + /// 实体索引 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_MessageBegin( + int msgDest, + int msgType, + [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] float[] origin, + int edict); + + /// + /// 结束消息发送 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_MessageEnd(); + + /// + /// 写入字节数据到消息 + /// + /// 字节值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteByte(int value); + + /// + /// 写入字符数据到消息 + /// + /// 字符值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteChar(int value); + + /// + /// 写入短整型数据到消息 + /// + /// 短整型值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteShort(int value); + + /// + /// 写入长整型数据到消息 + /// + /// 长整型值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteLong(int value); + + /// + /// 写入实体数据到消息 + /// + /// 实体索引 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteEntity(int value); + + /// + /// 写入角度数据到消息 + /// + /// 角度值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteAngle(float value); + + /// + /// 写入坐标数据到消息 + /// + /// 坐标值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteCoord(float value); + + /// + /// 写入字符串数据到消息 + /// + /// 字符串值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_WriteString([MarshalAs(UnmanagedType.LPStr)] string str); + + /// + /// 注册消息钩子 + /// + /// 消息ID + /// 回调函数指针 + /// 是否为后置钩子 + /// 是否注册成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterMessage(int msgId, IntPtr callback, int post); + + /// + /// 注销消息钩子 + /// + /// 消息ID + /// 回调函数指针 + /// 是否为后置钩子 + /// 是否注销成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_UnregisterMessage(int msgId, IntPtr callback, int post); + + /// + /// 设置消息阻塞 + /// + /// 消息ID + /// 是否阻塞 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetMessageBlock(int msgId, int blocking); + + /// + /// 获取消息阻塞状态 + /// + /// 消息ID + /// 阻塞状态 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMessageBlock(int msgId); + + /// + /// 获取消息参数数量 + /// + /// 参数数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMessageArgs(); + + /// + /// 获取消息参数类型 + /// + /// 参数索引 + /// 参数类型 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMessageArgType(int argIndex); + + /// + /// 获取消息参数整数值 + /// + /// 参数索引 + /// 整数值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMessageArgInt(int argIndex); + + /// + /// 获取消息参数浮点数值 + /// + /// 参数索引 + /// 浮点数值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern float AmxModx_Bridge_GetMessageArgFloat(int argIndex); + + /// + /// 获取消息参数字符串值 + /// + /// 参数索引 + /// 输出缓冲区 + /// 缓冲区大小 + /// 实际复制的字符数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMessageArgString(int argIndex, [MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, int bufferSize); + + /// + /// 设置消息参数整数值 + /// + /// 参数索引 + /// 整数值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetMessageArgInt(int argIndex, int value); + + /// + /// 设置消息参数浮点数值 + /// + /// 参数索引 + /// 浮点数值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetMessageArgFloat(int argIndex, float value); + + /// + /// 设置消息参数字符串值 + /// + /// 参数索引 + /// 字符串值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetMessageArgString(int argIndex, [MarshalAs(UnmanagedType.LPStr)] string str); + + /// + /// 消息管理器包装类 + /// + public static class MessageManager + { + /// + /// 开始发送消息 + /// + public static void BeginMessage(MessageDestination dest, int msgType, float[] origin = null, int entityIndex = 0) + { + float[] originArray = origin ?? new float[3]; + AmxModx_Bridge_MessageBegin((int)dest, msgType, originArray, entityIndex); + } + + /// + /// 结束消息发送 + /// + public static void EndMessage() + { + AmxModx_Bridge_MessageEnd(); + } + + /// + /// 发送简单消息 + /// + public static void SendMessage(MessageDestination dest, int msgType, Action writeAction) + { + BeginMessage(dest, msgType); + writeAction?.Invoke(); + EndMessage(); + } + + /// + /// 写入字节数据 + /// + public static void WriteByte(byte value) + { + AmxModx_Bridge_WriteByte(value); + } + + /// + /// 写入字符数据 + /// + public static void WriteChar(sbyte value) + { + AmxModx_Bridge_WriteChar(value); + } + + /// + /// 写入短整型数据 + /// + public static void WriteShort(short value) + { + AmxModx_Bridge_WriteShort(value); + } + + /// + /// 写入长整型数据 + /// + public static void WriteLong(int value) + { + AmxModx_Bridge_WriteLong(value); + } + + /// + /// 写入实体数据 + /// + public static void WriteEntity(int entityIndex) + { + AmxModx_Bridge_WriteEntity(entityIndex); + } + + /// + /// 写入角度数据 + /// + public static void WriteAngle(float angle) + { + AmxModx_Bridge_WriteAngle(angle); + } + + /// + /// 写入坐标数据 + /// + public static void WriteCoord(float coord) + { + AmxModx_Bridge_WriteCoord(coord); + } + + /// + /// 写入字符串数据 + /// + public static void WriteString(string text) + { + AmxModx_Bridge_WriteString(text); + } + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.CVar.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.CVar.cs new file mode 100644 index 0000000..44de2d7 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.CVar.cs @@ -0,0 +1,188 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.CVar +{ + /// + /// 控制台变量桥接接口,提供CVar操作功能 + /// + public static class CVarBridge + { + private const string NativeLibrary = "amxmodx_mm"; + + #region CVar操作 + + /// + /// 创建控制台变量 + /// + /// 变量名 + /// 初始值 + /// 变量标志 + /// 创建的变量指针 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_CreateCVar([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value, int flags); + + /// + /// 查找控制台变量 + /// + /// 变量名 + /// 找到的变量指针 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_FindCVar([MarshalAs(UnmanagedType.LPStr)] string name); + + /// + /// 获取控制台变量字符串值 + /// + /// 变量指针 + /// 字符串值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_GetCVarString(IntPtr cvar); + + /// + /// 获取控制台变量浮点数值 + /// + /// 变量指针 + /// 浮点数值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern float AmxModx_Bridge_GetCVarFloat(IntPtr cvar); + + /// + /// 获取控制台变量整数值 + /// + /// 变量指针 + /// 整数值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetCVarInt(IntPtr cvar); + + /// + /// 设置控制台变量字符串值 + /// + /// 变量指针 + /// 要设置的字符串值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetCVarString(IntPtr cvar, [MarshalAs(UnmanagedType.LPStr)] string value); + + /// + /// 设置控制台变量浮点数值 + /// + /// 变量指针 + /// 要设置的浮点数值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetCVarFloat(IntPtr cvar, float value); + + /// + /// 设置控制台变量整数值 + /// + /// 变量指针 + /// 要设置的整数值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetCVarInt(IntPtr cvar, int value); + + #endregion + + #region 便捷方法 + + /// + /// 获取CVar字符串值的安全封装 + /// + /// 变量指针 + /// 字符串值 + public static string GetCVarStringSafe(IntPtr cvar) + { + if (cvar == IntPtr.Zero) + return string.Empty; + + IntPtr ptr = AmxModx_Bridge_GetCVarString(cvar); + return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : string.Empty; + } + + /// + /// 通过变量名获取字符串值 + /// + /// 变量名 + /// 字符串值 + public static string GetCVarStringByName(string name) + { + if (string.IsNullOrEmpty(name)) + return string.Empty; + + IntPtr cvar = AmxModx_Bridge_FindCVar(name); + return GetCVarStringSafe(cvar); + } + + /// + /// 通过变量名获取浮点数值 + /// + /// 变量名 + /// 浮点数值 + public static float GetCVarFloatByName(string name) + { + if (string.IsNullOrEmpty(name)) + return 0.0f; + + IntPtr cvar = AmxModx_Bridge_FindCVar(name); + return cvar != IntPtr.Zero ? AmxModx_Bridge_GetCVarFloat(cvar) : 0.0f; + } + + /// + /// 通过变量名获取整数值 + /// + /// 变量名 + /// 整数值 + public static int GetCVarIntByName(string name) + { + if (string.IsNullOrEmpty(name)) + return 0; + + IntPtr cvar = AmxModx_Bridge_FindCVar(name); + return cvar != IntPtr.Zero ? AmxModx_Bridge_GetCVarInt(cvar) : 0; + } + + /// + /// 通过变量名设置字符串值 + /// + /// 变量名 + /// 要设置的值 + public static void SetCVarStringByName(string name, string value) + { + if (string.IsNullOrEmpty(name)) + return; + + IntPtr cvar = AmxModx_Bridge_FindCVar(name); + if (cvar != IntPtr.Zero) + AmxModx_Bridge_SetCVarString(cvar, value); + } + + /// + /// 通过变量名设置浮点数值 + /// + /// 变量名 + /// 要设置的值 + public static void SetCVarFloatByName(string name, float value) + { + if (string.IsNullOrEmpty(name)) + return; + + IntPtr cvar = AmxModx_Bridge_FindCVar(name); + if (cvar != IntPtr.Zero) + AmxModx_Bridge_SetCVarFloat(cvar, value); + } + + /// + /// 通过变量名设置整数值 + /// + /// 变量名 + /// 要设置的值 + public static void SetCVarIntByName(string name, int value) + { + if (string.IsNullOrEmpty(name)) + return; + + IntPtr cvar = AmxModx_Bridge_FindCVar(name); + if (cvar != IntPtr.Zero) + AmxModx_Bridge_SetCVarInt(cvar, value); + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.Config.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.Config.cs new file mode 100644 index 0000000..cb8cda2 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.Config.cs @@ -0,0 +1,51 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.Config +{ + /// + /// 配置文件桥接接口 + /// 提供游戏配置文件处理功能 + /// + public static class ConfigBridge + { + /// + /// 加载游戏配置文件 + /// + /// 配置文件名称 + /// 配置句柄 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_LoadGameConfig([MarshalAs(UnmanagedType.LPStr)] string configName); + + /// + /// 获取配置值 + /// + /// 配置句柄 + /// 配置键 + /// 输出缓冲区 + /// 缓冲区大小 + /// 实际长度 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetConfigValue(IntPtr configHandle, [MarshalAs(UnmanagedType.LPStr)] string key, [Out] byte[] buffer, int bufferSize); + + /// + /// 安全的获取配置值方法 + /// + /// 配置句柄 + /// 配置键 + /// 配置值 + public static string GetConfigValueSafe(IntPtr configHandle, string key) + { + if (configHandle == IntPtr.Zero || string.IsNullOrEmpty(key)) + return string.Empty; + + byte[] buffer = new byte[256]; + int length = AmxModx_Bridge_GetConfigValue(configHandle, key, buffer, buffer.Length); + if (length <= 0) + return string.Empty; + + return Encoding.UTF8.GetString(buffer, 0, Math.Min(length, buffer.Length)); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.DataPack.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.DataPack.cs new file mode 100644 index 0000000..f65a0fd --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.DataPack.cs @@ -0,0 +1,119 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.DataPack +{ + /// + /// 数据包桥接接口,提供CDataPack操作功能 + /// + public static class DataPackBridge + { + private const string NativeLibrary = "amxmodx_mm"; + + #region DataPack操作 + + /// + /// 创建新的数据包 + /// + /// 新创建的数据包指针 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_CreateDataPack(); + + /// + /// 销毁数据包 + /// + /// 要销毁的数据包指针 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_DestroyDataPack(IntPtr pack); + + /// + /// 获取数据包当前位置 + /// + /// 数据包指针 + /// 当前位置 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetDataPackPosition(IntPtr pack); + + /// + /// 设置数据包位置 + /// + /// 数据包指针 + /// 要设置的位置 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetDataPackPosition(IntPtr pack, int position); + + /// + /// 向数据包写入整数 + /// + /// 数据包指针 + /// 要写入的值 + /// 写入是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_WriteDataPackCell(IntPtr pack, int value); + + /// + /// 向数据包写入浮点数 + /// + /// 数据包指针 + /// 要写入的值 + /// 写入是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_WriteDataPackFloat(IntPtr pack, float value); + + /// + /// 向数据包写入字符串 + /// + /// 数据包指针 + /// 要写入的字符串 + /// 写入是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_WriteDataPackString(IntPtr pack, [MarshalAs(UnmanagedType.LPStr)] string value); + + /// + /// 从数据包读取整数 + /// + /// 数据包指针 + /// 读取的整数值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ReadDataPackCell(IntPtr pack); + + /// + /// 从数据包读取浮点数 + /// + /// 数据包指针 + /// 读取的浮点数值 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern float AmxModx_Bridge_ReadDataPackFloat(IntPtr pack); + + /// + /// 从数据包读取字符串 + /// + /// 数据包指针 + /// 读取的字符串 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_ReadDataPackString(IntPtr pack); + + #endregion + + #region 便捷方法 + + /// + /// 从数据包读取字符串的安全封装 + /// + /// 数据包指针 + /// 读取的字符串 + public static string ReadDataPackStringSafe(IntPtr pack) + { + if (pack == IntPtr.Zero) + return string.Empty; + + IntPtr ptr = AmxModx_Bridge_ReadDataPackString(pack); + return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : string.Empty; + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.DataStructs.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.DataStructs.cs new file mode 100644 index 0000000..98e9917 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.DataStructs.cs @@ -0,0 +1,188 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.Data +{ + /// + /// 数据结构桥接接口 + /// 提供动态数组和栈结构的C#访问 + /// + public static class DataStructsBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 创建动态数组 + /// + /// 每个元素的大小(以cell为单位) + /// 初始预留容量 + /// 数组句柄,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayCreate(int cellsize, int reserved = 32); + + /// + /// 销毁数组并释放内存 + /// + /// 数组句柄(传引用,成功后会置0) + /// 是否成功销毁 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ArrayDestroy(ref int handle); + + /// + /// 获取数组当前元素数量 + /// + /// 数组句柄 + /// 元素数量,失败返回-1 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArraySize(int handle); + + /// + /// 调整数组大小 + /// + /// 数组句柄 + /// 新的元素数量 + /// 是否成功调整 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ArrayResize(int handle, int count); + + /// + /// 获取数组元素(单元格值) + /// + /// 数组句柄 + /// 元素索引 + /// 数据块索引(默认为0) + /// 单元格值,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayGetCell(int handle, int index, int block = 0); + + /// + /// 设置数组元素(单元格值) + /// + /// 数组句柄 + /// 元素索引 + /// 要设置的值 + /// 数据块索引(默认为0) + /// 是否成功设置 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ArraySetCell(int handle, int index, int value, int block = 0); + + /// + /// 向数组末尾添加单元格值 + /// + /// 数组句柄 + /// 要添加的值 + /// 新元素的索引,失败返回-1 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayPushCell(int handle, int value); + + /// + /// 从数组获取字符串 + /// + /// 数组句柄 + /// 元素索引 + /// 输出缓冲区 + /// 缓冲区大小 + /// 实际复制的字符数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayGetString(int handle, int index, [Out] StringBuilder buffer, int size); + + /// + /// 向数组设置字符串 + /// + /// 数组句柄 + /// 元素索引 + /// 要设置的字符串 + /// 实际复制的字符数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArraySetString(int handle, int index, [MarshalAs(UnmanagedType.LPStr)] string str); + + /// + /// 克隆数组 + /// + /// 原数组句柄 + /// 新数组句柄,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayClone(int handle); + + /// + /// 清空数组内容 + /// + /// 数组句柄 + /// 是否成功清空 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ArrayClear(int handle); + + /// + /// 删除指定索引的元素 + /// + /// 数组句柄 + /// 要删除的索引 + /// 是否成功删除 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ArrayDeleteItem(int handle, int index); + + /// + /// 交换两个元素的位置 + /// + /// 数组句柄 + /// 第一个索引 + /// 第二个索引 + /// 是否成功交换 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ArraySwap(int handle, int index1, int index2); + + /// + /// 在数组中查找字符串 + /// + /// 数组句柄 + /// 要查找的字符串 + /// 找到返回索引,未找到返回-1 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayFindString(int handle, [MarshalAs(UnmanagedType.LPStr)] string str); + + /// + /// 在数组中查找数值 + /// + /// 数组句柄 + /// 要查找的值 + /// 找到返回索引,未找到返回-1 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ArrayFindValue(int handle, int value); + + /// + /// 安全的获取数组字符串 + /// + /// 数组句柄 + /// 元素索引 + /// 字符串值 + public static string GetArrayStringSafe(int handle, int index) + { + StringBuilder buffer = new StringBuilder(256); + int length = AmxModx_Bridge_ArrayGetString(handle, index, buffer, buffer.Capacity); + return length > 0 ? buffer.ToString() : string.Empty; + } + + /// + /// 安全的设置数组字符串 + /// + /// 数组句柄 + /// 元素索引 + /// 字符串值 + /// 是否成功设置 + public static bool SetArrayStringSafe(int handle, int index, string value) + { + if (string.IsNullOrEmpty(value)) + return false; + + int result = AmxModx_Bridge_ArraySetString(handle, index, value); + return result > 0; + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.File.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.File.cs new file mode 100644 index 0000000..6cd271b --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.File.cs @@ -0,0 +1,131 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.File +{ + /// + /// 文件系统桥接接口,提供文件操作功能 + /// + public static class FileBridge + { + private const string NativeLibrary = "amxmodx_mm"; + + #region 文件系统操作 + + /// + /// 读取文件内容到内存缓冲区 + /// + /// 文件路径 + /// 返回文件大小 + /// 文件内容缓冲区指针,需要手动释放 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_ReadFile([MarshalAs(UnmanagedType.LPStr)] string filePath, out int size); + + /// + /// 将数据写入文件 + /// + /// 文件路径 + /// 要写入的数据 + /// 数据大小 + /// 写入是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_WriteFile([MarshalAs(UnmanagedType.LPStr)] string filePath, [MarshalAs(UnmanagedType.LPStr)] string data, int size); + + /// + /// 释放由ReadFile分配的缓冲区 + /// + /// 要释放的缓冲区指针 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_FreeBuffer(IntPtr buffer); + + /// + /// 检查文件是否存在 + /// + /// 文件名 + /// 文件是否存在 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_FileExists([MarshalAs(UnmanagedType.LPStr)] string fileName); + + /// + /// 从文件读取字符串内容 + /// + /// 文件名 + /// 输出缓冲区 + /// 缓冲区大小 + /// 读取是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_ReadFileString([MarshalAs(UnmanagedType.LPStr)] string fileName, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, int bufferSize); + + /// + /// 将字符串写入文件 + /// + /// 文件名 + /// 要写入的内容 + /// 写入是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_WriteFileString([MarshalAs(UnmanagedType.LPStr)] string fileName, [MarshalAs(UnmanagedType.LPStr)] string content); + + /// + /// 删除文件 + /// + /// 文件名 + /// 删除是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_DeleteFile([MarshalAs(UnmanagedType.LPStr)] string fileName); + + #endregion + + #region 便捷方法 + + /// + /// 安全读取文件内容 + /// + /// 文件路径 + /// 文件内容字符串,失败返回null + public static string ReadFileSafe(string filePath) + { + if (string.IsNullOrEmpty(filePath)) + return null; + + IntPtr buffer = IntPtr.Zero; + try + { + buffer = AmxModx_Bridge_ReadFile(filePath, out int size); + if (buffer == IntPtr.Zero || size <= 0) + return null; + + byte[] data = new byte[size]; + Marshal.Copy(buffer, data, 0, size); + return Encoding.UTF8.GetString(data).TrimEnd('\0'); + } + finally + { + if (buffer != IntPtr.Zero) + AmxModx_Bridge_FreeBuffer(buffer); + } + } + + /// + /// 安全写入文件内容 + /// + /// 文件路径 + /// 要写入的内容 + /// 写入是否成功 + public static bool WriteFileSafe(string filePath, string content) + { + if (string.IsNullOrEmpty(filePath) || content == null) + return false; + + byte[] data = Encoding.UTF8.GetBytes(content); + return AmxModx_Bridge_WriteFile(filePath, content, data.Length); + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.GameConfigs.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.GameConfigs.cs new file mode 100644 index 0000000..8043c04 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.GameConfigs.cs @@ -0,0 +1,203 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.GameConfigs +{ + /// + /// 游戏配置系统桥接接口 + /// + public static class GameConfigBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 加载游戏配置文件 + /// + /// 配置文件名 + /// 错误信息缓冲区 + /// 缓冲区大小 + /// 游戏配置句柄,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_LoadGameConfigFile( + [MarshalAs(UnmanagedType.LPStr)] string fileName, + [MarshalAs(UnmanagedType.LPStr)] StringBuilder errorBuffer, + int errorBufferSize); + + /// + /// 获取游戏配置偏移量 + /// + /// 游戏配置句柄 + /// 配置键名 + /// 偏移量值,失败返回-1 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GameConfGetOffset( + int handle, + [MarshalAs(UnmanagedType.LPStr)] string key); + + /// + /// 获取类配置偏移量 + /// + /// 游戏配置句柄 + /// 类名 + /// 配置键名 + /// 偏移量值,失败返回-1 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GameConfGetClassOffset( + int handle, + [MarshalAs(UnmanagedType.LPStr)] string className, + [MarshalAs(UnmanagedType.LPStr)] string key); + + /// + /// 获取游戏配置键值 + /// + /// 游戏配置句柄 + /// 配置键名 + /// 输出缓冲区 + /// 缓冲区大小 + /// 是否成功获取 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GameConfGetKeyValue( + int handle, + [MarshalAs(UnmanagedType.LPStr)] string key, + [MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, + int bufferSize); + + /// + /// 获取游戏配置地址 + /// + /// 游戏配置句柄 + /// 地址名 + /// 地址值,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern UIntPtr AmxModx_Bridge_GameConfGetAddress( + int handle, + [MarshalAs(UnmanagedType.LPStr)] string name); + + /// + /// 关闭游戏配置文件 + /// + /// 游戏配置句柄 + /// 是否成功关闭 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_CloseGameConfigFile(ref int handle); + + /// + /// 游戏配置管理器包装类 + /// + public class GameConfigManager : IDisposable + { + private int _handle = -1; + private bool _disposed = false; + + /// + /// 加载游戏配置文件 + /// + /// 配置文件名 + /// 是否加载成功 + public bool LoadConfig(string fileName) + { + if (_handle != -1) + CloseConfig(); + + StringBuilder errorBuffer = new StringBuilder(256); + _handle = AmxModx_Bridge_LoadGameConfigFile(fileName, errorBuffer, errorBuffer.Capacity); + + if (_handle == 0) + { + throw new InvalidOperationException($"Failed to load game config: {errorBuffer}"); + } + + return true; + } + + /// + /// 获取配置偏移量 + /// + public int GetOffset(string key) + { + if (_handle == -1) + throw new InvalidOperationException("No config loaded"); + + return AmxModx_Bridge_GameConfGetOffset(_handle, key); + } + + /// + /// 获取类配置偏移量 + /// + public int GetClassOffset(string className, string key) + { + if (_handle == -1) + throw new InvalidOperationException("No config loaded"); + + return AmxModx_Bridge_GameConfGetClassOffset(_handle, className, key); + } + + /// + /// 获取配置键值 + /// + public string GetKeyValue(string key) + { + if (_handle == -1) + throw new InvalidOperationException("No config loaded"); + + StringBuilder buffer = new StringBuilder(256); + if (AmxModx_Bridge_GameConfGetKeyValue(_handle, key, buffer, buffer.Capacity) == 1) + { + return buffer.ToString(); + } + return null; + } + + /// + /// 获取配置地址 + /// + public IntPtr GetAddress(string name) + { + if (_handle == -1) + throw new InvalidOperationException("No config loaded"); + + UIntPtr address = AmxModx_Bridge_GameConfGetAddress(_handle, name); + return address == UIntPtr.Zero ? IntPtr.Zero : (IntPtr)address; + } + + /// + /// 关闭配置文件 + /// + public void CloseConfig() + { + if (_handle != -1) + { + AmxModx_Bridge_CloseGameConfigFile(ref _handle); + _handle = -1; + } + } + + /// + /// 释放资源 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + CloseConfig(); + } + _disposed = true; + } + } + + ~GameConfigManager() + { + Dispose(false); + } + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.Vault.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.Vault.cs new file mode 100644 index 0000000..16b2a6c --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Data/AmxModx.Bridge.Vault.cs @@ -0,0 +1,110 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Vault +{ + /// + /// Vault持久化存储桥接接口,提供键值存储功能 + /// + public static class VaultBridge + { + private const string NativeLibrary = "amxmodx_mm"; + + #region Vault操作 + + /// + /// 获取全局Vault实例 + /// + /// Vault实例指针 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_GetVault(); + + /// + /// 检查键是否存在 + /// + /// Vault实例指针 + /// 键名 + /// 键是否存在 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_VaultExists(IntPtr vault, [MarshalAs(UnmanagedType.LPStr)] string key); + + /// + /// 存储键值对 + /// + /// Vault实例指针 + /// 键名 + /// 值 + /// 存储是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_VaultPut(IntPtr vault, [MarshalAs(UnmanagedType.LPStr)] string key, [MarshalAs(UnmanagedType.LPStr)] string value); + + /// + /// 移除键值对 + /// + /// Vault实例指针 + /// 键名 + /// 移除是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_VaultRemove(IntPtr vault, [MarshalAs(UnmanagedType.LPStr)] string key); + + /// + /// 获取键对应的值 + /// + /// 键名 + /// 值字符串 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_VaultGet([MarshalAs(UnmanagedType.LPStr)] string key); + + #endregion + + #region 便捷方法 + + /// + /// 获取Vault值的安全封装 + /// + /// 键名 + /// 值字符串 + public static string GetVaultValueSafe(string key) + { + if (string.IsNullOrEmpty(key)) + return string.Empty; + + IntPtr ptr = AmxModx_Bridge_VaultGet(key); + return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : string.Empty; + } + + /// + /// 存储键值对的安全封装 + /// + /// 键名 + /// 值 + /// 存储是否成功 + public static bool SetVaultValueSafe(string key, string value) + { + if (string.IsNullOrEmpty(key) || value == null) + return false; + + IntPtr vault = AmxModx_Bridge_GetVault(); + return vault != IntPtr.Zero && AmxModx_Bridge_VaultPut(vault, key, value); + } + + /// + /// 检查键是否存在 + /// + /// 键名 + /// 键是否存在 + public static bool ExistsVaultKey(string key) + { + if (string.IsNullOrEmpty(key)) + return false; + + IntPtr vault = AmxModx_Bridge_GetVault(); + return vault != IntPtr.Zero && AmxModx_Bridge_VaultExists(vault, key); + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Engine.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Engine.cs new file mode 100644 index 0000000..0ba2675 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Engine.cs @@ -0,0 +1,456 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Engine +{ + /// + /// Engine模块的C#桥接接口 + /// 提供对AMX Mod X引擎功能的访问 + /// + public static class EngineBridge + { + private const string EngineBridgeDll = "engine_amxx"; + + #region 基本类型定义 + + /// + /// 3D向量结构 + /// + [StructLayout(LayoutKind.Sequential)] + public struct Vector3 + { + public float X; + public float Y; + public float Z; + + public Vector3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + public override string ToString() => $"({X}, {Y}, {Z})"; + + public static implicit operator Vector3(float[] array) + { + if (array == null || array.Length < 3) + return new Vector3(0, 0, 0); + return new Vector3(array[0], array[1], array[2]); + } + + public static implicit operator float[](Vector3 vec) + { + return new float[] { vec.X, vec.Y, vec.Z }; + } + } + + /// + /// 追踪结果信息 + /// + [StructLayout(LayoutKind.Sequential)] + public struct TraceResultInfo + { + public int AllSolid; + public int StartSolid; + public int InOpen; + public int InWater; + public float Fraction; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public float[] EndPos; + public float PlaneDist; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public float[] PlaneNormal; + public int HitEntity; + public int HitGroup; + + public TraceResultInfo() + { + EndPos = new float[3]; + PlaneNormal = new float[3]; + } + } + + /// + /// 用户命令信息 + /// + [StructLayout(LayoutKind.Sequential)] + public struct UserCmdInfo + { + public float ForwardMove; + public float SideMove; + public float UpMove; + public float LerpMsec; + public float Msec; + public float LightLevel; + public int Buttons; + public int WeaponSelect; + public int ImpactIndex; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public float[] ViewAngles; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public float[] ImpactPosition; + + public UserCmdInfo() + { + ViewAngles = new float[3]; + ImpactPosition = new float[3]; + } + } + + #endregion + + #region 委托定义 + + /// + /// 脉冲处理委托 + /// + /// 客户端索引 + /// 脉冲值 + public delegate void ImpulseCallback(int client, int impulse); + + /// + /// 触碰处理委托 + /// + /// 被触碰实体 + /// 触碰实体 + public delegate void TouchCallback(int touched, int toucher); + + /// + /// 思考处理委托 + /// + /// 实体索引 + public delegate void ThinkCallback(int entity); + + #endregion + + #region 时间相关 + + /// + /// 获取游戏时间 + /// + /// 当前游戏时间(秒) + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern float Engine_GetGameTime(); + + #endregion + + #region 实体操作 + + /// + /// 创建实体 + /// + /// 实体类名 + /// 实体ID,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_CreateEntity(string className); + + /// + /// 删除实体 + /// + /// 实体ID + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_RemoveEntity(int entityId); + + /// + /// 检查实体是否有效 + /// + /// 实体ID + /// 有效返回1,无效返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_IsValidEntity(int entityId); + + /// + /// 获取当前实体数量 + /// + /// 实体数量 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityCount(); + + /// + /// 计算两个实体间的距离 + /// + /// 实体A + /// 实体B + /// 距离值 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern float Engine_GetEntityDistance(int entityA, int entityB); + + #endregion + + #region 追踪系统 + + /// + /// 线条追踪 + /// + /// 起始点 + /// 结束点 + /// 忽略的实体ID(0表示不忽略) + /// 追踪结果 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_TraceLine(Vector3 start, Vector3 end, int ignoreEntity, out TraceResultInfo result); + + /// + /// 包围盒追踪 + /// + /// 起始点 + /// 结束点 + /// 包围盒类型 + /// 忽略的实体ID + /// 追踪结果 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_TraceHull(Vector3 start, Vector3 end, int hullType, int ignoreEntity, out TraceResultInfo result); + + /// + /// 法线追踪 + /// + /// 实体ID + /// 起始点 + /// 结束点 + /// 返回的法线向量 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_TraceNormal(int entity, Vector3 start, Vector3 end, out Vector3 normal); + + /// + /// 前向追踪 + /// + /// 起始点 + /// 角度 + /// 追踪距离 + /// 忽略的实体ID + /// 追踪结果 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_TraceForward(Vector3 start, Vector3 angles, float give, int ignoreEntity, out TraceResultInfo result); + + #endregion + + #region 游戏事件 + + /// + /// 播放游戏事件 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_PlaybackEvent(int flags, int invoker, ushort eventIndex, float delay, + Vector3 origin, Vector3 angles, float fparam1, float fparam2, + int iparam1, int iparam2, int bparam1, int bparam2); + + #endregion + + #region 范围伤害 + + /// + /// 范围伤害 + /// + /// 伤害中心点 + /// 伤害倍数 + /// 半径倍数 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_RadiusDamage(Vector3 origin, int damageMultiplier, int radiusMultiplier); + + #endregion + + #region 点内容检查 + + /// + /// 检查点的内容类型 + /// + /// 检查点 + /// 内容类型值 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_PointContents(Vector3 point); + + #endregion + + #region 字符串和索引 + + /// + /// 获取贴花索引 + /// + /// 贴花名称 + /// 索引值,失败返回-1 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetDecalIndex(string decalName); + + /// + /// 获取信息键缓冲区 + /// + /// 实体ID(-1表示全局) + /// 接收缓冲区 + /// 缓冲区大小 + /// 实际字符串长度 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetInfoKeyBuffer(int entity, byte[] buffer, int bufferSize); + + /// + /// 获取引擎字符串 + /// + /// 字符串ID + /// 接收缓冲区 + /// 缓冲区大小 + /// 实际字符串长度 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEngineString(int stringId, byte[] buffer, int bufferSize); + + #endregion + + #region 用户命令 + + /// + /// 获取用户命令 + /// + /// 客户端索引 + /// 命令类型 + /// 命令结构 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetUserCmd(int client, int type, out UserCmdInfo cmd); + + /// + /// 设置用户命令 + /// + /// 客户端索引 + /// 命令类型 + /// 命令结构 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetUserCmd(int client, int type, ref UserCmdInfo cmd); + + #endregion + + #region 说话权限 + + /// + /// 设置说话权限 + /// + /// 客户端索引 + /// 说话标志 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetSpeak(int client, int speakFlags); + + /// + /// 获取说话权限 + /// + /// 客户端索引 + /// 说话标志 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetSpeak(int client); + + #endregion + + #region 视角控制 + + /// + /// 设置玩家视角 + /// + /// 客户端索引 + /// 视角实体ID + /// 视角类型 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetView(int client, int viewEntity, int viewType); + + /// + /// 附加视角到目标实体 + /// + /// 客户端索引 + /// 目标实体ID + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_AttachView(int client, int targetEntity); + + #endregion + + #region 光照 + + /// + /// 设置光照 + /// + /// 光照字符串 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetLights(string lights); + + #endregion + + #region 地面放置 + + /// + /// 将实体放置到地面 + /// + /// 实体ID + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_DropToFloor(int entity); + + #endregion + + #region 可见性检查 + + /// + /// 检查实体间是否可见 + /// + /// 源实体 + /// 目标实体 + /// 可见返回1,不可见返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_IsVisible(int srcEntity, int destEntity); + + /// + /// 检查点是否在视角锥内 + /// + /// 实体 + /// 目标点 + /// 在锥内返回1,不在返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_IsInViewCone(int entity, Vector3 target); + + #endregion + + #region 事件注册 + + /// + /// 注册脉冲处理 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_RegisterImpulse(int impulse, ImpulseCallback callback); + + /// + /// 注册触碰处理 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_RegisterTouch(string touchedClass, string toucherClass, TouchCallback callback); + + /// + /// 注册思考处理 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_RegisterThink(string className, ThinkCallback callback); + + /// + /// 注销脉冲处理 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_UnregisterImpulse(int registerId); + + /// + /// 注销触碰处理 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_UnregisterTouch(int registerId); + + /// + /// 注销思考处理 + /// + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_UnregisterThink(int registerId); + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Entity.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Entity.cs new file mode 100644 index 0000000..af8c41a --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Entity.cs @@ -0,0 +1,407 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X Entity Bridge for C# +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Entity +{ + /// + /// 实体管理桥接接口,提供对游戏实体和玩家的访问 + /// + public static class EntityBridge + { + private const string DllName = "amxmodx_mm"; + + #region 实体管理接口 + + /// + /// 获取服务器最大客户端数量 + /// + /// 最大客户端数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMaxClients(); + + /// + /// 获取服务器最大实体数量 + /// + /// 最大实体数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetMaxEntities(); + + /// + /// 获取当前在线玩家数量 + /// + /// 在线玩家数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerCount(); + + /// + /// 检查玩家ID是否有效 + /// + /// 玩家ID + /// 是否有效 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_IsPlayerValid(int playerId); + + /// + /// 检查玩家是否在游戏中 + /// + /// 玩家ID + /// 是否在游戏中 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_IsPlayerInGame(int playerId); + + /// + /// 检查玩家是否存活 + /// + /// 玩家ID + /// 是否存活 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_IsPlayerAlive(int playerId); + + /// + /// 检查玩家是否为机器人 + /// + /// 玩家ID + /// 是否为机器人 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_IsPlayerBot(int playerId); + + #endregion + + #region 实体属性访问 + + /// + /// 获取玩家名称 + /// + /// 玩家ID + /// 玩家名称 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string AmxModx_Bridge_GetPlayerName(int playerId); + + /// + /// 获取玩家IP地址 + /// + /// 玩家ID + /// IP地址 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string AmxModx_Bridge_GetPlayerIPAddress(int playerId); + + /// + /// 获取玩家Steam Auth ID + /// + /// 玩家ID + /// Steam Auth ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string AmxModx_Bridge_GetPlayerAuthID(int playerId); + + /// + /// 获取玩家队伍 + /// + /// 玩家ID + /// 队伍名称 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string AmxModx_Bridge_GetPlayerTeam(int playerId); + + /// + /// 获取玩家UserID + /// + /// 玩家ID + /// UserID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerUserID(int playerId); + + /// + /// 获取玩家击杀数 + /// + /// 玩家ID + /// 击杀数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerFrags(int playerId); + + /// + /// 获取玩家死亡数 + /// + /// 玩家ID + /// 死亡数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerDeaths(int playerId); + + /// + /// 获取玩家生命值 + /// + /// 玩家ID + /// 生命值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerHealth(int playerId); + + /// + /// 获取玩家护甲值 + /// + /// 玩家ID + /// 护甲值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerArmor(int playerId); + + /// + /// 获取玩家延迟 + /// + /// 玩家ID + /// 延迟值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerPing(int playerId); + + #endregion + + #region 实体位置相关 + + /// + /// 获取玩家位置 + /// + /// 玩家ID + /// X坐标 + /// Y坐标 + /// Z坐标 + /// 是否成功获取 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_GetPlayerOrigin(int playerId, out float x, out float y, out float z); + + /// + /// 获取玩家速度 + /// + /// 玩家ID + /// X速度 + /// Y速度 + /// Z速度 + /// 是否成功获取 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_GetPlayerVelocity(int playerId, out float x, out float y, out float z); + + /// + /// 设置玩家位置 + /// + /// 玩家ID + /// X坐标 + /// Y坐标 + /// Z坐标 + /// 是否成功设置 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerOrigin(int playerId, float x, float y, float z); + + /// + /// 设置玩家速度 + /// + /// 玩家ID + /// X速度 + /// Y速度 + /// Z速度 + /// 是否成功设置 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerVelocity(int playerId, float x, float y, float z); + + #endregion + + #region 实体武器相关 + + /// + /// 获取玩家当前武器 + /// + /// 玩家ID + /// 武器ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerCurrentWeapon(int playerId); + + /// + /// 获取玩家弹药数量 + /// + /// 玩家ID + /// 武器ID + /// 弹药数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerAmmo(int playerId, int weaponId); + + /// + /// 检查玩家是否拥有武器 + /// + /// 玩家ID + /// 武器ID + /// 是否拥有武器 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_PlayerHasWeapon(int playerId, int weaponId); + + #endregion + + #region 实体操作 + + /// + /// 击杀玩家 + /// + /// 玩家ID + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_KillPlayer(int playerId); + + /// + /// 拍打玩家 + /// + /// 玩家ID + /// 伤害值 + /// 是否随机速度 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SlapPlayer(int playerId, int damage, [MarshalAs(UnmanagedType.Bool)] bool randomVelocity); + + /// + /// 传送玩家 + /// + /// 玩家ID + /// X坐标 + /// Y坐标 + /// Z坐标 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_TeleportPlayer(int playerId, float x, float y, float z); + + /// + /// 重新生成玩家 + /// + /// 玩家ID + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_RespawnPlayer(int playerId); + + /// + /// 移除玩家所有武器 + /// + /// 玩家ID + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_StripWeapons(int playerId); + + /// + /// 给予玩家武器 + /// + /// 玩家ID + /// 武器名称 + /// 弹药数量 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_GiveWeapon(int playerId, [MarshalAs(UnmanagedType.LPStr)] string weaponName, int ammo); + + /// + /// 设置玩家队伍 + /// + /// 玩家ID + /// 队伍ID + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerTeam(int playerId, int teamId); + + /// + /// 冻结/解冻玩家 + /// + /// 玩家ID + /// 是否冻结 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_FreezePlayer(int playerId, [MarshalAs(UnmanagedType.Bool)] bool freeze); + + /// + /// 设置玩家生命值 + /// + /// 玩家ID + /// 生命值 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerHealth(int playerId, int health); + + /// + /// 设置玩家护甲值 + /// + /// 玩家ID + /// 护甲值 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerArmor(int playerId, int armor); + + /// + /// 设置玩家击杀数 + /// + /// 玩家ID + /// 击杀数 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerFrags(int playerId, int frags); + + /// + /// 设置玩家死亡数 + /// + /// 玩家ID + /// 死亡数 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetPlayerDeaths(int playerId, int deaths); + + #endregion + + #region 实体查找 + + /// + /// 通过UserID查找玩家 + /// + /// UserID + /// 玩家ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_FindPlayerByUserID(int userId); + + /// + /// 通过名称查找玩家 + /// + /// 玩家名称 + /// 玩家ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_FindPlayerByName([MarshalAs(UnmanagedType.LPStr)] string name); + + /// + /// 通过IP地址查找玩家 + /// + /// IP地址 + /// 玩家ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_FindPlayerByIPAddress([MarshalAs(UnmanagedType.LPStr)] string ip); + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Vector.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Vector.cs new file mode 100644 index 0000000..7d6ca18 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/AmxModx.Bridge.Vector.cs @@ -0,0 +1,173 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge +{ + /// + /// 向量运算桥接接口 + /// + public static class Vector + { + private const string DllName = "amxmodx_mm"; + /// + /// 将3D向量转换为角度 + /// + /// 向量的X分量 + /// 向量的Y分量 + /// 向量的Z分量 + /// 输出的X角度 + /// 输出的Y角度 + /// 输出的Z角度 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_VectorToAngle(float x, float y, float z, out float outX, out float outY, out float outZ); + + /// + /// 将角度转换为3D向量 + /// + /// 俯仰角 + /// 偏航角 + /// 翻滚角 + /// 向量类型:1=前向,2=右向,3=上向 + /// 输出的X分量 + /// 输出的Y分量 + /// 输出的Z分量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_AngleVector(float pitch, float yaw, float roll, int type, out float outX, out float outY, out float outZ); + + /// + /// 计算3D向量的长度 + /// + /// 向量的X分量 + /// 向量的Y分量 + /// 向量的Z分量 + /// 向量的长度 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern float AmxModx_Bridge_VectorLength(float x, float y, float z); + + /// + /// 计算两个3D向量之间的距离 + /// + /// 第一个向量的X分量 + /// 第一个向量的Y分量 + /// 第一个向量的Z分量 + /// 第二个向量的X分量 + /// 第二个向量的Y分量 + /// 第二个向量的Z分量 + /// 两个向量之间的距离 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern float AmxModx_Bridge_VectorDistance(float x1, float y1, float z1, float x2, float y2, float z2); + + /// + /// 通过实体的瞄准方向获取速度向量 + /// + /// 实体索引 + /// 速度大小 + /// 输出的X分量 + /// 输出的Y分量 + /// 输出的Z分量 + /// 操作是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_VelocityByAim(int entity, int velocity, out float outX, out float outY, out float outZ); + } + + /// + /// 向量类型枚举 + /// + public enum AngleVectorType + { + /// + /// 前向向量 + /// + Forward = 1, + + /// + /// 右向向量 + /// + Right = 2, + + /// + /// 上向向量 + /// + Up = 3 + } + + /// + /// 3D向量结构 + /// + [StructLayout(LayoutKind.Sequential)] + public struct Vector3 + { + public float X; + public float Y; + public float Z; + + public Vector3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + /// + /// 计算向量长度 + /// + public float Length() + { + return Vector.AmxModx_Bridge_VectorLength(X, Y, Z); + } + + /// + /// 计算与另一个向量的距离 + /// + public float DistanceTo(Vector3 other) + { + return Vector.AmxModx_Bridge_VectorDistance(X, Y, Z, other.X, other.Y, other.Z); + } + + /// + /// 转换为角度 + /// + public Vector3 ToAngles() + { + Vector.AmxModx_Bridge_VectorToAngle(X, Y, Z, out float x, out float y, out float z); + return new Vector3(x, y, z); + } + } + + /// + /// 3D角度结构 + /// + [StructLayout(LayoutKind.Sequential)] + public struct Angle3 + { + public float Pitch; + public float Yaw; + public float Roll; + + public Angle3(float pitch, float yaw, float roll) + { + Pitch = pitch; + Yaw = yaw; + Roll = roll; + } + + /// + /// 转换为向量 + /// + public Vector3 ToVector(AngleVectorType type) + { + Vector.AmxModx_Bridge_AngleVector(Pitch, Yaw, Roll, (int)type, out float x, out float y, out float z); + return new Vector3(x, y, z); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/EngineBridgeExtensions.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/EngineBridgeExtensions.cs new file mode 100644 index 0000000..024fae4 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/EngineBridgeExtensions.cs @@ -0,0 +1,375 @@ +using System; +using System.Runtime.InteropServices; +using AmxModx.Bridge.Engine; +using System.Text; + +namespace AmxModx.Bridge.Engine +{ + /// + /// EngineBridge扩展类,提供额外的实体操作方法 + /// + public static class EngineBridgeExtensions + { + private const string EngineBridgeDll = "engine_amxx"; + + #region 实体位置相关 + + /// + /// 获取实体位置 + /// + /// 实体ID + /// 返回的位置 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityOrigin(int entityId, [Out] float[] origin); + + /// + /// 设置实体位置 + /// + /// 实体ID + /// 新位置 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetEntityOrigin(int entityId, [In] float[] origin); + + /// + /// 获取实体角度 + /// + /// 实体ID + /// 返回的角度 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityAngles(int entityId, [Out] float[] angles); + + /// + /// 设置实体角度 + /// + /// 实体ID + /// 新角度 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetEntityAngles(int entityId, [In] float[] angles); + + /// + /// 获取实体速度 + /// + /// 实体ID + /// 返回的速度 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityVelocity(int entityId, [Out] float[] velocity); + + /// + /// 设置实体速度 + /// + /// 实体ID + /// 新速度 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetEntityVelocity(int entityId, [In] float[] velocity); + + #endregion + + #region 实体属性相关 + + /// + /// 获取实体类名 + /// + /// 实体ID + /// 缓冲区 + /// 缓冲区大小 + /// 实际返回的字符串长度 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityClassName(int entityId, [Out] byte[] buffer, int bufferSize); + + /// + /// 获取实体模型名 + /// + /// 实体ID + /// 缓冲区 + /// 缓冲区大小 + /// 实际返回的字符串长度 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityModelName(int entityId, [Out] byte[] buffer, int bufferSize); + + /// + /// 获取实体健康值 + /// + /// 实体ID + /// 健康值 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityHealth(int entityId); + + /// + /// 设置实体健康值 + /// + /// 实体ID + /// 健康值 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetEntityHealth(int entityId, int health); + + /// + /// 获取实体护甲值 + /// + /// 实体ID + /// 护甲值 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetEntityArmor(int entityId); + + /// + /// 设置实体护甲值 + /// + /// 实体ID + /// 护甲值 + /// 成功返回1,失败返回0 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_SetEntityArmor(int entityId, int armor); + + #endregion + + #region 实体列表相关 + + /// + /// 获取所有实体 + /// + /// 最大实体数量 + /// 返回的实体ID数组 + /// 实际获取的实体数量 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetAllEntities([Out] int[] entityIds, int maxCount); + + /// + /// 按类名查找实体 + /// + /// 类名 + /// 最大返回数量 + /// 返回的实体ID数组 + /// 实际找到的实体数量 + [DllImport(EngineBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_FindEntitiesByClass(string className, [Out] int[] entityIds, int maxCount); + + #endregion + + #region 便捷包装方法 + + /// + /// 获取实体位置(便捷包装) + /// + /// 实体ID + /// 返回的位置 + /// 成功返回true,失败返回false + public static bool GetEntityOrigin(int entityId, out EngineBridge.Vector3 origin) + { + float[] originArray = new float[3]; + bool result = Engine_GetEntityOrigin(entityId, originArray) != 0; + if (result) + { + origin = new EngineBridge.Vector3(originArray[0], originArray[1], originArray[2]); + } + else + { + origin = new EngineBridge.Vector3(0, 0, 0); + } + return result; + } + + /// + /// 设置实体位置(便捷包装) + /// + /// 实体ID + /// 新位置 + /// 成功返回true,失败返回false + public static bool SetEntityOrigin(int entityId, EngineBridge.Vector3 origin) + { + float[] originArray = { origin.X, origin.Y, origin.Z }; + return Engine_SetEntityOrigin(entityId, originArray) != 0; + } + + /// + /// 获取实体角度(便捷包装) + /// + /// 实体ID + /// 返回的角度 + /// 成功返回true,失败返回false + public static bool GetEntityAngles(int entityId, out EngineBridge.Vector3 angles) + { + float[] anglesArray = new float[3]; + bool result = Engine_GetEntityAngles(entityId, anglesArray) != 0; + if (result) + { + angles = new EngineBridge.Vector3(anglesArray[0], anglesArray[1], anglesArray[2]); + } + else + { + angles = new EngineBridge.Vector3(0, 0, 0); + } + return result; + } + + /// + /// 设置实体角度(便捷包装) + /// + /// 实体ID + /// 新角度 + /// 成功返回true,失败返回false + public static bool SetEntityAngles(int entityId, EngineBridge.Vector3 angles) + { + float[] anglesArray = { angles.X, angles.Y, angles.Z }; + return Engine_SetEntityAngles(entityId, anglesArray) != 0; + } + + /// + /// 获取实体速度(便捷包装) + /// + /// 实体ID + /// 返回的速度 + /// 成功返回true,失败返回false + public static bool GetEntityVelocity(int entityId, out EngineBridge.Vector3 velocity) + { + float[] velocityArray = new float[3]; + bool result = Engine_GetEntityVelocity(entityId, velocityArray) != 0; + if (result) + { + velocity = new EngineBridge.Vector3(velocityArray[0], velocityArray[1], velocityArray[2]); + } + else + { + velocity = new EngineBridge.Vector3(0, 0, 0); + } + return result; + } + + /// + /// 设置实体速度(便捷包装) + /// + /// 实体ID + /// 新速度 + /// 成功返回true,失败返回false + public static bool SetEntityVelocity(int entityId, EngineBridge.Vector3 velocity) + { + float[] velocityArray = { velocity.X, velocity.Y, velocity.Z }; + return Engine_SetEntityVelocity(entityId, velocityArray) != 0; + } + + /// + /// 获取实体类名(便捷包装) + /// + /// 实体ID + /// 实体类名 + public static string GetEntityClassName(int entityId) + { + const int bufferSize = 256; + byte[] buffer = new byte[bufferSize]; + int length = Engine_GetEntityClassName(entityId, buffer, bufferSize); + if (length <= 0) return string.Empty; + + return Encoding.UTF8.GetString(buffer, 0, length); + } + + /// + /// 获取实体模型名(便捷包装) + /// + /// 实体ID + /// 实体模型名 + public static string GetEntityModelName(int entityId) + { + const int bufferSize = 256; + byte[] buffer = new byte[bufferSize]; + int length = Engine_GetEntityModelName(entityId, buffer, bufferSize); + if (length <= 0) return string.Empty; + + return Encoding.UTF8.GetString(buffer, 0, length); + } + + /// + /// 获取实体健康值(便捷包装) + /// + /// 实体ID + /// 健康值 + public static int GetEntityHealth(int entityId) + { + return Engine_GetEntityHealth(entityId); + } + + /// + /// 设置实体健康值(便捷包装) + /// + /// 实体ID + /// 健康值 + /// 成功返回true,失败返回false + public static bool SetEntityHealth(int entityId, int health) + { + return Engine_SetEntityHealth(entityId, health) != 0; + } + + /// + /// 获取实体护甲值(便捷包装) + /// + /// 实体ID + /// 护甲值 + public static int GetEntityArmor(int entityId) + { + return Engine_GetEntityArmor(entityId); + } + + /// + /// 设置实体护甲值(便捷包装) + /// + /// 实体ID + /// 护甲值 + /// 成功返回true,失败返回false + public static bool SetEntityArmor(int entityId, int armor) + { + return Engine_SetEntityArmor(entityId, armor) != 0; + } + + /// + /// 获取所有实体(便捷包装) + /// + /// 最大实体数量 + /// 实体ID数组 + public static int[] GetAllEntities(int maxCount) + { + if (maxCount <= 0) + return new int[0]; + + int[] entityIds = new int[maxCount]; + int actualCount = Engine_GetAllEntities(entityIds, maxCount); + + if (actualCount <= 0) + return new int[0]; + + // 调整数组大小到实际数量 + int[] result = new int[actualCount]; + Array.Copy(entityIds, result, actualCount); + return result; + } + + /// + /// 按类名查找实体(便捷包装) + /// + /// 类名 + /// 实体ID数组 + public static int[] FindEntitiesByClass(string className) + { + if (string.IsNullOrEmpty(className)) + return new int[0]; + + // 假设最大返回1000个实体 + const int maxCount = 1000; + int[] entityIds = new int[maxCount]; + int actualCount = Engine_FindEntitiesByClass(className, entityIds, maxCount); + + if (actualCount <= 0) + return new int[0]; + + // 调整数组大小到实际数量 + int[] result = new int[actualCount]; + Array.Copy(entityIds, result, actualCount); + return result; + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/EngineEffectsBridge.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/EngineEffectsBridge.cs new file mode 100644 index 0000000..bc1b6be --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Engine/EngineEffectsBridge.cs @@ -0,0 +1,241 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Engine +{ + /// + /// 引擎高级特效桥接接口 + /// 提供音效、光照、粒子系统的高级控制功能 + /// + public static class EngineEffectsBridge + { + private const string EngineEffectsDll = "engine_effects_bridge"; + + #region 音效系统 + + /// + /// 将音效附加到实体播放 + /// + /// 目标实体ID + /// 音效文件路径 + /// 音效通道 + /// 音量 (0.0-1.0) + /// 衰减系数 + /// 音调 + /// 音效标志 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_SoundPlayAttached( + int entity, + [MarshalAs(UnmanagedType.LPStr)] string sample, + int channel, + float volume, + float attenuation, + int pitch, + int flags); + + /// + /// 设置实体音效音调 + /// + /// 目标实体ID + /// 音效通道 + /// 新的音调值 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_SoundSetPitch( + int entity, + int channel, + int pitch); + + #endregion + + #region 光照系统 + + /// + /// 创建动态光源 + /// + /// 光源位置数组 [x, y, z] + /// 光源半径 + /// 红色分量 (0-255) + /// 绿色分量 (0-255) + /// 蓝色分量 (0-255) + /// 光源持续时间 (秒) + /// 光源样式 (0=常亮, 1=闪烁等) + /// 光源效果ID,失败返回0 + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_LightCreate( + [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] float[] origin, + float radius, + byte red, + byte green, + byte blue, + float life, + int style); + + /// + /// 设置光源颜色 + /// + /// 光源效果ID + /// 红色分量 + /// 绿色分量 + /// 蓝色分量 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_LightSetColor( + int lightId, + int red, + int green, + int blue); + + /// + /// 创建闪烁光源效果 + /// + /// 光源效果ID + /// 闪烁速度 + /// 最小亮度 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_LightFlicker( + int lightId, + float flickerSpeed, + float minIntensity); + + /// + /// 创建脉冲光源效果 + /// + /// 光源效果ID + /// 脉冲速度 + /// 最小亮度 + /// 最大亮度 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_LightPulse( + int lightId, + float pulseSpeed, + float minIntensity, + float maxIntensity); + + /// + /// 停止光源效果 + /// + /// 光源效果ID + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_LightStop(int lightId); + + #endregion + + #region 粒子系统 + + /// + /// 创建粒子系统 + /// + /// 粒子起始位置数组 [x, y, z] + /// 精灵文件路径 + /// 最大粒子数量 + /// 粒子效果ID,失败返回0 + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_ParticleCreate( + [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] float[] origin, + [MarshalAs(UnmanagedType.LPStr)] string sprite, + int maxParticles); + + /// + /// 设置粒子颜色 + /// + /// 粒子效果ID + /// 红色分量 + /// 绿色分量 + /// 蓝色分量 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_ParticleSetColor( + int particleId, + int red, + int green, + int blue); + + /// + /// 设置粒子规模 + /// + /// 粒子效果ID + /// 粒子规模 + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_ParticleSetScale( + int particleId, + float scale); + + /// + /// 停止粒子效果 + /// + /// 粒子效果ID + /// 成功返回true,失败返回false + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Engine_ParticleStop(int particleId); + + #endregion + + #region 辅助函数 + + /// + /// 获取精灵索引 + /// + /// 精灵文件路径 + /// 精灵索引,失败返回-1 + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_GetSpriteIndex( + [MarshalAs(UnmanagedType.LPStr)] string spriteName); + + /// + /// 预缓存模型 + /// + /// 模型文件路径 + /// 模型索引,失败返回-1 + [DllImport(EngineEffectsDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Engine_PrecacheModel( + [MarshalAs(UnmanagedType.LPStr)] string modelName); + + #endregion + } + + /// + /// 引擎特效桥接扩展类 + /// 提供C#友好的封装接口 + /// + public static class EngineEffectsExtensions + { + /// + /// 将音效附加到实体播放(简化版) + /// + public static bool PlaySoundAttached(int entity, string sample, float volume = 1.0f, int pitch = 100) + { + return EngineEffectsBridge.Engine_SoundPlayAttached(entity, sample, 0, volume, 1.0f, pitch, 0) != 0; + } + + /// + /// 创建动态光源(简化版) + /// + public static int CreateLight(float[] origin, float radius, int red, int green, int blue, float life = 5.0f) + { + return EngineEffectsBridge.Engine_LightCreate(origin, radius, (byte)red, (byte)green, (byte)blue, life, 0); + } + + /// + /// 创建爆炸效果 + /// + public static int CreateExplosion(float[] origin, string sprite, int particleCount = 50) + { + return EngineEffectsBridge.Engine_ParticleCreate(origin, sprite, particleCount); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.CStrike.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.CStrike.cs new file mode 100644 index 0000000..2a2018c --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.CStrike.cs @@ -0,0 +1,462 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.CStrike +{ + /// + /// Counter-Strike游戏功能桥接类 + /// 提供对CS1.6游戏引擎的直接访问 + /// + public static class CStrikeBridge + { + private const string DllName = "cstrike_bridge"; + + #region Player API + + /// + /// 获取玩家金钱 + /// + /// 玩家索引(1-32) + /// 玩家当前金钱数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetUserMoney(int playerIndex); + + /// + /// 设置玩家金钱 + /// + /// 玩家索引(1-32) + /// 要设置的金钱数量 + /// 是否显示更新提示(默认1) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserMoney(int playerIndex, int money, int flash = 1); + + /// + /// 获取玩家护甲值 + /// + /// 玩家索引(1-32) + /// 玩家当前护甲值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetUserArmor(int playerIndex); + + /// + /// 设置玩家护甲值 + /// + /// 玩家索引(1-32) + /// 要设置的护甲值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserArmor(int playerIndex, int armor); + + /// + /// 获取玩家队伍 + /// + /// 玩家索引(1-32) + /// 队伍ID (1=T, 2=CT, 3=SPEC) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetUserTeam(int playerIndex); + + /// + /// 设置玩家队伍 + /// + /// 玩家索引(1-32) + /// 队伍ID (1=T, 2=CT, 3=SPEC) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserTeam(int playerIndex, int team); + + /// + /// 获取玩家VIP状态 + /// + /// 玩家索引(1-32) + /// 是否为VIP + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetUserVip(int playerIndex); + + /// + /// 设置玩家VIP状态 + /// + /// 玩家索引(1-32) + /// VIP状态 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserVip(int playerIndex, [MarshalAs(UnmanagedType.Bool)] bool vip); + + /// + /// 获取玩家死亡次数 + /// + /// 玩家索引(1-32) + /// 死亡次数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetUserDeaths(int playerIndex); + + /// + /// 设置玩家死亡次数 + /// + /// 玩家索引(1-32) + /// 死亡次数 + /// 是否更新计分板 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserDeaths(int playerIndex, int deaths, [MarshalAs(UnmanagedType.Bool)] bool updateScoreboard = true); + + #endregion + + #region Weapon API + + /// + /// 获取武器ID + /// + /// 武器实体索引 + /// 武器ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetWeaponId(int weaponEntity); + + /// + /// 获取武器消音器状态 + /// + /// 武器实体索引 + /// 是否装备消音器 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetWeaponSilenced(int weaponEntity); + + /// + /// 设置武器消音器状态 + /// + /// 武器实体索引 + /// 消音器状态 + /// 是否播放动画 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetWeaponSilenced(int weaponEntity, [MarshalAs(UnmanagedType.Bool)] bool silenced, int drawAnimation = 1); + + /// + /// 获取武器连发模式 + /// + /// 武器实体索引 + /// 是否为连发模式 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetWeaponBurstMode(int weaponEntity); + + /// + /// 设置武器连发模式 + /// + /// 武器实体索引 + /// 连发模式 + /// 是否播放动画 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetWeaponBurstMode(int weaponEntity, [MarshalAs(UnmanagedType.Bool)] bool burstMode, int drawAnimation = 1); + + /// + /// 获取武器弹药数量 + /// + /// 武器实体索引 + /// 弹药数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetWeaponAmmo(int weaponEntity); + + /// + /// 设置武器弹药数量 + /// + /// 武器实体索引 + /// 弹药数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetWeaponAmmo(int weaponEntity, int ammo); + + #endregion + + #region Game State API + + /// + /// 检查玩家是否在购物区域 + /// + /// 玩家索引(1-32) + /// 是否在购物区域 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetUserInsideBuyzone(int playerIndex); + + /// + /// 获取玩家地图区域 + /// + /// 玩家索引(1-32) + /// 地图区域标志 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetUserMapzones(int playerIndex); + + /// + /// 检查玩家是否有主武器 + /// + /// 玩家索引(1-32) + /// 是否有主武器 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetUserHasPrimary(int playerIndex); + + /// + /// 检查玩家是否有拆弹器 + /// + /// 玩家索引(1-32) + /// 是否有拆弹器 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetUserDefusekit(int playerIndex); + + /// + /// 设置玩家拆弹器状态 + /// + /// 玩家索引(1-32) + /// 是否有拆弹器 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserDefusekit(int playerIndex, [MarshalAs(UnmanagedType.Bool)] bool hasKit); + + /// + /// 检查玩家是否有夜视镜 + /// + /// 玩家索引(1-32) + /// 是否有夜视镜 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetUserNvg(int playerIndex); + + /// + /// 设置玩家夜视镜状态 + /// + /// 玩家索引(1-32) + /// 是否有夜视镜 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserNvg(int playerIndex, [MarshalAs(UnmanagedType.Bool)] bool hasNvg); + + #endregion + + #region Model API + + /// + /// 获取玩家模型 + /// + /// 玩家索引(1-32) + /// 模型名称缓冲区 + /// 缓冲区大小 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsGetUserModel(int playerIndex, [Out] StringBuilder buffer, int bufferSize); + + /// + /// 设置玩家模型 + /// + /// 玩家索引(1-32) + /// 模型名称 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetUserModel(int playerIndex, [MarshalAs(UnmanagedType.LPStr)] string model); + + /// + /// 重置玩家模型为默认 + /// + /// 玩家索引(1-32) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsResetUserModel(int playerIndex); + + #endregion + + #region Entity API + + /// + /// 创建游戏实体 + /// + /// 实体类名 + /// 实体索引 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsCreateEntity([MarshalAs(UnmanagedType.LPStr)] string className); + + /// + /// 按类名查找实体 + /// + /// 起始索引 + /// 实体类名 + /// 实体索引 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsFindEntityByClass(int startIndex, [MarshalAs(UnmanagedType.LPStr)] string className); + + /// + /// 按所有者查找实体 + /// + /// 起始索引 + /// 所有者玩家索引 + /// 实体索引 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsFindEntityByOwner(int startIndex, int ownerIndex); + + /// + /// 设置实体类名 + /// + /// 实体索引 + /// 新的类名 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsSetEntityClass(int entityIndex, [MarshalAs(UnmanagedType.LPStr)] string className); + + #endregion + + #region Item API + + /// + /// 通过物品名称获取物品ID + /// + /// 物品名称 + /// 物品ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetItemId([MarshalAs(UnmanagedType.LPStr)] string itemName); + + /// + /// 获取物品别名 + /// + /// 物品ID + /// 别名缓冲区 + /// 缓冲区大小 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetItemAlias(int itemId, [Out] StringBuilder buffer, int bufferSize); + + /// + /// 获取物品翻译后的别名 + /// + /// 物品ID + /// 别名缓冲区 + /// 缓冲区大小 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetTranslatedItemAlias(int itemId, [Out] StringBuilder buffer, int bufferSize); + + #endregion + + #region Hostage API + + /// + /// 获取人质ID + /// + /// 人质索引 + /// 人质ID + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int CsGetHostageId(int hostageIndex); + + /// + /// 获取人质跟随状态 + /// + /// 人质索引 + /// 是否跟随 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetHostageFollow(int hostageIndex); + + /// + /// 设置人质跟随状态 + /// + /// 人质索引 + /// 是否跟随 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetHostageFollow(int hostageIndex, [MarshalAs(UnmanagedType.Bool)] bool follow); + + #endregion + + #region Bomb API + + /// + /// 获取C4爆炸时间 + /// + /// 爆炸时间(秒) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern float CsGetC4ExplodeTime(); + + /// + /// 设置C4爆炸时间 + /// + /// 爆炸时间(秒) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetC4ExplodeTime(float time); + + /// + /// 获取C4拆弹状态 + /// + /// 是否在拆弹 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CsGetC4Defusing(); + + /// + /// 设置C4拆弹状态 + /// + /// 拆弹状态 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsSetC4Defusing([MarshalAs(UnmanagedType.Bool)] bool defusing); + + #endregion + + #region Event Callbacks + + // 委托定义 + public delegate void CsPlayerDeathDelegate(int victim, int killer, int weapon); + public delegate void CsBombEventDelegate(int eventType, int player); + public delegate void CsWeaponPickupDelegate(int player, int weaponId); + + /// + /// 注册玩家死亡事件回调 + /// + /// 回调函数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsRegisterPlayerDeathCallback(CsPlayerDeathDelegate callback); + + /// + /// 注册炸弹事件回调 + /// + /// 回调函数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsRegisterBombEventCallback(CsBombEventDelegate callback); + + /// + /// 注册武器拾取事件回调 + /// + /// 回调函数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void CsRegisterWeaponPickupCallback(CsWeaponPickupDelegate callback); + + #endregion + + #region Helper Methods + + /// + /// 获取玩家模型名称 + /// + /// 玩家索引 + /// 模型名称 + public static string GetUserModel(int playerIndex) + { + var sb = new StringBuilder(256); + CsGetUserModel(playerIndex, sb, sb.Capacity); + return sb.ToString(); + } + + /// + /// 获取物品别名 + /// + /// 物品ID + /// 物品别名 + public static string GetItemAlias(int itemId) + { + var sb = new StringBuilder(64); + return CsGetItemAlias(itemId, sb, sb.Capacity) ? sb.ToString() : string.Empty; + } + + /// + /// 获取物品翻译别名 + /// + /// 物品ID + /// 翻译后的别名 + public static string GetTranslatedItemAlias(int itemId) + { + var sb = new StringBuilder(64); + return CsGetTranslatedItemAlias(itemId, sb, sb.Capacity) ? sb.ToString() : string.Empty; + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.Fakemeta.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.Fakemeta.cs new file mode 100644 index 0000000..71e9974 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.Fakemeta.cs @@ -0,0 +1,828 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace AmxModx.Bridge.Fakemeta +{ + /// + /// Fakemeta模块事件类型枚举 + /// + public enum ForwardType + { + PrecacheModel = 0, + PrecacheSound = 1, + SetModel = 2, + CreateEntity = 3, + RemoveEntity = 4, + Spawn = 5, + Think = 6, + Use = 7, + Touch = 8, + Blocked = 9, + ClientCommand = 10, + ClientUserInfoChanged = 11, + ServerActivate = 12, + ServerDeactivate = 13, + PlayerPreThink = 14, + PlayerPostThink = 15, + StartFrame = 16, + ClientConnect = 17, + ClientDisconnect = 18, + ClientPutInServer = 19, + ClientKill = 20, + ClientSpawn = 21, + TraceLine = 22, + TraceToss = 23, + TraceMonsterHull = 24, + TraceHull = 25, + TraceModel = 26, + TraceTexture = 27, + TraceSphere = 28, + GetAimVector = 29, + EmitSound = 30, + EmitAmbientSound = 31, + LightStyle = 32, + DecalIndex = 33, + PointContents = 34, + MessageBegin = 35, + MessageEnd = 36, + WriteByte = 37, + WriteChar = 38, + WriteShort = 39, + WriteLong = 40, + WriteAngle = 41, + WriteCoord = 42, + WriteString = 43, + WriteEntity = 44, + CVarGetFloat = 45, + CVarGetString = 46, + CVarSetFloat = 47, + CVarSetString = 48, + CVarRegister = 49, + AlertMessage = 50, + EngineFprintf = 51, + PvsFindEntity = 52, + PvsEntitiesInPvs = 53, + PvsCheckOrigin = 54, + PvsCheckEntity = 55, + PvsCheckBox = 56, + PvsCheckPoint = 57, + PvsCheckEverything = 58, + PvsCheckEverything2 = 59, + PvsCheckEverything3 = 60, + PvsCheckEverything4 = 61, + PvsCheckEverything5 = 62, + PvsCheckEverything6 = 63, + PvsCheckEverything7 = 64, + PvsCheckEverything8 = 65, + PvsCheckEverything9 = 66, + PvsCheckEverything10 = 67, + PvsCheckEverything11 = 68, + PvsCheckEverything12 = 69, + PvsCheckEverything13 = 70, + PvsCheckEverything14 = 71, + PvsCheckEverything15 = 72, + PvsCheckEverything16 = 73, + PvsCheckEverything17 = 74, + PvsCheckEverything18 = 75, + PvsCheckEverything19 = 76, + PvsCheckEverything20 = 77, + PvsCheckEverything21 = 78, + PvsCheckEverything22 = 79, + PvsCheckEverything23 = 80, + PvsCheckEverything24 = 81, + PvsCheckEverything25 = 82, + PvsCheckEverything26 = 83, + PvsCheckEverything27 = 84, + PvsCheckEverything28 = 85, + PvsCheckEverything29 = 86, + PvsCheckEverything30 = 87, + PvsCheckEverything31 = 88, + PvsCheckEverything32 = 89, + PvsCheckEverything33 = 90, + PvsCheckEverything34 = 91, + PvsCheckEverything35 = 92, + PvsCheckEverything36 = 93, + PvsCheckEverything37 = 94, + PvsCheckEverything38 = 95, + PvsCheckEverything39 = 96, + PvsCheckEverything40 = 97, + PvsCheckEverything41 = 98, + PvsCheckEverything42 = 99, + PvsCheckEverything43 = 100, + PvsCheckEverything44 = 101, + PvsCheckEverything45 = 102, + PvsCheckEverything46 = 103, + PvsCheckEverything47 = 104, + PvsCheckEverything48 = 105, + PvsCheckEverything49 = 106, + PvsCheckEverything50 = 107, + PvsCheckEverything51 = 108, + PvsCheckEverything52 = 109, + PvsCheckEverything53 = 110, + PvsCheckEverything54 = 111, + PvsCheckEverything55 = 112, + PvsCheckEverything56 = 113, + PvsCheckEverything57 = 114, + PvsCheckEverything58 = 115, + PvsCheckEverything59 = 116, + PvsCheckEverything60 = 117, + PvsCheckEverything61 = 118, + PvsCheckEverything62 = 119, + PvsCheckEverything63 = 120, + PvsCheckEverything64 = 121, + PvsCheckEverything65 = 122, + PvsCheckEverything66 = 123, + PvsCheckEverything67 = 124, + PvsCheckEverything68 = 125, + PvsCheckEverything69 = 126, + PvsCheckEverything70 = 127, + PvsCheckEverything71 = 128, + PvsCheckEverything72 = 129, + PvsCheckEverything73 = 130, + PvsCheckEverything74 = 131 + } + + /// + /// 事件执行时机 + /// + public enum ForwardTiming + { + Pre = 0, // 前置钩子 + Post = 1 // 后置钩子 + } + + /// + /// 事件返回值 + /// + public enum ForwardResult + { + Ignored = 0, // 忽略,继续执行 + Handled = 1, // 已处理,继续执行 + Override = 2, // 覆盖,继续执行 + Supercede = 3 // 取代,停止执行 + } + + /// + /// 事件参数结构体 + /// + [StructLayout(LayoutKind.Sequential)] + public struct EventData + { + public int EntityIndex; // 实体索引 + [MarshalAs(UnmanagedType.LPStr)] + public string StringValue; // 字符串值 + public float FloatValue; // 浮点值 + public int IntValue; // 整数值 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public float[] VectorValue; // 向量值 + public IntPtr CustomData; // 自定义数据 + } + + /// + /// 事件回调委托 + /// + /// 事件数据 + /// 用户数据 + /// 事件处理结果 + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate ForwardResult ForwardCallback(ref EventData data, IntPtr userData); + + /// + /// 简化的回调委托,用于lambda表达式 + /// + /// 实体索引 + /// 字符串值 + /// 浮点值 + /// 整数值 + /// 向量值 + /// 事件处理结果 + public delegate ForwardResult SimpleForwardCallback(int entityIndex, string stringValue, float floatValue, int intValue, float[] vectorValue); + + /// + /// 实体事件回调委托 + /// + /// 实体索引 + /// 事件处理结果 + public delegate ForwardResult EntityForwardCallback(int entity); + + /// + /// 玩家事件回调委托 + /// + /// 玩家索引 + /// 命令字符串 + /// 事件处理结果 + public delegate ForwardResult PlayerForwardCallback(int playerIndex, string command = null); + + /// + /// 无参数事件回调委托 + /// + /// 事件处理结果 + public delegate ForwardResult VoidForwardCallback(); + + internal static class NativeMethods + { + private const string DllName = "fakemeta_amxx"; + + /// + /// 初始化事件系统 + /// + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int FMB_InitializeForwardSystem(); + + /// + /// 清理事件系统 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void FMB_CleanupForwardSystem(); + + /// + /// 注册事件钩子 + /// + /// 事件类型 + /// 执行时机 + /// 回调函数 + /// 用户数据 + /// 注册句柄,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int FMB_RegisterForward(ForwardType type, ForwardTiming timing, ForwardCallback callback, IntPtr userData); + + /// + /// 注销事件钩子 + /// + /// 事件类型 + /// 执行时机 + /// 注册句柄 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int FMB_UnregisterForward(ForwardType type, ForwardTiming timing, int handle); + + /// + /// 触发事件 + /// + /// 事件类型 + /// 执行时机 + /// 事件数据 + /// 事件处理结果 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern ForwardResult FMB_ExecuteForwards(ForwardType type, ForwardTiming timing, ref EventData data); + + /// + /// 获取事件队列长度 + /// + /// 事件类型 + /// 执行时机 + /// 事件数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int FMB_GetForwardCount(ForwardType type, ForwardTiming timing); + + /// + /// 检查事件是否已注册 + /// + /// 事件类型 + /// 执行时机 + /// 注册句柄 + /// 已注册返回1,未注册返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int FMB_IsForwardRegistered(ForwardType type, ForwardTiming timing, int handle); + + /// + /// 获取事件类型名称 + /// + /// 事件类型 + /// 类型名称 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string FMB_GetForwardTypeName(ForwardType type); + + /// + /// 获取事件时机名称 + /// + /// 执行时机 + /// 时机名称 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string FMB_GetForwardTimingName(ForwardTiming timing); + + /// + /// 获取事件结果名称 + /// + /// 处理结果 + /// 结果名称 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string FMB_GetForwardResultName(ForwardResult result); + } + + /// + /// 事件管理器 - 提供简化的回调注册接口 + /// + public static class ForwardManager + { + private static readonly Dictionary callbacks = new Dictionary(); + private static readonly Dictionary gcHandles = new Dictionary(); + private static int nextHandle = 1; + private static bool isInitialized = false; + + /// + /// 初始化事件系统 + /// + public static void Initialize() + { + if (!isInitialized) + { + int result = NativeMethods.FMB_InitializeForwardSystem(); + if (result == 1) + { + isInitialized = true; + } + else + { + throw new InvalidOperationException("Failed to initialize Fakemeta forward system"); + } + } + } + + /// + /// 清理事件系统 + /// + public static void Cleanup() + { + if (isInitialized) + { + NativeMethods.FMB_CleanupForwardSystem(); + isInitialized = false; + } + + foreach (var handle in gcHandles.Values) + { + if (handle.IsAllocated) + handle.Free(); + } + + callbacks.Clear(); + gcHandles.Clear(); + } + + /// + /// 注册事件回调 + /// + /// 事件类型 + /// 执行时机 + /// 回调函数 + /// 用户数据 + /// 注册句柄 + public static int RegisterForward(ForwardType type, ForwardTiming timing, ForwardCallback callback, object userData = null) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + if (!isInitialized) + Initialize(); + + int handle = nextHandle++; + callbacks[handle] = callback; + + IntPtr userDataPtr = IntPtr.Zero; + if (userData != null) + { + var gcHandle = GCHandle.Alloc(userData); + gcHandles[handle] = gcHandle; + userDataPtr = GCHandle.ToIntPtr(gcHandle); + } + + int result = NativeMethods.FMB_RegisterForward(type, timing, callback, userDataPtr); + if (result == 0) + { + callbacks.Remove(handle); + if (userData != null && gcHandles.ContainsKey(handle)) + { + gcHandles[handle].Free(); + gcHandles.Remove(handle); + } + return 0; + } + + return handle; + } + + /// + /// 使用lambda表达式注册事件回调 + /// + /// 事件类型 + /// 执行时机 + /// lambda回调 + /// 注册句柄 + public static int RegisterForward(ForwardType type, ForwardTiming timing, SimpleForwardCallback callback) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + + ForwardCallback nativeCallback = (ref EventData data, IntPtr userData) => + { + return callback(data.EntityIndex, data.StringValue, data.FloatValue, data.IntValue, data.VectorValue); + }; + + return RegisterForward(type, timing, nativeCallback); + } + + /// + /// 注册实体事件回调 + /// + /// 事件类型 + /// 执行时机 + /// 实体回调 + /// 注册句柄 + public static int RegisterEntityForward(ForwardType type, ForwardTiming timing, EntityForwardCallback callback) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + + ForwardCallback nativeCallback = (ref EventData data, IntPtr userData) => + { + return callback(data.EntityIndex); + }; + + return RegisterForward(type, timing, nativeCallback); + } + + /// + /// 注册玩家事件回调 + /// + /// 事件类型 + /// 执行时机 + /// 玩家回调 + /// 注册句柄 + public static int RegisterPlayerForward(ForwardType type, ForwardTiming timing, PlayerForwardCallback callback) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + + ForwardCallback nativeCallback = (ref EventData data, IntPtr userData) => + { + return callback(data.EntityIndex, data.StringValue); + }; + + return RegisterForward(type, timing, nativeCallback); + } + + /// + /// 注册无参数事件回调 + /// + /// 事件类型 + /// 执行时机 + /// 无参数回调 + /// 注册句柄 + public static int RegisterVoidForward(ForwardType type, ForwardTiming timing, VoidForwardCallback callback) + { + if (callback == null) + throw new ArgumentNullException(nameof(callback)); + + ForwardCallback nativeCallback = (ref EventData data, IntPtr userData) => + { + return callback(); + }; + + return RegisterForward(type, timing, nativeCallback); + } + + /// + /// 注销事件回调 + /// + /// 事件类型 + /// 执行时机 + /// 注册句柄 + /// 是否成功 + public static bool UnregisterForward(ForwardType type, ForwardTiming timing, int handle) + { + if (!callbacks.ContainsKey(handle)) + return false; + if (!isInitialized) + return false; + + int result = NativeMethods.FMB_UnregisterForward(type, timing, handle); + if (result != 0) + { + callbacks.Remove(handle); + if (gcHandles.ContainsKey(handle)) + { + gcHandles[handle].Free(); + gcHandles.Remove(handle); + } + return true; + } + + return false; + } + + /// + /// 触发事件 + /// + /// 事件类型 + /// 执行时机 + /// 事件数据 + /// 事件处理结果 + public static ForwardResult ExecuteForwards(ForwardType type, ForwardTiming timing, ref EventData data) + { + if (!isInitialized) + return ForwardResult.Ignored; + + return NativeMethods.FMB_ExecuteForwards(type, timing, ref data); + } + + /// + /// 获取事件数量 + /// + /// 事件类型 + /// 执行时机 + /// 事件数量 + public static int GetForwardCount(ForwardType type, ForwardTiming timing) + { + if (!isInitialized) + return 0; + + return NativeMethods.FMB_GetForwardCount(type, timing); + } + + /// + /// 检查事件是否已注册 + /// + /// 事件类型 + /// 执行时机 + /// 注册句柄 + /// 是否已注册 + public static bool IsForwardRegistered(ForwardType type, ForwardTiming timing, int handle) + { + if (!isInitialized) + return false; + + return NativeMethods.FMB_IsForwardRegistered(type, timing, handle) != 0; + } + } + + /// + /// Fakemeta回调管理器 - 提供高级封装 + /// + public static class FakemetaCallbacks + { + /// + /// 注册实体创建回调 + /// + /// 创建回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityCreate(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.CreateEntity, timing, callback); + } + + /// + /// 注册实体销毁回调 + /// + /// 销毁回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityRemove(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.RemoveEntity, timing, callback); + } + + /// + /// 注册实体生成回调 + /// + /// 生成回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntitySpawn(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.Spawn, timing, callback); + } + + /// + /// 注册实体思考回调 + /// + /// 思考回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityThink(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.Think, timing, callback); + } + + /// + /// 注册实体使用回调 + /// + /// 使用回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityUse(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.Use, timing, callback); + } + + /// + /// 注册实体触碰回调 + /// + /// 触碰回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityTouch(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.Touch, timing, callback); + } + + /// + /// 注册实体阻挡回调 + /// + /// 阻挡回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityBlocked(EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterEntityForward(ForwardType.Blocked, timing, callback); + } + + /// + /// 注册玩家连接回调 + /// + /// 连接回调 + /// 执行时机 + /// 注册句柄 + public static int OnPlayerConnect(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.ClientConnect, timing, callback); + } + + /// + /// 注册玩家断开连接回调 + /// + /// 断开连接回调 + /// 执行时机 + /// 注册句柄 + public static int OnPlayerDisconnect(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.ClientDisconnect, timing, callback); + } + + /// + /// 注册玩家命令回调 + /// + /// 命令回调 + /// 执行时机 + /// 注册句柄 + public static int OnPlayerCommand(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.ClientCommand, timing, callback); + } + + /// + /// 注册玩家生成回调 + /// + /// 生成回调 + /// 执行时机 + /// 注册句柄 + public static int OnPlayerSpawn(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.ClientSpawn, timing, callback); + } + + /// + /// 注册玩家预思考回调 + /// + /// 预思考回调 + /// 执行时机 + /// 注册句柄 + public static int OnPlayerPreThink(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.PlayerPreThink, timing, callback); + } + + /// + /// 注册玩家后思考回调 + /// + /// 后思考回调 + /// 执行时机 + /// 注册句柄 + public static int OnPlayerPostThink(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.PlayerPostThink, timing, callback); + } + + /// + /// 注册服务器激活回调 + /// + /// 激活回调 + /// 执行时机 + /// 注册句柄 + public static int OnServerActivate(VoidForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterVoidForward(ForwardType.ServerActivate, timing, callback); + } + + /// + /// 注册服务器停用回调 + /// + /// 停用回调 + /// 执行时机 + /// 注册句柄 + public static int OnServerDeactivate(VoidForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterVoidForward(ForwardType.ServerDeactivate, timing, callback); + } + + /// + /// 注册每帧回调 + /// + /// 每帧回调 + /// 执行时机 + /// 注册句柄 + public static int OnStartFrame(VoidForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterVoidForward(ForwardType.StartFrame, timing, callback); + } + + /// + /// 注册模型预缓存回调 + /// + /// 预缓存回调 + /// 执行时机 + /// 注册句柄 + public static int OnPrecacheModel(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.PrecacheModel, timing, callback); + } + + /// + /// 注册声音预缓存回调 + /// + /// 预缓存回调 + /// 执行时机 + /// 注册句柄 + public static int OnPrecacheSound(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.PrecacheSound, timing, callback); + } + + /// + /// 注册模型设置回调 + /// + /// 模型设置回调 + /// 执行时机 + /// 注册句柄 + public static int OnSetModel(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.SetModel, timing, callback); + } + + /// + /// 注册追踪线回调 + /// + /// 追踪线回调 + /// 执行时机 + /// 注册句柄 + public static int OnTraceLine(PlayerForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return ForwardManager.RegisterPlayerForward(ForwardType.TraceLine, timing, callback); + } + } + + /// + /// 事件扩展方法,提供lambda表达式支持 + /// + public static class ForwardExtensions + { + /// + /// 使用lambda表达式注册实体创建事件 + /// + /// lambda回调 + /// 执行时机 + /// 注册句柄 + public static int OnEntityCreate(this EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return FakemetaCallbacks.OnEntityCreate(callback, timing); + } + + ///// + ///// 使用lambda表达式注册玩家连接事件 + ///// + ///// lambda回调 + ///// 执行时机 + ///// 注册句柄 + //public static int OnPlayerConnect(this EntityForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + //{ + // return FakemetaCallbacks.OnPlayerConnect(callback, timing); + //} + + /// + /// 使用lambda表达式注册每帧事件 + /// + /// lambda回调 + /// 执行时机 + /// 注册句柄 + public static int OnStartFrame(this VoidForwardCallback callback, ForwardTiming timing = ForwardTiming.Pre) + { + return FakemetaCallbacks.OnStartFrame(callback, timing); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.Fun.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.Fun.cs new file mode 100644 index 0000000..69d322d --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.Fun.cs @@ -0,0 +1,425 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Fun +{ + /// + /// Fun模块的C#桥接接口 + /// 提供对CS1.6游戏功能的访问 + /// + public static class FunBridge + { + private const string FunBridgeDll = "fun_bridge"; + + #region 客户端语音监听 + + /// + /// 获取客户端是否监听其他玩家的语音 + /// + /// 接收者玩家索引 + /// 发送者玩家索引 + /// 1表示监听,0表示不监听 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetClientListening(int receiver, int sender); + + /// + /// 设置客户端是否监听其他玩家的语音 + /// + /// 接收者玩家索引 + /// 发送者玩家索引 + /// 1表示监听,0表示不监听 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetClientListening(int receiver, int sender, int listen); + + #endregion + + #region 玩家无敌模式 + + /// + /// 设置玩家无敌模式 + /// + /// 玩家索引 + /// 1开启无敌,0关闭无敌 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserGodmode(int user, int godmode); + + /// + /// 获取玩家无敌模式状态 + /// + /// 玩家索引 + /// 1表示无敌,0表示非无敌 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserGodmode(int user); + + #endregion + + #region 玩家生命值 + + /// + /// 获取玩家生命值 + /// + /// 玩家索引 + /// 生命值 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern float GetUserHealth(int index); + + /// + /// 设置玩家生命值 + /// + /// 玩家索引 + /// 生命值 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserHealth(int index, float health); + + #endregion + + #region 物品和武器 + + /// + /// 给予玩家物品 + /// + /// 玩家索引 + /// 物品名称 + /// 物品实体ID,失败返回0或-1 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GiveItem(int index, [MarshalAs(UnmanagedType.LPStr)] string item); + + /// + /// 重新生成实体 + /// + /// 实体索引 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SpawnEntity(int index); + + #endregion + + #region 玩家击杀和护甲 + + /// + /// 获取玩家击杀数 + /// + /// 玩家索引 + /// 击杀数 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserFrags(int index); + + /// + /// 设置玩家击杀数 + /// + /// 玩家索引 + /// 击杀数 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserFrags(int index, int frags); + + /// + /// 获取玩家护甲值 + /// + /// 玩家索引 + /// 护甲值 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserArmor(int index); + + /// + /// 设置玩家护甲值 + /// + /// 玩家索引 + /// 护甲值 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserArmor(int index, int armor); + + #endregion + + #region 玩家位置和渲染 + + /// + /// 获取玩家位置 + /// + /// 玩家索引 + /// 位置坐标数组(x,y,z) + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern void GetUserOrigin(int index, [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] float[] origin); + + /// + /// 设置玩家位置 + /// + /// 玩家索引 + /// 位置坐标数组(x,y,z) + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserOrigin(int index, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] float[] origin); + + /// + /// 获取玩家渲染效果 + /// + /// 玩家索引 + /// 特效类型输出 + /// 红色分量输出 + /// 绿色分量输出 + /// 蓝色分量输出 + /// 渲染模式输出 + /// 透明度输出 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserRendering(int index, out int fx, out int r, out int g, out int b, out int render, out float amount); + + /// + /// 设置玩家渲染效果 + /// + /// 玩家索引 + /// 特效类型 + /// 红色分量 + /// 绿色分量 + /// 蓝色分量 + /// 渲染模式 + /// 透明度 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserRendering(int index, int fx, int r, int g, int b, int render, float amount); + + #endregion + + #region 玩家物理属性 + + /// + /// 获取玩家最大速度 + /// + /// 玩家索引 + /// 最大速度值 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern float GetUserMaxspeed(int index); + + /// + /// 设置玩家最大速度 + /// + /// 玩家索引 + /// 最大速度 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserMaxspeed(int index, float speed); + + /// + /// 获取玩家重力 + /// + /// 玩家索引 + /// 重力值 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern float GetUserGravity(int index); + + /// + /// 设置玩家重力 + /// + /// 玩家索引 + /// 重力值 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserGravity(int index, float gravity); + + #endregion + + #region 命中区域 + + /// + /// 获取玩家命中区域设置 + /// + /// 攻击者索引 + /// 目标索引 + /// 命中区域标志 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserHitzones(int attacker, int target); + + /// + /// 设置玩家命中区域 + /// + /// 攻击者索引,0表示所有玩家 + /// 目标索引,0表示所有玩家 + /// 命中区域标志 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserHitzones(int attacker, int target, int hitzones); + + #endregion + + #region 穿墙模式 + + /// + /// 设置玩家穿墙模式 + /// + /// 玩家索引 + /// 1开启穿墙,0关闭穿墙 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserNoclip(int index, int noclip); + + /// + /// 获取玩家穿墙模式状态 + /// + /// 玩家索引 + /// 1表示穿墙模式,0表示正常模式 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserNoclip(int index); + + #endregion + + #region 脚步声 + + /// + /// 设置玩家脚步声 + /// + /// 玩家索引 + /// 1开启无声脚步,0关闭无声脚步 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int SetUserFootsteps(int index, int footsteps); + + /// + /// 获取玩家脚步声状态 + /// + /// 玩家索引 + /// 1表示无声脚步,0表示正常脚步 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetUserFootsteps(int index); + + #endregion + + #region 武器管理 + + /// + /// 移除玩家所有武器 + /// + /// 玩家索引 + /// 操作是否成功 + [DllImport(FunBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int StripUserWeapons(int index); + + #endregion + + #region 辅助类和方法 + + /// + /// 玩家渲染模式枚举 + /// + public enum RenderMode + { + Normal = 0, + Color = 1, + Texture = 2, + Glow = 3, + Solid = 4, + Additive = 5 + } + + /// + /// 玩家特效类型枚举 + /// + public enum RenderFx + { + None = 0, + PulseSlow = 1, + PulseFast = 2, + PulseSlowWide = 3, + PulseFastWide = 4, + FadeSlow = 5, + FadeFast = 6, + SolidSlow = 7, + SolidFast = 8, + StrobeSlow = 9, + StrobeFast = 10, + StrobeFaster = 11, + FlickerSlow = 12, + FlickerFast = 13, + NoDissipation = 14, + Distort = 15, + Hologram = 16, + DeadPlayer = 17, + Explode = 18, + GlowShell = 19, + ClampMinScale = 20, + LightMultiplier = 21 + } + + /// + /// 命中区域枚举 + /// + [Flags] + public enum HitZones + { + Generic = 1 << 0, + Head = 1 << 1, + Chest = 1 << 2, + Stomach = 1 << 3, + LeftArm = 1 << 4, + RightArm = 1 << 5, + LeftLeg = 1 << 6, + RightLeg = 1 << 7, + All = (1 << 8) - 1 + } + + /// + /// 获取玩家渲染信息的结构体 + /// + public struct PlayerRendering + { + public RenderFx Fx; + public int Red; + public int Green; + public int Blue; + public RenderMode RenderMode; + public float Amount; + } + + /// + /// 获取玩家渲染信息的便捷方法 + /// + /// 玩家索引 + /// 玩家渲染信息 + public static PlayerRendering GetPlayerRendering(int index) + { + int fx, r, g, b, render; + float amount; + + int result = GetUserRendering(index, out fx, out r, out g, out b, out render, out amount); + if (result == 0) + throw new InvalidOperationException("无法获取玩家渲染信息"); + + return new PlayerRendering + { + Fx = (RenderFx)fx, + Red = r, + Green = g, + Blue = b, + RenderMode = (RenderMode)render, + Amount = amount + }; + } + + /// + /// 设置玩家渲染信息的便捷方法 + /// + /// 玩家索引 + /// 渲染信息 + public static void SetPlayerRendering(int index, PlayerRendering rendering) + { + int result = SetUserRendering(index, (int)rendering.Fx, rendering.Red, rendering.Green, + rendering.Blue, (int)rendering.RenderMode, rendering.Amount); + if (result == 0) + throw new InvalidOperationException("无法设置玩家渲染信息"); + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.HamSandwich.Direct.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.HamSandwich.Direct.cs new file mode 100644 index 0000000..fd0cfe6 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.HamSandwich.Direct.cs @@ -0,0 +1,146 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.HamSandwich.Direct +{ + /// + /// Ham Sandwich模块的直接桥接接口 - 不依赖AMXX函数 + /// 直接操作底层内存和实体数据 + /// + public static class NativeDirectBridge + { + private const string DllName = "hamsandwich_amxx"; + + // 实体验证 + /// + /// 验证实体ID是否有效 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern bool IsValidEntity(int entityId); + + /// + /// 验证偏移量是否有效 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern bool IsValidOffset(int offset); + + // 直接数据访问 + /// + /// 获取实体私有数据的整型值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetEntityPrivateDataInt(int entityId, int offset); + + /// + /// 获取实体私有数据的浮点值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern float GetEntityPrivateDataFloat(int entityId, int offset); + + /// + /// 获取实体私有数据的实体引用 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetEntityPrivateDataEntity(int entityId, int offset); + + /// + /// 设置实体私有数据的整型值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityPrivateDataInt(int entityId, int offset, int value); + + /// + /// 设置实体私有数据的浮点值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityPrivateDataFloat(int entityId, int offset, float value); + + /// + /// 设置实体私有数据的实体引用 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityPrivateDataEntity(int entityId, int offset, int targetEntity); + + // 向量数据访问 + /// + /// 获取实体私有数据的向量值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void GetEntityPrivateDataVector(int entityId, int offset, [Out] float[] vec); + + /// + /// 设置实体私有数据的向量值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityPrivateDataVector(int entityId, int offset, float[] vec); + + // 实体变量访问 + /// + /// 获取实体变量的整型值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetEntityVarInt(int entityId, int offset); + + /// + /// 获取实体变量的浮点值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern float GetEntityVarFloat(int entityId, int offset); + + /// + /// 获取实体变量的向量值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void GetEntityVarVector(int entityId, int offset, [Out] float[] vec); + + /// + /// 设置实体变量的整型值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityVarInt(int entityId, int offset, int value); + + /// + /// 设置实体变量的浮点值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityVarFloat(int entityId, int offset, float value); + + /// + /// 设置实体变量的向量值 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void SetEntityVarVector(int entityId, int offset, float[] vec); + + // 内存工具 + /// + /// 获取实体基础内存指针 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr GetEntityBasePointer(int entityId); + + /// + /// 获取实体内存大小 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int GetEntityMemorySize(int entityId); + + /// + /// 将实体指针转换为索引 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int EntityToIndex(IntPtr edict); + + /// + /// 将索引转换为实体指针 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr IndexToEntity(int index); + + /// + /// 获取私有数据指针 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr GetPrivateDataPtr(int entityId); + } + +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.NewMenus.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.NewMenus.cs new file mode 100644 index 0000000..736b24b --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/Gameplay/AmxModx.Bridge.NewMenus.cs @@ -0,0 +1,321 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.NewMenus +{ + /// + /// 新菜单系统桥接接口 + /// + public static class NewMenuBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 菜单属性类型 + /// + public enum MenuProperty + { + PER_PAGE = 0, + EXIT = 1, + BACK = 2, + NEXT = 3, + TITLE = 4, + EXITBUTTON = 5, + NOVOTE = 6, + NOMORE = 7, + TIME = 8, + KEYS = 9 + } + + /// + /// 菜单选项类型 + /// + public enum MenuItemType + { + NORMAL = 0, + BLANK = 1, + TEXT = 2, + SPACER = 3 + } + + /// + /// 创建新菜单 + /// + /// 菜单标题 + /// 页面回调 + /// 退出回调 + /// 返回回调 + /// 下一页回调 + /// 菜单句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuCreate( + [MarshalAs(UnmanagedType.LPStr)] string title, + IntPtr pageCallback, + IntPtr exitCallback, + IntPtr backCallback, + IntPtr nextCallback); + + /// + /// 销毁菜单 + /// + /// 菜单句柄 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuDestroy(int menu); + + /// + /// 添加菜单项 + /// + /// 菜单句柄 + /// 菜单文本 + /// 回调函数 + /// 附加信息 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuAddItem( + int menu, + [MarshalAs(UnmanagedType.LPStr)] string text, + IntPtr callback, + [MarshalAs(UnmanagedType.LPStr)] string info); + + /// + /// 添加空白菜单项 + /// + /// 菜单句柄 + /// 回调函数 + /// 附加信息 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuAddBlank( + int menu, + IntPtr callback, + [MarshalAs(UnmanagedType.LPStr)] string info); + + /// + /// 添加文本菜单项 + /// + /// 菜单句柄 + /// 菜单文本 + /// 回调函数 + /// 附加信息 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuAddText( + int menu, + [MarshalAs(UnmanagedType.LPStr)] string text, + IntPtr callback, + [MarshalAs(UnmanagedType.LPStr)] string info); + + /// + /// 显示菜单给玩家 + /// + /// 菜单句柄 + /// 玩家索引 + /// 页码 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuDisplay(int menu, int player, int page); + + /// + /// 设置菜单属性 + /// + /// 菜单句柄 + /// 属性类型 + /// 属性值 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuSetProperty( + int menu, + int prop, + int value); + + /// + /// 获取菜单属性 + /// + /// 菜单句柄 + /// 属性类型 + /// 属性值 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuGetProperty(int menu, int prop); + + /// + /// 获取菜单项信息 + /// + /// 菜单句柄 + /// 菜单项索引 + /// 输出缓冲区 + /// 缓冲区大小 + /// 附加信息缓冲区 + /// 附加信息缓冲区大小 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuGetItemInfo( + int menu, + int item, + [MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, + int bufferSize, + [MarshalAs(UnmanagedType.LPStr)] StringBuilder info, + int infoSize); + + /// + /// 获取菜单项数量 + /// + /// 菜单句柄 + /// 菜单项数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuGetItems(int menu); + + /// + /// 获取菜单页数 + /// + /// 菜单句柄 + /// 页数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuGetPages(int menu); + + /// + /// 获取当前页菜单项数量 + /// + /// 菜单句柄 + /// 页码 + /// 当前页菜单项数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuGetPageItems(int menu, int page); + + /// + /// 关闭玩家菜单 + /// + /// 玩家索引 + /// 是否成功 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_MenuClose(int player); + + /// + /// 获取玩家当前菜单 + /// + /// 玩家索引 + /// 菜单句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerMenu(int player); + + /// + /// 获取玩家菜单页 + /// + /// 玩家索引 + /// 当前页码 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetPlayerMenuPage(int player); + + /// + /// 菜单管理器包装类 + /// + public static class MenuManager + { + /// + /// 创建新菜单 + /// + public static int CreateMenu(string title) + { + return AmxModx_Bridge_MenuCreate(title, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + } + + /// + /// 创建带回调的菜单 + /// + public static int CreateMenu( + string title, + IntPtr pageCallback = default, + IntPtr exitCallback = default, + IntPtr backCallback = default, + IntPtr nextCallback = default) + { + return AmxModx_Bridge_MenuCreate(title, pageCallback, exitCallback, backCallback, nextCallback); + } + + /// + /// 添加菜单项 + /// + public static bool AddMenuItem(int menu, string text, IntPtr callback = default, string info = "") + { + return AmxModx_Bridge_MenuAddItem(menu, text, callback, info) != 0; + } + + /// + /// 添加空白菜单项 + /// + public static bool AddBlankItem(int menu, IntPtr callback = default, string info = "") + { + return AmxModx_Bridge_MenuAddBlank(menu, callback, info) != 0; + } + + /// + /// 添加文本菜单项 + /// + public static bool AddTextItem(int menu, string text, IntPtr callback = default, string info = "") + { + return AmxModx_Bridge_MenuAddText(menu, text, callback, info) != 0; + } + + /// + /// 显示菜单给玩家 + /// + public static bool DisplayMenu(int menu, int player, int page = 0) + { + return AmxModx_Bridge_MenuDisplay(menu, player, page) != 0; + } + + /// + /// 设置菜单每页显示数量 + /// + public static bool SetItemsPerPage(int menu, int count) + { + return AmxModx_Bridge_MenuSetProperty(menu, (int)MenuProperty.PER_PAGE, count) != 0; + } + + /// + /// 设置菜单标题 + /// + public static bool SetMenuTitle(int menu, string title) + { + return AmxModx_Bridge_MenuSetProperty(menu, (int)MenuProperty.TITLE, 0) != 0; + } + + /// + /// 获取菜单信息 + /// + public static string GetMenuItemText(int menu, int item) + { + var buffer = new StringBuilder(256); + var info = new StringBuilder(256); + if (AmxModx_Bridge_MenuGetItemInfo(menu, item, buffer, buffer.Capacity, info, info.Capacity) != 0) + { + return buffer.ToString(); + } + return string.Empty; + } + + /// + /// 获取菜单项信息 + /// + public static (string text, string info) GetMenuItemInfo(int menu, int item) + { + var buffer = new StringBuilder(256); + var info = new StringBuilder(256); + if (AmxModx_Bridge_MenuGetItemInfo(menu, item, buffer, buffer.Capacity, info, info.Capacity) != 0) + { + return (buffer.ToString(), info.ToString()); + } + return (string.Empty, string.Empty); + } + + /// + /// 销毁菜单 + /// + public static bool DestroyMenu(int menu) + { + return AmxModx_Bridge_MenuDestroy(menu) != 0; + } + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Command.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Command.cs new file mode 100644 index 0000000..7de8d0c --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Command.cs @@ -0,0 +1,193 @@ + +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Command +{ + /// + /// 命令类型枚举 + /// + public enum CommandType + { + /// + /// 控制台命令 + /// + Console = 0, + + /// + /// 客户端命令 + /// + Client = 1, + + /// + /// 服务器命令 + /// + Server = 2 + } + + /// + /// 命令标志位 + /// + [Flags] + public enum CommandFlags + { + /// + /// 管理员命令 + /// + Admin = 1, + + /// + /// RCON命令 + /// + Rcon = 2, + + /// + /// 公共命令 + /// + Public = 4, + + /// + /// 隐藏命令 + /// + Hidden = 8 + } + + /// + /// 命令信息结构 + /// + public struct CommandInfo + { + /// + /// 命令名称 + /// + public string Command; + + /// + /// 命令描述 + /// + public string Info; + + /// + /// 命令标志位 + /// + public CommandFlags Flags; + } + + /// + /// 命令系统P/Invoke接口 + /// + public static class CommandBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 注册控制台命令 + /// + /// 插件ID + /// 函数ID + /// 命令名称 + /// 命令描述 + /// 命令标志位 + /// 是否可列出 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterConsoleCommand( + int pluginId, + int funcId, + [MarshalAs(UnmanagedType.LPStr)] string cmd, + [MarshalAs(UnmanagedType.LPStr)] string info, + int flags, + [MarshalAs(UnmanagedType.Bool)] bool listable); + + /// + /// 注册客户端命令 + /// + /// 插件ID + /// 函数ID + /// 命令名称 + /// 命令描述 + /// 命令标志位 + /// 是否可列出 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterClientCommand( + int pluginId, + int funcId, + [MarshalAs(UnmanagedType.LPStr)] string cmd, + [MarshalAs(UnmanagedType.LPStr)] string info, + int flags, + [MarshalAs(UnmanagedType.Bool)] bool listable); + + /// + /// 注册服务器命令 + /// + /// 插件ID + /// 函数ID + /// 命令名称 + /// 命令描述 + /// 命令标志位 + /// 是否可列出 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterServerCommand( + int pluginId, + int funcId, + [MarshalAs(UnmanagedType.LPStr)] string cmd, + [MarshalAs(UnmanagedType.LPStr)] string info, + int flags, + [MarshalAs(UnmanagedType.Bool)] bool listable); + + /// + /// 获取命令数量 + /// + /// 命令类型 + /// 访问级别 + /// 命令数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetCommandCount(int type, int access); + + /// + /// 执行控制台命令 + /// + /// 命令字符串 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteConsoleCommand([MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 执行客户端命令 + /// + /// 玩家ID + /// 命令字符串 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteClientCommand(int playerId, [MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 执行服务器命令 + /// + /// 命令字符串 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteServerCommand([MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 检查命令是否存在 + /// + /// 命令类型 + /// 命令名称 + /// 存在返回true,否则返回false + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_CommandExists(int type, [MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 移除命令 + /// + /// 插件ID + /// 命令名称 + /// 移除的命令数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RemoveCommands(int pluginId, [MarshalAs(UnmanagedType.LPStr)] string cmd); + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.CommandSystem.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.CommandSystem.cs new file mode 100644 index 0000000..67e8ba3 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.CommandSystem.cs @@ -0,0 +1,438 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X Command System Bridge for C# +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Text; + +namespace AmxModx.Bridge.CommandSystem +{ + /// + /// 命令类型枚举 + /// + public enum CommandType + { + Console = 0, // 控制台命令 + Client = 1, // 客户端命令 + Server = 2 // 服务器命令 + } + + /// + /// 命令标志位枚举 + /// + [Flags] + public enum CommandFlags + { + None = 0, // 无标志 + Admin = 1, // 管理员命令 + Rcon = 2, // RCON命令 + Public = 4, // 公共命令 + Hidden = 8 // 隐藏命令 + } + + /// + /// 命令信息结构体 + /// + public struct CommandInfo + { + public string Name; + public string Description; + public CommandType Type; + public CommandFlags Flags; + public bool IsListable; + } + + /// + /// 命令回调委托 + /// + /// 玩家ID(-1表示控制台/服务器) + /// 命令参数 + public delegate void CommandHandler(int playerId, string[] args); + + /// + /// 命令系统桥接接口 + /// + public static class CommandBridge + { + private const string DllName = "amxmodx_mm"; + + #region P/Invoke接口定义 + + /// + /// 注册控制台命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterConsoleCommand( + int pluginId, + int funcId, + [MarshalAs(UnmanagedType.LPStr)] string cmd, + [MarshalAs(UnmanagedType.LPStr)] string info, + int flags, + [MarshalAs(UnmanagedType.Bool)] bool listable); + + /// + /// 注册客户端命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterClientCommand( + int pluginId, + int funcId, + [MarshalAs(UnmanagedType.LPStr)] string cmd, + [MarshalAs(UnmanagedType.LPStr)] string info, + int flags, + [MarshalAs(UnmanagedType.Bool)] bool listable); + + /// + /// 注册服务器命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterServerCommand( + int pluginId, + int funcId, + [MarshalAs(UnmanagedType.LPStr)] string cmd, + [MarshalAs(UnmanagedType.LPStr)] string info, + int flags, + [MarshalAs(UnmanagedType.Bool)] bool listable); + + /// + /// 获取命令数量 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetCommandCount(int type, int access); + + /// + /// 获取命令信息 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetCommandInfo( + int type, + int index, + int access, + [Out] byte[] cmd, + int cmdSize, + [Out] byte[] info, + int infoSize, + out int flags); + + /// + /// 执行控制台命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteConsoleCommand([MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 执行客户端命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteClientCommand( + int playerId, + [MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 执行服务器命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ExecuteServerCommand([MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 检查命令是否存在 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_CommandExists(int type, [MarshalAs(UnmanagedType.LPStr)] string cmd); + + /// + /// 移除命令 + /// + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RemoveCommands(int pluginId, [MarshalAs(UnmanagedType.LPStr)] string cmd); + + #endregion + } + + /// + /// 命令管理器,提供高级命令管理功能 + /// + public static class CommandManager + { + private static readonly Dictionary _handlers = new Dictionary(); + private static int _pluginId = 1; // 默认插件ID + + #region 命令注册 + + /// + /// 设置插件ID + /// + public static void SetPluginId(int pluginId) + { + _pluginId = pluginId; + } + + /// + /// 注册控制台命令 + /// + /// 命令名称 + /// 命令描述 + /// 命令处理器 + /// 命令标志 + /// 是否可列出 + public static bool RegisterConsoleCommand( + string command, + string description, + CommandHandler handler, + CommandFlags flags = CommandFlags.Public, + bool listable = true) + { + if (string.IsNullOrEmpty(command) || handler == null) + return false; + + int funcId = _handlers.Count + 1; + int result = CommandBridge.AmxModx_Bridge_RegisterConsoleCommand( + _pluginId, + funcId, + command, + description, + (int)flags, + listable); + + if (result != 0) + { + _handlers[command] = handler; + return true; + } + return false; + } + + /// + /// 注册客户端命令 + /// + /// 命令名称 + /// 命令描述 + /// 命令处理器 + /// 命令标志 + /// 是否可列出 + public static bool RegisterClientCommand( + string command, + string description, + CommandHandler handler, + CommandFlags flags = CommandFlags.Public, + bool listable = true) + { + if (string.IsNullOrEmpty(command) || handler == null) + return false; + + int funcId = _handlers.Count + 1; + int result = CommandBridge.AmxModx_Bridge_RegisterClientCommand( + _pluginId, + funcId, + command, + description, + (int)flags, + listable); + + if (result != 0) + { + _handlers[command] = handler; + return true; + } + return false; + } + + /// + /// 注册服务器命令 + /// + /// 命令名称 + /// 命令描述 + /// 命令处理器 + /// 命令标志 + /// 是否可列出 + public static bool RegisterServerCommand( + string command, + string description, + CommandHandler handler, + CommandFlags flags = CommandFlags.Public, + bool listable = true) + { + if (string.IsNullOrEmpty(command) || handler == null) + return false; + + int funcId = _handlers.Count + 1; + int result = CommandBridge.AmxModx_Bridge_RegisterServerCommand( + _pluginId, + funcId, + command, + description, + (int)flags, + listable); + + if (result != 0) + { + _handlers[command] = handler; + return true; + } + return false; + } + + #endregion + + #region 命令执行 + + /// + /// 执行控制台命令 + /// + public static bool ExecuteConsoleCommand(string command) + { + if (string.IsNullOrEmpty(command)) + return false; + + return CommandBridge.AmxModx_Bridge_ExecuteConsoleCommand(command) != 0; + } + + /// + /// 执行客户端命令 + /// + public static bool ExecuteClientCommand(int playerId, string command) + { + if (string.IsNullOrEmpty(command) || playerId <= 0) + return false; + + return CommandBridge.AmxModx_Bridge_ExecuteClientCommand(playerId, command) != 0; + } + + /// + /// 执行服务器命令 + /// + public static bool ExecuteServerCommand(string command) + { + if (string.IsNullOrEmpty(command)) + return false; + + return CommandBridge.AmxModx_Bridge_ExecuteServerCommand(command) != 0; + } + + #endregion + + #region 命令查询 + + /// + /// 获取命令数量 + /// + public static int GetCommandCount(CommandType type, int access = 0) + { + return CommandBridge.AmxModx_Bridge_GetCommandCount((int)type, access); + } + + /// + /// 获取所有命令信息 + /// + public static List GetAllCommands(CommandType type, int access = 0) + { + var commands = new List(); + int count = GetCommandCount(type, access); + + for (int i = 0; i < count; i++) + { + var cmdBuffer = new byte[64]; + var infoBuffer = new byte[256]; + int flags; + + if (CommandBridge.AmxModx_Bridge_GetCommandInfo( + (int)type, i, access, cmdBuffer, cmdBuffer.Length, + infoBuffer, infoBuffer.Length, out flags) != 0) + { + string cmdName = Encoding.UTF8.GetString(cmdBuffer).TrimEnd('\0'); + string cmdInfo = Encoding.UTF8.GetString(infoBuffer).TrimEnd('\0'); + + commands.Add(new CommandInfo + { + Name = cmdName, + Description = cmdInfo, + Type = type, + Flags = (CommandFlags)flags + }); + } + } + + return commands; + } + + /// + /// 检查命令是否存在 + /// + public static bool CommandExists(CommandType type, string command) + { + if (string.IsNullOrEmpty(command)) + return false; + + return CommandBridge.AmxModx_Bridge_CommandExists((int)type, command); + } + + #endregion + + #region 命令移除 + + /// + /// 移除指定命令 + /// + public static int RemoveCommands(string command) + { + if (string.IsNullOrEmpty(command)) + return 0; + + return CommandBridge.AmxModx_Bridge_RemoveCommands(_pluginId, command); + } + + /// + /// 移除所有命令 + /// + public static int RemoveAllCommands() + { + return CommandBridge.AmxModx_Bridge_RemoveCommands(_pluginId, null); + } + + #endregion + + #region 快捷方法 + + /// + /// 向所有玩家发送消息 + /// + public static bool BroadcastMessage(string message) + { + return ExecuteServerCommand($"say {message}"); + } + + /// + /// 向指定玩家发送消息 + /// + public static bool SendMessageToPlayer(int playerId, string message) + { + return ExecuteClientCommand(playerId, $"say {message}"); + } + + /// + /// 踢出玩家 + /// + public static bool KickPlayer(int playerId, string reason = "") + { + return ExecuteServerCommand($"kick #{playerId} {reason}"); + } + + /// + /// 更改地图 + /// + public static bool ChangeMap(string mapName) + { + return ExecuteServerCommand($"changelevel {mapName}"); + } + + #endregion + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Core.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Core.cs new file mode 100644 index 0000000..23c6a18 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Core.cs @@ -0,0 +1,145 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.Core +{ + /// + /// AMX Mod X核心桥接接口 + /// 提供amxcore.cpp中核心功能的C#访问 + /// + public static class CoreBridge + { + /// + /// 获取当前函数的参数数量 + /// + /// 参数数量 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetNumArgs(); + + /// + /// 获取指定索引的参数值 + /// + /// 参数索引(从0开始) + /// 数组偏移量(对于数组参数) + /// 参数值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetArg(int index, int offset); + + /// + /// 设置指定索引的参数值 + /// + /// 参数索引(从0开始) + /// 数组偏移量(对于数组参数) + /// 要设置的值 + /// 成功返回true,失败返回false + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetArg(int index, int offset, int value); + + /// + /// 获取可用堆空间大小 + /// + /// 堆空间字节数 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetHeapSpace(); + + /// + /// 根据函数名获取函数索引 + /// + /// 函数名称 + /// 函数索引,-1表示未找到 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetFunctionIndex([MarshalAs(UnmanagedType.LPStr)] string functionName); + + /// + /// 交换32位整数的字节顺序 + /// + /// 要交换的值 + /// 交换后的值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SwapChars(int value); + + /// + /// 获取属性值 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 输出缓冲区 + /// 缓冲区最大长度 + /// 属性值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetProperty(int id, [MarshalAs(UnmanagedType.LPStr)] string name, int value, [Out] StringBuilder buffer, int maxLen); + + /// + /// 设置属性值 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 新属性名称(可选) + /// 之前的属性值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SetProperty(int id, [MarshalAs(UnmanagedType.LPStr)] string name, int value, [MarshalAs(UnmanagedType.LPStr)] string newName); + + /// + /// 删除属性 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 被删除的属性值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_DeleteProperty(int id, [MarshalAs(UnmanagedType.LPStr)] string name, int value); + + /// + /// 检查属性是否存在 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 存在返回true,不存在返回false + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_PropertyExists(int id, [MarshalAs(UnmanagedType.LPStr)] string name, int value); + + /// + /// 安全的获取属性值方法 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 属性值和名称 + public static (int value, string name) GetPropertySafe(int id, string name, int value) + { + StringBuilder buffer = new StringBuilder(256); + int result = AmxModx_Bridge_GetProperty(id, name, value, buffer, buffer.Capacity); + return (result, buffer.ToString()); + } + + /// + /// 安全的设置属性值方法 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 之前的属性值 + public static int SetPropertySafe(int id, string name, int value) + { + return AmxModx_Bridge_SetProperty(id, name, value, null); + } + + /// + /// 安全的删除属性方法 + /// + /// 属性ID + /// 属性名称 + /// 属性值 + /// 被删除的属性值 + public static int DeletePropertySafe(int id, string name, int value) + { + return AmxModx_Bridge_DeleteProperty(id, name, value); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Debugger.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Debugger.cs new file mode 100644 index 0000000..6d7072f --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Debugger.cs @@ -0,0 +1,139 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.Debugger +{ + /// + /// 调试器桥接接口,提供调试相关功能 + /// + public static class DebuggerBridge + { + private const string NativeLibrary = "amxmodx_mm"; + + #region 调试器操作 + + /// + /// 设置错误过滤器 + /// + /// 过滤器类型 (0=全部, 1=警告, 2=错误) + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetErrorFilter(int filter); + + /// + /// 记录调试信息 + /// + /// 调试信息 + /// 日志级别 (0=调试, 1=信息, 2=警告, 3=错误) + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_LogDebug([MarshalAs(UnmanagedType.LPStr)] string message, int level); + + /// + /// 获取最后错误信息 + /// + /// 错误信息字符串 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_GetLastError(); + + /// + /// 清除最后错误信息 + /// + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_ClearLastError(); + + /// + /// 启用/禁用调试模式 + /// + /// 是否启用 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetDebugMode([MarshalAs(UnmanagedType.I1)] bool enabled); + + /// + /// 检查是否处于调试模式 + /// + /// 是否处于调试模式 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_IsDebugMode(); + + /// + /// 设置断点 + /// + /// 文件名 + /// 行号 + /// 设置是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_SetBreakpoint([MarshalAs(UnmanagedType.LPStr)] string file, int line); + + /// + /// 移除断点 + /// + /// 文件名 + /// 行号 + /// 移除是否成功 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public static extern bool AmxModx_Bridge_RemoveBreakpoint([MarshalAs(UnmanagedType.LPStr)] string file, int line); + + /// + /// 获取当前调用栈信息 + /// + /// 输出缓冲区 + /// 缓冲区大小 + /// 调用栈信息长度 + [DllImport(NativeLibrary, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetCallStack([Out, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, int bufferSize); + + #endregion + + #region 便捷方法 + + /// + /// 获取最后错误信息的安全封装 + /// + /// 错误信息字符串 + public static string GetLastErrorSafe() + { + IntPtr ptr = AmxModx_Bridge_GetLastError(); + return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : string.Empty; + } + + /// + /// 获取当前调用栈信息的安全封装 + /// + /// 调用栈信息字符串 + public static string GetCallStackSafe() + { + byte[] buffer = new byte[1024]; + int length = AmxModx_Bridge_GetCallStack(buffer, buffer.Length); + return length > 0 ? Encoding.ASCII.GetString(buffer, 0, length) : string.Empty; + } + + /// + /// 记录调试信息 + /// + /// 调试信息 + /// 日志级别 + public static void LogDebugSafe(string message, LogLevel level = LogLevel.Info) + { + if (!string.IsNullOrEmpty(message)) + { + AmxModx_Bridge_LogDebug(message, (int)level); + } + } + + #endregion + } + + /// + /// 日志级别枚举 + /// + public enum LogLevel + { + Debug = 0, + Info = 1, + Warning = 2, + Error = 3 + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Logging.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Logging.cs new file mode 100644 index 0000000..4fcb790 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Logging.cs @@ -0,0 +1,252 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.System +{ + /// + /// 日志级别枚举 + /// + public enum LogLevel + { + /// 调试日志 + Debug = 0, + /// 信息日志 + Info = 1, + /// 警告日志 + Warning = 2, + /// 错误日志 + Error = 3, + /// 致命错误 + Fatal = 4 + } + + /// + /// 日志目标枚举 + /// + public enum LogTarget + { + /// 控制台 + Console = 0, + /// 日志文件 + File = 1, + /// 游戏聊天 + Chat = 2, + /// 所有目标 + All = 3 + } + + /// + /// 日志系统桥接接口 + /// 提供AMX Mod X日志系统的C#访问 + /// + public static class LoggingBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 记录日志消息 + /// + /// 日志级别 + /// 日志消息 + /// 是否成功记录 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_LogMessage( + LogLevel level, + [MarshalAs(UnmanagedType.LPStr)] string message); + + /// + /// 记录格式化日志消息 + /// + /// 日志级别 + /// 格式化字符串 + /// 参数数组 + /// 是否成功记录 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_LogFormat( + LogLevel level, + [MarshalAs(UnmanagedType.LPStr)] string format, + [MarshalAs(UnmanagedType.LPArray)] object[] args, + int argCount); + + /// + /// 记录日志到指定目标 + /// + /// 日志级别 + /// 日志目标 + /// 日志消息 + /// 是否成功记录 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_LogToTarget( + LogLevel level, + LogTarget target, + [MarshalAs(UnmanagedType.LPStr)] string message); + + /// + /// 设置日志级别 + /// + /// 日志级别 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetLogLevel(LogLevel level); + + /// + /// 获取当前日志级别 + /// + /// 当前日志级别 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern LogLevel AmxModx_Bridge_GetLogLevel(); + + /// + /// 启用/禁用日志目标 + /// + /// 日志目标 + /// 是否启用 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_SetLogTargetEnabled( + LogTarget target, + [MarshalAs(UnmanagedType.Bool)] bool enabled); + + /// + /// 检查日志目标是否启用 + /// + /// 日志目标 + /// 是否启用 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_IsLogTargetEnabled(LogTarget target); + + /// + /// 设置日志文件路径 + /// + /// 日志文件路径 + /// 是否成功设置 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetLogFilePath([MarshalAs(UnmanagedType.LPStr)] string filePath); + + /// + /// 获取日志文件路径 + /// + /// 路径缓冲区 + /// 缓冲区大小 + /// 实际路径长度 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetLogFilePath( + [Out] StringBuilder buffer, + int bufferSize); + + /// + /// 清空日志文件 + /// + /// 是否成功清空 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ClearLogFile(); + + /// + /// 获取日志文件大小 + /// + /// 文件大小(字节) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern long AmxModx_Bridge_GetLogFileSize(); + + /// + /// 安全的记录日志消息 + /// + /// 日志级别 + /// 日志消息 + /// 是否成功记录 + public static bool LogMessageSafe(LogLevel level, string message) + { + if (string.IsNullOrEmpty(message)) + return false; + + return AmxModx_Bridge_LogMessage(level, message); + } + + /// + /// 安全的记录格式化日志消息 + /// + /// 日志级别 + /// 格式化字符串 + /// 参数数组 + /// 是否成功记录 + public static bool LogFormatSafe(LogLevel level, string format, params object[] args) + { + if (string.IsNullOrEmpty(format) || args == null) + return false; + + return AmxModx_Bridge_LogFormat(level, format, args, args.Length); + } + + /// + /// 获取日志文件路径 + /// + /// 日志文件路径 + public static string GetLogFilePathSafe() + { + StringBuilder pathBuilder = new StringBuilder(512); + int length = AmxModx_Bridge_GetLogFilePath(pathBuilder, pathBuilder.Capacity); + + if (length > 0) + { + return pathBuilder.ToString(); + } + + return string.Empty; + } + + /// + /// 记录调试日志 + /// + /// 日志消息 + /// 是否成功记录 + public static bool LogDebug(string message) + { + return LogMessageSafe(LogLevel.Debug, message); + } + + /// + /// 记录信息日志 + /// + /// 日志消息 + /// 是否成功记录 + public static bool LogInfo(string message) + { + return LogMessageSafe(LogLevel.Info, message); + } + + /// + /// 记录警告日志 + /// + /// 日志消息 + /// 是否成功记录 + public static bool LogWarning(string message) + { + return LogMessageSafe(LogLevel.Warning, message); + } + + /// + /// 记录错误日志 + /// + /// 日志消息 + /// 是否成功记录 + public static bool LogError(string message) + { + return LogMessageSafe(LogLevel.Error, message); + } + + /// + /// 记录致命错误日志 + /// + /// 日志消息 + /// 是否成功记录 + public static bool LogFatal(string message) + { + return LogMessageSafe(LogLevel.Fatal, message); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Memory.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Memory.cs new file mode 100644 index 0000000..f981403 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Memory.cs @@ -0,0 +1,260 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.System +{ + /// + /// 内存分配类型枚举 + /// + public enum MemoryType + { + /// 临时内存 + Temporary = 0, + /// 持久内存 + Permanent = 1, + /// 插件内存 + Plugin = 2, + /// 全局内存 + Global = 3 + } + + /// + /// 内存保护类型枚举 + /// + public enum MemoryProtection + { + /// 无保护 + None = 0, + /// 只读 + ReadOnly = 1, + /// 读写 + ReadWrite = 2, + /// 执行 + Execute = 4, + /// 读写执行 + ReadWriteExecute = 6 + } + + /// + /// 内存系统桥接接口 + /// 提供AMX Mod X内存管理的C#访问 + /// + public static class MemoryBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 分配内存 + /// + /// 内存大小(字节) + /// 内存类型 + /// 分配的内存指针 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_AllocateMemory(long size, MemoryType type); + + /// + /// 释放内存 + /// + /// 内存指针 + /// 内存类型 + /// 是否成功释放 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_FreeMemory(IntPtr ptr, MemoryType type); + + /// + /// 重新分配内存 + /// + /// 原内存指针 + /// 新内存大小 + /// 内存类型 + /// 重新分配的内存指针 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_ReallocateMemory(IntPtr ptr, long newSize, MemoryType type); + + /// + /// 获取内存大小 + /// + /// 内存指针 + /// 内存大小(字节) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern long AmxModx_Bridge_GetMemorySize(IntPtr ptr); + + /// + /// 设置内存保护 + /// + /// 内存指针 + /// 内存大小 + /// 保护类型 + /// 是否成功设置 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetMemoryProtection( + IntPtr ptr, + long size, + MemoryProtection protection); + + /// + /// 获取内存保护类型 + /// + /// 内存指针 + /// 保护类型 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern MemoryProtection AmxModx_Bridge_GetMemoryProtection(IntPtr ptr); + + /// + /// 复制内存 + /// + /// 目标指针 + /// 源指针 + /// 复制大小 + /// 是否成功复制 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_CopyMemory(IntPtr dest, IntPtr src, long size); + + /// + /// 填充内存 + /// + /// 内存指针 + /// 填充值 + /// 填充大小 + /// 是否成功填充 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_FillMemory(IntPtr ptr, byte value, long size); + + /// + /// 比较内存 + /// + /// 第一个内存指针 + /// 第二个内存指针 + /// 比较大小 + /// 比较结果(0表示相等) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_CompareMemory(IntPtr ptr1, IntPtr ptr2, long size); + + /// + /// 获取内存统计信息 + /// + /// 总分配内存 + /// 已使用内存 + /// 空闲内存 + /// 是否成功获取 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_GetMemoryStats( + out long totalAllocated, + out long totalUsed, + out long totalFree); + + /// + /// 检查内存指针是否有效 + /// + /// 内存指针 + /// 是否有效 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_IsMemoryValid(IntPtr ptr); + + /// + /// 获取内存类型 + /// + /// 内存指针 + /// 内存类型 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern MemoryType AmxModx_Bridge_GetMemoryType(IntPtr ptr); + + /// + /// 安全的分配内存 + /// + /// 内存大小(字节) + /// 内存类型 + /// 分配的内存指针 + public static IntPtr AllocateMemorySafe(long size, MemoryType type) + { + if (size <= 0) + return IntPtr.Zero; + + return AmxModx_Bridge_AllocateMemory(size, type); + } + + /// + /// 安全的释放内存 + /// + /// 内存指针 + /// 内存类型 + /// 是否成功释放 + public static bool FreeMemorySafe(IntPtr ptr, MemoryType type) + { + if (ptr == IntPtr.Zero) + return false; + + return AmxModx_Bridge_FreeMemory(ptr, type); + } + + /// + /// 安全的重新分配内存 + /// + /// 原内存指针 + /// 新内存大小 + /// 内存类型 + /// 重新分配的内存指针 + public static IntPtr ReallocateMemorySafe(IntPtr ptr, long newSize, MemoryType type) + { + if (newSize <= 0) + return IntPtr.Zero; + + return AmxModx_Bridge_ReallocateMemory(ptr, newSize, type); + } + + /// + /// 获取内存统计信息 + /// + /// 内存统计信息元组 + public static (long totalAllocated, long totalUsed, long totalFree) GetMemoryStatsSafe() + { + bool success = AmxModx_Bridge_GetMemoryStats( + out long totalAllocated, + out long totalUsed, + out long totalFree); + + if (success) + { + return (totalAllocated, totalUsed, totalFree); + } + + return (0, 0, 0); + } + + /// + /// 安全的复制内存 + /// + /// 目标指针 + /// 源指针 + /// 复制大小 + /// 是否成功复制 + public static bool CopyMemorySafe(IntPtr dest, IntPtr src, long size) + { + if (dest == IntPtr.Zero || src == IntPtr.Zero || size <= 0) + return false; + + return AmxModx_Bridge_CopyMemory(dest, src, size); + } + + /// + /// 安全的填充内存 + /// + /// 内存指针 + /// 填充值 + /// 填充大小 + /// 是否成功填充 + public static bool FillMemorySafe(IntPtr ptr, byte value, long size) + { + if (ptr == IntPtr.Zero || size <= 0) + return false; + + return AmxModx_Bridge_FillMemory(ptr, value, size); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Natives.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Natives.cs new file mode 100644 index 0000000..69f8548 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Natives.cs @@ -0,0 +1,271 @@ +// vim: set ts=4 sw=4 tw=99 noet: +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Natives +{ + /// + /// 原生函数样式枚举 + /// + public enum NativeStyle + { + /// + /// 标准样式 + /// + Default = 0, + /// + /// 引用参数 + /// + ByRef = 1, + /// + /// 数组参数 + /// + Array = 2, + /// + /// 可变参数 + /// + VarArgs = 3 + } + + /// + /// 参数类型枚举 + /// + public enum ParamType + { + /// + /// 单元格类型 + /// + Cell = 1, + /// + /// 数组类型 + /// + Array = 2, + /// + /// 引用类型 + /// + ByRef = 3, + /// + /// 可变参数类型 + /// + VarArg = 4 + } + + /// + /// 原生函数信息结构体 + /// + [StructLayout(LayoutKind.Sequential)] + public struct NativeInfo + { + /// + /// 函数名称 + /// + [MarshalAs(UnmanagedType.LPStr)] + public string Name; + + /// + /// 函数指针 + /// + public IntPtr Function; + } + + /// + /// 原生函数委托 + /// + /// AMX实例指针 + /// 参数数组 + /// 返回值 + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int NativeDelegate(IntPtr amx, IntPtr parameters); + + /// + /// 原生函数桥接类 + /// + public static class NativeBridge + { + /// + /// 注册原生函数 + /// + /// AMX实例指针 + /// 函数名称 + /// 函数指针 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterNative(IntPtr amx, [MarshalAs(UnmanagedType.LPStr)] string name, NativeDelegate func); + + /// + /// 注销原生函数 + /// + /// AMX实例指针 + /// 函数名称 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_UnregisterNative(IntPtr amx, [MarshalAs(UnmanagedType.LPStr)] string name); + + /// + /// 注册库 + /// + /// AMX实例指针 + /// 库名称 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RegisterLibrary(IntPtr amx, [MarshalAs(UnmanagedType.LPStr)] string libname); + + /// + /// 获取原生函数数量 + /// + /// AMX实例指针 + /// 函数数量 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetNativeCount(IntPtr amx); + + /// + /// 获取原生函数名称 + /// + /// AMX实例指针 + /// 函数索引 + /// 函数名称 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_GetNativeName(IntPtr amx, int index); + + /// + /// 检查原生函数是否存在 + /// + /// AMX实例指针 + /// 函数名称 + /// 存在返回true,不存在返回false + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_NativeExists(IntPtr amx, [MarshalAs(UnmanagedType.LPStr)] string name); + + /// + /// 清除库 + /// + /// AMX实例指针 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_ClearLibraries(IntPtr amx); + + /// + /// 获取字符串参数 + /// + /// AMX实例指针 + /// 参数索引 + /// 字符串长度输出 + /// 字符串内容 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_GetString(IntPtr amx, int param, out int length); + + /// + /// 设置字符串参数 + /// + /// AMX实例指针 + /// 参数索引 + /// 字符串内容 + /// 最大长度 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SetString(IntPtr amx, int param, [MarshalAs(UnmanagedType.LPStr)] string str, int maxlen); + + /// + /// 获取参数值 + /// + /// AMX实例指针 + /// 参数索引 + /// 参数值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetParam(IntPtr amx, int index); + + /// + /// 获取参数地址 + /// + /// AMX实例指针 + /// 参数索引 + /// 参数地址 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_GetParamAddress(IntPtr amx, int index); + + /// + /// 设置参数值 + /// + /// AMX实例指针 + /// 参数索引 + /// 参数值 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SetParam(IntPtr amx, int index, int value); + + /// + /// 获取浮点数参数 + /// + /// AMX实例指针 + /// 参数索引 + /// 浮点数值 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern float AmxModx_Bridge_GetFloat(IntPtr amx, int index); + + /// + /// 设置浮点数参数 + /// + /// AMX实例指针 + /// 参数索引 + /// 浮点数值 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SetFloat(IntPtr amx, int index, float value); + + /// + /// 获取数组参数 + /// + /// AMX实例指针 + /// 参数索引 + /// 目标数组 + /// 数组大小 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetArray(IntPtr amx, int param, [Out] int[] dest, int size); + + /// + /// 设置数组参数 + /// + /// AMX实例指针 + /// 参数索引 + /// 源数组 + /// 数组大小 + /// 成功返回1,失败返回0 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SetArray(IntPtr amx, int param, [In] int[] source, int size); + + /// + /// 记录错误 + /// + /// AMX实例指针 + /// 错误代码 + /// 错误消息 + [DllImport("amxmodx_mm", CallingConvention = CallingConvention.Cdecl)] + public static extern void AmxModx_Bridge_LogError(IntPtr amx, int err, [MarshalAs(UnmanagedType.LPStr)] string message); + + /// + /// 安全获取原生函数名称 + /// + /// AMX实例指针 + /// 函数索引 + /// 函数名称 + public static string GetNativeNameSafe(IntPtr amx, int index) + { + IntPtr namePtr = AmxModx_Bridge_GetNativeName(amx, index); + return namePtr != IntPtr.Zero ? Marshal.PtrToStringAnsi(namePtr) : string.Empty; + } + + /// + /// 安全获取字符串 + /// + /// AMX实例指针 + /// 参数索引 + /// 字符串内容 + public static string GetStringSafe(IntPtr amx, int param) + { + int length; + IntPtr strPtr = AmxModx_Bridge_GetString(amx, param, out length); + return strPtr != IntPtr.Zero ? Marshal.PtrToStringAnsi(strPtr, length) : string.Empty; + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.String.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.String.cs new file mode 100644 index 0000000..463d4a2 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.String.cs @@ -0,0 +1,321 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.System +{ + /// + /// 字符串编码枚举 + /// + public enum StringEncoding + { + /// ASCII编码 + Ascii = 0, + /// UTF-8编码 + Utf8 = 1, + /// UTF-16编码 + Utf16 = 2, + /// 本地编码 + Local = 3 + } + + /// + /// 字符串系统桥接接口 + /// 提供AMX Mod X字符串处理的C#访问 + /// + public static class StringBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 创建字符串 + /// + /// 字符串内容 + /// 编码类型 + /// 字符串句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_CreateString( + [MarshalAs(UnmanagedType.LPStr)] string text, + StringEncoding encoding); + + /// + /// 销毁字符串 + /// + /// 字符串句柄 + /// 是否成功销毁 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_DestroyString(IntPtr handle); + + /// + /// 获取字符串长度 + /// + /// 字符串句柄 + /// 字符串长度 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetStringLength(IntPtr handle); + + /// + /// 获取字符串内容 + /// + /// 字符串句柄 + /// 内容缓冲区 + /// 缓冲区大小 + /// 编码类型 + /// 实际内容长度 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetStringContent( + IntPtr handle, + [Out] StringBuilder buffer, + int bufferSize, + StringEncoding encoding); + + /// + /// 设置字符串内容 + /// + /// 字符串句柄 + /// 新内容 + /// 编码类型 + /// 是否成功设置 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_SetStringContent( + IntPtr handle, + [MarshalAs(UnmanagedType.LPStr)] string text, + StringEncoding encoding); + + /// + /// 字符串比较 + /// + /// 第一个字符串句柄 + /// 第二个字符串句柄 + /// 是否区分大小写 + /// 比较结果(0表示相等) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_CompareStrings( + IntPtr handle1, + IntPtr handle2, + [MarshalAs(UnmanagedType.Bool)] bool caseSensitive); + + /// + /// 字符串查找 + /// + /// 字符串句柄 + /// 子字符串 + /// 起始位置 + /// 是否区分大小写 + /// 子字符串位置(-1表示未找到) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_FindString( + IntPtr handle, + [MarshalAs(UnmanagedType.LPStr)] string subString, + int startIndex, + [MarshalAs(UnmanagedType.Bool)] bool caseSensitive); + + /// + /// 字符串替换 + /// + /// 字符串句柄 + /// 要替换的内容 + /// 替换为的内容 + /// 是否区分大小写 + /// 替换次数 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ReplaceString( + IntPtr handle, + [MarshalAs(UnmanagedType.LPStr)] string oldValue, + [MarshalAs(UnmanagedType.LPStr)] string newValue, + [MarshalAs(UnmanagedType.Bool)] bool caseSensitive); + + /// + /// 字符串分割 + /// + /// 字符串句柄 + /// 分隔符 + /// 分割结果数组 + /// 最大分割数量 + /// 实际分割数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_SplitString( + IntPtr handle, + [MarshalAs(UnmanagedType.LPStr)] string delimiter, + [Out] IntPtr[] parts, + int maxParts); + + /// + /// 字符串格式化 + /// + /// 格式化字符串 + /// 参数数组 + /// 参数数量 + /// 格式化后的字符串句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_FormatString( + [MarshalAs(UnmanagedType.LPStr)] string format, + [MarshalAs(UnmanagedType.LPArray)] object[] args, + int argCount); + + /// + /// 字符串转大写 + /// + /// 字符串句柄 + /// 是否成功转换 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ToUpperCase(IntPtr handle); + + /// + /// 字符串转小写 + /// + /// 字符串句柄 + /// 是否成功转换 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_ToLowerCase(IntPtr handle); + + /// + /// 去除字符串空白字符 + /// + /// 字符串句柄 + /// 是否成功去除 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_TrimString(IntPtr handle); + + /// + /// 字符串子串提取 + /// + /// 字符串句柄 + /// 起始位置 + /// 子串长度(-1表示到末尾) + /// 子字符串句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_Substring( + IntPtr handle, + int startIndex, + int length); + + /// + /// 字符串复制 + /// + /// 字符串句柄 + /// 复制的字符串句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_CopyString(IntPtr handle); + + /// + /// 字符串拼接 + /// + /// 字符串句柄数组 + /// 字符串数量 + /// 拼接后的字符串句柄 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr AmxModx_Bridge_ConcatenateStrings( + [MarshalAs(UnmanagedType.LPArray)] IntPtr[] handles, + int count); + + /// + /// 安全的创建字符串 + /// + /// 字符串内容 + /// 编码类型 + /// 字符串句柄 + public static IntPtr CreateStringSafe(string text, StringEncoding encoding = StringEncoding.Utf8) + { + if (string.IsNullOrEmpty(text)) + return IntPtr.Zero; + + return AmxModx_Bridge_CreateString(text, encoding); + } + + /// + /// 安全的销毁字符串 + /// + /// 字符串句柄 + /// 是否成功销毁 + public static bool DestroyStringSafe(IntPtr handle) + { + if (handle == IntPtr.Zero) + return false; + + return AmxModx_Bridge_DestroyString(handle); + } + + /// + /// 安全的获取字符串内容 + /// + /// 字符串句柄 + /// 编码类型 + /// 字符串内容 + public static string GetStringContentSafe(IntPtr handle, StringEncoding encoding = StringEncoding.Utf8) + { + if (handle == IntPtr.Zero) + return string.Empty; + + StringBuilder buffer = new StringBuilder(1024); + int length = AmxModx_Bridge_GetStringContent(handle, buffer, buffer.Capacity, encoding); + + if (length > 0) + { + return buffer.ToString(); + } + + return string.Empty; + } + + /// + /// 安全的字符串格式化 + /// + /// 格式化字符串 + /// 参数数组 + /// 格式化后的字符串句柄 + public static IntPtr FormatStringSafe(string format, params object[] args) + { + if (string.IsNullOrEmpty(format)) + return IntPtr.Zero; + + return AmxModx_Bridge_FormatString(format, args, args?.Length ?? 0); + } + + /// + /// 安全的字符串复制 + /// + /// 字符串句柄 + /// 复制的字符串句柄 + public static IntPtr CopyStringSafe(IntPtr handle) + { + if (handle == IntPtr.Zero) + return IntPtr.Zero; + + return AmxModx_Bridge_CopyString(handle); + } + + /// + /// 安全的字符串拼接 + /// + /// 字符串句柄数组 + /// 拼接后的字符串句柄 + public static IntPtr ConcatenateStringsSafe(params IntPtr[] handles) + { + if (handles == null || handles.Length == 0) + return IntPtr.Zero; + + return AmxModx_Bridge_ConcatenateStrings(handles, handles.Length); + } + + /// + /// 安全的子串提取 + /// + /// 字符串句柄 + /// 起始位置 + /// 子串长度 + /// 子字符串句柄 + public static IntPtr SubstringSafe(IntPtr handle, int startIndex, int length = -1) + { + if (handle == IntPtr.Zero || startIndex < 0) + return IntPtr.Zero; + + return AmxModx_Bridge_Substring(handle, startIndex, length); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Task.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Task.cs new file mode 100644 index 0000000..e728c9a --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Task.cs @@ -0,0 +1,120 @@ +using System; +using System.Runtime.InteropServices; + +namespace AmxModx.Bridge.Task +{ + /// + /// 任务标志位枚举 + /// + [Flags] + public enum TaskFlags + { + /// + /// 重复执行 + /// + Repeat = 1, + + /// + /// 循环执行 + /// + Loop = 2, + + /// + /// 在地图开始后执行 + /// + AfterStart = 4, + + /// + /// 在地图结束前执行 + /// + BeforeEnd = 8 + } + + /// + /// 任务调度系统P/Invoke接口 + /// + public static class TaskBridge + { + private const string DllName = "amxmodx_mm"; + + /// + /// 创建任务 + /// + /// 插件ID + /// 函数ID + /// 任务标志 + /// 任务ID + /// 执行间隔(秒) + /// 重复次数(-1为无限) + /// 参数数组 + /// 参数数量 + /// 成功返回1,失败返回0 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_CreateTask( + int pluginId, + int funcId, + int flags, + int taskId, + float interval, + int repeat, + [MarshalAs(UnmanagedType.LPArray)] int[] parameters, + int paramCount); + + /// + /// 移除任务 + /// + /// 插件ID + /// 任务ID + /// 移除的任务数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_RemoveTasks(int pluginId, int taskId); + + /// + /// 修改任务间隔 + /// + /// 插件ID + /// 任务ID + /// 新的间隔时间 + /// 修改的任务数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_ChangeTaskInterval( + int pluginId, + int taskId, + float newInterval); + + /// + /// 检查任务是否存在 + /// + /// 插件ID + /// 任务ID + /// 存在返回true,否则返回false + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_TaskExists(int pluginId, int taskId); + + /// + /// 获取当前活动任务数量 + /// + /// 活动任务数量 + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int AmxModx_Bridge_GetActiveTaskCount(); + + /// + /// 获取任务信息 + /// + /// 插件ID + /// 任务ID + /// 返回间隔时间 + /// 返回重复次数 + /// 返回任务标志 + /// 成功返回true,失败返回false + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AmxModx_Bridge_GetTaskInfo( + int pluginId, + int taskId, + out float interval, + out int repeat, + out int flags); + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Template.cs b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Template.cs new file mode 100644 index 0000000..860ebc2 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/PInvoke/System/AmxModx.Bridge.Template.cs @@ -0,0 +1,71 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace AmxModx.Bridge.Template +{ + /// + /// 模板模块桥接接口 + /// 提供模板模块功能的C#访问 + /// + public static class TemplateBridge + { + /// + /// 模板模块DLL名称常量 + /// + private const string TemplateBridgeDll = "template_amxx"; + + /// + /// 示例函数 - 获取模板信息 + /// + /// 模板信息缓冲区 + /// 缓冲区最大长度 + /// 实际长度 + [DllImport(TemplateBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Template_GetInfo([Out] byte[] info, int maxLen); + + /// + /// 示例函数 - 设置模板参数 + /// + /// 参数名称 + /// 参数值 + /// 成功返回true,失败返回false + [DllImport(TemplateBridgeDll, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool Template_SetParam([MarshalAs(UnmanagedType.LPStr)] string paramName, int value); + + /// + /// 示例函数 - 执行模板操作 + /// + /// 操作类型 + /// 操作数据 + /// 操作结果 + [DllImport(TemplateBridgeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern int Template_Execute(int operation, IntPtr data); + + /// + /// 安全的获取模板信息方法 + /// + /// 模板信息字符串 + public static string GetTemplateInfoSafe() + { + byte[] buffer = new byte[256]; + int length = Template_GetInfo(buffer, buffer.Length); + if (length <= 0) return string.Empty; + + return Encoding.UTF8.GetString(buffer, 0, Math.Min(length, buffer.Length)); + } + + /// + /// 安全的设置模板参数方法 + /// + /// 参数名称 + /// 参数值 + /// 是否设置成功 + public static bool SetTemplateParamSafe(string paramName, int value) + { + if (string.IsNullOrEmpty(paramName)) return false; + return Template_SetParam(paramName, value); + } + } +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Bridge/README.md b/Template/Amxmodx.Module.Template/Bridge/README.md new file mode 100644 index 0000000..ed699c7 --- /dev/null +++ b/Template/Amxmodx.Module.Template/Bridge/README.md @@ -0,0 +1,181 @@ +# AMX Mod X .NET 高级封装层 + +## 📋 概述 + +本项目为AMX Mod X提供了完整的.NET高级封装层,将原始的P/Invoke接口转换为易于使用的面向对象API。 + +## 🏗️ 项目结构 + +``` +Bridge/ +├── PInvoke/ # P/Invoke接口声明层 +│ ├── Communication/ # 通信模块P/Invoke +│ ├── Data/ # 数据模块P/Invoke +│ ├── Engine/ # 引擎模块P/Invoke +│ ├── Gameplay/ # 游戏模块P/Invoke +│ └── System/ # 系统模块P/Invoke +├── Wrappers/ # 高级封装层 +│ ├── Communication/ # 通信模块高级封装 +│ ├── Data/ # 数据模块高级封装 +│ ├── Engine/ # 引擎模块高级封装 +│ ├── Gameplay/ # 游戏模块高级封装 +│ └── System/ # 系统模块高级封装 +└── Examples/ # 使用示例 +``` + +## 🚀 快速开始 + +### 1. 初始化 + +```csharp +using AmxModx.Wrappers; + +// 初始化所有模块 +AmxModxManager.Initialize(); +``` + +### 2. 使用示例 + +#### 系统模块 +```csharp +// 获取参数 +int paramCount = CoreManager.ParameterCount; +string paramValue = CoreManager.GetStringParameter(0); + +// 设置属性 +var result = CoreManager.SetProperty(1, "test", 123); +``` + +#### 引擎模块 +```csharp +// 实体操作 +if (EngineManager.IsValidEntity(entityId)) +{ + var origin = EngineManager.GetEntityOrigin(entityId); + var distance = EngineManager.GetEntityDistance(entity1, entity2); +} + +// 追踪 +var trace = EngineManager.TraceLine(startPos, endPos, ignoreEntity); +``` + +#### 数据模块 +```csharp +// CVar操作 +var cvar = CVarManager.Create("my_var", "default_value"); +string value = CVarManager.GetString("hostname"); +CVarManager.SetFloat("sv_gravity", 800.0f); +``` + +#### 通信模块 +```csharp +// 事件系统 +EventManager.RegisterEvent("player_death", OnPlayerDeath); +EventManager.FireEvent("round_start", new Dictionary()); + +// 转发系统 +ForwardManager.RegisterClientConnect(OnClientConnect); +int result = ForwardManager.ExecuteForward("client_command", clientId, command); +``` + +## 📚 模块文档 + +### System 模块 +- **CoreManager**: 核心功能封装 +- **NativeManager**: 本地函数封装 +- **CommandManager**: 命令系统封装 +- **TaskManager**: 任务系统封装 + +### Engine 模块 +- **EngineManager**: 引擎功能封装 +- **TraceResult**: 追踪结果封装 + +### Data 模块 +- **CVarManager**: 控制台变量封装 +- **CVar**: CVar实例封装 + +### Communication 模块 +- **EventManager**: 事件系统封装 +- **ForwardManager**: 转发系统封装 + +### Gameplay 模块 +- **HamSandwichManager**: HAM系统封装 +- **HamSandwichWrapper**: HAM包装器 + +## 🔧 开发指南 + +### 创建新的高级封装 + +1. **分析P/Invoke接口**: 查看对应的P/Invoke文件 +2. **设计封装结构**: 确定类和方法的命名 +3. **实现封装**: 在对应模块目录下创建封装类 +4. **添加示例**: 在Examples目录下添加使用示例 + +### 命名规范 + +- **命名空间**: `AmxModx.Wrappers.[模块名]` +- **类名**: `[功能]Manager` 或 `[功能]Wrapper` +- **方法名**: 使用PascalCase,描述性命名 + +### 错误处理 + +所有高级封装都包含完整的错误处理: +- 参数验证 +- 空值检查 +- 异常捕获 +- 错误日志 + +## 📖 API 参考 + +### 统一入口 + +使用 `AmxModxManager` 作为统一入口: + +```csharp +// 系统模块 +AmxModxManager.System.Core.GetParameter(0); +AmxModxManager.System.Native.PtrToString(ptr); + +// 引擎模块 +AmxModxManager.Engine.Engine.IsValidEntity(entityId); + +// 数据模块 +AmxModxManager.Data.CVar.GetString("hostname"); + +// 通信模块 +AmxModxManager.Communication.Event.RegisterEvent("death", callback); +``` + +## 🎯 特性 + +- ✅ **类型安全**: 强类型API,避免指针操作 +- ✅ **面向对象**: 面向对象设计,易于使用 +- ✅ **错误处理**: 完整的错误处理和验证 +- ✅ **性能优化**: 最小化P/Invoke调用 +- ✅ **文档完整**: 详细的XML注释和示例 +- ✅ **扩展性**: 易于扩展和自定义 + +## 🔍 调试 + +### 日志记录 + +所有模块都包含详细的日志记录: +```csharp +// 启用调试日志 +AmxModxManager.EnableDebugLogging = true; +``` + +### 性能监控 + +```csharp +// 获取性能统计 +var stats = AmxModxManager.GetPerformanceStats(); +``` + +## 📞 支持 + +如有问题或建议,请查看项目文档或提交Issue。 + +## 📝 许可证 + +本项目采用MIT许可证,详见LICENSE文件。 \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/amxcore_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/amxcore_bridge.h new file mode 100644 index 0000000..cf91e19 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/amxcore_bridge.h @@ -0,0 +1,98 @@ +/* + * AMX Mod X Core Bridge Header + * 实现amxcore.cpp中核心接口的C#桥接 + */ +#ifndef AMXCORE_BRIDGE_H +#define AMXCORE_BRIDGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief 获取当前函数的参数数量 + * @return 参数数量 + */ +int AmxModx_Bridge_GetNumArgs(void); + +/** + * @brief 获取指定索引的参数值 + * @param index 参数索引(从0开始) + * @param offset 数组偏移量(对于数组参数) + * @return 参数值 + */ +int AmxModx_Bridge_GetArg(int index, int offset); + +/** + * @brief 设置指定索引的参数值 + * @param index 参数索引(从0开始) + * @param offset 数组偏移量(对于数组参数) + * @param value 要设置的值 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_SetArg(int index, int offset, int value); + +/** + * @brief 获取可用堆空间大小 + * @return 堆空间字节数 + */ +int AmxModx_Bridge_GetHeapSpace(void); + +/** + * @brief 根据函数名获取函数索引 + * @param functionName 函数名称 + * @return 函数索引,-1表示未找到 + */ +int AmxModx_Bridge_GetFunctionIndex(const char* functionName); + +/** + * @brief 交换32位整数的字节顺序 + * @param value 要交换的值 + * @return 交换后的值 + */ +int AmxModx_Bridge_SwapChars(int value); + +/** + * @brief 获取属性值 + * @param id 属性ID + * @param name 属性名称 + * @param value 属性值 + * @param buffer 输出缓冲区 + * @param maxLen 缓冲区最大长度 + * @return 属性值 + */ +int AmxModx_Bridge_GetProperty(int id, const char* name, int value, char* buffer, int maxLen); + +/** + * @brief 设置属性值 + * @param id 属性ID + * @param name 属性名称 + * @param value 属性值 + * @param newName 新属性名称(可选) + * @return 之前的属性值 + */ +int AmxModx_Bridge_SetProperty(int id, const char* name, int value, const char* newName); + +/** + * @brief 删除属性 + * @param id 属性ID + * @param name 属性名称 + * @param value 属性值 + * @return 被删除的属性值 + */ +int AmxModx_Bridge_DeleteProperty(int id, const char* name, int value); + +/** + * @brief 检查属性是否存在 + * @param id 属性ID + * @param name 属性名称 + * @param value 属性值 + * @return 存在返回1,不存在返回0 + */ +int AmxModx_Bridge_PropertyExists(int id, const char* name, int value); + +#ifdef __cplusplus +} +#endif + +#endif // AMXCORE_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/command_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/command_bridge.h new file mode 100644 index 0000000..2212017 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/command_bridge.h @@ -0,0 +1,164 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +#ifndef COMMAND_BRIDGE_H +#define COMMAND_BRIDGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 命令类型枚举 + */ +enum CommandType +{ + CMD_TYPE_CONSOLE = 0, // 控制台命令 + CMD_TYPE_CLIENT = 1, // 客户端命令 + CMD_TYPE_SERVER = 2 // 服务器命令 +}; + +/** + * 命令标志位 + */ +enum CommandFlags +{ + CMD_FLAG_ADMIN = 1, // 管理员命令 + CMD_FLAG_RCON = 2, // RCON命令 + CMD_FLAG_PUBLIC = 4, // 公共命令 + CMD_FLAG_HIDDEN = 8 // 隐藏命令 +}; + +/** + * 注册控制台命令 + * @param pluginId 插件ID + * @param funcId 函数ID + * @param cmd 命令名称 + * @param info 命令描述 + * @param flags 命令标志位 + * @param listable 是否可列出 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_RegisterConsoleCommand( + int pluginId, + int funcId, + const char* cmd, + const char* info, + int flags, + bool listable); + +/** + * 注册客户端命令 + * @param pluginId 插件ID + * @param funcId 函数ID + * @param cmd 命令名称 + * @param info 命令描述 + * @param flags 命令标志位 + * @param listable 是否可列出 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_RegisterClientCommand( + int pluginId, + int funcId, + const char* cmd, + const char* info, + int flags, + bool listable); + +/** + * 注册服务器命令 + * @param pluginId 插件ID + * @param funcId 函数ID + * @param cmd 命令名称 + * @param info 命令描述 + * @param flags 命令标志位 + * @param listable 是否可列出 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_RegisterServerCommand( + int pluginId, + int funcId, + const char* cmd, + const char* info, + int flags, + bool listable); + +/** + * 获取命令数量 + * @param type 命令类型 + * @param access 访问级别 + * @return 命令数量 + */ +int AmxModx_Bridge_GetCommandCount(int type, int access); + +/** + * 获取命令信息 + * @param type 命令类型 + * @param index 命令索引 + * @param access 访问级别 + * @param cmd 返回命令名称缓冲区 + * @param cmdSize 命令名称缓冲区大小 + * @param info 返回命令描述缓冲区 + * @param infoSize 命令描述缓冲区大小 + * @param flags 返回命令标志位 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_GetCommandInfo( + int type, + int index, + int access, + char* cmd, + int cmdSize, + char* info, + int infoSize, + int* flags); + +/** + * 执行控制台命令 + * @param cmd 命令字符串 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_ExecuteConsoleCommand(const char* cmd); + +/** + * 执行客户端命令 + * @param playerId 玩家ID + * @param cmd 命令字符串 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_ExecuteClientCommand(int playerId, const char* cmd); + +/** + * 执行服务器命令 + * @param cmd 命令字符串 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_ExecuteServerCommand(const char* cmd); + +/** + * 检查命令是否存在 + * @param type 命令类型 + * @param cmd 命令名称 + * @return 存在返回true,否则返回false + */ +bool AmxModx_Bridge_CommandExists(int type, const char* cmd); + +/** + * 移除命令 + * @param pluginId 插件ID + * @param cmd 命令名称 + * @return 移除的命令数量 + */ +int AmxModx_Bridge_RemoveCommands(int pluginId, const char* cmd); + +#ifdef __cplusplus +} +#endif + +#endif // COMMAND_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/cstrike_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/cstrike_bridge.h new file mode 100644 index 0000000..bf98b4b --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/cstrike_bridge.h @@ -0,0 +1,90 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// Counter-Strike Module C# Bridge +// C++ side bridge header +// + +#ifndef CSTRIKE_BRIDGE_H +#define CSTRIKE_BRIDGE_H + +#ifdef WIN32 +#define BRIDGE_API __declspec(dllexport) +#else +#define BRIDGE_API __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Player API +BRIDGE_API int CsGetUserMoney(int playerIndex); +BRIDGE_API void CsSetUserMoney(int playerIndex, int money, int flash = 1); +BRIDGE_API int CsGetUserArmor(int playerIndex); +BRIDGE_API void CsSetUserArmor(int playerIndex, int armor); +BRIDGE_API int CsGetUserTeam(int playerIndex); +BRIDGE_API void CsSetUserTeam(int playerIndex, int team); +BRIDGE_API bool CsGetUserVip(int playerIndex); +BRIDGE_API void CsSetUserVip(int playerIndex, bool vip); +BRIDGE_API int CsGetUserDeaths(int playerIndex); +BRIDGE_API void CsSetUserDeaths(int playerIndex, int deaths, bool updateScoreboard = true); + +// Weapon API +BRIDGE_API int CsGetWeaponId(int weaponEntity); +BRIDGE_API bool CsGetWeaponSilenced(int weaponEntity); +BRIDGE_API void CsSetWeaponSilenced(int weaponEntity, bool silenced, int drawAnimation = 1); +BRIDGE_API bool CsGetWeaponBurstMode(int weaponEntity); +BRIDGE_API void CsSetWeaponBurstMode(int weaponEntity, bool burstMode, int drawAnimation = 1); +BRIDGE_API int CsGetWeaponAmmo(int weaponEntity); +BRIDGE_API void CsSetWeaponAmmo(int weaponEntity, int ammo); + +// Game State API +BRIDGE_API bool CsGetUserInsideBuyzone(int playerIndex); +BRIDGE_API int CsGetUserMapzones(int playerIndex); +BRIDGE_API bool CsGetUserHasPrimary(int playerIndex); +BRIDGE_API bool CsGetUserDefusekit(int playerIndex); +BRIDGE_API void CsSetUserDefusekit(int playerIndex, bool hasKit); +BRIDGE_API bool CsGetUserNvg(int playerIndex); +BRIDGE_API void CsSetUserNvg(int playerIndex, bool hasNvg); + +// Model API +BRIDGE_API void CsGetUserModel(int playerIndex, char* buffer, int bufferSize); +BRIDGE_API void CsSetUserModel(int playerIndex, const char* model); +BRIDGE_API void CsResetUserModel(int playerIndex); + +// Entity API +BRIDGE_API int CsCreateEntity(const char* className); +BRIDGE_API int CsFindEntityByClass(int startIndex, const char* className); +BRIDGE_API int CsFindEntityByOwner(int startIndex, int ownerIndex); +BRIDGE_API bool CsSetEntityClass(int entityIndex, const char* className); + +// Item API +BRIDGE_API int CsGetItemId(const char* itemName); +BRIDGE_API bool CsGetItemAlias(int itemId, char* buffer, int bufferSize); +BRIDGE_API bool CsGetTranslatedItemAlias(int itemId, char* buffer, int bufferSize); + +// Hostage API +BRIDGE_API int CsGetHostageId(int hostageIndex); +BRIDGE_API bool CsGetHostageFollow(int hostageIndex); +BRIDGE_API void CsSetHostageFollow(int hostageIndex, bool follow); + +// Bomb API +BRIDGE_API float CsGetC4ExplodeTime(); +BRIDGE_API void CsSetC4ExplodeTime(float time); +BRIDGE_API bool CsGetC4Defusing(); +BRIDGE_API void CsSetC4Defusing(bool defusing); + +// Event delegates +typedef void (*CsPlayerDeathCallback)(int victim, int killer, int weapon); +typedef void (*CsBombEventCallback)(int eventType, int player); +typedef void (*CsWeaponPickupCallback)(int player, int weaponId); + +BRIDGE_API void CsRegisterPlayerDeathCallback(CsPlayerDeathCallback callback); +BRIDGE_API void CsRegisterBombEventCallback(CsBombEventCallback callback); +BRIDGE_API void CsRegisterWeaponPickupCallback(CsWeaponPickupCallback callback); + +#ifdef __cplusplus +} +#endif + +#endif // CSTRIKE_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/datastructs_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/datastructs_bridge.h new file mode 100644 index 0000000..8bd7d43 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/datastructs_bridge.h @@ -0,0 +1,136 @@ +// datastructs_bridge.h +// 数据结构桥接接口定义 +#pragma once + +#include "../amxmodx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 创建动态数组 + * @param cellsize 每个元素的大小(以cell为单位) + * @param reserved 初始预留容量 + * @return 数组句柄,失败返回0 + */ +int AmxModx_Bridge_ArrayCreate(int cellsize, int reserved = 32); + +/** + * 销毁数组并释放内存 + * @param handle 数组句柄(传引用,成功后会置0) + * @return 是否成功销毁 + */ +int AmxModx_Bridge_ArrayDestroy(int* handle); + +/** + * 获取数组当前元素数量 + * @param handle 数组句柄 + * @return 元素数量,失败返回-1 + */ +int AmxModx_Bridge_ArraySize(int handle); + +/** + * 调整数组大小 + * @param handle 数组句柄 + * @param count 新的元素数量 + * @return 是否成功调整 + */ +int AmxModx_Bridge_ArrayResize(int handle, int count); + +/** + * 获取数组元素(单元格值) + * @param handle 数组句柄 + * @param index 元素索引 + * @param block 数据块索引(默认为0) + * @return 单元格值,失败返回0 + */ +int AmxModx_Bridge_ArrayGetCell(int handle, int index, int block = 0); + +/** + * 设置数组元素(单元格值) + * @param handle 数组句柄 + * @param index 元素索引 + * @param value 要设置的值 + * @param block 数据块索引(默认为0) + * @return 是否成功设置 + */ +int AmxModx_Bridge_ArraySetCell(int handle, int index, int value, int block = 0); + +/** + * 向数组末尾添加单元格值 + * @param handle 数组句柄 + * @param value 要添加的值 + * @return 新元素的索引,失败返回-1 + */ +int AmxModx_Bridge_ArrayPushCell(int handle, int value); + +/** + * 从数组获取字符串 + * @param handle 数组句柄 + * @param index 元素索引 + * @param buffer 输出缓冲区 + * @param size 缓冲区大小 + * @return 实际复制的字符数 + */ +int AmxModx_Bridge_ArrayGetString(int handle, int index, char* buffer, int size); + +/** + * 向数组设置字符串 + * @param handle 数组句柄 + * @param index 元素索引 + * @param str 要设置的字符串 + * @return 实际复制的字符数 + */ +int AmxModx_Bridge_ArraySetString(int handle, int index, const char* str); + +/** + * 克隆数组 + * @param handle 原数组句柄 + * @return 新数组句柄,失败返回0 + */ +int AmxModx_Bridge_ArrayClone(int handle); + +/** + * 清空数组内容 + * @param handle 数组句柄 + * @return 是否成功清空 + */ +int AmxModx_Bridge_ArrayClear(int handle); + +/** + * 删除指定索引的元素 + * @param handle 数组句柄 + * @param index 要删除的索引 + * @return 是否成功删除 + */ +int AmxModx_Bridge_ArrayDeleteItem(int handle, int index); + +/** + * 交换两个元素的位置 + * @param handle 数组句柄 + * @param index1 第一个索引 + * @param index2 第二个索引 + * @return 是否成功交换 + */ +int AmxModx_Bridge_ArraySwap(int handle, int index1, int index2); + +/** + * 在数组中查找字符串 + * @param handle 数组句柄 + * @param str 要查找的字符串 + * @return 找到返回索引,未找到返回-1 + */ +int AmxModx_Bridge_ArrayFindString(int handle, const char* str); + +/** + * 在数组中查找数值 + * @param handle 数组句柄 + * @param value 要查找的值 + * @return 找到返回索引,未找到返回-1 + */ +int AmxModx_Bridge_ArrayFindValue(int handle, int value); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/debugger_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/debugger_bridge.h new file mode 100644 index 0000000..3d558e3 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/debugger_bridge.h @@ -0,0 +1,84 @@ +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license +// + +#ifndef DEBUGGER_BRIDGE_H +#define DEBUGGER_BRIDGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// 调试器桥接接口 +/** + * 设置错误过滤器 + * @param filter 过滤器类型 (0=全部, 1=警告, 2=错误) + */ +void AmxModx_Bridge_SetErrorFilter(int filter); + +/** + * 记录调试信息 + * @param message 调试信息 + * @param level 日志级别 (0=调试, 1=信息, 2=警告, 3=错误) + */ +void AmxModx_Bridge_LogDebug(const char* message, int level); + +/** + * 获取最后错误信息 + * @return 错误信息字符串 + */ +const char* AmxModx_Bridge_GetLastError(); + +/** + * 清除最后错误信息 + */ +void AmxModx_Bridge_ClearLastError(); + +/** + * 启用/禁用调试模式 + * @param enabled 是否启用 + */ +void AmxModx_Bridge_SetDebugMode(bool enabled); + +/** + * 检查是否处于调试模式 + * @return 是否处于调试模式 + */ +bool AmxModx_Bridge_IsDebugMode(); + +/** + * 设置断点 + * @param file 文件名 + * @param line 行号 + * @return 设置是否成功 + */ +bool AmxModx_Bridge_SetBreakpoint(const char* file, int line); + +/** + * 移除断点 + * @param file 文件名 + * @param line 行号 + * @return 移除是否成功 + */ +bool AmxModx_Bridge_RemoveBreakpoint(const char* file, int line); + +/** + * 获取当前调用栈信息 + * @param buffer 输出缓冲区 + * @param bufferSize 缓冲区大小 + * @return 调用栈信息长度 + */ +int AmxModx_Bridge_GetCallStack(char* buffer, int bufferSize); + +#ifdef __cplusplus +} +#endif + +#endif // DEBUGGER_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/engine_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/engine_bridge.h new file mode 100644 index 0000000..5d14c3a --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/engine_bridge.h @@ -0,0 +1,140 @@ +// Engine Bridge Header +// AMX Mod X Engine Module C# Bridge + + +#define ENGINE_BRIDGE_H + +#define WINDOWS_IGNORE_PACKING_MISMATCH +#include + +#pragma once + +#ifdef ENGINE_BRIDGE_EXPORTS +#define ENGINE_BRIDGE_API __declspec(dllexport) +#else +#define ENGINE_BRIDGE_API __declspec(dllimport) +#endif + +// 基本类型定义 +typedef int EntityId; +typedef float Vector3[3]; +typedef unsigned int TraceResultType; + +// 追踪结果结构 +struct TraceResultInfo +{ + int allSolid; + int startSolid; + int inOpen; + int inWater; + float fraction; + Vector3 endPos; + float planeDist; + Vector3 planeNormal; + int hitEntity; + int hitGroup; +}; + +// 用户命令结构 +struct UserCmdInfo +{ + float forwardmove; // 前后移动 + float sidemove; // 左右移动 + float upmove; // 上下移动 + float lerp_msec; // 插值毫秒 + float msec; // 毫秒 + float lightlevel; // 光照等级 + int buttons; // 按键 + int weaponselect; // 武器选择 + int impact_index; // 碰撞索引 + float viewangles[3]; // 视角角度 + float impact_position[3]; // 碰撞位置 +}; + +// 引擎桥接接口声明 +extern "C" { + // 时间相关 + ENGINE_BRIDGE_API float Engine_GetGameTime(); + + // 实体操作 + ENGINE_BRIDGE_API int Engine_CreateEntity(const char* className); + ENGINE_BRIDGE_API int Engine_RemoveEntity(int entityId); + ENGINE_BRIDGE_API int Engine_IsValidEntity(int entityId); + ENGINE_BRIDGE_API int Engine_GetEntityCount(); + ENGINE_BRIDGE_API float Engine_GetEntityDistance(int entityA, int entityB); + + // 追踪系统 + ENGINE_BRIDGE_API int Engine_TraceLine(const Vector3 start, const Vector3 end, int ignoreEntity, TraceResultInfo* result); + ENGINE_BRIDGE_API int Engine_TraceHull(const Vector3 start, const Vector3 end, int hullType, int ignoreEntity, TraceResultInfo* result); + ENGINE_BRIDGE_API int Engine_TraceNormal(int entity, const Vector3 start, const Vector3 end, Vector3 normal); + ENGINE_BRIDGE_API int Engine_TraceForward(const Vector3 start, const Vector3 angles, float give, int ignoreEntity, TraceResultInfo* result); + + // 游戏事件 + ENGINE_BRIDGE_API int Engine_PlaybackEvent(int flags, int invoker, unsigned short eventIndex, float delay, + const Vector3 origin, const Vector3 angles, float fparam1, float fparam2, + int iparam1, int iparam2, int bparam1, int bparam2); + + // 范围伤害 + ENGINE_BRIDGE_API int Engine_RadiusDamage(const Vector3 origin, int damageMultiplier, int radiusMultiplier); + + // 点内容检查 + ENGINE_BRIDGE_API int Engine_PointContents(const Vector3 point); + + // 字符串和索引 + ENGINE_BRIDGE_API int Engine_GetDecalIndex(const char* decalName); + ENGINE_BRIDGE_API int Engine_GetInfoKeyBuffer(int entity, char* buffer, int bufferSize); + ENGINE_BRIDGE_API int Engine_GetEngineString(int stringId, char* buffer, int bufferSize); + + // 用户命令 + ENGINE_BRIDGE_API int Engine_GetUserCmd(int client, int type, UserCmdInfo* cmd); + ENGINE_BRIDGE_API int Engine_SetUserCmd(int client, int type, const UserCmdInfo* cmd); + + // 说话权限 + ENGINE_BRIDGE_API int Engine_SetSpeak(int client, int speakFlags); + ENGINE_BRIDGE_API int Engine_GetSpeak(int client); + + // 视角控制 + ENGINE_BRIDGE_API int Engine_SetView(int client, int viewEntity, int viewType); + ENGINE_BRIDGE_API int Engine_AttachView(int client, int targetEntity); + + // 光照 + ENGINE_BRIDGE_API int Engine_SetLights(const char* lights); + + // 地面放置 + ENGINE_BRIDGE_API int Engine_DropToFloor(int entity); + + // 可见性检查 + ENGINE_BRIDGE_API int Engine_IsVisible(int srcEntity, int destEntity); + ENGINE_BRIDGE_API int Engine_IsInViewCone(int entity, const Vector3 target); + + // 实体属性访问 +ENGINE_BRIDGE_API int Engine_GetEntityOrigin(int entityId, Vector3 origin); +ENGINE_BRIDGE_API int Engine_SetEntityOrigin(int entityId, const Vector3 origin); +ENGINE_BRIDGE_API int Engine_GetEntityAngles(int entityId, Vector3 angles); +ENGINE_BRIDGE_API int Engine_SetEntityAngles(int entityId, const Vector3 angles); +ENGINE_BRIDGE_API int Engine_GetEntityVelocity(int entityId, Vector3 velocity); +ENGINE_BRIDGE_API int Engine_SetEntityVelocity(int entityId, const Vector3 velocity); +ENGINE_BRIDGE_API int Engine_GetEntityClassName(int entityId, char* buffer, int bufferSize); +ENGINE_BRIDGE_API int Engine_GetEntityModelName(int entityId, char* buffer, int bufferSize); +ENGINE_BRIDGE_API int Engine_GetEntityHealth(int entityId); +ENGINE_BRIDGE_API int Engine_SetEntityHealth(int entityId, int health); +ENGINE_BRIDGE_API int Engine_GetEntityArmor(int entityId); +ENGINE_BRIDGE_API int Engine_SetEntityArmor(int entityId, int armor); + +// 实体列表操作 +ENGINE_BRIDGE_API int Engine_GetAllEntities(int* entities, int maxCount); +ENGINE_BRIDGE_API int Engine_FindEntitiesByClass(const char* className, int* entities, int maxCount); + +// 事件注册(回调机制) +typedef void (*ImpulseCallback)(int client, int impulse); +typedef void (*TouchCallback)(int touched, int toucher); +typedef void (*ThinkCallback)(int entity); + +ENGINE_BRIDGE_API int Engine_RegisterImpulse(int impulse, ImpulseCallback callback); +ENGINE_BRIDGE_API int Engine_RegisterTouch(const char* touchedClass, const char* toucherClass, TouchCallback callback); +ENGINE_BRIDGE_API int Engine_RegisterThink(const char* className, ThinkCallback callback); + +ENGINE_BRIDGE_API int Engine_UnregisterImpulse(int registerId); +ENGINE_BRIDGE_API int Engine_UnregisterTouch(int registerId); +ENGINE_BRIDGE_API int Engine_UnregisterThink(int registerId); +} diff --git a/Template/Amxmodx.Module.Template/CppInterface/engine_effects_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/engine_effects_bridge.h new file mode 100644 index 0000000..db3181e --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/engine_effects_bridge.h @@ -0,0 +1,83 @@ +// Engine Effects Bridge Header +// AMX Mod X Engine Module Advanced Effects C# Bridge + +#ifndef ENGINE_EFFECTS_BRIDGE_H +#define ENGINE_EFFECTS_BRIDGE_H + +#pragma once + +#ifdef _WIN32 + #ifdef ENGINE_EFFECTS_BRIDGE_EXPORTS + #define ENGINE_EFFECTS_BRIDGE_API __declspec(dllexport) + #else + #define ENGINE_EFFECTS_BRIDGE_API __declspec(dllimport) + #endif +#else + #define ENGINE_EFFECTS_BRIDGE_API __attribute__((visibility("default"))) +#endif + +// 基本类型定义 +typedef int EntityId; +typedef float Vector3[3]; +typedef unsigned int EffectId; + +// 粒子系统参数结构 +struct ParticleParams { + Vector3 origin; + Vector3 velocity; + Vector3 angles; + float scale; + int color; + float life; + float decay; + int spriteIndex; + int flags; +}; + +// 光照参数结构 +struct LightParams { + Vector3 origin; + float radius; + int color[3]; // RGB + float life; + float decay; + int style; // 闪烁模式 + int flags; +}; + +// 音效参数结构 +struct SoundParams { + Vector3 origin; + const char* sample; + float volume; + float attenuation; + int channel; + int pitch; + int flags; + EntityId entity; +}; + +extern "C" { + // 音效系统接口 + ENGINE_EFFECTS_BRIDGE_API int Engine_SoundPlayAttached(EntityId entity, const char* sample, int channel, float volume, float attenuation, int pitch, int flags); + ENGINE_EFFECTS_BRIDGE_API int Engine_SoundSetPitch(EntityId entity, int channel, int pitch); + + // 光照系统接口 +ENGINE_EFFECTS_BRIDGE_API EffectId Engine_LightCreate(const float origin[3], float radius, int red, int green, int blue, float life, int style); + ENGINE_EFFECTS_BRIDGE_API int Engine_LightSetColor(EffectId lightId, int red, int green, int blue); + ENGINE_EFFECTS_BRIDGE_API int Engine_LightFlicker(EffectId lightId, float flickerSpeed, float minIntensity); + ENGINE_EFFECTS_BRIDGE_API int Engine_LightPulse(EffectId lightId, float pulseSpeed, float minIntensity, float maxIntensity); + ENGINE_EFFECTS_BRIDGE_API int Engine_LightStop(EffectId lightId); + + // 粒子系统接口 +ENGINE_EFFECTS_BRIDGE_API EffectId Engine_ParticleCreate(const float origin[3], const char* sprite, int maxParticles); + ENGINE_EFFECTS_BRIDGE_API int Engine_ParticleSetColor(EffectId particleId, int red, int green, int blue); + ENGINE_EFFECTS_BRIDGE_API int Engine_ParticleSetScale(EffectId particleId, float scale); + ENGINE_EFFECTS_BRIDGE_API int Engine_ParticleStop(EffectId particleId); + + // 辅助函数 + ENGINE_EFFECTS_BRIDGE_API int Engine_GetSpriteIndex(const char* spriteName); + ENGINE_EFFECTS_BRIDGE_API int Engine_PrecacheModel(const char* modelName); +} + +#endif // ENGINE_EFFECTS_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/entity_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/entity_bridge.h new file mode 100644 index 0000000..2c7664f --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/entity_bridge.h @@ -0,0 +1,72 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X Entity Bridge Header +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +#ifndef _ENTITY_BRIDGE_H +#define _ENTITY_BRIDGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +// 实体管理接口 +int AmxModx_Bridge_GetMaxClients(void); +int AmxModx_Bridge_GetMaxEntities(void); +int AmxModx_Bridge_GetPlayerCount(void); +bool AmxModx_Bridge_IsPlayerValid(int playerId); +bool AmxModx_Bridge_IsPlayerInGame(int playerId); +bool AmxModx_Bridge_IsPlayerAlive(int playerId); +bool AmxModx_Bridge_IsPlayerBot(int playerId); + +// 实体属性访问 +const char* AmxModx_Bridge_GetPlayerName(int playerId); +const char* AmxModx_Bridge_GetPlayerIPAddress(int playerId); +const char* AmxModx_Bridge_GetPlayerAuthID(int playerId); +const char* AmxModx_Bridge_GetPlayerTeam(int playerId); +int AmxModx_Bridge_GetPlayerUserID(int playerId); +int AmxModx_Bridge_GetPlayerFrags(int playerId); +int AmxModx_Bridge_GetPlayerDeaths(int playerId); +int AmxModx_Bridge_GetPlayerHealth(int playerId); +int AmxModx_Bridge_GetPlayerArmor(int playerId); +int AmxModx_Bridge_GetPlayerPing(int playerId); + +// 实体位置相关 +bool AmxModx_Bridge_GetPlayerOrigin(int playerId, float* x, float* y, float* z); +bool AmxModx_Bridge_GetPlayerVelocity(int playerId, float* x, float* y, float* z); +bool AmxModx_Bridge_SetPlayerOrigin(int playerId, float x, float y, float z); +bool AmxModx_Bridge_SetPlayerVelocity(int playerId, float x, float y, float z); + +// 实体武器相关 +int AmxModx_Bridge_GetPlayerCurrentWeapon(int playerId); +int AmxModx_Bridge_GetPlayerAmmo(int playerId, int weaponId); +bool AmxModx_Bridge_PlayerHasWeapon(int playerId, int weaponId); + +// 实体操作 +bool AmxModx_Bridge_KillPlayer(int playerId); +bool AmxModx_Bridge_SlapPlayer(int playerId, int damage, bool randomVelocity); +bool AmxModx_Bridge_TeleportPlayer(int playerId, float x, float y, float z); +bool AmxModx_Bridge_RespawnPlayer(int playerId); +bool AmxModx_Bridge_StripWeapons(int playerId); +bool AmxModx_Bridge_GiveWeapon(int playerId, const char* weaponName, int ammo); +bool AmxModx_Bridge_SetPlayerTeam(int playerId, int teamId); +bool AmxModx_Bridge_FreezePlayer(int playerId, bool freeze); +bool AmxModx_Bridge_SetPlayerHealth(int playerId, int health); +bool AmxModx_Bridge_SetPlayerArmor(int playerId, int armor); +bool AmxModx_Bridge_SetPlayerFrags(int playerId, int frags); +bool AmxModx_Bridge_SetPlayerDeaths(int playerId, int deaths); + +// 实体查找 +int AmxModx_Bridge_FindPlayerByUserID(int userId); +int AmxModx_Bridge_FindPlayerByName(const char* name); +int AmxModx_Bridge_FindPlayerByIPAddress(const char* ip); + +#ifdef __cplusplus +} +#endif + +#endif // _ENTITY_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/event_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/event_bridge.h new file mode 100644 index 0000000..65a70e5 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/event_bridge.h @@ -0,0 +1,102 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// Event System Bridge - C++ Header +// Copyright (C) The AMX Mod X Development Team +// +// This software is licensed under the GNU General Public License, version 3 or higher. + +#pragma once + +#include +#include "CEvent.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief 注册游戏事件 + * @param eventName 事件名称 + * @param callbackFunc 回调函数名 + * @param flags 事件标志 + * @param conditions 事件条件数组 + * @param conditionCount 条件数量 + * @return 事件句柄,失败返回0 + */ +int AmxModx_Bridge_RegisterEvent(const char* eventName, const char* callbackFunc, int flags, const char** conditions, int conditionCount); + +/** + * @brief 扩展注册游戏事件 + * @param eventName 事件名称 + * @param callbackFunc 回调函数名 + * @param flags 事件标志 + * @param conditions 事件条件数组 + * @param conditionCount 条件数量 + * @return 事件句柄,失败返回0 + */ +int AmxModx_Bridge_RegisterEventEx(const char* eventName, const char* callbackFunc, int flags, const char** conditions, int conditionCount); + +/** + * @brief 启用事件 + * @param eventHandle 事件句柄 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_EnableEvent(int eventHandle); + +/** + * @brief 禁用事件 + * @param eventHandle 事件句柄 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_DisableEvent(int eventHandle); + +/** + * @brief 获取事件ID + * @param eventName 事件名称 + * @return 事件ID,0表示无效事件 + */ +int AmxModx_Bridge_GetEventId(const char* eventName); + +/** + * @brief 检查事件是否有效 + * @param eventHandle 事件句柄 + * @return 有效返回1,无效返回0 + */ +int AmxModx_Bridge_IsEventValid(int eventHandle); + +/** + * @brief 获取事件名称列表 + * @param buffer 存储事件名称的缓冲区 + * @param bufferSize 缓冲区大小 + * @return 事件数量 + */ +int AmxModx_Bridge_GetEventList(char** buffer, int bufferSize); + +/** + * @brief 获取事件参数数量 + * @param eventName 事件名称 + * @return 参数数量,-1表示无效事件 + */ +int AmxModx_Bridge_GetEventParamCount(const char* eventName); + +/** + * @brief 获取事件参数名称 + * @param eventName 事件名称 + * @param paramIndex 参数索引(从0开始) + * @param buffer 存储参数名称的缓冲区 + * @param bufferSize 缓冲区大小 + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_GetEventParamName(const char* eventName, int paramIndex, char* buffer, int bufferSize); + +/** + * @brief 获取事件参数类型 + * @param eventName 事件名称 + * @param paramIndex 参数索引(从0开始) + * @return 参数类型字符串,NULL表示无效事件或索引 + */ +const char* AmxModx_Bridge_GetEventParamType(const char* eventName, int paramIndex); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/fakemeta_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/fakemeta_bridge.h new file mode 100644 index 0000000..af6f8dc --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/fakemeta_bridge.h @@ -0,0 +1,271 @@ +#pragma once + +#include +#include +#include +#include + +// C++版本的事件类型枚举,与C#保持一致 +enum class FMB_ForwardType +{ + PrecacheModel = 0, + PrecacheSound = 1, + SetModel = 2, + CreateEntity = 3, + RemoveEntity = 4, + Spawn = 5, + Think = 6, + Use = 7, + Touch = 8, + Blocked = 9, + ClientCommand = 10, + ClientUserInfoChanged = 11, + ServerActivate = 12, + ServerDeactivate = 13, + PlayerPreThink = 14, + PlayerPostThink = 15, + StartFrame = 16, + ClientConnect = 17, + ClientDisconnect = 18, + ClientPutInServer = 19, + ClientKill = 20, + ClientSpawn = 21, + TraceLine = 22, + TraceToss = 23, + TraceMonsterHull = 24, + TraceHull = 25, + TraceModel = 26, + TraceTexture = 27, + TraceSphere = 28, + GetAimVector = 29, + EmitSound = 30, + EmitAmbientSound = 31, + LightStyle = 32, + DecalIndex = 33, + PointContents = 34, + MessageBegin = 35, + MessageEnd = 36, + WriteByte = 37, + WriteChar = 38, + WriteShort = 39, + WriteLong = 40, + WriteAngle = 41, + WriteCoord = 42, + WriteString = 43, + WriteEntity = 44, + CVarGetFloat = 45, + CVarGetString = 46, + CVarSetFloat = 47, + CVarSetString = 48, + CVarRegister = 49, + AlertMessage = 50, + EngineFprintf = 51, + PvsFindEntity = 52, + PvsEntitiesInPvs = 53, + PvsCheckOrigin = 54, + PvsCheckEntity = 55, + PvsCheckBox = 56, + PvsCheckPoint = 57, + PvsCheckEverything = 58, + PvsCheckEverything2 = 59, + PvsCheckEverything3 = 60, + PvsCheckEverything4 = 61, + PvsCheckEverything5 = 62, + PvsCheckEverything6 = 63, + PvsCheckEverything7 = 64, + PvsCheckEverything8 = 65, + PvsCheckEverything9 = 66, + PvsCheckEverything10 = 67, + PvsCheckEverything11 = 68, + PvsCheckEverything12 = 69, + PvsCheckEverything13 = 70, + PvsCheckEverything14 = 71, + PvsCheckEverything15 = 72, + PvsCheckEverything16 = 73, + PvsCheckEverything17 = 74, + PvsCheckEverything18 = 75, + PvsCheckEverything19 = 76, + PvsCheckEverything20 = 77, + PvsCheckEverything21 = 78, + PvsCheckEverything22 = 79, + PvsCheckEverything23 = 80, + PvsCheckEverything24 = 81, + PvsCheckEverything25 = 82, + PvsCheckEverything26 = 83, + PvsCheckEverything27 = 84, + PvsCheckEverything28 = 85, + PvsCheckEverything29 = 86, + PvsCheckEverything30 = 87, + PvsCheckEverything31 = 88, + PvsCheckEverything32 = 89, + PvsCheckEverything33 = 90, + PvsCheckEverything34 = 91, + PvsCheckEverything35 = 92, + PvsCheckEverything36 = 93, + PvsCheckEverything37 = 94, + PvsCheckEverything38 = 95, + PvsCheckEverything39 = 96, + PvsCheckEverything40 = 97, + PvsCheckEverything41 = 98, + PvsCheckEverything42 = 99, + PvsCheckEverything43 = 100, + PvsCheckEverything44 = 101, + PvsCheckEverything45 = 102, + PvsCheckEverything46 = 103, + PvsCheckEverything47 = 104, + PvsCheckEverything48 = 105, + PvsCheckEverything49 = 106, + PvsCheckEverything50 = 107, + PvsCheckEverything51 = 108, + PvsCheckEverything52 = 109, + PvsCheckEverything53 = 110, + PvsCheckEverything54 = 111, + PvsCheckEverything55 = 112, + PvsCheckEverything56 = 113, + PvsCheckEverything57 = 114, + PvsCheckEverything58 = 115, + PvsCheckEverything59 = 116, + PvsCheckEverything60 = 117, + PvsCheckEverything61 = 118, + PvsCheckEverything62 = 119, + PvsCheckEverything63 = 120, + PvsCheckEverything64 = 121, + PvsCheckEverything65 = 122, + PvsCheckEverything66 = 123, + PvsCheckEverything67 = 124, + PvsCheckEverything68 = 125, + PvsCheckEverything69 = 126, + PvsCheckEverything70 = 127, + PvsCheckEverything71 = 128, + PvsCheckEverything72 = 129, + PvsCheckEverything73 = 130, + PvsCheckEverything74 = 131 +}; + +// 事件执行时机 +enum class FMB_ForwardTiming +{ + Pre = 0, // 前置钩子 + Post = 1 // 后置钩子 +}; + +// 事件处理结果 +enum class FMB_ForwardResult +{ + Ignored = 0, // 忽略,继续执行 + Handled = 1, // 已处理,继续执行 + Override = 2, // 覆盖,继续执行 + Supercede = 3 // 取代,停止执行 +}; + +// 事件数据结构体,与C#保持二进制兼容 +struct FMB_EventData +{ + int entityIndex; // 实体索引 + const char* stringValue; // 字符串值 + float floatValue; // 浮点值 + int intValue; // 整数值 + float vectorValue[3]; // 向量值 + void* customData; // 自定义数据 +}; + +// 回调函数类型定义 +using FMB_ForwardCallback = FMB_ForwardResult(*)(FMB_EventData&, void*); + +// 回调信息结构体 +struct FMB_CallbackInfo +{ + FMB_ForwardCallback callback; + void* userData; + int handle; + int priority; // 优先级,数值越高优先级越高 +}; + +// 事件系统管理类 +class FMB_ForwardSystem +{ +public: + static FMB_ForwardSystem& Instance(); + + // 初始化事件系统 + bool Initialize(); + + // 清理事件系统 + void Cleanup(); + + // 注册事件钩子 + int RegisterForward(FMB_ForwardType type, FMB_ForwardTiming timing, FMB_ForwardCallback callback, void* userData); + + // 注销事件钩子 + bool UnregisterForward(FMB_ForwardType type, FMB_ForwardTiming timing, int handle); + + // 触发事件 + FMB_ForwardResult ExecuteForwards(FMB_ForwardType type, FMB_ForwardTiming timing, FMB_EventData& data); + + // 获取事件数量 + int GetForwardCount(FMB_ForwardType type, FMB_ForwardTiming timing); + + // 检查事件是否已注册 + bool IsForwardRegistered(FMB_ForwardType type, FMB_ForwardTiming timing, int handle); + + // 获取事件类型名称 + const char* GetForwardTypeName(FMB_ForwardType type); + + // 获取事件时机名称 + const char* GetForwardTimingName(FMB_ForwardTiming timing); + + // 获取事件结果名称 + const char* GetForwardResultName(FMB_ForwardResult result); + +private: + FMB_ForwardSystem() = default; + ~FMB_ForwardSystem() = default; + + // 禁用拷贝构造和赋值 + FMB_ForwardSystem(const FMB_ForwardSystem&) = delete; + FMB_ForwardSystem& operator=(const FMB_ForwardSystem&) = delete; + + // 内部方法 + std::vector& GetCallbacks(FMB_ForwardType type, FMB_ForwardTiming timing); + void SortCallbacksByPriority(std::vector& callbacks); + + // 数据结构 + std::unordered_map> preCallbacks; + std::unordered_map> postCallbacks; + int nextHandle = 1; + bool isInitialized = false; +}; + +// C接口导出函数 +extern "C" +{ + // 初始化事件系统 + __declspec(dllexport) int FMB_InitializeForwardSystem(); + + // 清理事件系统 + __declspec(dllexport) void FMB_CleanupForwardSystem(); + + // 注册事件钩子 + __declspec(dllexport) int FMB_RegisterForward(FMB_ForwardType type, FMB_ForwardTiming timing, FMB_ForwardCallback callback, void* userData); + + // 注销事件钩子 + __declspec(dllexport) int FMB_UnregisterForward(FMB_ForwardType type, FMB_ForwardTiming timing, int handle); + + // 触发事件 + __declspec(dllexport) FMB_ForwardResult FMB_ExecuteForwards(FMB_ForwardType type, FMB_ForwardTiming timing, FMB_EventData& data); + + // 获取事件数量 + __declspec(dllexport) int FMB_GetForwardCount(FMB_ForwardType type, FMB_ForwardTiming timing); + + // 检查事件是否已注册 + __declspec(dllexport) int FMB_IsForwardRegistered(FMB_ForwardType type, FMB_ForwardTiming timing, int handle); + + // 获取事件类型名称 + __declspec(dllexport) const char* FMB_GetForwardTypeName(FMB_ForwardType type); + + // 获取事件时机名称 + __declspec(dllexport) const char* FMB_GetForwardTimingName(FMB_ForwardTiming timing); + + // 获取事件结果名称 + __declspec(dllexport) const char* FMB_GetForwardResultName(FMB_ForwardResult result); +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/file_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/file_bridge.h new file mode 100644 index 0000000..4c3d011 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/file_bridge.h @@ -0,0 +1,277 @@ +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license +// + +#ifndef FILE_BRIDGE_H +#define FILE_BRIDGE_H + +#include + +// 前向声明 +class CDataPack; +class IGameConfig; +class Vault; +struct cvar_s; +typedef struct cvar_s cvar_t; + +#ifdef __cplusplus +extern "C" { +#endif + +// 文件系统桥接接口 +/** + * 读取文件内容到内存缓冲区 + * @param filePath 文件路径 + * @param size 返回文件大小 + * @return 文件内容缓冲区,需要手动释放 + */ +char* AmxModx_Bridge_ReadFile(const char* filePath, int* size); + +/** + * 将数据写入文件 + * @param filePath 文件路径 + * @param data 要写入的数据 + * @param size 数据大小 + * @return 写入是否成功 + */ +bool AmxModx_Bridge_WriteFile(const char* filePath, const char* data, int size); + +/** + * 释放由ReadFile分配的缓冲区 + * @param buffer 要释放的缓冲区 + */ +void AmxModx_Bridge_FreeBuffer(char* buffer); + +/** + * 检查文件是否存在 + * @param fileName 文件名 + * @return 文件是否存在 + */ +bool AmxModx_Bridge_FileExists(const char* fileName); + +/** + * 从文件读取字符串内容 + * @param fileName 文件名 + * @param buffer 输出缓冲区 + * @param bufferSize 缓冲区大小 + * @return 读取是否成功 + */ +bool AmxModx_Bridge_ReadFileString(const char* fileName, char* buffer, int bufferSize); + +/** + * 将字符串写入文件 + * @param fileName 文件名 + * @param content 要写入的内容 + * @return 写入是否成功 + */ +bool AmxModx_Bridge_WriteFileString(const char* fileName, const char* content); + +/** + * 删除文件 + * @param fileName 文件名 + * @return 删除是否成功 + */ +bool AmxModx_Bridge_DeleteFile(const char* fileName); + +// CDataPack桥接接口 +/** + * 创建新的数据包 + * @return 新创建的数据包指针 + */ +CDataPack* AmxModx_Bridge_CreateDataPack(); + +/** + * 销毁数据包 + * @param pack 要销毁的数据包 + */ +void AmxModx_Bridge_DestroyDataPack(CDataPack* pack); + +/** + * 获取数据包当前位置 + * @param pack 数据包指针 + * @return 当前位置 + */ +int AmxModx_Bridge_GetDataPackPosition(CDataPack* pack); + +/** + * 设置数据包位置 + * @param pack 数据包指针 + * @param position 要设置的位置 + */ +void AmxModx_Bridge_SetDataPackPosition(CDataPack* pack, int position); + +/** + * 向数据包写入整数 + * @param pack 数据包指针 + * @param value 要写入的值 + * @return 写入是否成功 + */ +bool AmxModx_Bridge_WriteDataPackCell(CDataPack* pack, int value); + +/** + * 向数据包写入浮点数 + * @param pack 数据包指针 + * @param value 要写入的值 + * @return 写入是否成功 + */ +bool AmxModx_Bridge_WriteDataPackFloat(CDataPack* pack, float value); + +/** + * 向数据包写入字符串 + * @param pack 数据包指针 + * @param value 要写入的字符串 + * @return 写入是否成功 + */ +bool AmxModx_Bridge_WriteDataPackString(CDataPack* pack, const char* value); + +/** + * 从数据包读取整数 + * @param pack 数据包指针 + * @return 读取的整数值 + */ +int AmxModx_Bridge_ReadDataPackCell(CDataPack* pack); + +/** + * 从数据包读取浮点数 + * @param pack 数据包指针 + * @return 读取的浮点数值 + */ +float AmxModx_Bridge_ReadDataPackFloat(CDataPack* pack); + +/** + * 从数据包读取字符串 + * @param pack 数据包指针 + * @return 读取的字符串(静态缓冲区) + */ +const char* AmxModx_Bridge_ReadDataPackString(CDataPack* pack); + +// 控制台变量桥接接口 +/** + * 创建控制台变量 + * @param name 变量名 + * @param value 初始值 + * @param flags 变量标志 + * @return 创建的变量指针 + */ +cvar_t* AmxModx_Bridge_CreateCVar(const char* name, const char* value, int flags); + +/** + * 查找控制台变量 + * @param name 变量名 + * @return 找到的变量指针 + */ +cvar_t* AmxModx_Bridge_FindCVar(const char* name); + +/** + * 获取控制台变量字符串值 + * @param cvar 变量指针 + * @return 字符串值 + */ +const char* AmxModx_Bridge_GetCVarString(cvar_t* cvar); + +/** + * 获取控制台变量浮点数值 + * @param cvar 变量指针 + * @return 浮点数值 + */ +float AmxModx_Bridge_GetCVarFloat(cvar_t* cvar); + +/** + * 获取控制台变量整数值 + * @param cvar 变量指针 + * @return 整数值 + */ +int AmxModx_Bridge_GetCVarInt(cvar_t* cvar); + +/** + * 设置控制台变量字符串值 + * @param cvar 变量指针 + * @param value 要设置的字符串值 + */ +void AmxModx_Bridge_SetCVarString(cvar_t* cvar, const char* value); + +/** + * 设置控制台变量浮点数值 + * @param cvar 变量指针 + * @param value 要设置的浮点数值 + */ +void AmxModx_Bridge_SetCVarFloat(cvar_t* cvar, float value); + +/** + * 设置控制台变量整数值 + * @param cvar 变量指针 + * @param value 要设置的整数值 + */ +void AmxModx_Bridge_SetCVarInt(cvar_t* cvar, int value); + +// 游戏配置桥接接口 +/** + * 加载游戏配置文件 + * @param filePath 配置文件路径 + * @return 加载的配置对象指针 + */ +IGameConfig* AmxModx_Bridge_LoadGameConfig(const char* filePath); + +/** + * 卸载游戏配置文件 + * @param config 配置对象指针 + */ +void AmxModx_Bridge_UnloadGameConfig(IGameConfig* config); + +/** + * 获取配置值 + * @param config 配置对象指针 + * @param key 配置键名 + * @return 配置值字符串 + */ +const char* AmxModx_Bridge_GetConfigValue(IGameConfig* config, const char* key); + +// 持久化存储桥接接口 +/** + * 获取全局Vault实例 + * @return Vault实例指针 + */ +Vault* AmxModx_Bridge_GetVault(); + +/** + * 检查键是否存在 + * @param vault Vault实例指针 + * @param key 键名 + * @return 键是否存在 + */ +bool AmxModx_Bridge_VaultExists(Vault* vault, const char* key); + +/** + * 存储键值对 + * @param vault Vault实例指针 + * @param key 键名 + * @param value 值 + * @return 存储是否成功 + */ +bool AmxModx_Bridge_VaultPut(Vault* vault, const char* key, const char* value); + +/** + * 移除键值对 + * @param vault Vault实例指针 + * @param key 键名 + * @return 移除是否成功 + */ +bool AmxModx_Bridge_VaultRemove(Vault* vault, const char* key); + +/** + * 获取键对应的值 + * @param key 键名 + * @return 值字符串 + */ +const char* AmxModx_Bridge_VaultGet(const char* key); + +#ifdef __cplusplus +} +#endif + +#endif // FILE_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/forward_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/forward_bridge.h new file mode 100644 index 0000000..858955c --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/forward_bridge.h @@ -0,0 +1,81 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +#ifndef _FORWARD_BRIDGE_H_ +#define _FORWARD_BRIDGE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 创建多插件转发器 + * @param funcName 转发器名称 + * @param execType 执行类型 (0=忽略, 1=停止, 2=停止2, 3=继续) + * @param numParams 参数数量 + * @param paramTypes 参数类型数组 + * @return 转发器ID,失败返回-1 + */ +int AmxModx_Bridge_CreateMultiForward(const char* funcName, int execType, int numParams, int* paramTypes); + +/** + * 创建单插件转发器 + * @param pluginId 插件ID + * @param funcName 函数名称 + * @param numParams 参数数量 + * @param paramTypes 参数类型数组 + * @return 转发器ID,失败返回-1 + */ +int AmxModx_Bridge_CreateOneForward(int pluginId, const char* funcName, int numParams, int* paramTypes); + +/** + * 销毁转发器 + * @param forwardId 转发器ID + * @return 成功返回1,失败返回0 + */ +int AmxModx_Bridge_DestroyForward(int forwardId); + +/** + * 执行转发器 + * @param forwardId 转发器ID + * @param params 参数数组 + * @param numParams 参数数量 + * @return 执行结果 + */ +int AmxModx_Bridge_ExecuteForward(int forwardId, int* params, int numParams); + +/** + * 准备数组参数 + * @param arrayData 数组数据 + * @param size 数组大小 + * @param copyBack 是否复制回数据 + * @return 数组句柄 + */ +int AmxModx_Bridge_PrepareArray(int* arrayData, int size, int copyBack); + +/** + * 获取转发器参数数量 + * @param forwardId 转发器ID + * @return 参数数量,失败返回-1 + */ +int AmxModx_Bridge_GetForwardParamCount(int forwardId); + +/** + * 获取转发器参数类型 + * @param forwardId 转发器ID + * @param paramIndex 参数索引 + * @return 参数类型,失败返回-1 + */ +int AmxModx_Bridge_GetForwardParamType(int forwardId, int paramIndex); + +#ifdef __cplusplus +} +#endif + +#endif // _FORWARD_BRIDGE_H_ \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/fun_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/fun_bridge.h new file mode 100644 index 0000000..3bc0cdb --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/fun_bridge.h @@ -0,0 +1,54 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +// +// Fun Module Bridge +// + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// 玩家状态管理 +int GetClientListening(int receiver, int sender); +int SetClientListening(int receiver, int sender, int listen); +int SetUserGodmode(int index, int godmode); +int GetUserGodmode(int index); +int SetUserHealth(int index, float health); +float GetUserHealth(int index); +int GiveItem(int index, const char* item); +int SpawnEntity(int index); +int SetUserFrags(int index, int frags); +int GetUserFrags(int index); +int SetUserArmor(int index, int armor); +int GetUserArmor(int index); +int SetUserOrigin(int index, const float origin[3]); +int GetUserOrigin(int index, float *origin); +int SetUserRendering(int index, int renderMode, int renderAmount, int renderFx, const float *renderColor); +int GetUserRendering(int index, int *renderMode, int *renderAmount, int *renderFx, float *renderColor); +int SetUserMaxspeed(int index, float maxspeed); +float GetUserMaxspeed(int index); +int SetUserGravity(int index, float gravity); +float GetUserGravity(int index); +int SetUserHitzones(int index, int zones); +int GetUserHitzones(int index); +int SetUserNoclip(int index, int noclip); +int GetUserNoclip(int index); +int SetUserFootsteps(int index, int footsteps); +int GetUserFootsteps(int index); +int StripUserWeapons(int index); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/gameconfigs_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/gameconfigs_bridge.h new file mode 100644 index 0000000..a366e63 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/gameconfigs_bridge.h @@ -0,0 +1,65 @@ +// gameconfigs_bridge.h +// 游戏配置系统桥接接口定义 +#pragma once + +#include "../amxmodx.h" +#include "../gameconfigs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 加载游戏配置文件 + * @param fileName 配置文件名 + * @param errorBuffer 错误信息缓冲区 + * @param errorBufferSize 缓冲区大小 + * @return 游戏配置句柄,失败返回0 + */ +int AmxModx_Bridge_LoadGameConfigFile(const char* fileName, char* errorBuffer, int errorBufferSize); + +/** + * 获取游戏配置偏移量 + * @param handle 游戏配置句柄 + * @param key 配置键名 + * @return 偏移量值,失败返回-1 + */ +int AmxModx_Bridge_GameConfGetOffset(int handle, const char* key); + +/** + * 获取类配置偏移量 + * @param handle 游戏配置句柄 + * @param className 类名 + * @param key 配置键名 + * @return 偏移量值,失败返回-1 + */ +int AmxModx_Bridge_GameConfGetClassOffset(int handle, const char* className, const char* key); + +/** + * 获取游戏配置键值 + * @param handle 游戏配置句柄 + * @param key 配置键名 + * @param buffer 输出缓冲区 + * @param bufferSize 缓冲区大小 + * @return 是否成功获取 + */ +int AmxModx_Bridge_GameConfGetKeyValue(int handle, const char* key, char* buffer, int bufferSize); + +/** + * 获取游戏配置地址 + * @param handle 游戏配置句柄 + * @param name 地址名 + * @return 地址值,失败返回0 + */ +uintptr_t AmxModx_Bridge_GameConfGetAddress(int handle, const char* name); + +/** + * 关闭游戏配置文件 + * @param handle 游戏配置句柄(传引用,成功后会置0) + * @return 是否成功关闭 + */ +int AmxModx_Bridge_CloseGameConfigFile(int* handle); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_bridge.h new file mode 100644 index 0000000..015cdeb --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_bridge.h @@ -0,0 +1,53 @@ +// hamsandwich_bridge.h +// HAM Sandwich桥接层头文件 + +#ifndef HAMSANDWICH_BRIDGE_H +#define HAMSANDWICH_BRIDGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +// 初始化/清理 +void InitializeHamSandwichBridge(); +void CleanupHamSandwichBridge(); + +// 钩子管理 +int RegisterHamHook(int function, int entityIndex, void* preCallback, void* postCallback); +bool EnableHamHook(int hookId); +bool DisableHamHook(int hookId); +bool RemoveHamHook(int hookId); + +// 返回值处理 +int GetReturnStatus(); +int GetReturnValueInt(); +float GetReturnValueFloat(); +int GetReturnValueEntity(); +void GetReturnValueVector(float vec[3]); + +void SetReturnValueInt(int value); +void SetReturnValueFloat(float value); +void SetReturnValueVector(const float vec[3]); +void SetReturnValueEntity(int entity); + +// 参数处理 +int GetParameterInt(int paramIndex); +float GetParameterFloat(int paramIndex); +int GetParameterEntity(int paramIndex); +void GetParameterVector(int paramIndex, float vec[3]); + +void SetParameterInt(int paramIndex, int value); +void SetParameterFloat(int paramIndex, float value); +void SetParameterVector(int paramIndex, const float vec[3]); +void SetParameterEntity(int paramIndex, int entity); + +// 实用工具 +bool IsValidHamFunction(int function); +const char* GetHamFunctionName(int function); +int GetHamFunctionCount(); + +#ifdef __cplusplus +} +#endif + +#endif // HAMSANDWICH_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_direct_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_direct_bridge.h new file mode 100644 index 0000000..804af77 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_direct_bridge.h @@ -0,0 +1,43 @@ +#pragma once + +// 前置声明,避免包含vector.h头文件 +struct edict_s; +typedef struct edict_s edict_t; + +// 直接桥接接口 - 不依赖AMXX函数 +extern "C" { + +// 实体和偏移验证 +bool IsValidEntity(int entityId); +bool IsValidOffset(int offset); + +// 直接数据访问 +int GetEntityPrivateDataInt(int entityId, int offset); +float GetEntityPrivateDataFloat(int entityId, int offset); +int GetEntityPrivateDataEntity(int entityId, int offset); +void SetEntityPrivateDataInt(int entityId, int offset, int value); +void SetEntityPrivateDataFloat(int entityId, int offset, float value); +void SetEntityPrivateDataEntity(int entityId, int offset, int targetEntity); + +// 向量数据访问 +void GetEntityPrivateDataVector(int entityId, int offset, float vec[3]); +void SetEntityPrivateDataVector(int entityId, int offset, const float vec[3]); + +// 实体变量访问 +int GetEntityVarInt(int entityId, int offset); +float GetEntityVarFloat(int entityId, int offset); +void GetEntityVarVector(int entityId, int offset, float vec[3]); +void SetEntityVarInt(int entityId, int offset, int value); +void SetEntityVarFloat(int entityId, int offset, float value); +void SetEntityVarVector(int entityId, int offset, const float vec[3]); + +// 直接内存操作 +void* GetEntityBasePointer(int entityId); +int GetEntityMemorySize(int entityId); + +// 工具函数 +int EntityToIndex(edict_t* edict); +edict_t* IndexToEntity(int index); +void* GetPrivateDataPtr(int entityId); + +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_game_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_game_bridge.h new file mode 100644 index 0000000..107ab1c --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_game_bridge.h @@ -0,0 +1,48 @@ +// hamsandwich_game_bridge.h +// 游戏特定钩子的桥接头文件 + +#ifndef HAMSANDWICH_GAME_BRIDGE_H +#define HAMSANDWICH_GAME_BRIDGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +// 游戏特定钩子注册函数 +extern "C" { + +// Counter-Strike钩子 +int RegisterCsPlayerOnTouchingWeaponHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterCsItemGetMaxSpeedHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterCsItemCanDropHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterCsRestartHook(void* preCallback, void* postCallback); +int RegisterCsRoundRespawnHook(void* preCallback, void* postCallback); + +// Team Fortress Classic钩子 +int RegisterTfcEngineerUseHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterTfcEmpExplodeHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterTfcTakeEmpBlastHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterTfcRadiusDamage2Hook(const char* entityClass, void* preCallback, void* postCallback); + +// Day of Defeat钩子 +int RegisterDodWeaponSpecialHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterDodRoundRespawnHook(void* preCallback, void* postCallback); +int RegisterDodItemCanDropHook(const char* entityClass, void* preCallback, void* postCallback); + +// The Specialists钩子 +int RegisterTsBreakableRespawnHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterTsShouldCollideHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterTsCanUsedThroughWallsHook(const char* entityClass, void* preCallback, void* postCallback); + +// Natural Selection钩子 +int RegisterNsUpdateOnRemoveHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterNsGetPointValueHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterNsAwardKillHook(void* preCallback, void* postCallback); + +// Earth's Special Forces钩子 +int RegisterEsfWeaponHolsterWhenMeleedHook(const char* entityClass, void* preCallback, void* postCallback); +int RegisterEsfTakeDamage2Hook(const char* entityClass, void* preCallback, void* postCallback); +} +#endif + +#endif // HAMSANDWICH_GAME_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_hook_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_hook_bridge.h new file mode 100644 index 0000000..2a19067 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_hook_bridge.h @@ -0,0 +1,61 @@ +#pragma once + +// 前置声明 +struct edict_s; +typedef struct edict_s edict_t; + +// 回调函数类型定义 +typedef void (*HamHookCallback)(int entity, int paramCount, void** parameters); +typedef void (*HamHookCallbackPost)(int entity, int paramCount, void** parameters); + +// 注意:HAM函数枚举值已在ham_const.h中定义,这里直接使用 + +// 钩子管理接口 +extern "C" { + // 注册钩子 + int RegisterHamHook(int function, const char* entityClass, + HamHookCallback preCallback, HamHookCallbackPost postCallback); + + int RegisterHamHookFromEntity(int function, int entityId, + HamHookCallback preCallback, HamHookCallbackPost postCallback); + + int RegisterHamHookPlayer(int function, + HamHookCallback preCallback, HamHookCallbackPost postCallback); + + // 钩子控制 + void EnableHamHook(int hookId); + void DisableHamHook(int hookId); + int IsHamHookValid(int function); + + // 初始化/清理 + void InitializeHamSandwichBridge(); + void CleanupHamSandwichBridge(); +} + +// 内部使用的前向声明 +namespace HamHooks { + struct HookData; + struct ForwardData; +} + +// 参数访问辅助函数 +extern "C" { + // 返回值处理 + int GetReturnStatus(); + int GetReturnValueInt(); + float GetReturnValueFloat(); + void GetReturnValueVector(float vec[3]); + int GetReturnValueEntity(); + + // 设置返回值 + void SetReturnValueInt(int value); + void SetReturnValueFloat(float value); + void SetReturnValueVector(const float vec[3]); + void SetReturnValueEntity(int entity); + + // 参数处理 + void SetParameterInt(int paramIndex, int value); + void SetParameterFloat(int paramIndex, float value); + void SetParameterVector(int paramIndex, const float vec[3]); + void SetParameterEntity(int paramIndex, int entity); +} \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_structs_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_structs_bridge.h new file mode 100644 index 0000000..de1d05d --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/hamsandwich_structs_bridge.h @@ -0,0 +1,54 @@ +// hamsandwich_structs_bridge.h +// 复杂结构体的桥接头文件 + +#ifndef HAMSANDWICH_STRUCTS_BRIDGE_H +#define HAMSANDWICH_STRUCTS_BRIDGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +// TraceResult结构体访问函数 +void GetTraceResultAllSolid(void* traceResult, int* allSolid); +void GetTraceResultStartSolid(void* traceResult, int* startSolid); +void GetTraceResultFraction(void* traceResult, float* fraction); +void GetTraceResultEndPos(void* traceResult, float endPos[3]); +void GetTraceResultPlaneNormal(void* traceResult, float normal[3]); +void GetTraceResultHit(void* traceResult, int* hit); +void GetTraceResultHitGroup(void* traceResult, int* hitGroup); + +// ItemInfo结构体访问函数 +void GetItemInfoName(void* itemInfo, char* name, int maxLen); +void GetItemInfoMaxClip(void* itemInfo, int* maxClip); +void GetItemInfoSlot(void* itemInfo, int* slot); +void GetItemInfoPosition(void* itemInfo, int* position); +void GetItemInfoId(void* itemInfo, int* id); +void GetItemInfoFlags(void* itemInfo, int* flags); + +void SetItemInfoMaxClip(void* itemInfo, int maxClip); +void SetItemInfoSlot(void* itemInfo, int slot); +void SetItemInfoPosition(void* itemInfo, int position); +void SetItemInfoFlags(void* itemInfo, int flags); + +// 向量操作辅助函数 +void VectorNormalize(float vec[3]); +float VectorLength(const float vec[3]); +void VectorAdd(const float a[3], const float b[3], float result[3]); +void VectorSubtract(const float a[3], const float b[3], float result[3]); +void VectorScale(const float vec[3], float scale, float result[3]); + +// 实体变换矩阵访问 +void GetEntityOrigin(int entity, float origin[3]); +void GetEntityAngles(int entity, float angles[3]); +void SetEntityOrigin(int entity, const float origin[3]); +void SetEntityAngles(int entity, const float angles[3]); + +// 距离和可见性检查 +float GetDistanceBetweenEntities(int entity1, int entity2); +bool IsEntityVisible(int entity, int target); + +#ifdef __cplusplus +} +#endif + +#endif // HAMSANDWICH_STRUCTS_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/messages_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/messages_bridge.h new file mode 100644 index 0000000..05c25e2 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/messages_bridge.h @@ -0,0 +1,165 @@ +// messages_bridge.h +// 消息系统桥接接口定义 +#pragma once + +#include "../amxmodx.h" +#include "../messages.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 开始发送消息 + * @param msg_dest 消息目标 + * @param msg_type 消息类型 + * @param origin 消息原点坐标 + * @param edict 实体指针 + */ +void AmxModx_Bridge_MessageBegin(int msg_dest, int msg_type, const float* origin, int edict); + +/** + * 结束消息发送 + */ +void AmxModx_Bridge_MessageEnd(void); + +/** + * 写入字节数据到消息 + * @param value 字节值 + */ +void AmxModx_Bridge_WriteByte(int value); + +/** + * 写入字符数据到消息 + * @param value 字符值 + */ +void AmxModx_Bridge_WriteChar(int value); + +/** + * 写入短整型数据到消息 + * @param value 短整型值 + */ +void AmxModx_Bridge_WriteShort(int value); + +/** + * 写入长整型数据到消息 + * @param value 长整型值 + */ +void AmxModx_Bridge_WriteLong(int value); + +/** + * 写入实体数据到消息 + * @param value 实体索引 + */ +void AmxModx_Bridge_WriteEntity(int value); + +/** + * 写入角度数据到消息 + * @param value 角度值 + */ +void AmxModx_Bridge_WriteAngle(float value); + +/** + * 写入坐标数据到消息 + * @param value 坐标值 + */ +void AmxModx_Bridge_WriteCoord(float value); + +/** + * 写入字符串数据到消息 + * @param str 字符串值 + */ +void AmxModx_Bridge_WriteString(const char* str); + +/** + * 注册消息钩子 + * @param msgId 消息ID + * @param callback 回调函数指针 + * @param post 是否为后置钩子 + * @return 是否注册成功 + */ +int AmxModx_Bridge_RegisterMessage(int msgId, void* callback, int post); + +/** + * 注销消息钩子 + * @param msgId 消息ID + * @param callback 回调函数指针 + * @param post 是否为后置钩子 + * @return 是否注销成功 + */ +int AmxModx_Bridge_UnregisterMessage(int msgId, void* callback, int post); + +/** + * 设置消息阻塞 + * @param msgId 消息ID + * @param blocking 是否阻塞 + */ +void AmxModx_Bridge_SetMessageBlock(int msgId, int blocking); + +/** + * 获取消息阻塞状态 + * @param msgId 消息ID + * @return 阻塞状态 + */ +int AmxModx_Bridge_GetMessageBlock(int msgId); + +/** + * 获取消息参数数量 + * @return 参数数量 + */ +int AmxModx_Bridge_GetMessageArgs(void); + +/** + * 获取消息参数类型 + * @param argIndex 参数索引 + * @return 参数类型 + */ +int AmxModx_Bridge_GetMessageArgType(int argIndex); + +/** + * 获取消息参数整数值 + * @param argIndex 参数索引 + * @return 整数值 + */ +int AmxModx_Bridge_GetMessageArgInt(int argIndex); + +/** + * 获取消息参数浮点数值 + * @param argIndex 参数索引 + * @return 浮点数值 + */ +float AmxModx_Bridge_GetMessageArgFloat(int argIndex); + +/** + * 获取消息参数字符串值 + * @param argIndex 参数索引 + * @param buffer 输出缓冲区 + * @param bufferSize 缓冲区大小 + * @return 实际复制的字符数 + */ +int AmxModx_Bridge_GetMessageArgString(int argIndex, char* buffer, int bufferSize); + +/** + * 设置消息参数整数值 + * @param argIndex 参数索引 + * @param value 整数值 + */ +void AmxModx_Bridge_SetMessageArgInt(int argIndex, int value); + +/** + * 设置消息参数浮点数值 + * @param argIndex 参数索引 + * @param value 浮点数值 + */ +void AmxModx_Bridge_SetMessageArgFloat(int argIndex, float value); + +/** + * 设置消息参数字符串值 + * @param argIndex 参数索引 + * @param str 字符串值 + */ +void AmxModx_Bridge_SetMessageArgString(int argIndex, const char* str); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/natives_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/natives_bridge.h new file mode 100644 index 0000000..bac4d8d --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/natives_bridge.h @@ -0,0 +1,45 @@ +// vim: set ts=4 sw=4 tw=99 noet: +#ifndef _INCLUDE_NATIVES_BRIDGE_H +#define _INCLUDE_NATIVES_BRIDGE_H + +#include + +// 前向声明AMX结构体 +#include "amx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// 原生函数注册管理 +int AmxModx_Bridge_RegisterNative(AMX *amx, const char *name, AMX_NATIVE func); +int AmxModx_Bridge_UnregisterNative(AMX *amx, const char *name); +int AmxModx_Bridge_RegisterLibrary(AMX *amx, const char *libname); +int AmxModx_Bridge_GetNativeCount(AMX *amx); +const char *AmxModx_Bridge_GetNativeName(AMX *amx, int index); +bool AmxModx_Bridge_NativeExists(AMX *amx, const char *name); +void AmxModx_Bridge_ClearLibraries(AMX *amx); + +// 参数处理 +const char *AmxModx_Bridge_GetString(AMX *amx, cell param, int *length); +int AmxModx_Bridge_SetString(AMX *amx, cell param, const char *string, int maxlen); +cell AmxModx_Bridge_GetParam(AMX *amx, int index); +cell *AmxModx_Bridge_GetParamAddress(AMX *amx, int index); +int AmxModx_Bridge_SetParam(AMX *amx, int index, cell value); + +// 浮点数处理 +float AmxModx_Bridge_GetFloat(AMX *amx, int index); +int AmxModx_Bridge_SetFloat(AMX *amx, int index, float value); + +// 数组处理 +int AmxModx_Bridge_GetArray(AMX *amx, cell param, cell *dest, int size); +int AmxModx_Bridge_SetArray(AMX *amx, cell param, const cell *source, int size); + +// 错误处理 +void AmxModx_Bridge_LogError(AMX *amx, int err, const char *message); + +#ifdef __cplusplus +} +#endif + +#endif // _INCLUDE_NATIVES_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/newmenus_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/newmenus_bridge.h new file mode 100644 index 0000000..5a18632 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/newmenus_bridge.h @@ -0,0 +1,147 @@ +// newmenus_bridge.h +// 新菜单系统桥接接口定义 +#pragma once + +#include "../amxmodx.h" +#include "../CMenu.h" +#include "../newmenus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 创建新菜单 + * @param title 菜单标题 + * @param handler 菜单处理函数 + * @param useMultiLanguage 是否使用多语言 + * @return 菜单句柄,失败返回-1 + */ +int AmxModx_Bridge_MenuCreate(const char* title, void* handler, int useMultiLanguage); + +/** + * 销毁菜单 + * @param menuHandle 菜单句柄(传引用,成功后会置-1) + * @return 是否成功销毁 + */ +int AmxModx_Bridge_MenuDestroy(int* menuHandle); + +/** + * 添加菜单项 + * @param menuHandle 菜单句柄 + * @param text 菜单项文本 + * @param command 菜单项命令 + * @param access 访问权限 + * @return 菜单项索引,失败返回-1 + */ +int AmxModx_Bridge_MenuAddItem(int menuHandle, const char* text, const char* command, int access); + +/** + * 添加空白菜单项 + * @param menuHandle 菜单句柄 + * @param slots 占用的槽位数 + * @return 是否成功添加 + */ +int AmxModx_Bridge_MenuAddBlank(int menuHandle, int slots); + +/** + * 添加文本菜单项 + * @param menuHandle 菜单句柄 + * @param text 菜单项文本 + * @param slots 占用的槽位数 + * @return 是否成功添加 + */ +int AmxModx_Bridge_MenuAddText(int menuHandle, const char* text, int slots); + +/** + * 显示菜单给玩家 + * @param menuHandle 菜单句柄 + * @param playerIndex 玩家索引 + * @param page 起始页码 + * @return 是否成功显示 + */ +int AmxModx_Bridge_MenuDisplay(int menuHandle, int playerIndex, int page); + +/** + * 取消玩家菜单 + * @param playerIndex 玩家索引 + * @return 是否成功取消 + */ +int AmxModx_Bridge_MenuCancel(int playerIndex); + +/** + * 设置菜单属性 + * @param menuHandle 菜单句柄 + * @param prop 属性类型 + * @param value 属性值 + * @return 是否成功设置 + */ +int AmxModx_Bridge_MenuSetProperty(int menuHandle, int prop, int value); + +/** + * 获取菜单项信息 + * @param menuHandle 菜单句柄 + * @param itemIndex 菜单项索引 + * @param textBuffer 文本输出缓冲区 + * @param textBufferSize 文本缓冲区大小 + * @param commandBuffer 命令输出缓冲区 + * @param commandBufferSize 命令缓冲区大小 + * @param access 访问权限输出 + * @return 是否成功获取 + */ +int AmxModx_Bridge_MenuGetItemInfo(int menuHandle, int itemIndex, + char* textBuffer, int textBufferSize, + char* commandBuffer, int commandBufferSize, + int* access); + +/** + * 设置菜单项名称 + * @param menuHandle 菜单句柄 + * @param itemIndex 菜单项索引 + * @param newName 新名称 + * @return 是否成功设置 + */ +int AmxModx_Bridge_MenuSetItemName(int menuHandle, int itemIndex, const char* newName); + +/** + * 设置菜单项命令 + * @param menuHandle 菜单句柄 + * @param itemIndex 菜单项索引 + * @param newCommand 新命令 + * @return 是否成功设置 + */ +int AmxModx_Bridge_MenuSetItemCommand(int menuHandle, int itemIndex, const char* newCommand); + +/** + * 获取菜单页数 + * @param menuHandle 菜单句柄 + * @return 页数,失败返回-1 + */ +int AmxModx_Bridge_MenuGetPages(int menuHandle); + +/** + * 获取菜单项数 + * @param menuHandle 菜单句柄 + * @return 项数,失败返回-1 + */ +int AmxModx_Bridge_MenuGetItems(int menuHandle); + +/** + * 查找菜单ID + * @param menuName 菜单名称 + * @return 菜单ID,失败返回-1 + */ +int AmxModx_Bridge_MenuFindId(const char* menuName); + +/** + * 获取玩家菜单信息 + * @param playerIndex 玩家索引 + * @param menuHandle 菜单句柄输出 + * @param item 选择项输出 + * @return 是否成功获取 + */ +int AmxModx_Bridge_PlayerMenuInfo(int playerIndex, int* menuHandle, int* item); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/stackstructs_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/stackstructs_bridge.h new file mode 100644 index 0000000..af195bd --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/stackstructs_bridge.h @@ -0,0 +1,47 @@ +// stackstructs_bridge.h +// 栈管理接口 + +#ifndef STACKSTRUCTS_BRIDGE_H +#define STACKSTRUCTS_BRIDGE_H + +#include "../amxmodx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// 创建栈 +int AmxModx_Bridge_CreateStack(); + +// 销毁栈 +int AmxModx_Bridge_DestroyStack(int* handle); + +// 压入单元格值 +int AmxModx_Bridge_PushStackCell(int handle, int value); + +// 压入字符串 +int AmxModx_Bridge_PushStackString(int handle, const char* str); + +// 压入数组 +int AmxModx_Bridge_PushStackArray(int handle, int arrayHandle); + +// 弹出单元格值 +int AmxModx_Bridge_PopStackCell(int handle, int* value); + +// 弹出字符串 +int AmxModx_Bridge_PopStackString(int handle, char* buffer, int size); + +// 弹出数组 +int AmxModx_Bridge_PopStackArray(int handle, int* arrayHandle); + +// 获取栈深度 +int AmxModx_Bridge_GetStackDepth(int handle); + +// 清空栈 +int AmxModx_Bridge_ClearStack(int handle); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/task_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/task_bridge.h new file mode 100644 index 0000000..3dfeef1 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/task_bridge.h @@ -0,0 +1,42 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +#ifndef TASK_BRIDGE_H +#define TASK_BRIDGE_H + +#include "amxmodx.h" + +// 任务标志位定义 +#define TASK_FLAG_REPEAT 1 +#define TASK_FLAG_LOOP 2 +#define TASK_FLAG_AFTER_START 4 +#define TASK_FLAG_BEFORE_END 8 + +// 任务调度系统桥接接口 +extern "C" { + // 创建任务 + int AmxModx_Bridge_CreateTask(int pluginId, int funcId, int flags, int taskId, float interval, int repeat, cell* params, int paramCount); + + // 移除任务 + int AmxModx_Bridge_RemoveTasks(int pluginId, int taskId); + + // 修改任务间隔 + int AmxModx_Bridge_ChangeTaskInterval(int pluginId, int taskId, float newInterval); + + // 检查任务是否存在 + bool AmxModx_Bridge_TaskExists(int pluginId, int taskId); + + // 获取当前活动任务数量 + int AmxModx_Bridge_GetActiveTaskCount(); + + // 获取任务信息 + bool AmxModx_Bridge_GetTaskInfo(int pluginId, int taskId, float* interval, int* repeat, int* flags); +} + +#endif // TASK_BRIDGE_H \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/CppInterface/vector_bridge.h b/Template/Amxmodx.Module.Template/CppInterface/vector_bridge.h new file mode 100644 index 0000000..bc667f5 --- /dev/null +++ b/Template/Amxmodx.Module.Template/CppInterface/vector_bridge.h @@ -0,0 +1,38 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +#ifndef _VECTOR_BRIDGE_H_ +#define _VECTOR_BRIDGE_H_ + +#include "amxmodx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// 向量转角度 +void AmxModx_Bridge_VectorToAngle(float x, float y, float z, float* outX, float* outY, float* outZ); + +// 角度转向量 +void AmxModx_Bridge_AngleVector(float pitch, float yaw, float roll, int type, float* outX, float* outY, float* outZ); + +// 向量长度 +float AmxModx_Bridge_VectorLength(float x, float y, float z); + +// 向量距离 +float AmxModx_Bridge_VectorDistance(float x1, float y1, float z1, float x2, float y2, float z2); + +// 通过实体瞄准方向获取速度 +bool AmxModx_Bridge_VelocityByAim(int entity, int velocity, float* outX, float* outY, float* outZ); + +#ifdef __cplusplus +} +#endif + +#endif // _VECTOR_BRIDGE_H_ \ No newline at end of file diff --git a/Template/Amxmodx.Module.Template/Module.cs b/Template/Amxmodx.Module.Template/Module.cs index bf1c429..9b1017c 100644 --- a/Template/Amxmodx.Module.Template/Module.cs +++ b/Template/Amxmodx.Module.Template/Module.cs @@ -1,4 +1,4 @@ -using GoldSrc.Amxmodx; +using GoldSrc.Amxmodx; using GoldSrc.Amxmodx.Native; using GoldSrc.HLSDK; using GoldSrc.HLSDK.Native; diff --git a/Template/Amxmodx.Module.Template/Plugin.cs b/Template/Amxmodx.Module.Template/Plugin.cs index a810207..11e83d0 100644 --- a/Template/Amxmodx.Module.Template/Plugin.cs +++ b/Template/Amxmodx.Module.Template/Plugin.cs @@ -1,4 +1,4 @@ -using GoldSrc.Amxmodx.Native; +using GoldSrc.Amxmodx.Native; using GoldSrc.HLSDK; using GoldSrc.HLSDK.Native; using System.Runtime.CompilerServices;