[CS:GO] Uncache all particles & tables [NEW]

qubka

Zombie Plague Разработчик
Сообщения
245
Реакции
244
Так как проблема существовала уже долго: There is a way to cleanup precached assets? - AlliedModders
то это должно решить проблему

Добавлена поддержка Windows, и убраны многие не нужные сигнатуры
PHP:
/**
 * Variables to store SDK calls handlers.
 **/
Handle hSDKCallDestructorParticleDictionary;
Handle hSDKCallContainerFindTable;
Handle hSDKCallTableDeleteAllStrings;

/**
 * Variables to store virtual SDK offsets.
 **/
Address particleSystemDictionary;
Address networkStringTable;
int ParticleSystem_Count;

/**
 * @brief Particles module init function.
 **/
void ParticlesOnInit(/*void*/)
{
    // Starts the preparation of an SDK call
    StartPrepSDKCall(SDKCall_Raw);
    PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Signature, "CParticleSystemDictionary::~CParticleSystemDictionary");
   
    // Validate call
    if((hSDKCallDestructorParticleDictionary = EndPrepSDKCall()) == null)
    {
        // Log failure
        LogEvent(false, LogType_Fatal, LOG_GAME_EVENTS, LogModule_Effects, "GameData Validation", "Failed to load SDK call \"CParticleSystemDictionary::~CParticleSystemDictionary\". Update signature in \"%s\"", PLUGIN_CONFIG);
        return;
    }
   
    /*_________________________________________________________________________________________________________________________________________*/

    // Starts the preparation of an SDK call
    StartPrepSDKCall(SDKCall_Raw);
    PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Virtual, "CNetworkStringTableContainer::FindTable");
   
    // Adds a parameter to the calling convention. This should be called in normal ascending order
    PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
    PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
   
    // Validate call
    if((hSDKCallContainerFindTable = EndPrepSDKCall()) == null)
    {
        // Log failure
        LogEvent(false, LogType_Fatal, LOG_GAME_EVENTS, LogModule_Effects, "GameData Validation", "Failed to load SDK call \"CNetworkStringTableContainer::FindTable\". Update virtual offset in \"%s\"", PLUGIN_CONFIG);
        return;
    }
   
    /*_________________________________________________________________________________________________________________________________________*/

    // Starts the preparation of an SDK call
    StartPrepSDKCall(SDKCall_Raw);
    PrepSDKCall_SetFromConf(gServerData.Config, SDKConf_Signature, "CNetworkStringTable::DeleteAllStrings");
   
    // Validate call
    if((hSDKCallTableDeleteAllStrings = EndPrepSDKCall()) == null)
    {
        // Log failure
        LogEvent(false, LogType_Fatal, LOG_GAME_EVENTS, LogModule_Effects, "GameData Validation", "Failed to load SDK call \"CNetworkStringTable::DeleteAllStrings\". Update signature in \"%s\"", PLUGIN_CONFIG);
        return;
    }
   
    /*_________________________________________________________________________________________________________________________________________*/
   
    // Load other offsets
    fnInitGameConfAddress(gServerData.Config, particleSystemDictionary, "m_pParticleSystemDictionary");
    fnInitGameConfAddress(gServerData.Config, networkStringTable, "s_NetworkStringTable");
    fnInitGameConfOffset(gServerData.Config, ParticleSystem_Count, "CParticleSystemMgr::GetParticleSystemCount");
}

/**
 * @brief Particles module load function.
 **/
void ParticlesOnLoad(/*void*/)
{
    // Initialize buffer char
    static char sBuffer[PLATFORM_LINE_LENGTH];

    // Validate that particles wasn't precache yet
    bool bSave = LockStringTables(false);
    int iCount = LoadFromAddress(particleSystemDictionary + view_as<Address>(ParticleSystem_Count), NumberType_Int16);
    int iTable = SDKCall(hSDKCallContainerFindTable, networkStringTable, "ParticleEffectNames");
    if(!iCount && iTable) /// Validate that table is exist and it empty
    {
        // Opens the file
        File hFile = OpenFile("particles/particles_manifest.txt", "rt", true);
       
        // If doesn't exist stop
        if(hFile == null)
        {
            LogEvent(false, LogType_Fatal, LOG_CORE_EVENTS, LogModule_Effects, "Config Validation", "Error opening file: \"particles/particles_manifest.txt\"");
            return;
        }

        // Read lines in the file
        while(hFile.ReadLine(sBuffer, sizeof(sBuffer)))
        {
            // Checks if string has correct quotes
            int iQuotes = CountCharInString(sBuffer, '"');
            if(iQuotes == 4)
            {
                // Trim string
                TrimString(sBuffer);

                // Copy value string
                strcopy(sBuffer, sizeof(sBuffer), sBuffer[strlen("\"file\"")]);
               
                // Trim string
                TrimString(sBuffer);
               
                // Strips a quote pair off a string 
                StripQuotes(sBuffer);

                // Precache model
                int i; if(sBuffer[i] == '!') i++;
                PrecacheGeneric(sBuffer[i], true);
                SDKCall(hSDKCallTableDeleteAllStrings, iTable); /// HACK~HACK
                /// Clear tables after each file because some of them contains
                /// huge amount of particles and we work around the limit
            }
        }
    }
   
    // Initialize the table index
    static int tableIndex = INVALID_STRING_TABLE;

    // Validate table
    if(tableIndex == INVALID_STRING_TABLE)
    {
        // Searches for a string table
        tableIndex = FindStringTable("ParticleEffectNames");
    }
   
    // If array hasn't been created, then create
    if(gServerData.Particles == null)
    {
        // Initialize a particle list array
        gServerData.Particles = CreateArray(NORMAL_LINE_LENGTH); 

        // i = table string
        iCount = GetStringTableNumStrings(tableIndex);
        for(int i = 0; i < iCount; i++)
        {
            // Gets the string at a given index
            ReadStringTable(tableIndex, i, sBuffer, sizeof(sBuffer));
           
            // Push data into array 
            gServerData.Particles.PushString(sBuffer);
        }
    }
    else
    {
        // i = particle name
        iCount = gServerData.Particles.Length;
        for(int i = 0; i < iCount; i++)
        {
            // Gets the string at a given index
            gServerData.Particles.GetString(i, sBuffer, sizeof(sBuffer));
           
            // Push data into table 
            AddToStringTable(tableIndex, sBuffer);
        }
    }   
    LockStringTables(bSave);
}

/**
 * @brief Particles module purge function.
 **/
void ParticlesOnPurge(/*void*/)
{
    // @link https://github.com/VSES/SourceEngine2007/blob/43a5c90a5ada1e69ca044595383be67f40b33c61/src_main/particles/particles.cpp#L81
    SDKCall(hSDKCallDestructorParticleDictionary, particleSystemDictionary);

    /*_________________________________________________________________________________________________________________________________________*/
   
    /// Clear all particles effect table
    bool bSave = LockStringTables(false);
    int iTable = SDKCall(hSDKCallContainerFindTable, networkStringTable, "ParticleEffectNames");
    if(iTable)   SDKCall(hSDKCallTableDeleteAllStrings, iTable);
    LockStringTables(bSave);
}

PHP:
"Games"
{
    "csgo"
    {
        "Offsets"
        {
            "CParticleSystemMgr::GetParticleSystemCount" // Str: "PrecacheStandardParticleSystems()"
            {
                "windows"   "38"
                "linux"     "38"
            }
        }

        // Sigs from the lib ( https://forums.alliedmods.net/showthread.php?t=309074 )
        // You can update them only by yourself using tutorial in the link
        "Signatures"
        {
            /*
             * Info: Every custom particle precached during a map is not removed from precache table on the map end. 
             *       Then, if a lot of maps that uses custom particles are running in my server the precache table will be filled 
             *       and the custom particles used on the next maps will not show right but erros will appear in their place.
             */
            "CParticleSystemDictionary::~CParticleSystemDictionary" // Str: "CParticleSystemMgr::InitAttributeTable has an out-of-date attribute list! (element %d not set up)\n" | "CParticleSystemMgr::InitAttributeTable" -> "CParticleSystemMgr::CParticleSystemMgr" -> "CParticleSystemMgr::~CParticleSystemMgr" 
            {
                "library"   "server"
                "windows"   "\x55\x8B\xEC\x51\x56\x57\x8B\xF9\x33\xF6\x8B\x47\x58"
                "linux"     "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x7D\x08\x8B\x47\x58\x85\xC0"
            }
            "CParticleSystemDefinition::ParseChildren" // Str: "DmeParticleSystemDefinition" and "children" and "preventNameBasedLookup"
            {
                "library"    "server"
                "windows"   "\x55\x8B\xEC\x83\xEC\x20\x53\x56\x57\x8B\xF9\x51"
                "linux"        "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x45\x0C\xC7\x44\x24\x04"
            }
            "SV_ActivateServer" // Str: "SV_ActivateServer"
            {
                "library"   "engine"
                "windows"   "\x55\x8B\xEC\x83\xE4\xF8\x83\xEC\x0C\x53\x8B\x1D\x2A\x2A\x2A\x2A"
                "linux"     "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xC7\x04\x24\x2A\x2A\x2A\x2A"
            }
            "CNetworkStringTable::DeleteAllStrings" // Str: "___clientsideitemsplaceholder0___"
            {
                "library"   "engine"
                "windows"   "\x56\x8B\xF1\x57\x8B\x4E\x40"
                "linux"     "\x55\x89\xE5\x53\x83\xEC\x14\x8B\x5D\x08\x8B\x43\x40"
            }
        }
       
        // Addr from the lib ( https://forums.alliedmods.net/showthread.php?t=309074 )
        // You can update them only by yourself using tutorial in the link
        "Addresses"
        {
            "m_pParticleSystemDictionary"
            {
                "linux"
                {
                    "signature"     "CParticleSystemDefinition::ParseChildren"
                    "read"          "375"
                    "read"          "0"
                    "read"          "140"
                }
                "windows"
                {
                    "signature"     "CParticleSystemDefinition::ParseChildren"
                    "read"          "401"
                    "read"          "0"
                }
            }
            "s_NetworkStringTable"
            {
                "linux"
                {
                    "signature"     "SV_ActivateServer"
                    "read"          "34"
                    "read"          "0"
                }
                "windows"
                {
                    "signature"     "SV_ActivateServer"
                    "read"          "997"
                    "read"          "0"
                }
            }
        }
    }
}
 
Последнее редактирование:
Сверху Снизу