// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "nel/misc/sstring.h" #include "game_share/egs_sheets/egs_sheets.h" #include "sabrina_phrase_description.h" #include "sabrina_phrase_model_factory.h" #include "sabrina_pointers.h" #include "sabrina_phrase_model.h" /** * CSabrinaStaticPhraseDescriptionManager container class for the static phrase descriptions... * \author Sadge * \author Nevrax France * \date 2003 */ // singleton data std::vector CSabrinaStaticPhraseDescriptionManager::_StaticPhrases; bool CSabrinaStaticPhraseDescriptionManager::_Initialised=false; bool CSabrinaStaticPhraseDescriptionManager::_Released=false; // init void CSabrinaStaticPhraseDescriptionManager::init() { // make sure we don't try to initialise more than once without releasing in between if(_Initialised && !_Released) return; _Initialised=true; _Released=false; // get a handle to the map of sheet ids to sphrase sheet records CSheets::init(); std::vector phraseSheets; NLMISC::CSheetId::buildIdVector(phraseSheets,"sphrase"); nlassert(!phraseSheets.empty()); // iterate through the set of sphrases to generate static sabrina phrase description records for (uint32 j=0;jgetPhraseModel()!=NULL) _StaticPhrases[phraseId]=newPhrasePtr; } // count the number of empty slots in the phrase table in order to generate an approppriate warning message uint32 count=0; for (uint32 i=_StaticPhrases.size();i--;) if (_StaticPhrases[i]==NULL) ++count; nlinfo("CSabrinaStaticPhraseDescriptionManager::init(): %i of %i static phrases built successfully", _StaticPhrases.size()-count,_StaticPhrases.size()); if (count!=0) nlwarning("CSabrinaStaticPhraseDescriptionManager::init(): %i of %i static phrases missing due to missing files or invalid brick lists", count,_StaticPhrases.size()); } // release void CSabrinaStaticPhraseDescriptionManager::release() { // make sure we don't release more than once if (!_Initialised || _Released) return; _Released=true; // we're using smart pointers so the following clears up memory very effectively _StaticPhrases.clear(); } // getPhrase CSabrinaPhraseDescriptionStatic* CSabrinaStaticPhraseDescriptionManager::getPhrase(NLMISC::CSheetId sheetId) { #ifdef NL_DEBUG nlassert(_Initialised); nlassert(!_Released); #endif // make sure the sheet id exists within our vector uint32 phraseId= sheetId.getShortId(); if (phraseId>=_StaticPhrases.size()) { nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Attempt to access past end of phrase vector: %s", sheetId.toString().c_str()); #ifdef NL_DEBUG nlstop #endif return NULL; } // make sure the phrase was built correctly during the init CSabrinaPhraseDescriptionStatic* thePhrase=NLMISC::safe_cast((ISabrinaPhraseDescription*)_StaticPhrases[phraseId]); if (thePhrase==NULL) { nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Attempt to access missing phrase: %s", sheetId.toString().c_str()); return NULL; } // make sure the sheet id's 'type' matches (typically, the sheetId::Unknown constant will fail here) if (thePhrase->getSheetId()!=sheetId) { nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Invalid file type - should be a .sphrase: %s", sheetId.toString().c_str()); #ifdef NL_DEBUG nlstop #endif return NULL; } // success - return the pointer to our phrase... return thePhrase; } /** * ISabrinaPhraseDescription phrase description base class * \author Sadge * \author Nevrax France * \date 2003 */ ISabrinaPhraseDescription::ISabrinaPhraseDescription() { } ISabrinaPhraseDescription::ISabrinaPhraseDescription(const ISabrinaPhraseDescription& other) { this->_Bricks= other._Bricks; } const std::vector& ISabrinaPhraseDescription::getBricks() const { return _Bricks; } void ISabrinaPhraseDescription::writeToString(std::string& output) const { output+= (getType()==STATIC)? "S": "U"; appendToString(output); } ISabrinaPhraseDescriptionPtr ISabrinaPhraseDescription::readFromString(std::string& input) { ISabrinaPhraseDescriptionPtr result= NULL; switch(CSString(input).strip()[0]) { case 'S': input=input.substr(1); result= new CSabrinaPhraseDescriptionStatic; if (!result->extractFromString(input)) result=NULL; break; case 'U': input=input.substr(1); result= new CSabrinaPhraseDescriptionUser; if (!result->extractFromString(input)) result=NULL; break; default: nlwarning("ISabrinaPhraseDescription::readFromString: Failed due to invalid input: '%s'",input.c_str()); return NULL; } return result; } /** * CSabrinaPhraseDescriptionStatic phrase description base class * \author Sadge * \author Nevrax France * \date 2003 */ // construction CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic() { init(NLMISC::CSheetId::Unknown); } CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic(NLMISC::CSheetId sheet) { init(sheet); } CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic(const CSabrinaPhraseDescriptionStatic& other) { _Bricks = other._Bricks; _Model = other._Model; _SheetId = other._SheetId; } // initialisation of the private data & construction of a sabrina phrase model record void CSabrinaPhraseDescriptionStatic::init(NLMISC::CSheetId sheetId) { _SheetId=sheetId; _Model=NULL; // lookup the packed_sheet record for this sheet const CStaticRolemasterPhrase* theSPhrase = CSheets::getSRolemasterPhrase(sheetId); if (theSPhrase==NULL) { nlwarning("CSabrinaPhraseDescriptionStatic::init(): Ignoring phrase because not found in packed sheets: %s", sheetId.toString().c_str()); return; } // try setting up the new phrase record from the brick list in the sphrase... _Model= CSabrinaPhraseModelFactory::newPhraseModel(theSPhrase->Bricks); // if the phrase isn't valid then display a warning if (_Model==NULL) { nlwarning("CSabrinaPhraseDescriptionStatic::init(): Ignoring phrase because failed to build phrase model: %s", sheetId.toString().c_str()); } } // specialisation of public methods from parent class CSabrinaPhraseDescriptionStatic::TType CSabrinaPhraseDescriptionStatic::getType() const { return STATIC; } const std::string& CSabrinaPhraseDescriptionStatic::getName() const { return _SheetId.toString(); } const ISabrinaPhraseModel* CSabrinaPhraseDescriptionStatic::getPhraseModel() const { return _Model; } NLMISC::CSheetId CSabrinaPhraseDescriptionStatic::getSheetId() const { return _SheetId; } // specialisation of protected methods from parent class void CSabrinaPhraseDescriptionStatic::appendToString(std::string& output) const { output+= '('; output+= _SheetId.toString(); output+= ')'; } bool CSabrinaPhraseDescriptionStatic::extractFromString(std::string& input) { // our phrase is built as '('')' // make sure the input begins with a '(' and contains a ')' CSString s=input; if (s.strip()[0]!='(' || !s.contains(")")); { nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to invalid input: '%s'",input.c_str()); return false; } // extract the sub-string between the '(' and ')' and make sure there are no more '('s between the 2 s=s.splitFrom('(').splitTo(')').strip(); if (s.contains("(")) { nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to bracket missmatch in input: '%s'",input.c_str()); return false; } // extract the sheet id and make sure it exists NLMISC::CSheetId sheet= NLMISC::CSheetId(s); if (sheet==NLMISC::CSheetId::Unknown) { nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to brick name not found in sheetid.bin: '%s'",s.c_str()); return false; } // build the phrase description record init(sheet); // remove the parsed segment from the input string and return input=CSString(input).splitFrom(')'); return true; } /** * CSabrinaPhraseDescriptionUser * \author Sadge * \author Nevrax France * \date 2003 */ // construction CSabrinaPhraseDescriptionUser::CSabrinaPhraseDescriptionUser() { } CSabrinaPhraseDescriptionUser::CSabrinaPhraseDescriptionUser(const std::string& name,const std::vector& bricks) { _Name= name; _Bricks= bricks; } // specialisation of public methods from parent class CSabrinaPhraseDescriptionUser::TType CSabrinaPhraseDescriptionUser::getType() const { return STATIC; } const std::string& CSabrinaPhraseDescriptionUser::getName() const { return _Name; } const ISabrinaPhraseModel* CSabrinaPhraseDescriptionUser::getPhraseModel() const { return CSabrinaPhraseModelFactory::newPhraseModel(_Bricks); } // specialisation of protected methods from parent class void CSabrinaPhraseDescriptionUser::appendToString(std::string& output) const { output+="("; output+=_Name; for (uint32 i=0; i<_Bricks.size();++i) { output+=':'; output+=_Bricks[i].toString(); } output+=")"; } bool CSabrinaPhraseDescriptionUser::extractFromString(std::string& input) { // our phrase is built as '(' [':'[...]]')' // make sure the input begins with a '(' and contains a ')' CSString s=input; if (s.strip()[0]!='(' || !s.contains(")")); { nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to invalid input: '%s'",input.c_str()); return false; } // extract the sub-string between the '(' and ')' and make sure there are no more '('s between the 2 s=s.splitFrom('(').splitTo(')').strip(); if (s.contains("(")) { nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to bracket missmatch in input: '%s'",input.c_str()); return false; } // extract the phrase name _Name= s.strtok(": \t"); // extract the sheet ids bool allSheetIdsOk=true; while (!s.strip().empty()) { CSString sheetName= s.strtok(": \t"); NLMISC::CSheetId sheet= NLMISC::CSheetId(sheetName); if (sheet==NLMISC::CSheetId::Unknown) { nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to brick name not found in sheetid.bin: '%s'",sheetName.c_str()); allSheetIdsOk= false; } _Bricks.push_back(sheet); } // remove the parsed segment from the input string and return input=CSString(input).splitFrom(')'); return allSheetIdsOk; }