1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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"
28 * CSabrinaStaticPhraseDescriptionManager container class for the static phrase descriptions...
30 * \author Nevrax France
35 std::vector
<ISabrinaPhraseDescriptionPtr
> CSabrinaStaticPhraseDescriptionManager::_StaticPhrases
;
36 bool CSabrinaStaticPhraseDescriptionManager::_Initialised
=false;
37 bool CSabrinaStaticPhraseDescriptionManager::_Released
=false;
40 void CSabrinaStaticPhraseDescriptionManager::init()
42 // make sure we don't try to initialise more than once without releasing in between
43 if(_Initialised
&& !_Released
)
48 // get a handle to the map of sheet ids to sphrase sheet records
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
77 for (uint32 i
=_StaticPhrases
.size();i
--;)
78 if (_StaticPhrases
[i
]==NULL
)
80 nlinfo("CSabrinaStaticPhraseDescriptionManager::init(): %i of %i static phrases built successfully",
81 _StaticPhrases
.size()-count
,_StaticPhrases
.size());
83 nlwarning("CSabrinaStaticPhraseDescriptionManager::init(): %i of %i static phrases missing due to missing files or invalid brick lists",
84 count
,_StaticPhrases
.size());
88 void CSabrinaStaticPhraseDescriptionManager::release()
90 // make sure we don't release more than once
91 if (!_Initialised
|| _Released
)
95 // we're using smart pointers so the following clears up memory very effectively
96 _StaticPhrases
.clear();
100 CSabrinaPhraseDescriptionStatic
* CSabrinaStaticPhraseDescriptionManager::getPhrase(NLMISC::CSheetId sheetId
)
103 nlassert(_Initialised
);
104 nlassert(!_Released
);
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());
119 // make sure the phrase was built correctly during the init
120 CSabrinaPhraseDescriptionStatic
* thePhrase
=NLMISC::safe_cast
<CSabrinaPhraseDescriptionStatic
*>((ISabrinaPhraseDescription
*)_StaticPhrases
[phraseId
]);
123 nlwarning("CSabrinaStaticPhraseDescriptionManager::getPhrase(): Attempt to access missing phrase: %s",
124 sheetId
.toString().c_str());
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());
139 // success - return the pointer to our phrase...
146 * ISabrinaPhraseDescription phrase description base class
148 * \author Nevrax France
152 ISabrinaPhraseDescription::ISabrinaPhraseDescription()
156 ISabrinaPhraseDescription::ISabrinaPhraseDescription(const ISabrinaPhraseDescription
& other
)
158 this->_Bricks
= other
._Bricks
;
161 const std::vector
<NLMISC::CSheetId
>& ISabrinaPhraseDescription::getBricks() const
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])
178 input
=input
.substr(1);
179 result
= new CSabrinaPhraseDescriptionStatic
;
180 if (!result
->extractFromString(input
))
185 input
=input
.substr(1);
186 result
= new CSabrinaPhraseDescriptionUser
;
187 if (!result
->extractFromString(input
))
192 nlwarning("ISabrinaPhraseDescription::readFromString: Failed due to invalid input: '%s'",input
.c_str());
201 * CSabrinaPhraseDescriptionStatic phrase description base class
203 * \author Nevrax France
208 CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic()
210 init(NLMISC::CSheetId::Unknown
);
212 CSabrinaPhraseDescriptionStatic::CSabrinaPhraseDescriptionStatic(NLMISC::CSheetId 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
)
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());
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
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
256 const std::string
& CSabrinaPhraseDescriptionStatic::getName() const
258 return _SheetId
.toString();
261 const ISabrinaPhraseModel
* CSabrinaPhraseDescriptionStatic::getPhraseModel() const
266 NLMISC::CSheetId
CSabrinaPhraseDescriptionStatic::getSheetId() const
271 // specialisation of protected methods from parent class
272 void CSabrinaPhraseDescriptionStatic::appendToString(std::string
& output
) const
275 output
+= _SheetId
.toString();
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 ')'
284 if (s
.strip()[0]!='(' || !s
.contains(")"));
286 nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to invalid input: '%s'",input
.c_str());
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();
293 nlwarning("CSabrinaPhraseDescriptionStatic::extractFromString: Failed due to bracket missmatch in input: '%s'",input
.c_str());
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());
305 // build the phrase description record
308 // remove the parsed segment from the input string and return
309 input
=CSString(input
).splitFrom(')');
316 * CSabrinaPhraseDescriptionUser
318 * \author Nevrax France
323 CSabrinaPhraseDescriptionUser::CSabrinaPhraseDescriptionUser()
326 CSabrinaPhraseDescriptionUser::CSabrinaPhraseDescriptionUser(const std::string
& name
,const std::vector
<NLMISC::CSheetId
>& bricks
)
332 // specialisation of public methods from parent class
333 CSabrinaPhraseDescriptionUser::TType
CSabrinaPhraseDescriptionUser::getType() const
338 const std::string
& CSabrinaPhraseDescriptionUser::getName() const
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
353 for (uint32 i
=0; i
<_Bricks
.size();++i
)
356 output
+=_Bricks
[i
].toString();
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 ')'
367 if (s
.strip()[0]!='(' || !s
.contains(")"));
369 nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to invalid input: '%s'",input
.c_str());
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();
376 nlwarning("CSabrinaPhraseDescriptionUser::extractFromString: Failed due to bracket missmatch in input: '%s'",input
.c_str());
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
;