diff --git a/amxmodx/CLang.cpp b/amxmodx/CLang.cpp index ee041185..2a7263fb 100755 --- a/amxmodx/CLang.cpp +++ b/amxmodx/CLang.cpp @@ -256,9 +256,9 @@ int CLangMngr::GetKeyEntry(const char *key) return val.index; } -int CLangMngr::AddKeyEntry(String &key) +int CLangMngr::AddKeyEntry(const char *key) { - keytbl_val val; + keytbl_val val; val.index = static_cast(KeyList.size()); String *pString = new String(key); @@ -269,6 +269,11 @@ int CLangMngr::AddKeyEntry(String &key) return val.index; } +int CLangMngr::AddKeyEntry(String &key) +{ + return AddKeyEntry(key.c_str()); +} + int CLangMngr::GetKeyEntry(String &key) { keytbl_val &val = KeyTable[key]; diff --git a/amxmodx/CLang.h b/amxmodx/CLang.h index bb58e2ba..a6aea58e 100755 --- a/amxmodx/CLang.h +++ b/amxmodx/CLang.h @@ -127,9 +127,11 @@ class CLangMngr public: void AddEntry(int key, const char *definition); }; - +public: // Merge definitions into a language void MergeDefinitions(const char *lang, CQueue &tmpVec); + +private: // strip lowercase; make lower if needed static size_t strip(char *str, char *newstr, bool makelower = false); @@ -160,11 +162,11 @@ public: // Get index int GetKeyEntry(String &key); int GetKeyEntry(const char *key); - int GetKeyIndex(const char *key); // Get key from index const char *GetKey(int key); // Add key int AddKeyEntry(String &key); + int AddKeyEntry(const char *key); // Get the number of languages int GetLangsNum(); diff --git a/amxmodx/JIT/amxjitsn.o b/amxmodx/JIT/amxjitsn.o index d93eedbd..4b484531 100755 Binary files a/amxmodx/JIT/amxjitsn.o and b/amxmodx/JIT/amxjitsn.o differ diff --git a/amxmodx/JIT/amxjitsn.obj b/amxmodx/JIT/amxjitsn.obj index 09f89a78..24682e00 100755 Binary files a/amxmodx/JIT/amxjitsn.obj and b/amxmodx/JIT/amxjitsn.obj differ diff --git a/amxmodx/amx.cpp b/amxmodx/amx.cpp index a1392b6f..aed8616f 100755 --- a/amxmodx/amx.cpp +++ b/amxmodx/amx.cpp @@ -990,6 +990,7 @@ int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code) amx->cip = hdr->cip; amx->hea = hdr->hea; amx->stp = hdr->stp - sizeof(cell); + amx->hlw = hdr->hea; /* also put a sentinel for strings at the top the stack */ *(cell *)((char*)native_code + hdr->dat + hdr->stp - sizeof(cell)) = 0; amx->stk = amx->stp; diff --git a/amxmodx/amx.h b/amxmodx/amx.h index 5b1de9ce..fea1be8d 100755 --- a/amxmodx/amx.h +++ b/amxmodx/amx.h @@ -322,6 +322,7 @@ enum { #define AMX_FLAG_COMPACT 0x04 /* compact encoding */ #define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */ #define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */ +#define AMX_FLAG_OLDFILE 0x20 /* Old AMX Mod plugin */ #define AMX_FLAG_PRENIT 0x100 /* pre-initialized, do not check natives */ #define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */ #define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */ diff --git a/amxmodx/amxjitsn.asm b/amxmodx/amxjitsn.asm index d9844cc2..ec0e2fe8 100755 --- a/amxmodx/amxjitsn.asm +++ b/amxmodx/amxjitsn.asm @@ -2122,7 +2122,9 @@ err_heaplow: _CHKMARGIN_HEAP: cmp esi,stp jg err_stacklow - cmp dword hea,0 + mov ebp,amx + mov ebp,[ebp+_hlw] + cmp dword hea,ebp jl err_heaplow ret diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 52fc2b55..7e556844 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -4076,6 +4076,40 @@ static cell AMX_NATIVE_CALL amxx_setpl_curweap(AMX *amx, cell *params) return 1; } +static cell AMX_NATIVE_CALL CreateLangKey(AMX *amx, cell *params) +{ + int len; + const char *key = get_amxstring(amx, params[1], 0, len); + int suki = g_langMngr.GetKeyEntry(key); + + if (suki != -1) + { + return suki; + } + + return g_langMngr.AddKeyEntry(key); +} + +static cell AMX_NATIVE_CALL AddTranslation(AMX *amx, cell *params) +{ + int len; + const char *lang = get_amxstring(amx, params[1], 0, len); + int suki = params[2]; + const char *phrase = get_amxstring(amx, params[3], 1, len); + + CQueue queue; + sKeyDef def; + + def.definition = new String(phrase); + def.key = suki; + + queue.push(def); + + g_langMngr.MergeDefinitions(lang, queue); + + return 1; +} + AMX_NATIVE_INFO amxmodx_Natives[] = { {"abort", amx_abort}, @@ -4255,8 +4289,10 @@ AMX_NATIVE_INFO amxmodx_Natives[] = {"user_kill", user_kill}, {"user_slap", user_slap}, {"xvar_exists", xvar_exists}, + {"AddTranslation", AddTranslation}, {"ClearSyncHud", ClearSyncHud}, {"CreateHudSyncObj", CreateHudSyncObj}, + {"CreateLangKey", CreateLangKey}, {"CreateMultiForward", CreateMultiForward}, {"CreateOneForward", CreateOneForward}, {"DestroyForward", DestroyForward}, diff --git a/amxmodx/amxxfile.h b/amxmodx/amxxfile.h index 9e2c7833..e03e34dd 100755 --- a/amxmodx/amxxfile.h +++ b/amxmodx/amxxfile.h @@ -92,6 +92,7 @@ public: Error GetStatus(); // Get the current status size_t GetBufferSize(); // Get the size for the buffer Error GetSection(void *buffer); // Copy the currently selected section to the buffer + inline bool IsOldFile() const { return m_OldFile; } }; #endif // __AMXXFILE_H__ diff --git a/amxmodx/messages.h b/amxmodx/messages.h index 8a781b2b..19f5c2fd 100755 --- a/amxmodx/messages.h +++ b/amxmodx/messages.h @@ -9,6 +9,8 @@ #define MAX_MESSAGES 255 +#define MSGBLOCK_SET 0 +#define MSGBLOCK_GET 1 #define BLOCK_NOT 0 #define BLOCK_ONCE 1 #define BLOCK_SET 2 diff --git a/amxmodx/modules.cpp b/amxmodx/modules.cpp index c44a9699..e220ecf2 100755 --- a/amxmodx/modules.cpp +++ b/amxmodx/modules.cpp @@ -1742,6 +1742,33 @@ const char *MNF_GetLocalInfo(char *name, const char *def) return get_localinfo(name, def); } +void MNF_MessageBlock(int mode, int msg, int *opt) +{ + switch (mode) + { + case MSGBLOCK_SET: + { + if (msg < 0 || msg > MAX_MESSAGES || opt == NULL) + { + return; + } + int _opt = msgBlocks[msg]; + msgBlocks[msg] = *opt; + *opt = _opt; + break; + } + case MSGBLOCK_GET: + { + if (msg < 0 || msg > MAX_MESSAGES || opt == NULL) + { + return; + } + *opt = msgBlocks[msg]; + break; + } + } +} + void *MNF_PlayerPropAddr(int id, int prop) { if (id < 1 || id > gpGlobals->maxClients) @@ -1891,6 +1918,8 @@ void Module_CacheFunctions() REGISTER_FUNC("OverrideNatives", MNF_OverrideNatives); REGISTER_FUNC("GetLocalInfo", MNF_GetLocalInfo); + REGISTER_FUNC("MessageBlock", MNF_MessageBlock); + #ifdef MEMORY_TEST REGISTER_FUNC("Allocator", m_allocator) REGISTER_FUNC("Deallocator", m_deallocator) diff --git a/amxmodx/natives.cpp b/amxmodx/natives.cpp index bf165335..a5d22542 100755 --- a/amxmodx/natives.cpp +++ b/amxmodx/natives.cpp @@ -33,6 +33,7 @@ #include "natives.h" #include "debugger.h" #include "libraries.h" +#include "format.h" #ifdef __linux__ #include @@ -98,7 +99,7 @@ int amxx_DynaCallback(int idx, AMX *amx, cell *params) { amx_Push(pNative->amx, numParams); amx_Push(pNative->amx, pPlugin->getId()); - for (int i=numParams; i>=1; i--) + for (int i=numParams; i>=0; i--) pNative->params[i] = params[i]; } else if (pNative->style == 1) { //use dJeyL's system .. very clever! @@ -328,6 +329,70 @@ static cell AMX_NATIVE_CALL set_array(AMX *amx, cell *params) return 1; } +static cell AMX_NATIVE_CALL vdformat(AMX *amx, cell *params) +{ + if (!g_NativeStack.size()) + { + LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); + return 0; + } + + regnative *pNative = g_NativeStack.front(); + + if (pNative->style) + { + LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); + return 0; + } + + int vargPos = static_cast(params[4]); + int fargPos = static_cast(params[3]); + + /** get the parent parameter array */ + cell *local_params = pNative->params; + + cell max = local_params[0] / sizeof(cell); + if (vargPos > (int)max + 1) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid vararg parameter passed: %d", vargPos); + return 0; + } + if (fargPos > (int)max + 1) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid fmtarg parameter passed: %d", fargPos); + return 0; + } + + /* get destination info */ + cell *fmt; + if (fargPos == 0) + { + if (params[0] / sizeof(cell) != 5) + { + LogError(amx, AMX_ERR_NATIVE, "Expected fmtarg as fifth parameter, found none"); + return 0; + } + fmt = get_amxaddr(amx, params[5]); + } else { + fmt = get_amxaddr(pNative->caller, pNative->params[fargPos]); + } + cell *realdest = get_amxaddr(amx, params[1]); + size_t maxlen = static_cast(params[2]); + cell *dest = realdest; + + /* if this is necessary... */ + static cell cpbuf[4096]; + dest = cpbuf; + + /* perform format */ + size_t total = atcprintf(dest, maxlen, fmt, pNative->caller, local_params, &vargPos); + + /* copy back */ + memcpy(realdest, dest, (total+1) * sizeof(cell)); + + return total; +} + //This is basically right from dJeyL's lib_convert function //This awesome hack modifies the stack frame to have an address offset // that will align to the other plugin's memory. @@ -444,6 +509,7 @@ AMX_NATIVE_INFO g_NativeNatives[] = { {"set_float_byref", set_param_byref}, {"get_array_f", get_array}, {"set_array_f", set_array}, + {"vdformat", vdformat}, {"param_convert", param_convert}, ////////////////////////// {NULL, NULL}, diff --git a/dlls/engine/engine.h b/dlls/engine/engine.h index 89d5f53c..94a601b8 100755 --- a/dlls/engine/engine.h +++ b/dlls/engine/engine.h @@ -174,6 +174,17 @@ void pfnTouch(edict_t *pToucher, edict_t *pTouched); void Think(edict_t *pent); void StartFrame_Post(); +#define CHECK_ENTITY_SIMPLE(x) \ + if (x < 0 || x > gpGlobals->maxEntities) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ + return 0; \ + } else { \ + if (x != 0 && FNullEnt(INDEXENT(x))) { \ + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid entity %d", x); \ + return 0; \ + } \ + } + #define CHECK_ENTITY(x) \ if (x < 0 || x > gpGlobals->maxEntities) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ diff --git a/dlls/engine/entity.cpp b/dlls/engine/entity.cpp index 7c8dffe7..7b7402e2 100755 --- a/dlls/engine/entity.cpp +++ b/dlls/engine/entity.cpp @@ -338,7 +338,7 @@ static cell AMX_NATIVE_CALL entity_set_float(AMX *amx, cell *params) int idx = params[2]; REAL fVal = amx_ctof(params[3]); - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -469,7 +469,7 @@ static cell AMX_NATIVE_CALL entity_get_int(AMX *amx, cell *params) int idx = params[2]; int iRetValue = 0; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -601,7 +601,7 @@ static cell AMX_NATIVE_CALL entity_set_int(AMX *amx, cell *params) int idx = params[2]; int iNewValue = params[3]; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -733,7 +733,7 @@ static cell AMX_NATIVE_CALL entity_get_vector(AMX *amx, cell *params) cell *vRet = MF_GetAmxAddr(amx, params[3]); Vector vRetValue = Vector(0, 0, 0); - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -826,7 +826,7 @@ static cell AMX_NATIVE_CALL entity_set_vector(AMX *amx, cell *params) int idx = params[2]; cell *vAmx = MF_GetAmxAddr(amx, params[3]); - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); REAL fX = amx_ctof(vAmx[0]); REAL fY = amx_ctof(vAmx[1]); @@ -920,7 +920,7 @@ static cell AMX_NATIVE_CALL entity_get_string(AMX *amx, cell *params) int iszString = 0; const char *szRet = NULL; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -982,7 +982,7 @@ static cell AMX_NATIVE_CALL entity_set_string(AMX *amx, cell *params) int iLen; int iszString = AmxStringToEngine(amx, params[3], iLen); - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -1041,7 +1041,7 @@ static cell AMX_NATIVE_CALL entity_get_edict(AMX *amx, cell *params) int idx = params[2]; edict_t *pRet; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -1097,7 +1097,7 @@ static cell AMX_NATIVE_CALL entity_set_edict(AMX *amx, cell *params) int idx = params[2]; int iSetEnt = params[3]; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); edict_t *pSetEnt = INDEXENT2(iSetEnt); @@ -1151,7 +1151,7 @@ static cell AMX_NATIVE_CALL entity_get_byte(AMX *amx, cell *params) int idx = params[2]; int iRetValue = 0; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -1189,7 +1189,7 @@ static cell AMX_NATIVE_CALL entity_set_byte(AMX *amx, cell *params) int idx = params[2]; int iNewValue = params[3]; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); if(iNewValue > 255) iNewValue = 255; @@ -1230,7 +1230,7 @@ static cell AMX_NATIVE_CALL entity_set_origin(AMX *amx, cell *params) { int iEnt = params[1]; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); cell *vVector = MF_GetAmxAddr(amx, params[2]); @@ -1249,7 +1249,7 @@ static cell AMX_NATIVE_CALL entity_set_model(AMX *amx, cell *params) { int iEnt = params[1]; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); int iLen; @@ -1265,7 +1265,7 @@ static cell AMX_NATIVE_CALL entity_set_size(AMX *amx, cell *params) { int iEnt = params[1]; - CHECK_ENTITY(iEnt); + CHECK_ENTITY_SIMPLE(iEnt); edict_t *pEnt = INDEXENT2(iEnt); diff --git a/plugins/include/lang.inc b/plugins/include/lang.inc index e52bd4b3..e7e3725b 100755 --- a/plugins/include/lang.inc +++ b/plugins/include/lang.inc @@ -23,4 +23,14 @@ native get_lang(id, name[3]); native register_dictionary(const filename[]); //returns 1 if the language is loaded, 0 otherwise. -native lang_exists(const name[]); \ No newline at end of file +native lang_exists(const name[]); + +/** + * Adds or finds a translation key. + */ +native TransKey:CreateLangKey(const key[]); + +/** + * Adds a translation. + */ +native AddTranslation(const lang[3], TransKey:key, const phrase[]); diff --git a/plugins/include/string.inc b/plugins/include/string.inc index b056e5c8..20863d06 100755 --- a/plugins/include/string.inc +++ b/plugins/include/string.inc @@ -58,6 +58,15 @@ native formatex(output[] ,len ,const format[] , {Float,Sql,Result,_}:...); */ native vformat(buffer[], len, const fmt[], vararg); +/* + * Same as vformat(), except works in normal style dynamic natives. + * Instead of passing the format arg string, you can only pass the + * actual format argument number itself. + * If you pass 0, it will read the format string from an optional + * fifth parameter. + */ +native vdformat(buffer[], len, fmt_arg, vararg, ...); + /* Gets parameters from function as formated string. */ native format_args(output[] ,len ,pos = 0);