reapi
reapi copied to clipboard
Add natives to check if resources are precached (model, generic, sound, event) and the pfn engine forwards
Hello. It would be cool if the pfnPrecache forwards could be added to ReAPI. I'm using fakemeta on a plugin to block precaching some game resources (that are taking up precache space but are not used on the map), to avoid the 512 limit. However, fakemeta doesn't detect resources that were precached by external AMXX plugins, and Orpheu is a bit buggy when it comes to hooking engine functions, probably because of the way ReHLDS was compiled. Adding natives to check if those resources are precached would also be cool, SourceMod already have natives for them, for example https://sourcemod.dev/#/halflife/function.IsModelPrecached I need this for an EntMod plugin, where I spawn entities with different keys and values. We can't guess all models precached by a map anyways, and if a player would spawn an entity with an unprecached model, the server would crash. So it would be really cool to have new natives added to check for precache, just as in SourceMod.
Thanks :-)
Here is a plugin with an API:
#include <amxmodx>
#include <fakemeta>
#define PLUGIN "[Precache List]"
#define VERSION "1.0"
#define AUTHOR "Shadows Adi"
enum _:Data
{
Resource[256],
Type
}
enum _:Types
{
TypeModel = 1,
TypeSound,
TypeGeneric
}
new Array:g_aResources
new g_iPrecachedNum[Types]
public plugin_precache()
{
g_aResources = ArrayCreate(Data)
register_forward(FM_PrecacheModel, "fw_PrecacheModel")
register_forward(FM_PrecacheSound, "fw_PrecacheSound")
register_forward(FM_PrecacheGeneric, "fw_PrecacheGeneric")
}
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
}
public plugin_natives()
{
register_native("precache_get_item", "native_get_item")
register_native("precache_get_size", "native_get_size")
}
public fw_PrecacheModel(szModel[])
{
new szTemp[Data]
copy(szTemp[Resource], charsmax(szTemp[Resource]), szModel)
szTemp[Type] = TypeModel
ArrayPushArray(g_aResources, szTemp)
g_iPrecachedNum[TypeModel]++
}
public fw_PrecacheSound(szSound[])
{
new szTemp[Data]
copy(szTemp[Resource], charsmax(szTemp[Resource]), szSound)
szTemp[Type] = TypeSound
ArrayPushArray(g_aResources, szTemp)
g_iPrecachedNum[TypeSound]++
}
public fw_PrecacheGeneric(szResource[])
{
new szTemp[Data]
copy(szTemp[Resource], charsmax(szTemp[Resource]), szResource)
szTemp[Type] = TypeGeneric
ArrayPushArray(g_aResources, szTemp)
g_iPrecachedNum[TypeGeneric]++
}
public plugin_end()
{
ArrayDestroy(g_aResources)
}
// native precache_get_item(iNum, szItem[], iLen, iType)
public native_get_item(iPluginID, iParamNum)
{
if(iParamNum != 4)
{
log_error(AMX_ERR_NATIVE, "%s Incorrect param num. Valid: iNum, szItem[], iLen, iType", PLUGIN)
return -1
}
new szTemp[Data]
new iNum = get_param(1)
new iSize = get_param(3)
new iType = get_param(4)
do
{
ArrayGetArray(g_aResources, iNum, szTemp)
iNum += 1
}
while(iType != szTemp[Type])
set_string(2, szTemp, iSize)
return 1
}
// native precache_get_size(iType)
public native_get_size(iPluginID, iParamNum)
{
return g_iPrecachedNum[get_param(1)]
}
Usage of API:
/* Sublime AMXX Editor v4.2 */
#include <amxmodx>
native precache_get_item(iNum, szItem[], iLen, iType)
native precache_get_size(iType)
enum
{
TypeModel = 1,
TypeSound,
TypeGeneric
}
#define PLUGIN "Test [Precache list]"
#define VERSION "1.0"
#define AUTHOR "Shadows Adi"
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
register_concmd("debugs", "show_precache")
}
public show_precache(id)
{
new iSize = precache_get_size(TypeModel)
new szTemp[256]
for(new i; i < iSize; i++)
{
precache_get_item(i, szTemp, charsmax(szTemp), TypeModel)
log_to_file("debugs.log", "Model: %s", szTemp)
}
iSize = precache_get_size(TypeSound)
for(new i; i < iSize; i++)
{
precache_get_item(i, szTemp, charsmax(szTemp), TypeSound)
log_to_file("debugs.log", "Sound: %s", szTemp)
}
iSize = precache_get_size(TypeGeneric)
for(new i; i < iSize; i++)
{
precache_get_item(i, szTemp, charsmax(szTemp), TypeGeneric)
log_to_file("debugs.log", "Generic: %s", szTemp)
}
}
This can only detect resources precached by the engine, not from external plugins, because it is using Fakemeta. So if I precache something this plugin will not detect it.
Try this one. You have the test plugin above.
#include <amxmodx>
#include <orpheu>
#include <orpheu_stocks>
#include <fakemeta>
#define PLUGIN "[Precache List]"
#define VERSION "1.1"
#define AUTHOR "Shadows Adi"
enum _:Data
{
Resource[256],
Type
}
enum _:Types
{
TypeModel = 1,
TypeSound,
TypeGeneric
}
new Array:g_aResources
new Trie:g_tResources
new g_iPrecachedNum[Types]
public plugin_precache()
{
g_aResources = ArrayCreate(Data)
g_tResources = TrieCreate()
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnPrecacheGeneric", "PrecacheGeneric"), "fw_PrecacheGeneric", OrpheuHookPre)
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnPrecacheModel", "PrecacheModel"), "fw_PrecacheModel", OrpheuHookPre)
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnPrecacheSound", "PrecacheSound"), "fw_PrecacheSound", OrpheuHookPre)
register_forward(FM_PrecacheModel, "fw_PrecacheModel")
register_forward(FM_PrecacheSound, "fw_PrecacheSound")
register_forward(FM_PrecacheGeneric, "fw_PrecacheGeneric")
}
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
}
public plugin_natives()
{
register_native("precache_get_item", "native_get_item")
register_native("precache_get_size", "native_get_size")
}
public fw_PrecacheModel(szModel[])
{
new szTemp[Data]
copy(szTemp[Resource], charsmax(szTemp[Resource]), szModel)
szTemp[Type] = TypeModel
if(!TrieKeyExists(g_tResources, szTemp[Resource]))
{
ArrayPushArray(g_aResources, szTemp)
TrieSetString(g_tResources, szTemp[Resource], szTemp[Type])
g_iPrecachedNum[TypeModel]++
}
}
public fw_PrecacheSound(szSound[])
{
new szTemp[Data]
copy(szTemp[Resource], charsmax(szTemp[Resource]), szSound)
szTemp[Type] = TypeSound
if(!TrieKeyExists(g_tResources, szTemp[Resource]))
{
ArrayPushArray(g_aResources, szTemp)
TrieSetString(g_tResources, szTemp[Resource], szTemp[Type])
g_iPrecachedNum[TypeSound]++
}
}
public fw_PrecacheGeneric(szResource[])
{
new szTemp[Data]
copy(szTemp[Resource], charsmax(szTemp[Resource]), szResource)
szTemp[Type] = TypeGeneric
if(!TrieKeyExists(g_tResources, szTemp[Resource]))
{
ArrayPushArray(g_aResources, szTemp)
TrieSetString(g_tResources, szTemp[Resource], szTemp[Type])
g_iPrecachedNum[TypeGeneric]++
}
}
public plugin_end()
{
ArrayDestroy(g_aResources)
TrieDestroy(g_tResources)
}
// native precache_get_item(iNum, szItem[], iLen, iType)
public native_get_item(iPluginID, iParamNum)
{
if(iParamNum != 4)
{
log_error(AMX_ERR_NATIVE, "%s Incorrect param num. Valid: iNum, szItem[], iLen, iType", PLUGIN)
return -1
}
new szTemp[Data]
new iNum = get_param(1)
new iSize = get_param(3)
new iType = get_param(4)
do
{
ArrayGetArray(g_aResources, iNum, szTemp)
iNum += 1
}
while(iType != szTemp[Type])
set_string(2, szTemp, iSize)
return 1
}
// native precache_get_size(iType)
public native_get_size(iPluginID, iParamNum)
{
return g_iPrecachedNum[get_param(1)]
}
Orpheu functions signatures ( engine version: https://github.com/dreamstalker/rehlds/actions/runs/1838133332 ):
PF_precache_generic_I:
{
"name" : "PF_precache_generic_I",
"library" : "engine",
"arguments" :
[
{
"type" : "char *"
}
],
"identifiers" :
[
{
"os" : "windows",
"value" : [0x55, 0x8B, "*", 0x83, "*", 0x50, 0xA1, 0xC8, 0x53, "*", 0x04, 0x33, 0xC5, 0x89, 0x45, 0xFC]
},
{
"os" : "linux",
"value" : 0x4D5D0
}
]
}
PF_precache_model_I:
{
"name" : "PF_precache_model_I",
"library" : "engine",
"arguments" :
[
{
"type" : "char *"
}
],
"identifiers" :
[
{
"os" : "windows",
"value" : [0x55, 0x8B, "*", 0x53, 0x56, 0x57, 0x8B, 0x7D, 0x08, 0x33, "*", 0x85, "*", 0x0F, 0x84, 0xE3]
},
{
"os" : "linux",
"value" : 0x7B0F0
}
]
}
PF_precache_sound_I:
{
"name" : "PF_precache_sound_I",
"library" : "engine",
"arguments" :
[
{
"type" : "char *"
}
],
"identifiers" :
[
{
"os" : "windows",
"value" : [0x55, 0x8B, "*", 0x56, 0x57, 0x8B, 0x7D, "*", 0x85, "*", 0x0F, 0x84, 0x84]
},
{
"os" : "linux",
"value" : 0x7B3C0
}
]
}
If you're still interested, I've just made this plugin which catches all resources precached: https://github.com/ShadowsAdi/PrecacheList
If you're still interested, I've just made this plugin which catches all resources precached: https://github.com/ShadowsAdi/PrecacheList
Good job