Rev 35 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "VirtualFileSystem.h"#include "File_IO.h"#include "CatFile.h"#include "XspFile.h"namespace SPK {CVirtualFileSystem::CVirtualFileSystem(){m_bLoaded = false;m_pMap = new FileList;m_pModMap = new FileList;m_pTexts = new CTextDB();m_pModTexts = new CTextDB();m_sAddon = "";m_iLang = 0;}CVirtualFileSystem::~CVirtualFileSystem(void){if ( m_pMap ) delete m_pMap;if ( m_pModMap ) delete m_pModMap;if ( m_pTexts ) delete m_pTexts;if ( m_pModTexts ) delete m_pModTexts;}void CVirtualFileSystem::setLanguage(int iLang){m_iLang = iLang;}bool CVirtualFileSystem::LoadFilesystem(const Utils::String &dir, int maxPatch){return this->LoadFilesystem(dir, "", maxPatch);}bool CVirtualFileSystem::LoadFilesystem(const Utils::String &dir, const Utils::String &mod, int maxPatch){m_sDir = dir;this->_clear();int number = 1;while ( CFileIO(CyString(dir) + "/" + CyString::Number(number).PadNumber(2) + ".cat").Exists() ){if ( maxPatch && maxPatch > number ) break;CyString file = CyString(dir) + "/" + CyString::Number(number).PadNumber(2);if ( !CFileIO(file + ".dat").Exists() )break;CCatFile cat;if ( cat.Open(file + ".cat", m_sAddon, CATREAD_JUSTCONTENTS, false) == CATERR_NONE ){for ( CListNode<SInCatFile> *c = cat.GetFiles()->Front(); c; c = c->next() ){(*m_pMap)[CFileIO(c->Data()->sFile).GetFullFilename().ToLower().c_str()] = CyString(file + ".cat").c_str();m_bLoaded = true;}}++number;}// now add all the extracted dataif ( !mod.empty() )this->addMod(mod);return m_bLoaded;}bool CVirtualFileSystem::loadMod(const Utils::String &mod){bool loaded = false;if ( !m_pModMap ) m_pModMap = new FileList;CCatFile cat;if ( CCatFile::Opened(cat.Open(mod, m_sAddon, CATREAD_JUSTCONTENTS, false), false) ){for ( CListNode<SInCatFile> *c = cat.GetFiles()->Front(); c; c = c->next() ){(*m_pModMap)[CFileIO(c->Data()->sFile).GetFullFilename().ToLower().c_str()] = mod.c_str();loaded = true;}}return loaded;}bool CVirtualFileSystem::addMod(const Utils::String &mod){bool loaded = false;if ( !m_pMap ) m_pMap = new FileList;CCatFile cat;if ( CCatFile::Opened(cat.Open(mod, m_sAddon, CATREAD_JUSTCONTENTS, false), false) ){for ( CListNode<SInCatFile> *c = cat.GetFiles()->Front(); c; c = c->next() ){(*m_pMap)[CFileIO(c->Data()->sFile).GetFullFilename().ToLower().c_str()] = mod.c_str();loaded = true;}}return loaded;}bool CVirtualFileSystem::textExists(int iLang, int iPage, int iID) const{if ( m_pTexts ) {if ( m_pTexts->exists(iLang, iPage, iID) ) return m_pTexts->exists(iLang, iPage, iID);}if ( m_pModTexts ) {if ( m_pModTexts->exists(iLang, iPage, iID) ) return m_pModTexts->exists(iLang, iPage, iID);}return false;}Utils::String CVirtualFileSystem::findText(int iLang, int iPage, int iID) const{if ( m_pTexts ) {if ( m_pTexts->exists(iLang, iPage, iID) ) return m_pTexts->get(iLang, iPage, iID);}if ( m_pModTexts ) {if ( m_pModTexts->exists(iLang, iPage, iID) ) return m_pModTexts->get(iLang, iPage, iID);}return Utils::String("ReadText") + (long)iPage + "-" + (long)iID;}Utils::String CVirtualFileSystem::findFile(const Utils::String &file){if ( m_pModMap && !m_pModMap->empty() ) {if ( !m_sAddon.empty() ) {FileListItr aitr = m_pModMap->find(CFileIO(m_sAddon + "/" + file).GetFullFilename().ToLower().c_str());if ( aitr == m_pModMap->end() ) aitr = m_pModMap->find(CFileIO(_convertExtension(m_sAddon + "/" + file)).GetFullFilename().ToLower().c_str());if ( aitr != m_pModMap->end() ) return aitr->second;}FileListItr itr = m_pModMap->find(CFileIO(file).GetFullFilename().ToLower().c_str());if ( itr == m_pModMap->end() ) itr = m_pModMap->find(CFileIO(_convertExtension(file)).GetFullFilename().ToLower().c_str());if ( itr != m_pModMap->end() ) return itr->second;}else if ( m_pMap && !m_pMap->empty() ) {if ( !m_sAddon.empty() ) {FileListItr aitr = m_pMap->find(CFileIO(m_sAddon + "/" + file).GetFullFilename().ToLower().c_str());if ( aitr == m_pMap->end() ) aitr = m_pMap->find(CFileIO(_convertExtension(m_sAddon + "/" + file)).GetFullFilename().ToLower().c_str());if ( aitr != m_pMap->end() ) return aitr->second;}FileListItr itr = m_pMap->find(CFileIO(file).GetFullFilename().ToLower().c_str());if ( itr == m_pMap->end() ) itr = m_pMap->find(CFileIO(_convertExtension(file)).GetFullFilename().ToLower().c_str());if ( itr != m_pMap->end() ) return itr->second;}return "";}bool CVirtualFileSystem::ExtractGameFile(const Utils::String &file, const Utils::String &to){Utils::String sIn = findFile(file);if ( sIn.empty() ) return false;CCatFile catFile;if ( catFile.Open(sIn, m_sAddon, CATREAD_CATDECRYPT, false) == CATERR_NONE ){// check for the fileif ( catFile.ExtractFile(file, to) )return true;if ( catFile.Error() == CATERR_INVALIDDEST || catFile.Error() == CATERR_CANTCREATEDIR ){if ( catFile.ExtractFile(file) )return true;}}return false;}Utils::String CVirtualFileSystem::_convertExtension(const Utils::String &sFile){CFileIO File(sFile);if ( File.CheckFileExtension("pck") ) {return File.ChangeFileExtension("xml").ToString();}else if ( File.CheckFileExtension("xml") ) {return File.ChangeFileExtension("pck").ToString();}else if ( File.CheckFileExtension("pbb") ) {return File.ChangeFileExtension("bob").ToString();}else if ( File.CheckFileExtension("bob") ) {return File.ChangeFileExtension("pbb").ToString();}else if ( File.CheckFileExtension("pbd") ) {return File.ChangeFileExtension("bod").ToString();}else if ( File.CheckFileExtension("bod") ) {return File.ChangeFileExtension("pbd").ToString();}return sFile;}CyStringList *CVirtualFileSystem::GetTShipsEntries(){if ( this->ExtractGameFile("types/tships.pck", "tships.txt") ) {CFileIO TShips("tships.txt");if ( TShips.Exists() ){CyStringList *lines = TShips.ReadLinesStr();if ( lines ){// remove any commands, blank lines, and start// and put the id as the dataint entries = -1;for ( SStringList *str = lines->Head(); str; str = str->next ){str->str.RemoveFirstSpace();str->str.RemoveChar(9);str->str.RemoveChar('\r');str->str.RemoveChar('\n');if ( str->str.Empty() ){str->remove = true;continue;}if ( str->str[0] == '/' ){str->remove = true;continue;}if ( entries == -1 ){entries = str->str.GetToken(";", 2, 2).ToInt();str->remove = true;continue;}// hopefully we now have a valid tships lineint num = -1;while ( str->data.Empty() )str->data = str->str.GetToken(";", num--, (num + 2));}}// remove the tmp fileTShips.Remove();if ( lines )lines->RemoveMarked();return lines;}}return NULL;}C_File *CVirtualFileSystem::extractGameFileToPackage(CBaseFile *pPackage, const Utils::String &sFile, FileType iFileType){return this->extractGameFileToPackage(pPackage, sFile, iFileType, sFile);}C_File *CVirtualFileSystem::extractGameFileToPackage(CBaseFile *pPackage, const Utils::String &sFile, FileType iFileType, const Utils::String &sTo){if ( this->ExtractGameFile(sFile, "tmp") ) {CFileIO File("tmp");C_File *f = pPackage->AddFile(CFileIO(sTo).GetFilename(), CFileIO(sTo).GetDir(), iFileType);if ( f ) {if ( f->ReadFromFile("tmp") ) {File.Remove();return f;}}File.Remove();}return NULL;}Utils::String CVirtualFileSystem::getTShipsEntry(const Utils::String &sId){CyStringList *ships = this->GetTShipsEntries();if ( ships ){SStringList *node = ships->FindData(CyString(sId).upper());if ( node )return node->str.ToString();}return "";}void CVirtualFileSystem::extractTexts(CXspFile *pPackage, int textId){//TODO: check for better finding of files in mapfor ( FileListItr itr = m_pMap->begin(); itr != m_pMap->end(); ++itr ) {Utils::String str = itr->first;if ( !m_sAddon.empty() ) {if ( !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "/t/") && !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "\\t\\") )continue;}else {if ( !str.left(2).Compare("t\\") && !str.left(2).Compare("t/") && !str.left(8).Compare("addon\t\\") && !str.left(8).Compare("addon/t/") )continue;}if ( this->ExtractGameFile(str, "tmp") ) {pPackage->AddTextFromFile("tmp", textId);CFileIO("tmp").Remove();}}}void CVirtualFileSystem::updateTexts(int iFromPage, int iToPage){this->_updateTexts(iFromPage, iToPage, m_pMap, m_pTexts);}void CVirtualFileSystem::updateTexts(int iPage){this->_updateTexts(iPage, iPage, m_pMap, m_pTexts);}void CVirtualFileSystem::updateModTexts(int iFromPage, int iToPage){this->_updateTexts(iFromPage, iToPage, m_pModMap, m_pModTexts);}void CVirtualFileSystem::updateModTexts(int iPage){this->_updateTexts(iPage, iPage, m_pModMap, m_pModTexts);}void CVirtualFileSystem::_clear(){m_bLoaded = false;if ( m_pMap ) delete m_pMap;m_pMap = new FileList;if ( m_pModMap ) delete m_pModMap;m_pModMap = new FileList;}void CVirtualFileSystem::_updateTexts(int iFromPage, int iToPage, FileList *pFileList, CTextDB *pTextList){// read all text filesfor ( FileListItr itr = pFileList->begin(); itr != pFileList->end(); ++itr ) {Utils::String str = itr->first;if ( !m_sAddon.empty() ) {if ( !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "/t/") && !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "\\t\\") )continue;}else {if ( !str.left(2).Compare("t\\") && !str.left(2).Compare("t/") )continue;}if ( this->ExtractGameFile(str, "tmp") ) {// add all texts into the map, id=(pageid, tid) data=textUtils::String baseFile = CFileIO(str).GetBaseName().ToString();int lang = (baseFile.isin("-L")) ? baseFile.right(3) : baseFile.truncate(-4);if ( m_iLang && lang != m_iLang ) continue;// open the text file to addpTextList->parseTextFile(iFromPage, iToPage, "tmp", lang);}}}void CVirtualFileSystem::clearMods(){if ( m_pTexts ) delete m_pTexts;m_pTexts = new CTextDB();if ( m_pModTexts ) delete m_pModTexts;m_pModTexts = new CTextDB();}bool CVirtualFileSystem::loadShipData(CyStringList *list){bool ret = false;if ( this->ExtractGameFile("types/TShips.pck", "tmp") ) {CFileIO File("tmp");CyStringList *lines = File.ReadLinesStr();if ( lines ){bool readFirst = false;for ( SStringList *str = lines->Head(); str; str = str->next ){if ( str->str.Empty() )continue;str->str.RemoveChar('\r');str->str.RemoveChar(9);str->str.RemoveFirstSpace();if ( str->str.Empty() )continue;if ( str->str[0] == '/' || str->str[0] == '#' )continue;if ( !readFirst )readFirst = true;else{CyString t = str->str.GetToken(";", -2);while ( t.Right(1) == ";" )t.Truncate((int)t.Length() - 1);list->PushBack(t, str->str);}}delete lines;ret = true;}File.Remove();}return ret;}} //NAMESPACE