Dodany przez: shiq, 17:41 20-08-2026

Nowy Pobierz
  1. /*
  2. ================================================================================
  3.  Model Precache Monitor
  4.  --------------------------------------------------------------------------
  5.  Purpose:
  6.    GoldSrc (Half-Life 1.6) has a hard engine limit of 512 precached models
  7.    per map (MAX_MODELS). When a map + its plugins (e.g. BlockMaker) exceed
  8.    this limit, clients get silently disconnected/crashed with NO error
  9.    message anywhere, because the overflow happens in the client's network
  10.    delta-decoding, not in server-side game logic.
  11.  
  12.    This plugin hooks the engine's model precache function, counts every
  13.    model precached on map start, logs each one with its index, and warns
  14.    loudly (server console + log file) if the count approaches or exceeds
  15.    the 512 limit. This gives you hard evidence of which maps are at risk
  16.    and by how much, so you know exactly how many models to cut.
  17.  
  18.  Requirements:
  19.    - AMX Mod X 1.10.x
  20.    - Fakemeta module (ships with AMXX by default)
  21.  
  22.  Author: (generated for user diagnostic use)
  23. ================================================================================
  24. */
  25.  
  26. #include <amxmodx>
  27. #include <amxmisc>
  28. #include <fakemeta>
  29.  
  30. #define PLUGIN_NAME    "Model Precache Monitor"
  31. #define PLUGIN_VERSION "1.0"
  32. #define PLUGIN_AUTHOR  "Diagnostic Tool"
  33.  
  34. // Hard engine limit for GoldSrc. Do not change - this is fixed by the engine.
  35. #define MAX_MODELS_LIMIT   512
  36.  
  37. // Threshold at which we start warning (models remaining gets tight).
  38. #define WARNING_THRESHOLD  480
  39.  
  40. new g_modelCount;
  41. new g_logFile[128];
  42. new g_mapName[64];
  43.  
  44. // Simple growable log of precached model names for this map load.
  45. new g_modelNames[MAX_MODELS_LIMIT + 64][64];
  46.  
  47. public plugin_init()
  48. {
  49.     register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);
  50.  
  51.     register_concmd("model_report", "cmd_model_report", ADMIN_RCON,
  52.         "- prints the current map's precached model count/report to console");
  53. }
  54.  
  55. public plugin_precache()
  56. {
  57.     // Reset counters for the new map load. plugin_precache() runs before
  58.     // other plugins' precache in load order, but since AMXX loads plugins
  59.     // in the order listed in plugins.ini, place this plugin FIRST in
  60.     // plugins.ini so it hooks before BlockMaker precaches its models.
  61.     g_modelCount = 0;
  62.     get_mapname(g_mapName, charsmax(g_mapName));
  63.  
  64.     new dataDir[64];
  65.     formatex(dataDir, charsmax(dataDir), "addons/amxmodx/logs/model_precache");
  66.     // Ensure log directory exists (AMXX will create logs/ itself; this is a subfolder)
  67.     if (!dir_exists(dataDir))
  68.     {
  69.         mkdir(dataDir);
  70.     }
  71.  
  72.     formatex(g_logFile, charsmax(g_logFile), "%s/%s.log", dataDir, g_mapName);
  73.  
  74.     // Start fresh log file for this map load
  75.     new f = fopen(g_logFile, "wt");
  76.     if (f)
  77.     {
  78.         fprintf(f, "=== Model Precache Report for map: %s ===^n", g_mapName);
  79.         fprintf(f, "Engine hard limit: %d models^n^n", MAX_MODELS_LIMIT);
  80.         fclose(f);
  81.     }
  82.  
  83.     // Hook the engine precache_model calls from this point forward.
  84.     // We use a forward on the engine function via fakemeta.
  85.     register_forward(FM_PrecacheModel, "fw_PrecacheModel");
  86. }
  87.  
  88. public fw_PrecacheModel(const model[])
  89. {
  90.     if (g_modelCount >= (MAX_MODELS_LIMIT + 64))
  91.     {
  92.         // Safety bound on our own tracking array, should never realistically hit this.
  93.         return FMRES_IGNORED;
  94.     }
  95.  
  96.     // Avoid double-counting exact duplicate precache calls (engine also
  97.     // de-duplicates internally, but we mirror that so our count matches reality).
  98.     for (new i = 0; i < g_modelCount; i++)
  99.     {
  100.         if (equal(g_modelNames[i], model))
  101.         {
  102.             return FMRES_IGNORED; // already counted, not a new index
  103.         }
  104.     }
  105.  
  106.     copy(g_modelNames[g_modelCount], 63, model);
  107.     g_modelCount++;
  108.  
  109.     new f = fopen(g_logFile, "a");
  110.     if (f)
  111.     {
  112.         fprintf(f, "[%03d] %s^n", g_modelCount, model);
  113.         fclose(f);
  114.     }
  115.  
  116.     if (g_modelCount == WARNING_THRESHOLD)
  117.     {
  118.         log_amx("[Model Precache Monitor] WARNING: Map '%s' has reached %d/%d precached models. Getting close to the engine limit!",
  119.             g_mapName, g_modelCount, MAX_MODELS_LIMIT);
  120.         server_print("[Model Precache Monitor] WARNING: %d/%d models precached on map %s",
  121.             g_modelCount, MAX_MODELS_LIMIT, g_mapName);
  122.     }
  123.  
  124.     if (g_modelCount == MAX_MODELS_LIMIT)
  125.     {
  126.         log_amx("[Model Precache Monitor] CRITICAL: Map '%s' has HIT the %d model limit. Any further precache calls WILL cause client crashes/disconnects.",
  127.             g_mapName, MAX_MODELS_LIMIT);
  128.         server_print("[Model Precache Monitor] CRITICAL: model limit reached on map %s! Clients will start crashing.",
  129.             g_mapName);
  130.     }
  131.  
  132.     return FMRES_IGNORED;
  133. }
  134.  
  135. public cmd_model_report(id, level, cid)
  136. {
  137.     if (!cmd_access(id, level, cid, 1))
  138.         return PLUGIN_HANDLED;
  139.  
  140.     console_print(id, "=== Model Precache Report ===");
  141.     console_print(id, "Map: %s", g_mapName);
  142.     console_print(id, "Total unique models precached: %d / %d", g_modelCount, MAX_MODELS_LIMIT);
  143.     console_print(id, "Remaining headroom: %d", MAX_MODELS_LIMIT - g_modelCount);
  144.     console_print(id, "Full log written to: %s", g_logFile);
  145.  
  146.     if (g_modelCount >= MAX_MODELS_LIMIT)
  147.     {
  148.         console_print(id, "STATUS: OVER LIMIT - this map WILL crash clients.");
  149.     }
  150.     else if (g_modelCount >= WARNING_THRESHOLD)
  151.     {
  152.         console_print(id, "STATUS: WARNING - close to limit, reduce models soon.");
  153.     }
  154.     else
  155.     {
  156.         console_print(id, "STATUS: OK");
  157.     }
  158.  
  159.     return PLUGIN_HANDLED;
  160. }
  161.  

Źródło:

Ostatnie wpisy

Linki

Funkcje