8 Správa zdrojů
8.1 Společné metody
Resource Manager (správce zdrojů) slouží k přípravě a následném úklidu všech používaných externích dat. Načítané XML soubory převádí do struktur, řeší problémy spojené s neexistencí souborů nebo jejich částí. Nakonec se pak stará o dealokaci paměti, kterou tyto data v paměti zabíraly.
Společný předek všech RM je třída TRM. Zde jsou implementovány všechny hlavní operace, které lze se všemi RM provádět.
První z nich je načítání dat. To může probíhat přímo pomocí metody loadData - uživatel zadá, které data chce načíst a RM je vzápětí načte. Druhý a používaný způsob využívá frontu požadavků, do které se v první částí vkládají požadavky (request) které zdroje načíst a ty jsou načteny až ve chvíli kdy uživatel dá příkaz - tj. ve chvíli kdy zavolá (loadBuffer). Některé RM mají navíc requestDep, které přidá požadavek na načtení nejen na samotné data, ale i všechna data, které využívá. Například jednotka využívá kromě vlastních dat o jednotce (její síle, rychlosti apod.) také i např. model a zvuky. Pomocí této metody se načtou i všechny tyto data - požadavky se přidávají rekurzivně - dokud nějaký RM vyžaduje data z jiného RM, jsou požadavky přidávány. Je zřejmé, že by zde hrozilo zacyklení, v případě, že by závislosti byly uspořádány do kruhu, logika závislostí však takovouto věc vylučuje.
Druhá operace je práce se skupinami. Načteným datům se přiřadí číslo skupiny, ve které se nachází, a v případě, že se zdroje z jedné skupiny přestanou používat, lze je jednoduše z paměti odstranit.
Ve chvíli, kdy jsou data načtena, mohou být kladeny požadavky na jejich získání. To se typicky provádí metodou get.
8.2 Interface
Každý typ je v aplikaci právě jednou. Pomocí zámků z knihovny SDL předchází možným konfliktům mezi jednotlivými vlákny. Uživatel však nepracuje přímo s RM, nýbrž s interfacem k těmto RM. Každý RM má k dispozici svůj vlastní interface, přes který s uživatelem komunikuje.
Interface do jisté míry někdy upravuje výstupy z RM, jeho hlavní výhoda je však ta, že lze v aplikaci vytvořit libovolné množství instancí. Dokonce je možné, že i v jednom vlákně se inicializuje více interfaců ke stejnému RM. Práce uživatele pak probíhá tak, že ve chvíli kdy chce pracovat s nějakými daty, vytvoří si vlastní interface a zruší ho až ve chvíli, kdy k datům nebude přistupovat.
RM lze rozdělit do dvou druhů podle toho kolik dat má v jednu chvíli načtených. První typ (např. pro jednotky, modely, obrázky) je připraven uchovávat různé množství dat, druhý typ (mapa, jazyk) má k dispozici pouze jedny aktuální data, neboť ke změně dochází velmi zřídka a paměť, kterou dané data zabírají je nemalá.
8.3 Jednotlivé typy
Prvním RM, který se inicializuje je RM_conf - RM pro různé konfigurační soubory. Udržuje informace o nastaveních uživatele, profily (uživatelské účty ve hře) a jména indexových souborů pro ostatní RM. Interface k tomuto RM je součástí konstruktorů ostatních RM - sloužící nejen k určení pozice příslušného indexového souboru.
RM_txt uchovává všechny texty a hlášky, které se v aplikaci objeví. Zvláštností tohoto RM je fakt, že v každé chvíli musí být načtena právě jedna jazyková sada. Je to z důvodu, že i ke změně jazykové sady je potřeba zobrazit externímu uživateli (hráči) nějaký dialog, jehož textová část se získává z RM.
Dále existuje RM na rastrové obrázky RM_raster. Aplikace využívá dvou typů těchto souborů - bmp a dokáže načíst i "průhledný" obrázek uložený ve formátu tga. Načítání bmp souborů je zajišťováno přes funkce knihovny SDL, načítání tga souborů se provádí pomocí vlastní funkce LoadTGA.
RM_model slouží k nahrávání modelů a animací pohybu, útoku a úmrtí.
RM_sound pomocí knihovny SDL_mixer načítá a zvukové efekty a hudbu. Práce s tímto RM je stejná jako s jinými až na práci s hudbou. SDL_mixer nedovoluje (před)načíst do paměti více než jednu hudební skladbu a tedy je nutné volat metodu loadSound() při každé změně hudby.
RM_xml pak slouží k načítání XML souborů obsahující TCL skripty a informace a terénech.
TRM_advxml je šablona a podle typu slouží jako RM na jednotky, budovy, kouzla a bonusy. Jelikož se tyto tři typy dat příliš neliší, bylo možné toto sjednocení provést.
Posledním avšak stejně důležitým RM je RM_map. Ten se stará o načítání, vytváření a ukládání map. V RM_map je načtena vždy nejvýše jedna mapa. Odlišností je také neexistence indexového souboru map. Seznam všech map se vždy získá z aktuálního obsahu adresářů res/xml/maps a savegame. To přináší externím uživatelům možnost jednoduše vytvářet a sdílet mapy.
Na druhou stranu je nutné počítat s tím, že index aktuálně načtené mapy se může měnit aniž by došlo k manipulaci s mapou, v závislosti na přidávání nebo mazání souborů v těchto adresářích. Další odlišností je, že data jsou z XML souborů map transformovány do různých struktur, zatímco u ostatních RM jsou data transformovány do jedné konkrétní struktury. Důvodem k tomu je prezence zcela různých typů informací v mapě. Poslední netypičnost tohoto RM spočívá v tom, že k data obsažená v něm nejsou během hry pouze ke čtení, ale dochází i k jejich změně. Kvůli ušetření potřebné operační paměti je při dotazu na data poskytnut odkaz na již připravenou paměť, avšak RM_map si zároveň poznačí, že s daty právě někdo manipuluje a dokud mu nejsou vráceny, nelze je od něj opět získat.
8.4 Inicializace
Inicializace modulu RM se provede zavoláním funkce RMInit, zrušení pak pomocí funkce RMDestroy. O interface k jednotlivým RM se pak žádá pomocí zpráv MSG_GET_RM_TXT_I, MSG_GET_RM_CONF_I, MSG_GET_RM_RASTER_I, MSG_GET_RM_SYMBOL_I, MSG_GET_RM_MODEL_I, MSG_GET_RM_XML_I, MSG_GET_RM_UNIT_I, MSG_GET_RM_BUILDING_I, MSG_GET_RM_SPELL_I, MSG_GET_RM_MAP_I a MSG_GET_RM_SOUND_I. Každý interface se následně ruší voláním delete().