Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / sabrina / sabrina_phrase_description.cpp
blob1e014ca323874160d2bd3c59f176ed98f0ea69a9
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "nel/misc/sstring.h"
21 #include "game_share/egs_sheets/egs_sheets.h"
22 #include "sabrina_phrase_description.h"
23 #include "sabrina_phrase_model_factory.h"
24 #include "sabrina_pointers.h"
25 #include "sabrina_phrase_model.h"
27 /**
28 * CSabrinaStaticPhraseDescriptionManager container class for the static phrase descriptions...
29 * \author Sadge
30 * \author Nevrax France
31 * \date 2003
34 // singleton data
35 std::vector<ISabrinaPhraseDescriptionPtr> CSabrinaStaticPhraseDescriptionManager::_StaticPhrases;
36 bool CSabrinaStaticPhraseDescriptionManager::_Initialised=false;
37 bool CSabrinaStaticPhraseDescriptionManager::_Released=false;
39 // init
40 void CSabrinaStaticPhraseDescriptionManager::init()
42 // make sure we don't try to initialise more than once without releasing in between
43 if(_Initialised && !_Released)
44 return;
45 _Initialised=true;
46 _Released=false;
48 // get a handle to the map of sheet ids to sphrase sheet records
49 CSheets::init();
50 std::vector<NLMISC::CSheetId> phraseSheets;
51 NLMISC::CSheetId::buildIdVector(phraseSheets,"sphrase");
52 nlassert(!phraseSheets.empty());
54 // iterate through the set of sphrases to generate static sabrina phrase description records
55 for (uint32 j=0;j<phraseSheets.size();++j)
57 // extract the sheet id from the map iterator
58 NLMISC::CSheetId sheetId= phraseSheets[j];
60 // make sure the phrase table is big enough to hold the new phrase
61 // NOTE: we do this even if we fail to build the phrase (due to a data bug) as an attempt
62 // to access passed the end of the table can then be classed as a code bug and asserted against.
63 uint32 phraseId= sheetId.getShortId();
64 if (_StaticPhrases.size()<=phraseId)
65 _StaticPhrases.resize(phraseId+1,NULL);
67 // try building the phrase description for the new phrase and record it in our phrase table
68 // note that we use a generic smart pointer as well as a specialised pointer
69 CSabrinaPhraseDescriptionStatic* newPhrase= new CSabrinaPhraseDescriptionStatic(sheetId);
70 ISabrinaPhraseDescriptionPtr newPhrasePtr= newPhrase;
71 if (newPhrase->getPhraseModel()!=NULL)
72 _StaticPhrases[phraseId]=newPhrasePtr;
75 // count the number of empty slots in the phrase table in order to generate an approppriate warning message
76 uint32 count=0;
77 for (uint32 i=_StaticPhrases.size();i--;)
78 if (_StaticPhrases[i]==NULL)
79 ++count;
80 nlinfo("CSabrinaStaticPhraseDescriptionManager::init(): %i of %i static phrases built successfully",
81 _StaticPhrases.size()-count,_StaticPhrases.size());
82 if (count!=0)
83 nlwarning("CSabrinaStaticPhraseDescriptionManager::init(): %i of %i static phrases missing due to missing files or invalid brick lists",
84 count,_StaticPhrases.size());
87 // release
88 void CSabrinaStaticPhraseDescriptionManager::release()
90 // make sure we don't release more than once
91 if (!_Initialised || _Released)
92 return;
93 _Released=true;
95 // we're using smart pointers so the following clears up memory very effectively
96 _StaticPhrases.clear();
99 // getPhrase
100 CSabrinaPhraseDescriptionStatic* CSabrinaStaticPhraseDescriptionManager::getPhrase(NLMISC::CSheetId sheetId)
102 #ifdef NL_DEBUG
103 nlassert(_Initialised);
104 nlassert(!_Released);
105 #endif
107 // make sure the sheet id exists within our vector
108 uint32 phraseId= sheetId.getShortId();
109 if (phraseId>=_StaticPhrases.size())
111 nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Attempt to access past end of phrase vector: %s",
112 sheetId.toString().c_str());
113 #ifdef NL_DEBUG
114 nlstop
115 #endif
116 return NULL;
119 // make sure the phrase was built correctly during the init
120 CSabrinaPhraseDescriptionStatic* thePhrase=NLMISC::safe_cast<CSabrinaPhraseDescriptionStatic*>((ISabrinaPhraseDescription*)_StaticPhrases[phraseId]);
121 if (thePhrase==NULL)
123 nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Attempt to access missing phrase: %s",
124 sheetId.toString().c_str());
125 return NULL;
128 // make sure the sheet id's 'type' matches (typically, the sheetId::Unknown constant will fail here)
129 if (thePhrase->getSheetId()!=sheetId)
131 nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Invalid file type - should be a .sphrase: %s",
132 sheetId.toString().c_str());
133 #ifdef NL_DEBUG
134 nlstop
135 #endif
136 return NULL;
139 // success - return the pointer to our phrase...
140 return thePhrase;
146 * ISabrinaPhraseDescription phrase description base class
147 * \author Sadge
148 * \author Nevrax France
149 * \date 2003
152 ISabrinaPhraseDescription::ISabrinaPhraseDescription()
156 ISabrinaPhraseDescription::ISabrinaPhraseDescription(const ISabrinaPhraseDescription& other)
158 this->_Bricks= other._Bricks;
161 const std::vector<NLMISC::CSheetId>& ISabrinaPhraseDescription::getBricks() const
163 return _Bricks;
166 void ISabrinaPhraseDescription::writeToString(std::string& output) const
168 output+= (getType()==STATIC)? "S": "U";
169 appendToString(output);
172 ISabrinaPhraseDescriptionPtr ISabrinaPhraseDescription::readFromString(std::string& input)
174 ISabrinaPhraseDescriptionPtr result= NULL;
175 switch(CSString(input).strip()[0])
177 case 'S':
178 input=input.substr(1);
179 result= new CSabrinaPhraseDescriptionStatic;
180 if (!result->extractFromString(input))
181 result=NULL;
182 break;
184 case 'U':
185 input=input.substr(1);
186 result= new CSabrinaPhraseDescriptionUser;
187 if (!result->extractFromString(input))
188 result=NULL;
189 break;
191 default:
192 nlwarning("ISabrinaPhraseDescription::readFromString: Failed due to invalid input: '%s'",input.c_str());
193 return NULL;
195 return result;
201 * CSabrinaPhraseDescriptionStatic phrase description base class
202 * \author Sadge
203 * \author Nevrax France
204 * \date 2003
207 // construction
208 CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic()
210 init(NLMISC::CSheetId::Unknown);
212 CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic(NLMISC::CSheetId sheet)
214 init(sheet);
217 CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic(const CSabrinaPhraseDescriptionStatic& other)
219 _Bricks = other._Bricks;
220 _Model = other._Model;
221 _SheetId = other._SheetId;
224 // initialisation of the private data & construction of a sabrina phrase model record
225 void CSabrinaPhraseDescriptionStatic::init(NLMISC::CSheetId sheetId)
227 _SheetId=sheetId;
228 _Model=NULL;
230 // lookup the packed_sheet record for this sheet
231 const CStaticRolemasterPhrase* theSPhrase = CSheets::getSRolemasterPhrase(sheetId);
232 if (theSPhrase==NULL)
234 nlwarning("CSabrinaPhraseDescriptionStatic::init(): Ignoring phrase because not found in packed sheets: %s",
235 sheetId.toString().c_str());
236 return;
239 // try setting up the new phrase record from the brick list in the sphrase...
240 _Model= CSabrinaPhraseModelFactory::newPhraseModel(theSPhrase->Bricks);
242 // if the phrase isn't valid then display a warning
243 if (_Model==NULL)
245 nlwarning("CSabrinaPhraseDescriptionStatic::init(): Ignoring phrase because failed to build phrase model: %s",
246 sheetId.toString().c_str());
250 // specialisation of public methods from parent class
251 CSabrinaPhraseDescriptionStatic::TType CSabrinaPhraseDescriptionStatic::getType() const
253 return STATIC;
256 const std::string& CSabrinaPhraseDescriptionStatic::getName() const
258 return _SheetId.toString();
261 const ISabrinaPhraseModel* CSabrinaPhraseDescriptionStatic::getPhraseModel() const
263 return _Model;
266 NLMISC::CSheetId CSabrinaPhraseDescriptionStatic::getSheetId() const
268 return _SheetId;
271 // specialisation of protected methods from parent class
272 void CSabrinaPhraseDescriptionStatic::appendToString(std::string& output) const
274 output+= '(';
275 output+= _SheetId.toString();
276 output+= ')';
278 bool CSabrinaPhraseDescriptionStatic::extractFromString(std::string& input)
280 // our phrase is built as '('<sheet name>')'
282 // make sure the input begins with a '(' and contains a ')'
283 CSString s=input;
284 if (s.strip()[0]!='(' || !s.contains(")"));
286 nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to invalid input: '%s'",input.c_str());
287 return false;
289 // extract the sub-string between the '(' and ')' and make sure there are no more '('s between the 2
290 s=s.splitFrom('(').splitTo(')').strip();
291 if (s.contains("("))
293 nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to bracket missmatch in input: '%s'",input.c_str());
294 return false;
297 // extract the sheet id and make sure it exists
298 NLMISC::CSheetId sheet= NLMISC::CSheetId(s);
299 if (sheet==NLMISC::CSheetId::Unknown)
301 nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to brick name not found in sheetid.bin: '%s'",s.c_str());
302 return false;
305 // build the phrase description record
306 init(sheet);
308 // remove the parsed segment from the input string and return
309 input=CSString(input).splitFrom(')');
310 return true;
316 * CSabrinaPhraseDescriptionUser
317 * \author Sadge
318 * \author Nevrax France
319 * \date 2003
322 // construction
323 CSabrinaPhraseDescriptionUser::CSabrinaPhraseDescriptionUser()
326 CSabrinaPhraseDescriptionUser::CSabrinaPhraseDescriptionUser(const std::string& name,const std::vector<NLMISC::CSheetId>& bricks)
328 _Name= name;
329 _Bricks= bricks;
332 // specialisation of public methods from parent class
333 CSabrinaPhraseDescriptionUser::TType CSabrinaPhraseDescriptionUser::getType() const
335 return STATIC;
338 const std::string& CSabrinaPhraseDescriptionUser::getName() const
340 return _Name;
343 const ISabrinaPhraseModel* CSabrinaPhraseDescriptionUser::getPhraseModel() const
345 return CSabrinaPhraseModelFactory::newPhraseModel(_Bricks);
348 // specialisation of protected methods from parent class
349 void CSabrinaPhraseDescriptionUser::appendToString(std::string& output) const
351 output+="(";
352 output+=_Name;
353 for (uint32 i=0; i<_Bricks.size();++i)
355 output+=':';
356 output+=_Bricks[i].toString();
358 output+=")";
361 bool CSabrinaPhraseDescriptionUser::extractFromString(std::string& input)
363 // our phrase is built as '(' <phrase name>[':'<brick name>[...]]')'
365 // make sure the input begins with a '(' and contains a ')'
366 CSString s=input;
367 if (s.strip()[0]!='(' || !s.contains(")"));
369 nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to invalid input: '%s'",input.c_str());
370 return false;
372 // extract the sub-string between the '(' and ')' and make sure there are no more '('s between the 2
373 s=s.splitFrom('(').splitTo(')').strip();
374 if (s.contains("("))
376 nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to bracket missmatch in input: '%s'",input.c_str());
377 return false;
380 // extract the phrase name
381 _Name= s.strtok(": \t");
383 // extract the sheet ids
384 bool allSheetIdsOk=true;
385 while (!s.strip().empty())
387 CSString sheetName= s.strtok(": \t");
388 NLMISC::CSheetId sheet= NLMISC::CSheetId(sheetName);
389 if (sheet==NLMISC::CSheetId::Unknown)
391 nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to brick name not found in sheetid.bin: '%s'",sheetName.c_str());
392 allSheetIdsOk= false;
394 _Bricks.push_back(sheet);
397 // remove the parsed segment from the input string and return
398 input=CSString(input).splitFrom(')');
399 return allSheetIdsOk;