From c531ad756d70338cc2bc8bb2952e37392eb187a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Sun, 10 May 2015 23:21:12 +0200 Subject: [PATCH 01/15] Engine: Dynamically hook StartFrame for set_lights() --- modules/engine/amxxapi.cpp | 11 ++++++----- modules/engine/engine.cpp | 10 ++++------ modules/engine/engine.h | 1 - modules/engine/forwards.cpp | 11 ++--------- modules/engine/moduleconfig.h | 4 ++-- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/modules/engine/amxxapi.cpp b/modules/engine/amxxapi.cpp index b21ab8cf..259978e2 100644 --- a/modules/engine/amxxapi.cpp +++ b/modules/engine/amxxapi.cpp @@ -57,7 +57,6 @@ void OnAmxxAttach() MF_AddNatives(global_Natives); memset(glinfo.szLastLights, 0x0, 128); memset(glinfo.szRealLights, 0x0, 128); - glinfo.fNextLights = 0; glinfo.bCheckLights = false; } @@ -197,7 +196,6 @@ void ServerDeactivate() memset(glinfo.szLastLights, 0x0, 128); memset(glinfo.szRealLights, 0x0, 128); glinfo.bCheckLights = false; - glinfo.fNextLights = 0; // Reset all forwarding function tables (so that forwards won't be called before plugins are initialized) g_pFunctionTable->pfnAddToFullPack=NULL; @@ -226,10 +224,13 @@ void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) RETURN_META(MRES_IGNORED); } -void LightStyle(int style, const char *val) { - if (!style) { +void LightStyle_Post(int style, const char *val) { + if (!style && strcmp(val, glinfo.szRealLights)) { memset(glinfo.szRealLights, 0x0, 128); - memcpy(glinfo.szRealLights, val, strlen(val)); + memcpy(glinfo.szRealLights, val, min(strlen(val), 127)); + + if (glinfo.bCheckLights && strcmp(val, glinfo.szLastLights)) + g_pFunctionTable_Post->pfnStartFrame = StartFrame_Post; } RETURN_META(MRES_IGNORED); diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index 042dfa8e..8c8b6f34 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -493,19 +493,17 @@ static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { glinfo.bCheckLights = false; g_pFunctionTable_Post->pfnStartFrame = NULL; memset(glinfo.szLastLights, 0x0, 128); - (g_engfuncs.pfnLightStyle)(0, glinfo.szRealLights); + LIGHT_STYLE(0, glinfo.szRealLights); return 1; } - g_pFunctionTable_Post->pfnStartFrame = StartFrame_Post; glinfo.bCheckLights = true; - //Reset LastLights + //Reset LastLights and store custom lighting memset(glinfo.szLastLights, 0x0, 128); - //Store the previous lighting. - memcpy(glinfo.szLastLights, szLights, strlen(szLights)); + memcpy(glinfo.szLastLights, szLights, min(iLength, 127)); - (g_engfuncs.pfnLightStyle)(0, szLights); + LIGHT_STYLE(0, szLights); // These make it so that players/weaponmodels look like whatever the lighting is // at. otherwise it would color players under the skybox to these values. diff --git a/modules/engine/engine.h b/modules/engine/engine.h index d0415445..2ea243d8 100644 --- a/modules/engine/engine.h +++ b/modules/engine/engine.h @@ -118,7 +118,6 @@ struct PlayerInfo { }; struct GlobalInfo { - float fNextLights; char szLastLights[128]; char szRealLights[128]; bool bCheckLights; diff --git a/modules/engine/forwards.cpp b/modules/engine/forwards.cpp index a5b6c22c..34faf6c4 100644 --- a/modules/engine/forwards.cpp +++ b/modules/engine/forwards.cpp @@ -120,15 +120,8 @@ void StartFrame() void StartFrame_Post() { - if (glinfo.bCheckLights) - { - if (glinfo.fNextLights < gpGlobals->time) - { - (g_engfuncs.pfnLightStyle)(0, glinfo.szLastLights); - glinfo.fNextLights = gpGlobals->time + 1; - } - } - + g_pFunctionTable_Post->pfnStartFrame = NULL; + LIGHT_STYLE(0, glinfo.szLastLights); RETURN_META(MRES_IGNORED); } diff --git a/modules/engine/moduleconfig.h b/modules/engine/moduleconfig.h index 827f3234..72e5796f 100644 --- a/modules/engine/moduleconfig.h +++ b/modules/engine/moduleconfig.h @@ -243,7 +243,7 @@ // #define FN_ServerExecute ServerExecute // #define FN_engClientCommand engClientCommand // #define FN_ParticleEffect ParticleEffect -#define FN_LightStyle LightStyle +// #define FN_LightStyle LightStyle // #define FN_DecalIndex DecalIndex // #define FN_PointContents PointContents // #define FN_MessageBegin MessageBegin @@ -389,7 +389,7 @@ // #define FN_ServerExecute_Post ServerExecute_Post // #define FN_engClientCommand_Post engClientCommand_Post // #define FN_ParticleEffect_Post ParticleEffect_Post -// #define FN_LightStyle_Post LightStyle_Post +#define FN_LightStyle_Post LightStyle_Post // #define FN_DecalIndex_Post DecalIndex_Post // #define FN_PointContents_Post PointContents_Post // #define FN_MessageBegin_Post MessageBegin_Post From 218fb9c794c0aca226250de961e428d97e6de1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Sun, 10 May 2015 23:40:22 +0200 Subject: [PATCH 02/15] Engine: Add unregister_[touch|think|impulse]() --- modules/engine/engine.cpp | 67 +++++++++++++++++++++++++++++++++++++- plugins/include/engine.inc | 33 +++++++++++++++++-- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index 8c8b6f34..a635fd4b 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -55,6 +55,27 @@ static cell AMX_NATIVE_CALL register_think(AMX *amx, cell *params) return p->Forward; } +static cell AMX_NATIVE_CALL unregister_think(AMX *amx, cell *params) +{ + int fwd = params[1]; + for (size_t i = 0; i < Thinks.length(); ++i) + { + EntClass *p = Thinks.at(i); + if (p->Forward == fwd) + { + Thinks.remove(i); + delete p; + + if (!Thinks.length()) + g_pFunctionTable->pfnThink = NULL; + + return 1; + } + } + + return 0; +} + static cell AMX_NATIVE_CALL register_impulse(AMX *amx, cell *params) { int len; @@ -72,6 +93,27 @@ static cell AMX_NATIVE_CALL register_impulse(AMX *amx, cell *params) return p->Forward; } +static cell AMX_NATIVE_CALL unregister_impulse(AMX *amx, cell *params) +{ + int fwd = params[1]; + for (size_t i = 0; i < Impulses.length(); ++i) + { + Impulse *p = Impulses.at(i); + if (p->Forward == fwd) + { + Impulses.remove(i); + delete p; + + if (!Impulses.length()) + g_pFunctionTable->pfnCmdStart = NULL; + + return 1; + } + } + + return 0; +} + static cell AMX_NATIVE_CALL register_touch(AMX *amx, cell *params) { int len; @@ -102,6 +144,27 @@ static cell AMX_NATIVE_CALL register_touch(AMX *amx, cell *params) return p->Forward; } +static cell AMX_NATIVE_CALL unregister_touch(AMX *amx, cell *params) +{ + int fwd = params[1]; + for (size_t i = 0; i < Touches.length(); ++i) + { + Touch *p = Touches.at(i); + if (p->Forward == fwd) + { + Touches.remove(i); + delete p; + + if (!Touches.length()) + g_pFunctionTable->pfnTouch = NULL; + + return 1; + } + } + + return 0; +} + static cell AMX_NATIVE_CALL halflife_time(AMX *amx, cell *params) { REAL fVal = gpGlobals->time; @@ -983,10 +1046,12 @@ AMX_NATIVE_INFO engine_Natives[] = { {"get_usercmd", get_usercmd}, {"set_usercmd", set_usercmd}, - {"register_impulse", register_impulse}, {"register_think", register_think}, {"register_touch", register_touch}, + {"unregister_impulse", unregister_impulse}, + {"unregister_think", unregister_think}, + {"unregister_touch", unregister_touch}, {"eng_get_string", get_string}, {"is_in_viewcone", in_view_cone}, diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index cd0b5e5f..9d9bcdbd 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -70,7 +70,7 @@ native traceresult(type, any:...); * @param impulse Impulse to hook * @param function Name of callback function * - * @noreturn + * @return Impulse forward id */ native register_impulse(impulse, const function[]); @@ -96,7 +96,7 @@ native register_impulse(impulse, const function[]); * @param Toucher Entity classname touching, "*" or "" for any class * @param function Name of callback function * - * @noreturn + * @return Touch forward id */ native register_touch(const Touched[], const Toucher[], const function[]); @@ -120,10 +120,37 @@ native register_touch(const Touched[], const Toucher[], const function[]); * @param Touched Entity classname to hook * @param function Name of callback function * - * @noreturn + * @return Think forward id */ native register_think(const Classname[], const function[]); +/** + * Removes a previously registered impulse hook. + * + * @param registerid Impulse forward id + * + * @return 1 on success, 0 if nothing was removed + */ +native unregister_impulse(registerid); + +/** + * Removes a previously registered touch hook. + * + * @param registerid Touch forward id + * + * @return 1 on success, 0 if nothing was removed + */ +native unregister_touch(registerid); + +/** + * Removes a previously registered think hook. + * + * @param registerid Think forward id + * + * @return 1 on success, 0 if nothing was removed + */ +native unregister_think(registerid); + /** * Precaches an event file. * From d69fddf8b4e4a4fd105abcf79a815be20293bb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Sun, 10 May 2015 23:45:01 +0200 Subject: [PATCH 03/15] Engine/Core: Move precache_event() to core --- amxmodx/amxmodx.cpp | 8 ++++++++ modules/engine/engine.cpp | 9 --------- plugins/include/amxmodx.inc | 19 +++++++++++++++++++ plugins/include/engine.inc | 19 ------------------- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 2aa0efaf..90398e30 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -2806,6 +2806,14 @@ static cell AMX_NATIVE_CALL precache_generic(AMX *amx, cell *params) return PRECACHE_GENERIC((char*)STRING(ALLOC_STRING(sptemp))); } +static cell AMX_NATIVE_CALL precache_event(AMX *amx, cell *params) +{ + int len; + char *sptemp = format_amxstring(amx, params, 2, len); + + return PRECACHE_EVENT(params[1], (char*)STRING(ALLOC_STRING(sptemp))); +} + static cell AMX_NATIVE_CALL random_float(AMX *amx, cell *params) /* 2 param */ { float one = amx_ctof(params[1]); diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index a635fd4b..f996f8ef 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -366,14 +366,6 @@ static cell AMX_NATIVE_CALL get_decal_index(AMX *amx, cell *params) return DECAL_INDEX(szDecal); } -static cell AMX_NATIVE_CALL precache_event(AMX *amx, cell *params) -{ - int len; - char *szEvent = MF_FormatAmxString(amx, params, 2, &len); - return PRECACHE_EVENT(params[1], (char *)STRING(ALLOC_STRING(szEvent))); - -} - static cell AMX_NATIVE_CALL get_info_keybuffer(AMX *amx, cell *params) { int iEnt = params[1]; @@ -1032,7 +1024,6 @@ AMX_NATIVE_INFO engine_Natives[] = { {"set_speak", set_speak}, {"get_speak", get_speak}, - {"precache_event", precache_event}, {"playback_event", playback_event}, {"set_view", set_view}, diff --git a/plugins/include/amxmodx.inc b/plugins/include/amxmodx.inc index b58239de..46ae4431 100755 --- a/plugins/include/amxmodx.inc +++ b/plugins/include/amxmodx.inc @@ -248,6 +248,25 @@ native precache_sound(const name[]); */ native precache_generic(const szFile[]); +/** + * Precaches an event file. + * + * @note The event type should always be 1. + * @note Contrary to the other precache_* natives, this can be used outside of + * the plugin_precache() forward, e.g. in plugin_init() or plugin_cfg(). + * A bug in some clients makes this necessary, as plugin_precache() is + * called before the mod has precached its own, default event files. This + * can cause the event table to be misaligned on the client, leading to + * visual and audio bugs that are hard to diagnose. + * + * @param type Event type + * @param Name Formatting rules, path to the event file + * @param ... Variable number of formatting parameters + * + * @return Unique cache id of the event + */ +native precache_event(type, const Name[], any:...); + /** * Changes the map. * diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index 9d9bcdbd..ae3bd98a 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -151,25 +151,6 @@ native unregister_touch(registerid); */ native unregister_think(registerid); -/** - * Precaches an event file. - * - * @note The event type should always be 1. - * @note Contrary to the other precache_* natives, this can be used outside of - * the plugin_precache() forward, e.g. in plugin_init() or plugin_cfg(). - * A bug in some clients makes this necessary, as plugin_precache() is - * called before the mod has precached its own, default event files. This - * can cause the event table to be misaligned on the client, leading to - * visual and audio bugs that are hard to diagnose. - * - * @param type Event type - * @param Name Formatting rules, path to the event file - * @param ... Variable number of formatting parameters - * - * @return Unique cache id of the event - */ -native precache_event(type, const Name[], any:...); - /** * Sets the engine module speak flags on a client. * From add4867d21fe82f0775879a59997116b8b67332a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Sun, 10 May 2015 23:56:06 +0200 Subject: [PATCH 04/15] Engine: Add safe get_global_edict2() and entity_get_edict2() --- modules/engine/entity.cpp | 17 ++++++++++++++--- modules/engine/globals.cpp | 17 ++++++++++++++--- plugins/include/engine.inc | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/modules/engine/entity.cpp b/modules/engine/entity.cpp index c1f76491..a0fc86c8 100644 --- a/modules/engine/entity.cpp +++ b/modules/engine/entity.cpp @@ -1057,7 +1057,7 @@ static cell AMX_NATIVE_CALL entity_set_string(AMX *amx, cell *params) return 1; } -static cell AMX_NATIVE_CALL entity_get_edict(AMX *amx, cell *params) +static cell AMX_NATIVE_CALL entity_get_edict2(AMX *amx, cell *params) { int iEnt = params[1]; int idx = params[2]; @@ -1103,16 +1103,26 @@ static cell AMX_NATIVE_CALL entity_get_edict(AMX *amx, cell *params) pRet = pEnt->v.euser4; break; default: - return 0; + return -1; break; } if (FNullEnt(pRet)) - return 0; + return -1; return ENTINDEX(pRet); } +static cell AMX_NATIVE_CALL entity_get_edict(AMX *amx, cell *params) +{ + cell res = entity_get_edict2(amx, params); + + if (res == -1) + res = 0; + + return res; +} + static cell AMX_NATIVE_CALL entity_set_edict(AMX *amx, cell *params) { int iEnt = params[1]; @@ -1602,6 +1612,7 @@ AMX_NATIVE_INFO ent_Natives[] = { {"entity_get_string", entity_get_string}, {"entity_set_string", entity_set_string}, {"entity_get_edict", entity_get_edict}, + {"entity_get_edict2", entity_get_edict2}, {"entity_set_edict", entity_set_edict}, {"entity_get_byte", entity_get_byte}, {"entity_set_byte", entity_set_byte}, diff --git a/modules/engine/globals.cpp b/modules/engine/globals.cpp index 3b8a281d..4b859c12 100644 --- a/modules/engine/globals.cpp +++ b/modules/engine/globals.cpp @@ -157,7 +157,7 @@ static cell AMX_NATIVE_CALL get_global_vector(AMX *amx, cell *params) // globals return 1; } -static cell AMX_NATIVE_CALL get_global_edict(AMX *amx, cell *params) // globals_get_edict(variable); = 1 param +static cell AMX_NATIVE_CALL get_global_edict2(AMX *amx, cell *params) { edict_t* pReturnEntity; @@ -167,14 +167,24 @@ static cell AMX_NATIVE_CALL get_global_edict(AMX *amx, cell *params) // globals_ break; default: MF_LogError(amx, AMX_ERR_NATIVE, "Undefined global_edict index %d", params[1]); - return 0; + return -1; } // Will crash if ENTINDEX() is called on bad pointer? if(!FNullEnt(pReturnEntity)) return ENTINDEX(pReturnEntity); - return 0; + return -1; +} + +static cell AMX_NATIVE_CALL get_global_edict(AMX *amx, cell *params) // globals_get_edict(variable); = 1 param +{ + cell res = get_global_edict2(amx, params); + + if (res == -1) + res = 0; + + return res; } AMX_NATIVE_INFO global_Natives[] = { @@ -182,6 +192,7 @@ AMX_NATIVE_INFO global_Natives[] = { {"get_global_int", get_global_int}, {"get_global_string", get_global_string}, {"get_global_edict", get_global_edict}, + {"get_global_edict2", get_global_edict2}, {"get_global_vector", get_global_vector}, {NULL, NULL}, /////////////////// diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index ae3bd98a..4b811429 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -306,6 +306,21 @@ native get_global_vector(variable, Float:vector[3]); */ native get_global_edict(variable); +/** + * Returns a edict type value from the server globals. + * + * @note For a list of valid edict type entries, see the GL_* constants in + * engine_const.inc under the "Edict" section. + * @note This native returns -1 as a safe error value if the edict retrieved is + * an invalid entity. Otherwise it is identical to get_global_edict(). + * + * @param variable Entry to retrieve from + * + * @return Value of specified entry + * @error If an invalid entry is provided, an error will be thrown. + */ +native get_global_edict2(variable); + /** * Sets the size of the entity bounding box, as described by the minimum and * maximum vectors relative to the origin. @@ -476,6 +491,26 @@ native entity_set_vector(iIndex, iKey, const Float:vNewVector[3]); */ native entity_get_edict(iIndex, iKey); +/** + * Returns an edict type value from an entities entvar struct. + * + * @note For a list of valid edict type entries, see the EV_ENT_* constants in + * engine_const.inc + * @note This native returns -1 as a safe error value if the edict retrieved + * from the entvar is an invalid entity. Otherwise it is identical to + * entity_get_edict(). + * + * @param iIndex Entity index + * @param iKey Entry to retrieve from + * + * @return Entity index in specified entry, -1 if the edict in the + * entvar is not a valid entity or an invalid entry was + * specified + * @error If an invalid entity index is provided, an error will be + * thrown. + */ +native entity_get_edict2(iIndex, iKey); + /** * Sets an edict type value in an entities entvar struct. * From 3c1022af995570dfd13cede6eac42f7f4d8a3bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:05:25 +0200 Subject: [PATCH 05/15] Engine: Add a destination parameter to trace_hull() to make it more useful --- modules/engine/engine.cpp | 21 ++++++++++++++++----- plugins/include/engine.inc | 7 ++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index f996f8ef..59fc8ddd 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -574,16 +574,27 @@ static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) { int iResult=0; TraceResult tr; - Vector vPos; + Vector vStart; + Vector vEnd; cell *vCell; vCell = MF_GetAmxAddr(amx, params[1]); - vPos.x = amx_ctof(vCell[0]); - vPos.y = amx_ctof(vCell[1]); - vPos.z = amx_ctof(vCell[2]); + vStart.x = amx_ctof(vCell[0]); + vStart.y = amx_ctof(vCell[1]); + vStart.z = amx_ctof(vCell[2]); - TRACE_HULL(vPos,vPos, params[4], params[2], params[3] > 0 ? INDEXENT2(params[3]) : 0 , &tr); + if (params[0] / sizeof(cell) >= 5 && (vCell = MF_GetAmxVectorNull(amx, params[5]))) + { + + vEnd.x = amx_ctof(vCell[0]); + vEnd.y = amx_ctof(vCell[1]); + vEnd.z = amx_ctof(vCell[2]); + } + else + vEnd = vStart; + + TRACE_HULL(vStart, vEnd, params[4], params[2], params[3] > 0 ? INDEXENT2(params[3]) : 0, &tr); if (tr.fStartSolid) { iResult += 1; diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index 4b811429..cbe11a5b 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -999,7 +999,7 @@ native trace_line(iIgnoreEnt, const Float:fStart[3], const Float:fEnd[3], Float: native trace_normal(iIgnoreEnt, const Float:fStart[3], const Float:fEnd[3], Float:vReturn[3]); /** - * Fires a trace hull on a specified origin. + * Fires a trace hull on a specified origin or between two origins. * * @note This native writes to the global trace handle. Additional trace results * can be retrieved using traceresult(). @@ -1008,15 +1008,16 @@ native trace_normal(iIgnoreEnt, const Float:fStart[3], const Float:fEnd[3], Floa * @note For a list of valid ignore types see the *IGNORE_* constants in * hlsdk_const.inc * - * @param origin Trace startin and end point + * @param origin Trace start point (and end point if not specified) * @param hull Hull type * @param ignoredent Entity index that trace will ignore * @param ignoremonsters Entity ignore type + * @param end Trace end point, pass NULL_VECTOR to use start point * * @return Custom bitflag sum of relevant trace results * StartSolid (1), AllSolid (2) and InOpen (4) */ -native trace_hull(const Float:origin[3], hull, ignoredent = 0, ignoremonsters = 0); +native trace_hull(const Float:origin[3], hull, ignoredent = 0, ignoremonsters = 0, const Float:end[3] = NULL_VECTOR); /** * Attempts to describe an obstacle by firing trace lines in a specified From ebdd015aaea5564de4bf94e3df8ab03c1aa8ed6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:08:47 +0200 Subject: [PATCH 06/15] Restore traceresult() functionality by writing to g_tr in trace functions --- modules/engine/engine.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index 59fc8ddd..89f0adde 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -284,14 +284,13 @@ static cell AMX_NATIVE_CALL trace_normal(AMX *amx, cell *params) Vector vStart = Vector(fStartX, fStartY, fStartZ); Vector vEnd = Vector(fEndX, fEndY, fEndZ); - TraceResult tr; - TRACE_LINE(vStart, vEnd, dont_ignore_monsters, INDEXENT2(iEnt), &tr); + TRACE_LINE(vStart, vEnd, dont_ignore_monsters, INDEXENT2(iEnt), &g_tr); - vRet[0] = amx_ftoc(tr.vecPlaneNormal.x); - vRet[1] = amx_ftoc(tr.vecPlaneNormal.y); - vRet[2] = amx_ftoc(tr.vecPlaneNormal.z); + vRet[0] = amx_ftoc(g_tr.vecPlaneNormal.x); + vRet[1] = amx_ftoc(g_tr.vecPlaneNormal.y); + vRet[2] = amx_ftoc(g_tr.vecPlaneNormal.z); - if (tr.flFraction >= 1.0) + if (g_tr.flFraction >= 1.0) return 0; return 1; @@ -314,19 +313,17 @@ static cell AMX_NATIVE_CALL trace_line(AMX *amx, cell *params) Vector vStart = Vector(fStartX, fStartY, fStartZ); Vector vEnd = Vector(fEndX, fEndY, fEndZ); - - TraceResult tr; - + if (iEnt == -1) - TRACE_LINE(vStart, vEnd, ignore_monsters, NULL, &tr); + TRACE_LINE(vStart, vEnd, ignore_monsters, NULL, &g_tr); else - TRACE_LINE(vStart, vEnd, dont_ignore_monsters, INDEXENT2(iEnt), &tr); + TRACE_LINE(vStart, vEnd, dont_ignore_monsters, INDEXENT2(iEnt), &g_tr); - edict_t *pHit = tr.pHit; + edict_t *pHit = g_tr.pHit; - vRet[0] = amx_ftoc(tr.vecEndPos.x); - vRet[1] = amx_ftoc(tr.vecEndPos.y); - vRet[2] = amx_ftoc(tr.vecEndPos.z); + vRet[0] = amx_ftoc(g_tr.vecEndPos.x); + vRet[1] = amx_ftoc(g_tr.vecEndPos.y); + vRet[2] = amx_ftoc(g_tr.vecEndPos.z); if (FNullEnt(pHit)) return 0; @@ -573,7 +570,6 @@ static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) { int iResult=0; - TraceResult tr; Vector vStart; Vector vEnd; cell *vCell; @@ -594,15 +590,15 @@ static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) else vEnd = vStart; - TRACE_HULL(vStart, vEnd, params[4], params[2], params[3] > 0 ? INDEXENT2(params[3]) : 0, &tr); + TRACE_HULL(vStart, vEnd, params[4], params[2], params[3] > 0 ? INDEXENT2(params[3]) : 0, &g_tr); - if (tr.fStartSolid) { + if (g_tr.fStartSolid) { iResult += 1; } - if (tr.fAllSolid) { + if (g_tr.fAllSolid) { iResult += 2; } - if (!tr.fInOpen) { + if (!g_tr.fInOpen) { iResult += 4; } return iResult; From ee0bcc39f17e78bb28cc31109a5bb0f586bf59c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:10:25 +0200 Subject: [PATCH 07/15] Engine: Clarify difference between the engine module trace handle and the "real" global trace --- plugins/include/engine.inc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index cbe11a5b..8e0fd069 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -25,7 +25,7 @@ #endif /** - * Retrieves a result from the global trace handle. + * Retrieves a result from the global engine module trace handle. * * @note For a list of trace results available see the TR_* constants in * engine_const.inc. @@ -964,8 +964,8 @@ native is_visible(entity, target); * Fires a trace line between two origins, retrieving the end point and entity * hit. * - * @note This native writes to the global trace handle. Additional trace results - * can be retrieved using traceresult(). + * @note This native writes to the global engine module trace handle. Additional + * trace results can be retrieved using traceresult(). * @note This native returns 0 if the trace did not hit anything. As 0 is an * entity index that is considered to be a valid value for a trace hit * ("worldspawn"), this native can potentially return a misleading value. @@ -984,8 +984,8 @@ native trace_line(iIgnoreEnt, const Float:fStart[3], const Float:fEnd[3], Float: /** * Fires a trace line between two origins, retrieving the trace normal. * - * @note This native writes to the global trace handle. Additional trace results - * can be retrieved using traceresult(). + * @note This native writes to the global engine module trace handle. Additional + * trace results can be retrieved using traceresult(). * * @param iIgnoreEnt Entity index that trace will ignore, -1 if trace should * not ignore any entities @@ -1001,8 +1001,8 @@ native trace_normal(iIgnoreEnt, const Float:fStart[3], const Float:fEnd[3], Floa /** * Fires a trace hull on a specified origin or between two origins. * - * @note This native writes to the global trace handle. Additional trace results - * can be retrieved using traceresult(). + * @note This native writes to the global engine module trace handle. Additional + * trace results can be retrieved using traceresult(). * @note For a list of valid hull types see the HULL_* constants in * hlsdk_const.inc * @note For a list of valid ignore types see the *IGNORE_* constants in @@ -1024,7 +1024,8 @@ native trace_hull(const Float:origin[3], hull, ignoredent = 0, ignoremonsters = * direction, offset on the z-axis around an origin. * * @note The functionality of this native can mostly be replaced by a single - * hull trace. This native does not write to the global trace handle. + * hull trace. This native does not write to the global engine module + * trace handle. * @note This native is intended to examine an obstacle in front of a standing * player. Start should usually be the origin of a client while angle * should be its forward angle vector. 73 traces are fired, each offset by From ff0ca9ba6785d58d32a54deee110e622ad619381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:12:07 +0200 Subject: [PATCH 08/15] Engine: Remove inconsistent error path from entity_get_int() --- modules/engine/entity.cpp | 1 - plugins/include/engine.inc | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/engine/entity.cpp b/modules/engine/entity.cpp index a0fc86c8..48e5e642 100644 --- a/modules/engine/entity.cpp +++ b/modules/engine/entity.cpp @@ -609,7 +609,6 @@ static cell AMX_NATIVE_CALL entity_get_int(AMX *amx, cell *params) iRetValue = pEnt->v.deadflag; break; default: - MF_LogError(amx, AMX_ERR_NATIVE, "Invalid property %d", idx); return 0; break; } diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index 8e0fd069..e355dcd4 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -380,8 +380,8 @@ native bool:entity_intersects(entity, other); * @param iKey Entry to retrieve from * * @return Value of specified entry - * @error If an invalid entity index or entry is provided, an error - * will be thrown. + * @error If an invalid entity index is provided, an error will be + * thrown. */ native entity_get_int(iIndex, iKey); From 679714c8be26589e0eed82f550d585744664bcba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:15:06 +0200 Subject: [PATCH 09/15] Engine: Add error path for remove_entity() and unsafe entity ids --- modules/engine/entity.cpp | 8 +++++++- plugins/include/engine.inc | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/engine/entity.cpp b/modules/engine/entity.cpp index 48e5e642..2d572505 100644 --- a/modules/engine/entity.cpp +++ b/modules/engine/entity.cpp @@ -120,11 +120,17 @@ static cell AMX_NATIVE_CALL create_entity(AMX *amx, cell *params) static cell AMX_NATIVE_CALL remove_entity(AMX *amx, cell *params) { int id = params[1]; + if (id >= 0 && id <= gpGlobals->maxClients) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Entity %d can not be removed", id); + return 0; + } + edict_t *pEnt = INDEXENT2(id); if (FNullEnt(pEnt)) return 0; - + REMOVE_ENTITY(pEnt); return 1; diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index e355dcd4..09e2f427 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -621,6 +621,8 @@ native create_entity(const szClassname[]); * * @return 1 if entity was sucessfully removed, 0 if an invalid entity * was provided + * @error If an entity index in the range of 0 to MaxClients is + * provided, an error will be thrown. */ native remove_entity(iIndex); From 702f784e44a932ca29d4b817afcf5834a3893176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:19:26 +0200 Subject: [PATCH 10/15] Engine: Fix get_info_keybuffer() not being able to retrieve local keybuffer --- modules/engine/engine.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index 89f0adde..673d916e 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -367,11 +367,10 @@ static cell AMX_NATIVE_CALL get_info_keybuffer(AMX *amx, cell *params) { int iEnt = params[1]; - CHECK_ENTITY(iEnt); + if (iEnt != -1) + CHECK_ENTITY(iEnt); - edict_t *e = INDEXENT2(iEnt); - - char *info = GETINFOKEYBUFFER(e); + char *info = GETINFOKEYBUFFER((iEnt == -1) ? NULL : INDEXENT2(iEnt)); return MF_SetAmxString(amx, params[2], info, params[3]); } From c24fbda3021444581028224c33e391101bddce64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:24:20 +0200 Subject: [PATCH 11/15] Engine: Add error path to DispatchKeyValue() based on g_inKeyValue This was unsafe as g_pkvd is pointed to a stack variable that is only valid while inside of pfn_keyvalue() --- modules/engine/entity.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/engine/entity.cpp b/modules/engine/entity.cpp index 2d572505..61d19d01 100644 --- a/modules/engine/entity.cpp +++ b/modules/engine/entity.cpp @@ -174,7 +174,13 @@ static cell AMX_NATIVE_CALL DispatchKeyValue(AMX *amx, cell *params) kvd.fHandled = 0; MDLL_KeyValue(pEntity, &kvd); - } else { + } else if (count == 2) { + if (!g_inKeyValue) + { + MF_LogError(amx, AMX_ERR_NATIVE, "DispatchKeyValue() with two arguments can only be used inside of pfn_keyvalue()"); + return 0; + } + int iLength; char *char1 = MF_GetAmxString(amx, params[1], 0, &iLength); char *char2 = MF_GetAmxString(amx, params[2], 1, &iLength); From 7bf47f90d9cbd19c7805e9c65502841a6cda1921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:35:14 +0200 Subject: [PATCH 12/15] Engine: Use UTF-8 functions where KeyValueData is touched --- modules/engine/engine.cpp | 2 +- modules/engine/entity.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index 673d916e..c9e52c60 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -372,7 +372,7 @@ static cell AMX_NATIVE_CALL get_info_keybuffer(AMX *amx, cell *params) char *info = GETINFOKEYBUFFER((iEnt == -1) ? NULL : INDEXENT2(iEnt)); - return MF_SetAmxString(amx, params[2], info, params[3]); + return MF_SetAmxStringUTF8Char(amx, params[2], info, strlen(info), params[3]); } //from jghg, who says it doesn't work diff --git a/modules/engine/entity.cpp b/modules/engine/entity.cpp index 61d19d01..440d8c9f 100644 --- a/modules/engine/entity.cpp +++ b/modules/engine/entity.cpp @@ -200,20 +200,21 @@ static cell AMX_NATIVE_CALL get_keyvalue(AMX *amx, cell *params) edict_t *pEntity = INDEXENT2(idx); int iLength=0; char *char1 = MF_GetAmxString(amx, params[2], 1, &iLength); - return MF_SetAmxString(amx, params[3], INFO_KEY_VALUE(INFO_KEY_BUFFER(pEntity),char1), params[4]); + char *val = INFO_KEY_VALUE(INFO_KEY_BUFFER(pEntity), char1); + return MF_SetAmxStringUTF8Char(amx, params[3], val, strlen(val), params[4]); } static cell AMX_NATIVE_CALL copy_keyvalue(AMX *amx, cell *params) { if (!g_inKeyValue) return 0; - + if (g_pkvd->szClassName) - MF_SetAmxString(amx, params[1], g_pkvd->szClassName, params[2]); + MF_SetAmxStringUTF8Char(amx, params[1], g_pkvd->szClassName, strlen(g_pkvd->szClassName), params[2]); if (g_pkvd->szKeyName) - MF_SetAmxString(amx, params[3], g_pkvd->szKeyName, params[4]); + MF_SetAmxStringUTF8Char(amx, params[3], g_pkvd->szKeyName, strlen(g_pkvd->szKeyName), params[4]); if (g_pkvd->szValue) - MF_SetAmxString(amx, params[5], g_pkvd->szValue, params[6]); + MF_SetAmxStringUTF8Char(amx, params[5], g_pkvd->szValue, strlen(g_pkvd->szValue), params[6]); return 1; } From dc73473394609f614c6e26e18296bb669113aa29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 00:39:17 +0200 Subject: [PATCH 13/15] Engine: Fix CHECK_ENTITY() logic error (0 is not a player) --- modules/engine/engine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/engine/engine.h b/modules/engine/engine.h index 2ea243d8..e48d93bc 100644 --- a/modules/engine/engine.h +++ b/modules/engine/engine.h @@ -204,7 +204,7 @@ void StartFrame_Post(); MF_LogError(amx, AMX_ERR_NATIVE, "Entity out of range (%d)", x); \ return 0; \ } else { \ - if (x <= gpGlobals->maxClients) { \ + if (x > 0 && x <= gpGlobals->maxClients) { \ if (!MF_IsPlayerIngame(x)) { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d (not in-game)", x); \ return 0; \ From 8b6d85eb78d166be1c55c96e8b4db7b64b75a1b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Mon, 11 May 2015 01:09:45 +0200 Subject: [PATCH 14/15] Engine: Add a bunch of missing CHECK_ENTITY() and CHECK_ENTITY_SIMPLE() --- modules/engine/engine.cpp | 15 ++++++++++++++- modules/engine/entity.cpp | 17 +++++++++-------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index c9e52c60..71df442f 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -269,6 +269,7 @@ static cell AMX_NATIVE_CALL PointContents(AMX *amx, cell *params) static cell AMX_NATIVE_CALL trace_normal(AMX *amx, cell *params) { int iEnt = params[1]; + CHECK_ENTITY(iEnt); cell *cStart = MF_GetAmxAddr(amx, params[2]); cell *cEnd = MF_GetAmxAddr(amx, params[3]); @@ -299,6 +300,8 @@ static cell AMX_NATIVE_CALL trace_normal(AMX *amx, cell *params) static cell AMX_NATIVE_CALL trace_line(AMX *amx, cell *params) { int iEnt = params[1]; + if (iEnt != -1) + CHECK_ENTITY(iEnt); cell *cStart = MF_GetAmxAddr(amx, params[2]); cell *cEnd = MF_GetAmxAddr(amx, params[3]); @@ -397,6 +400,7 @@ static cell AMX_NATIVE_CALL attach_view(AMX *amx, cell *params) int iTargetIndex = params[2]; CHECK_ENTITY(iIndex); + CHECK_ENTITY(iTargetIndex); SET_VIEW(INDEXENT2(iIndex), INDEXENT2(iTargetIndex)); @@ -568,6 +572,10 @@ static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { //(mahnsawce) static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) { + int iEnt = params[3]; + if (iEnt > 0) + CHECK_ENTITY(iEnt); + int iResult=0; Vector vStart; Vector vEnd; @@ -589,7 +597,8 @@ static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) else vEnd = vStart; - TRACE_HULL(vStart, vEnd, params[4], params[2], params[3] > 0 ? INDEXENT2(params[3]) : 0, &g_tr); + + TRACE_HULL(vStart, vEnd, params[4], params[2], iEnt > 0 ? INDEXENT2(iEnt) : NULL, &g_tr); if (g_tr.fStartSolid) { iResult += 1; @@ -623,6 +632,7 @@ static cell AMX_NATIVE_CALL playback_event(AMX *amx, cell *params) int bparam1; int bparam2; flags = params[1]; + CHECK_ENTITY(params[2]); pInvoker=INDEXENT2(params[2]); eventindex=params[3]; delay=amx_ctof(params[4]); @@ -940,6 +950,9 @@ static cell AMX_NATIVE_CALL trace_forward(AMX *amx, cell *params) cell *cAngles = MF_GetAmxAddr(amx, params[2]); REAL fGive = amx_ctof(params[3]); int iIgnoreEnt = params[4]; + if (iIgnoreEnt != -1) + CHECK_ENTITY(iIgnoreEnt); + cell *hitX = MF_GetAmxAddr(amx, params[5]); cell *hitY = MF_GetAmxAddr(amx, params[6]); cell *shortestDistance = MF_GetAmxAddr(amx, params[7]); diff --git a/modules/engine/entity.cpp b/modules/engine/entity.cpp index 440d8c9f..4449c145 100644 --- a/modules/engine/entity.cpp +++ b/modules/engine/entity.cpp @@ -120,7 +120,7 @@ static cell AMX_NATIVE_CALL create_entity(AMX *amx, cell *params) static cell AMX_NATIVE_CALL remove_entity(AMX *amx, cell *params) { int id = params[1]; - if (id >= 0 && id <= gpGlobals->maxClients) + if (id <= gpGlobals->maxClients || id > gpGlobals->maxEntities) { MF_LogError(amx, AMX_ERR_NATIVE, "Entity %d can not be removed", id); return 0; @@ -156,11 +156,7 @@ static cell AMX_NATIVE_CALL DispatchKeyValue(AMX *amx, cell *params) cell *cVal = MF_GetAmxAddr(amx, params[1]); int iValue = *cVal; - if (iValue != 0 && (FNullEnt(INDEXENT2(iValue)) || iValue < 0 || iValue > gpGlobals->maxEntities)) - { - MF_LogError(amx, AMX_ERR_NATIVE, "Invalid entity %d", iValue); - return 0; - } + CHECK_ENTITY_SIMPLE(iValue); edict_t *pEntity = INDEXENT2(iValue); KeyValueData kvd; @@ -1342,6 +1338,7 @@ static cell AMX_NATIVE_CALL get_entity_pointer(AMX *amx, cell *params) // get_en static cell AMX_NATIVE_CALL find_ent_in_sphere(AMX *amx, cell *params) { int idx = params[1]; + CHECK_ENTITY_SIMPLE(idx); edict_t *pEnt = INDEXENT2(idx); cell *cAddr = MF_GetAmxAddr(amx, params[2]); @@ -1362,7 +1359,10 @@ static cell AMX_NATIVE_CALL find_ent_in_sphere(AMX *amx, cell *params) static cell AMX_NATIVE_CALL find_ent_by_class(AMX *amx, cell *params) /* 3 param */ { - edict_t *pEnt = INDEXENT2(params[1]); + int idx = params[1]; + CHECK_ENTITY_SIMPLE(idx); + + edict_t *pEnt = INDEXENT2(idx); int len; char* sValue = MF_GetAmxString(amx, params[2], 0, &len); @@ -1498,7 +1498,7 @@ static cell AMX_NATIVE_CALL find_ent_by_owner(AMX *amx, cell *params) // native { int iEnt = params[1]; int oEnt = params[3]; - // Check index to start searching at, 0 must be possible for iEnt. + CHECK_ENTITY_SIMPLE(iEnt); CHECK_ENTITY_SIMPLE(oEnt); edict_t *pEnt = INDEXENT2(iEnt); @@ -1534,6 +1534,7 @@ static cell AMX_NATIVE_CALL get_grenade_id(AMX *amx, cell *params) /* 4 param * int index = params[1]; const char *szModel; + CHECK_ENTITY_SIMPLE(params[4]); CHECK_ENTITY(index); edict_t* pentFind = INDEXENT2(params[4]); From 7059f5b3b980f1e4addfd81054d815a64cc0e3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Gr=C3=BCnbacher?= Date: Thu, 11 Jun 2015 16:08:46 +0200 Subject: [PATCH 15/15] Engine: Detour LightStyle to catch all calls, restores set_lights() functionality --- modules/engine/AMBuilder | 3 ++ modules/engine/Makefile | 5 ++- modules/engine/amxxapi.cpp | 44 +++++++++++++++++--- modules/engine/engine.cpp | 17 +++++--- modules/engine/engine.h | 3 ++ modules/engine/forwards.cpp | 7 ---- modules/engine/moduleconfig.h | 2 +- modules/engine/msvc12/engine.vcxproj | 9 +++- modules/engine/msvc12/engine.vcxproj.filters | 30 +++++++++++++ public/amtl | 2 +- 10 files changed, 99 insertions(+), 23 deletions(-) diff --git a/modules/engine/AMBuilder b/modules/engine/AMBuilder index e94a3797..12715fb0 100644 --- a/modules/engine/AMBuilder +++ b/modules/engine/AMBuilder @@ -14,6 +14,9 @@ binary.sources = [ 'entity.cpp', 'globals.cpp', 'forwards.cpp', + '../../public/memtools/MemoryUtils.cpp', + '../../public/memtools/CDetour/detours.cpp', + '../../public/memtools/CDetour/asm/asm.c', ] if builder.target_platform == 'windows': diff --git a/modules/engine/Makefile b/modules/engine/Makefile index c7044492..1797f04b 100644 --- a/modules/engine/Makefile +++ b/modules/engine/Makefile @@ -30,7 +30,7 @@ CPP_OSX = clang LINK = -INCLUDE = -I. -I$(PUBLIC_ROOT) -I$(PUBLIC_ROOT)/sdk -I$(PUBLIC_ROOT)/amtl \ +INCLUDE = -I. -I$(PUBLIC_ROOT) -I$(PUBLIC_ROOT)/sdk -I$(PUBLIC_ROOT)/memtools -I$(PUBLIC_ROOT)/memtools/CDetour -I$(PUBLIC_ROOT)/memtools/CDetour/asm -I$(PUBLIC_ROOT)/amtl \ -I$(HLSDK) -I$(HLSDK)/public -I$(HLSDK)/common -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared -I$(HLSDK)/pm_shared\ -I$(MM_ROOT) @@ -108,6 +108,9 @@ $(BIN_DIR)/%.o: %.cpp all: mkdir -p $(BIN_DIR) ln -sf $(PUBLIC_ROOT)/sdk/amxxmodule.cpp + ln -sf $(PUBLIC_ROOT)/memtools/MemoryUtils.cpp + ln -sf $(PUBLIC_ROOT)/memtools/CDetour/detours.cpp + ln -sf $(PUBLIC_ROOT)/memtools/CDetour/asm/asm.c $(MAKE) -f $(MAKEFILE_NAME) $(PROJECT) $(PROJECT): $(OBJ_BIN) diff --git a/modules/engine/amxxapi.cpp b/modules/engine/amxxapi.cpp index 259978e2..3be75992 100644 --- a/modules/engine/amxxapi.cpp +++ b/modules/engine/amxxapi.cpp @@ -14,6 +14,10 @@ #include "engine.h" BOOL CheckForPublic(const char *publicname); +void CreateDetours(); +void DestroyDetours(); + +CDetour *LightStyleDetour = NULL; edict_t *g_player_edicts[33]; @@ -58,6 +62,13 @@ void OnAmxxAttach() memset(glinfo.szLastLights, 0x0, 128); memset(glinfo.szRealLights, 0x0, 128); glinfo.bCheckLights = false; + + CreateDetours(); +} + +void OnAmxxDetach() +{ + DestroyDetours(); } void OnPluginsLoaded() @@ -209,7 +220,6 @@ void ServerDeactivate() g_pFunctionTable->pfnThink=NULL; // "pfn_think", "register_think" g_pFunctionTable->pfnStartFrame=NULL; // "server_frame","ServerFrame" g_pFunctionTable->pfnTouch=NULL; // "pfn_touch","vexd_pfntouch" - g_pFunctionTable_Post->pfnStartFrame = NULL; // "set_lights" ClearHooks(); @@ -224,15 +234,27 @@ void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) RETURN_META(MRES_IGNORED); } -void LightStyle_Post(int style, const char *val) { +DETOUR_DECL_STATIC2(LightStyle, void, int, style, const char *, val) // void (*pfnLightStyle) (int style, const char* val); +{ + DETOUR_STATIC_CALL(LightStyle)(style, val); + if (!style && strcmp(val, glinfo.szRealLights)) { memset(glinfo.szRealLights, 0x0, 128); - memcpy(glinfo.szRealLights, val, min(strlen(val), 127)); - - if (glinfo.bCheckLights && strcmp(val, glinfo.szLastLights)) - g_pFunctionTable_Post->pfnStartFrame = StartFrame_Post; + memcpy(glinfo.szRealLights, val, ke::Min(strlen(val), (size_t)127)); } + if (glinfo.bCheckLights && strcmp(val, glinfo.szLastLights)) + g_pFunctionTable_Post->pfnStartFrame = StartFrame_Post; +} + +void StartFrame_Post() +{ + g_pFunctionTable_Post->pfnStartFrame = NULL; + + LightStyleDetour->DisableDetour(); + LIGHT_STYLE(0, glinfo.szLastLights); + LightStyleDetour->EnableDetour(); + RETURN_META(MRES_IGNORED); } @@ -256,3 +278,13 @@ BOOL CheckForPublic(const char *publicname) return FALSE; // no public found in any loaded script } + +void CreateDetours() +{ + LightStyleDetour = DETOUR_CREATE_STATIC_FIXED(LightStyle, (void*)(g_engfuncs.pfnLightStyle)); +} + +void DestroyDetours() +{ + LightStyleDetour->Destroy(); +} \ No newline at end of file diff --git a/modules/engine/engine.cpp b/modules/engine/engine.cpp index 71df442f..666d1f9a 100644 --- a/modules/engine/engine.cpp +++ b/modules/engine/engine.cpp @@ -300,8 +300,9 @@ static cell AMX_NATIVE_CALL trace_normal(AMX *amx, cell *params) static cell AMX_NATIVE_CALL trace_line(AMX *amx, cell *params) { int iEnt = params[1]; - if (iEnt != -1) + if (iEnt != -1) { CHECK_ENTITY(iEnt); + } cell *cStart = MF_GetAmxAddr(amx, params[2]); cell *cEnd = MF_GetAmxAddr(amx, params[3]); @@ -370,8 +371,9 @@ static cell AMX_NATIVE_CALL get_info_keybuffer(AMX *amx, cell *params) { int iEnt = params[1]; - if (iEnt != -1) + if (iEnt != -1) { CHECK_ENTITY(iEnt); + } char *info = GETINFOKEYBUFFER((iEnt == -1) ? NULL : INDEXENT2(iEnt)); @@ -546,7 +548,6 @@ static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { if (FStrEq(szLights, "#OFF")) { glinfo.bCheckLights = false; - g_pFunctionTable_Post->pfnStartFrame = NULL; memset(glinfo.szLastLights, 0x0, 128); LIGHT_STYLE(0, glinfo.szRealLights); return 1; @@ -556,9 +557,11 @@ static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { //Reset LastLights and store custom lighting memset(glinfo.szLastLights, 0x0, 128); - memcpy(glinfo.szLastLights, szLights, min(iLength, 127)); + memcpy(glinfo.szLastLights, szLights, ke::Min(iLength, 127)); + LightStyleDetour->DisableDetour(); LIGHT_STYLE(0, szLights); + LightStyleDetour->EnableDetour(); // These make it so that players/weaponmodels look like whatever the lighting is // at. otherwise it would color players under the skybox to these values. @@ -573,8 +576,9 @@ static cell AMX_NATIVE_CALL set_lights(AMX *amx, cell *params) { static cell AMX_NATIVE_CALL trace_hull(AMX *amx,cell *params) { int iEnt = params[3]; - if (iEnt > 0) + if (iEnt > 0) { CHECK_ENTITY(iEnt); + } int iResult=0; Vector vStart; @@ -950,8 +954,9 @@ static cell AMX_NATIVE_CALL trace_forward(AMX *amx, cell *params) cell *cAngles = MF_GetAmxAddr(amx, params[2]); REAL fGive = amx_ctof(params[3]); int iIgnoreEnt = params[4]; - if (iIgnoreEnt != -1) + if (iIgnoreEnt != -1) { CHECK_ENTITY(iIgnoreEnt); + } cell *hitX = MF_GetAmxAddr(amx, params[5]); cell *hitY = MF_GetAmxAddr(amx, params[6]); diff --git a/modules/engine/engine.h b/modules/engine/engine.h index e48d93bc..1b5337d5 100644 --- a/modules/engine/engine.h +++ b/modules/engine/engine.h @@ -25,6 +25,7 @@ #include "entity_state.h" #include #include +#include "CDetour/detours.h" extern DLL_FUNCTIONS *g_pFunctionTable; extern DLL_FUNCTIONS *g_pFunctionTable_Post; @@ -47,6 +48,8 @@ extern int DispatchUseForward; extern int VexdTouchForward; extern int VexdServerForward; +extern CDetour *LightStyleDetour; + #define AMS_OFFSET 0.01 #define GETINFOKEYBUFFER (*g_engfuncs.pfnGetInfoKeyBuffer) diff --git a/modules/engine/forwards.cpp b/modules/engine/forwards.cpp index 34faf6c4..5c1f3c64 100644 --- a/modules/engine/forwards.cpp +++ b/modules/engine/forwards.cpp @@ -118,13 +118,6 @@ void StartFrame() RETURN_META(MRES_IGNORED); } -void StartFrame_Post() -{ - g_pFunctionTable_Post->pfnStartFrame = NULL; - LIGHT_STYLE(0, glinfo.szLastLights); - RETURN_META(MRES_IGNORED); -} - void CmdStart(const edict_t *player, const struct usercmd_s *_cmd, unsigned int random_seed) { unsigned int i = 0; diff --git a/modules/engine/moduleconfig.h b/modules/engine/moduleconfig.h index 72e5796f..170e03e5 100644 --- a/modules/engine/moduleconfig.h +++ b/modules/engine/moduleconfig.h @@ -389,7 +389,7 @@ // #define FN_ServerExecute_Post ServerExecute_Post // #define FN_engClientCommand_Post engClientCommand_Post // #define FN_ParticleEffect_Post ParticleEffect_Post -#define FN_LightStyle_Post LightStyle_Post +// #define FN_LightStyle_Post LightStyle_Post // #define FN_DecalIndex_Post DecalIndex_Post // #define FN_PointContents_Post PointContents_Post // #define FN_MessageBegin_Post MessageBegin_Post diff --git a/modules/engine/msvc12/engine.vcxproj b/modules/engine/msvc12/engine.vcxproj index 88b4f687..84e647d0 100644 --- a/modules/engine/msvc12/engine.vcxproj +++ b/modules/engine/msvc12/engine.vcxproj @@ -54,7 +54,7 @@ Disabled - ..\;..\..\..\public;..\..\..\public\sdk; ..\..\..\public\amtl\include;..\..\third_party;..\..\third_party\hashing;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) + ..\;..\..\..\public;..\..\..\public\memtools;..\..\..\public\sdk;..\..\..\public\amtl\include;..\..\third_party;..\..\third_party\hashing;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;ENGINE_EXPORTS;HAVE_STDINT_H;%(PreprocessorDefinitions) true EnableFastChecks @@ -98,6 +98,9 @@ + + + @@ -106,6 +109,10 @@ + + + + diff --git a/modules/engine/msvc12/engine.vcxproj.filters b/modules/engine/msvc12/engine.vcxproj.filters index b062f64c..5e439186 100644 --- a/modules/engine/msvc12/engine.vcxproj.filters +++ b/modules/engine/msvc12/engine.vcxproj.filters @@ -18,6 +18,15 @@ {e7f2c5c2-cba9-4712-a576-ceb676c94b36} + + {ca6abf66-eee2-4d06-813e-792d82d6e846} + + + {59354b8c-0925-4d8b-bb2b-684f6638de6b} + + + {6c2c3c74-4dc3-45bf-b3a5-6224971eee69} + @@ -38,6 +47,15 @@ Module SDK\SDK Base + + Memtools + + + Memtools\CDetour + + + Memtools\CDetour\asm + @@ -55,6 +73,18 @@ Module SDK\SDK Base + + Memtools + + + Memtools\CDetour + + + Memtools\CDetour + + + Memtools\CDetour\asm + diff --git a/public/amtl b/public/amtl index 9b1cb728..1bb5196c 160000 --- a/public/amtl +++ b/public/amtl @@ -1 +1 @@ -Subproject commit 9b1cb728c931c0b42a23b96a3c0909470769a72f +Subproject commit 1bb5196ce39ff3ed59445e51f9223734d4bcf886