Guida [HowTo] Src - Eliminare caricamento item/mob_proto.txt dal core del DB

Stato
Discussione chiusa ad ulteriori risposte.

ErNabbone

Utente Gold
24 Settembre 2008
765
51
121
328
Ultima modifica:

Premessa

Cercavo questa soluzione per una questione personale e, pur avendo cercato, non l'ho trovata qui dunque pensavo fosse giusto condividerla.
Quel che faremo è sostituire la lettura rigo a rigo dai file mob_proto.txt ed item_proto.txt con una lettura diretta via queries MySQL sulle tabelle mob_proto ed item_proto ed eliminare il controllo automatico dell'identità tra i due file di testo nel core del database, e le relative tabelle del database in se. Il tutto in due semplici passi.


Primo Passo

Dirigiamoci nella directory "db/src/" dei nostri file sorgenti preferiti ed apriamo il file "ClientManagerBoot.cpp"; è facilmente deducibile dal nome che questo file è eseguito durante l'avvio del processo relativo alla gestione del database.
Se non avete mai modificato questo file, noterete che, definizioni iniziali a parte, è definito subito un metodo (o funzione) della classe CClientManager di nome InitializeTables().
Questa funzione a sua volta richiama in ordine sparso altre funzioni definite in seguito nel medesimo file.
Le funzioni che c'interessano sono InitializeMobTable() e InitializeItemTable() per il primo passo (successivamente ci interesseremo della chiamata della funzione MirrorMobTableIntoDB() e della gemella MirrorMobTableIntoDB()).

Sostituiamo la funzione InitializeMobTable() con la seguente (fate attenzione alla sintassi, ossia ordine delle parentesi, maiuscole e minuscole, etc ed ovviamente quando mi riferisco alla funzione mi riferisco sia all'intestazione che al il corpo):

Codice:
 CClientManager::InitializeMobTable()
{
    char query[2048];
    fprintf(stderr,"Loading mob_proto from MySQL ");
    snprintf(query, sizeof(query),
            "SELECT vnum,name,%s,rank,type,battle_type,level,size,ai_flag,mount_capacity,setRaceFlag,setImmuneFlag,"
"empire,folder,on_click,st,dx,ht,iq,damage_min,damage_max,max_hp,regen_cycle,regen_percent,gold_min,"
"gold_max,exp,def,attack_speed,move_speed,aggressive_hp_pct,aggressive_sight,attack_range,drop_item,"
"resurrection_vnum,enchant_curse,enchant_slow,enchant_poison,enchant_stun,enchant_critical,enchant_penetrate,"
"resist_sword,resist_twohand,resist_dagger,resist_bell,resist_fan,resist_bow,resist_fire,resist_elect,"
"resist_magic,resist_wind,resist_poison,dam_multiply,summon,drain_sp,mob_color,polymorph_item,skill_level0,"
"skill_vnum0,skill_level1,skill_vnum1,sp_berserk,sp_stoneskin,sp_godspeed,sp_deathblow,sp_revive,skill_level2,"
"skill_vnum2,skill_level3,skill_vnum3,skill_level4,skill_vnum4 FROM mob_proto%s"
,g_stLocaleNameColumn.c_str(),
            GetTablePostfix());

    std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
    SQLResult * pRes = pkMsg->Get();

    if (!pRes->uiNumRows)
        return false;

    if (!m_vec_mobTable.empty())
    {
        sys_log(0, "RELOAD: mob_proto");
        m_vec_mobTable.clear();
    }
    int size = pRes->uiNumRows;
    m_vec_mobTable.resize(size);
    memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size());
    TMobTable * mob_table = &m_vec_mobTable[0];

    MYSQL_ROW data;
    //return true;
    set<int> vnumSet;
    while ((data = mysql_fetch_row(pRes->pSQLResult)))
    {

        /*
        "SELECT vnum,name,locale_name,rank,type,battle_type,level,size,ai_flag,mount_capacity,setRaceFlag,setImmuneFlag,"
"empire,folder,on_click,st,dx,ht,iq,damage_min,damage_max,max_hp,regen_cycle,regen_percent,gold_min,"
"gold_max,exp,def,attack_speed,move_speed,aggressive_hp_pct,aggressive_sight,attack_range,drop_item,"
"resurrection_vnum,enchant_curse,enchant_slow,enchant_poison,enchant_stun,enchant_critical,enchant_penetrate,"
"resist_sword,resist_twohand,resist_dagger,resist_bell,resist_fan,resist_bow,resist_fire,resist_elect,"
"resist_magic,resist_wind,resist_poison,dam_multiply,summon,drain_sp,mob_color,polymorph_item,skill_level0,"
"skill_vnum0,skill_level1,skill_vnum1,sp_berserk,sp_stoneskin,sp_godspeed,sp_deathblow,sp_revive,skill_level2,"
"skill_vnum2,skill_level3,skill_vnum3,skill_level4,skill_vnum4 FROM mob_proto%s */
        int col = 0;
        str_to_number(mob_table->dwVnum, data[col++]);
        if(mob_table->dwVnum ==0) continue;
        strlcpy(mob_table->szName,data[col++] , sizeof(mob_table->szName));
        strlcpy(mob_table->szLocaleName, data[col++], sizeof(mob_table->szLocaleName));
        str_to_number(mob_table->bRank,data[col++]);
        str_to_number(mob_table->bType,data[col++]);
        str_to_number(mob_table->bBattleType,data[col++]);
        str_to_number(mob_table->bLevel,data[col++]);
        str_to_number(mob_table->bSize,data[col++]);
        //AI_FLAG
        mob_table->dwAIFlag = get_Mob_AIFlag_Value(data[col++]);
        //mount_capacity;
        col++;
        //RACE_FLAG
        mob_table->dwRaceFlag = get_Mob_RaceFlag_Value(data[col++]);
        //IMMUNE_FLAG
        mob_table->dwImmuneFlag = get_Mob_ImmuneFlag_Value(data[col++]);
        mob_table->bEmpire = atoi(data[col++]);
        strlcpy(mob_table->szFolder, data[col++], sizeof(mob_table->szFolder));
        mob_table->bOnClickType = atoi(data[col++]);
        mob_table->bStr = atoi(data[col++]);
        mob_table->bDex = atoi(data[col++]);
        mob_table->bCon = atoi(data[col++]);
        mob_table->bInt = atoi(data[col++]);
        mob_table->dwDamageRange[0] = atoi(data[col++]);
        mob_table->dwDamageRange[1] = atoi(data[col++]);
        mob_table->dwMaxHP = atoi(data[col++]);
        mob_table->bRegenCycle = atoi(data[col++]);
        mob_table->bRegenPercent = atoi(data[col++]);
        mob_table->dwGoldMin = atoi(data[col++]);
        mob_table->dwGoldMax = atoi(data[col++]);
        mob_table->dwExp = atoi(data[col++]);
        mob_table->wDef = atoi(data[col++]);
        mob_table->sAttackSpeed = atoi(data[col++]);
        mob_table->sMovingSpeed = atoi(data[col++]);
        mob_table->bAggresiveHPPct = atoi(data[col++]);
        mob_table->wAggressiveSight = atoi(data[col++]);
        mob_table->wAttackRange = atoi(data[col++]);
        str_to_number(mob_table->dwDropItemVnum, data[col++]);    //32
        str_to_number(mob_table->dwResurrectionVnum, data[col++]);
        for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i)
            str_to_number(mob_table->cEnchants[i], data[col++]);

        for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i)
            str_to_number(mob_table->cResists[i], data[col++]);

        str_to_number(mob_table->fDamMultiply, data[col++]);
        str_to_number(mob_table->dwSummonVnum, data[col++]);
        str_to_number(mob_table->dwDrainSP, data[col++]);

        //Mob_Color
        ++col;

        str_to_number(mob_table->dwPolymorphItemVnum, data[col++]);

        str_to_number(mob_table->Skills[0].bLevel, data[col++]);
        str_to_number(mob_table->Skills[0].dwVnum, data[col++]);
        str_to_number(mob_table->Skills[1].bLevel, data[col++]);
        str_to_number(mob_table->Skills[1].dwVnum, data[col++]);
        str_to_number(mob_table->Skills[2].bLevel, data[col++]);
        str_to_number(mob_table->Skills[2].dwVnum, data[col++]);
        str_to_number(mob_table->Skills[3].bLevel, data[col++]);
        str_to_number(mob_table->Skills[3].dwVnum, data[col++]);
        str_to_number(mob_table->Skills[4].bLevel, data[col++]);
        str_to_number(mob_table->Skills[4].dwVnum, data[col++]);

        str_to_number(mob_table->bBerserkPoint, data[col++]);
        str_to_number(mob_table->bStoneSkinPoint, data[col++]);
        str_to_number(mob_table->bGodSpeedPoint, data[col++]);
        str_to_number(mob_table->bDeathBlowPoint, data[col++]);
        str_to_number(mob_table->bRevivePoint, data[col++]);

        //ĽÂżˇ vnum Ăß°ˇ
        vnumSet.insert(mob_table->dwVnum);


        //fprintf(stderr, "MOB #%d %s %s level: %u rank: %u empire: %d\n", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire);
        sys_log(0, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire);
        ++mob_table;
    }
    fprintf(stderr," Complete! %d/%d Mobs loaded.\r\n",size,vnumSet.size());
    sort(m_vec_mobTable.begin(), m_vec_mobTable.end(), FCompareVnum());
    return true;

}

...e sostituite la funzione InitializateMobTable() con quest'altra:

Codice:
boolCClientManager::InitializeItemTable()
{
char query[2048];
fprintf(stderr,"Loading item_proto from MySQL");
snprintf(query,sizeof(query),
"SELECT vnum,name,%s,type,subtype,weight,size,antiflag,flag,wearflag,immuneflag+0,gold,shop_buy_price,refined_vnum,"
"refine_set,magic_pct,limittype0,limitvalue0,limittype1,limitvalue1,applytype0,applyvalue0,"
"applytype1,applyvalue1,applytype2,applyvalue2,value0,value1,value2,value3,value4,value5,socket_pct,addon_type FROM item_proto%s ORDER BY vnum",
g_stLocaleNameColumn.c_str(),
GetTablePostfix());

std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult* pRes = pkMsg->Get();

if(!pRes->uiNumRows)
return false;
int addNumber = pRes->uiNumRows;
if(!m_vec_itemTable.empty())
{
sys_log(0,"RELOAD: item_proto");
m_vec_itemTable.clear();
m_map_itemTableByVnum.clear();
}

m_vec_itemTable.resize(addNumber-1);
memset(&m_vec_itemTable[0],0,sizeof(TItemTable)* m_vec_itemTable.size());
TItemTable* item_table =&m_vec_itemTable[0];

MYSQL_ROW data;
//return true;
set<int> vnumSet;
while((data = mysql_fetch_row(pRes->pSQLResult)))
{
str_to_number(item_table->dwVnum, data[0]);
strlcpy(item_table->szName,data[1],sizeof(item_table->szName));
strlcpy(item_table->szLocaleName, data[2],sizeof(item_table->szLocaleName));
str_to_number(item_table->bType, data[3]);
str_to_number(item_table->bSubType, data[4]);
str_to_number(item_table->bWeight, data[5]);
str_to_number(item_table->bSize, data[6]);
str_to_number(item_table->dwAntiFlags, data[7]);
str_to_number(item_table->dwFlags, data[8]);
str_to_number(item_table->dwWearFlags, data[9]);
str_to_number(item_table->dwImmuneFlag, data[10]);
str_to_number(item_table->dwGold, data[11]);
str_to_number(item_table->dwShopBuyPrice, data[12]);
str_to_number(item_table->dwRefinedVnum, data[13]);
str_to_number(item_table->wRefineSet, data[14]);
str_to_number(item_table->bAlterToMagicItemPct, data[15]);
item_table->cLimitRealTimeFirstUseIndex =-1;
item_table->cLimitTimerBasedOnWearIndex =-1;

str_to_number(item_table->aLimits[0].bType, data[16]);
str_to_number(item_table->aLimits[0].lValue, data[17]);
if(LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[0].bType)
item_table->cLimitRealTimeFirstUseIndex =(char)0;
if(LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[0].bType)
item_table->cLimitTimerBasedOnWearIndex =(char)0;

str_to_number(item_table->aLimits[1].bType, data[18]);
str_to_number(item_table->aLimits[1].lValue, data[19]);
if(LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[1].bType)
item_table->cLimitRealTimeFirstUseIndex =(char)1;
if(LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[1].bType)
item_table->cLimitTimerBasedOnWearIndex =(char)1;


str_to_number(item_table->aApplies[0].bType, data[20]);
str_to_number(item_table->aApplies[0].lValue, data[21]);

str_to_number(item_table->aApplies[1].bType, data[22]);
str_to_number(item_table->aApplies[1].lValue, data[23]);

str_to_number(item_table->aApplies[2].bType, data[24]);
str_to_number(item_table->aApplies[2].lValue, data[25]);


str_to_number(item_table->alValues[0], data[26]);
str_to_number(item_table->alValues[1], data[27]);
str_to_number(item_table->alValues[2], data[28]);
str_to_number(item_table->alValues[3], data[29]);
str_to_number(item_table->alValues[4], data[30]);
str_to_number(item_table->alValues[5], data[31]);

str_to_number(item_table->bGainSocketPct, data[32]);
str_to_number(item_table->sAddonType, data[33]);


vnumSet.insert(item_table->dwVnum);
m_map_itemTableByVnum.insert(std::map<DWORD,TItemTable*>::value_type(item_table->dwVnum, item_table));
sys_log(0,"ITEM: #%-5lu %-24s %-24s VAL: %d %ld %d %d %d %d WEAR %d ANTI %d IMMUNE %d REFINE %lu REFINE_SET %u MAGIC_PCT %u",
item_table->dwVnum,
item_table->szName,
item_table->szLocaleName,
item_table->alValues[0],
item_table->alValues[1],
item_table->alValues[2],
item_table->alValues[3],
item_table->alValues[4],
item_table->alValues[5],
item_table->dwWearFlags,
item_table->dwAntiFlags,
item_table->dwImmuneFlag,
item_table->dwRefinedVnum,
item_table->wRefineSet,
item_table->bAlterToMagicItemPct);

item_table++;
}
fprintf(stderr," Complete! %d Items loaded.\r\n",addNumber);
return true;

}


Secondo (e ultimo) Passo

Una volta fatto ciò, siamo già all'80% del lavoro. L'ultima cosa che resta fare, per quanto banale, è davvero importante in quanto essenziale affinché il core del DB non ricerchii file che stiamo cercando di non dover più usare.

Parlo delle funzioni Mirror(Mob || Item)IntoDB() che verificano appunto l'autenticità delle informazioni ottenute dalle funzioni Initialize(Mob || Item)Table().

Per evitare questo, basta eliminare o commentare le parti di codice sottolineate di seguente (per chi non l'avesse capito, stiamo ancora modificando lo stesso file "ClientManagerBoot.cpp"):

## Codice (inizio): ##

if (!InitializeMobTable())
{
sys_err("InitializeMobTable FAILED");
return false;
}

if (!MirrorMobTableIntoDB())
{
sys_err("MirrorMobTableIntoDB FAILED");
return false;
}


if (!InitializeItemTable())
{
sys_err("InitializeItemTable FAILED");
return false;
}

if (!MirrorItemTableIntoDB())

{
sys_err("MirrorItemTableIntoDB FAILED");
return false;
}


## Codice (fine) ##

Tutto fatto, ricompilate il db come di consueto, sostituite il nuovo bin con il vecchio, eliminate i fastidiosi (ed inutili) ".txt" e testate ;)


Conclusione e Fonti

Spero di aver spiegato tutto in maniera semplice e comprensibile e che questa guida possa esservi utile.
Ci tengo a specificare che le funzioni C++ CClientManager::InitializeItemTable() e CClientManager::InitializeMobTable() non sono state programmate da me ma trovate sul web, anche se è evidente che siano un riadattamento di altre funzioni che si possono trovare sempre nello stesso file come InitializateSkillTable() ed altre.
Guida in italiano e spiegazioni interamente opera mia (non ho fatto una traduzione).
La guida è "pubblica" e rispetta le norme di licenza per i prodotti come da T&C della piattaforma in uso ed è altresì regolata dalla medesima norma. È autorizzata la copia ed il riutilizzo a fini non commerciali previa citazione del sottoscritto.

Ricordo, per concludere, che è d'obbligo fare sempre un back-up dei propri files prima di ogni modifica se non si vuole rischiare di danneggiarli o perderli e che la responsabilità di ogni uso/modifica che vi apportate è solo vostra.



Sono a piena disposizione per critiche, chiarimenti e domande.
Saluti da @ErNabbone
 
  • Mi piace
Reazioni: Hik
Stato
Discussione chiusa ad ulteriori risposte.