// Ryzom - MMORPG Framework // Copyright (C) 2010-2017 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 . #ifndef STRING_MANAGER_CLIENT_H #define STRING_MANAGER_CLIENT_H #include "nel/misc/static_map.h" #include "nel/misc/ucstring.h" #include "nel/misc/bit_mem_stream.h" #include "nel/misc/i18n.h" #include "nel/misc/sheet_id.h" #include "nel/misc/diff_tool.h" #include "game_share/brick_families.h" #include "game_share/skills.h" namespace STRING_MANAGER { class IStringWaiterRemover; class IStringWaitCallback; class CStringManagerClient { friend class IStringWaiterRemover; friend class IStringWaitCallback; public: // Singleton pattern implementation static CStringManagerClient *instance(); static void release(bool mustReleaseStaticArrays); /** Prepare the string manager to use a persistent string cache. * There is one cache file for each language and for each encountered shard. */ void initCache(const std::string &shardId, const std::string &languageCode); /** Clear the current string table and load the content of the cache file. * This method is called after receiving the impulse RELOAD_CACHE from * IOS. * If the received timestamp and the file timestamp differ, the file cache * is reseted. */ void loadCache(uint32 timestamp); bool isCacheLoaded() {return _CacheLoaded;}; // Force the cache to be saved void flushStringCache(); bool getString(uint32 stringId, std::string &result) { ucstring temp; getString(stringId, temp); result = temp.toUtf8(); } // FIXME: UTF-8 bool getString(uint32 stringId, ucstring &result); void waitString(uint32 stringId, const IStringWaiterRemover *premover, ucstring *result); void waitString(uint32 stringId, IStringWaitCallback *pcallback); bool getDynString(uint32 dynStringId, ucstring &result); void waitDynString(uint32 stringId, const IStringWaiterRemover *premover, ucstring *result); void waitDynString(uint32 stringId, IStringWaitCallback *pcallback); void receiveString(uint32 stringId, const ucstring &str); void receiveDynString(NLMISC::CBitMemStream &bms); void releaseDynString(uint32 stringId); // Yoyo: Append to the I18N some words (skills, bricks...) static void initI18NSpecialWords(const std::string &languageCode); static void specialWordsMemoryCompress(); // Yoyo: Replace the Brick Name with Filled stats (CSBrickManager work). No-Op if not found static void replaceSBrickName(NLMISC::CSheetId id, const ucstring &name, const ucstring &desc, const ucstring &desc2); static void replaceDynString(const ucstring &name, const ucstring &text); // Get the Localized Name of the Places. static const ucchar *getPlaceLocalizedName(const std::string &placeNameID); // Get the Localized Name of the faction (for the fame) static const ucchar *getFactionLocalizedName(const std::string &factionNameID); // Get the Localized Name of the Skill. static const ucchar *getSkillLocalizedName(SKILLS::ESkills e); // Get the Localized Name of the Item. static const ucchar *getItemLocalizedName(NLMISC::CSheetId id); // Get the Localized Name of the Creature. static const ucchar *getCreatureLocalizedName(NLMISC::CSheetId id); // Get the Localized Name of the SBrick. static const ucchar *getSBrickLocalizedName(NLMISC::CSheetId id); // Get the Localized Name of the SPhrase. static const ucchar *getSPhraseLocalizedName(NLMISC::CSheetId id); // Get the Localized Description of the Skill. static const ucchar *getSkillLocalizedDescription(SKILLS::ESkills e); // Get the Localized Descriptionof the Item. static const ucchar *getItemLocalizedDescription(NLMISC::CSheetId id); // Get the Localized Description of the SBrick. static const ucchar *getSBrickLocalizedDescription(NLMISC::CSheetId id); // Get the Localized Composition Description of the SBrick. static const ucchar *getSBrickLocalizedCompositionDescription(NLMISC::CSheetId id); // Get the Localized Description of the SPhrase. static const ucchar *getSPhraseLocalizedDescription(NLMISC::CSheetId id); // Get the Localized Title name static const ucchar *getTitleLocalizedName(const ucstring &titleId, bool women); static const ucchar *getLocalizedName(const ucstring &text); static std::vector getTitleInfos(const ucstring &titleId, bool women); // Get the Localized name of a classification type static const ucchar *getClassificationTypeLocalizedName(EGSPD::CClassificationType::TClassificationType type); // Outpost name static const ucchar *getOutpostLocalizedName(NLMISC::CSheetId id); // Outpost description static const ucchar *getOutpostLocalizedDescription(NLMISC::CSheetId id); // Outpost building name static const ucchar *getOutpostBuildingLocalizedName(NLMISC::CSheetId id); // Outpost building description static const ucchar *getOutpostBuildingLocalizedDescription(NLMISC::CSheetId id); // Squad name static const ucchar *getSquadLocalizedName(NLMISC::CSheetId id); // Squad description static const ucchar *getSquadLocalizedDescription(NLMISC::CSheetId id); private: // constructor. CStringManagerClient(); // destructor. ~CStringManagerClient(); /// A string waiter is destoyed, remove any waiting string reference from it. void removeStringWaiter(const IStringWaiterRemover *remover); /// A string wait callback is destoyed, remove any waiting string reference from it. void removeStringWaiter(const IStringWaitCallback *callback); enum TParamType { string_id, integer, time, money, dyn_string_id, sheet_id }; struct TParamValue { TParamType Type; ucstring::size_type ReplacementPoint; union { uint32 StringId; sint32 Integer; uint32 Time; uint64 Money; uint32 DynStringId; }; }; struct TDynStringInfo { enum TStatus { received, serialized, complete }; TStatus Status; NLMISC::CBitMemStream Message; uint32 StringId; std::vector Params; ucstring String; }; enum { EmptyStringId= 0, EmptyDynStringId= 0xffffffff }; struct TStringWaiter { /// Pointer to the ucstring to fill ucstring *Result; /// Pointer to the remover that contains this string reference const IStringWaiterRemover *Remover; }; bool buildDynString(TDynStringInfo &dynInfo); /// Container for simple strings typedef CHashMap TStringsContainer; /// Container for dyn strings typedef CHashMap TDynStringsContainer; /// Container of string reference waiting for value. typedef CHashMultiMap TStringWaitersContainer; /// Container of string reference to string callback object. typedef CHashMultiMap TStringCallbacksContainer; TStringsContainer _ReceivedStrings; CHashSet _WaitingStrings; TDynStringsContainer _ReceivedDynStrings; TDynStringsContainer _WaitingDynStrings; /// String waiting the string value from the server. TStringWaitersContainer _StringsWaiters; // String waiting the dyn string value from the server. TStringWaitersContainer _DynStringsWaiters; // Callback for string value from the server TStringCallbacksContainer _StringsCallbacks; // Callback for dyn string value from the server TStringCallbacksContainer _DynStringsCallbacks; // Return value for waiting string.. static ucstring _WaitString; // Singleton pattern implementation static CStringManagerClient *_Instance; //@{ //\name Cache management /// Flag for cache management initialisation done. bool _CacheInited; /// Shard id is used to identify the cache file to use. std::string _ShardId; /// Language code is used to identify the cache file to use. std::string _LanguageCode; /// Timestamp (unix date) of the corrently loaded cache file. uint32 _Timestamp; /// Fullpath name of the current cache file. std::string _CacheFilename; /// Flag to incate that the cache is loaded. bool _CacheLoaded; /// Waiting string to be saved in cache struct CCacheString { uint32 StringId; ucstring String; }; std::vector _CacheStringToSave; //@} // SpecialItems. class CItem { public: // The Name of the item ucstring Name; // The Women Name of the item ucstring WomenName; // Description of the item ucstring Desc; // Optional Second description (For SBrick composition for example) ucstring Desc2; void serial(NLMISC::IStream &f) { sint ver= f.serialVersion(1); f.serial(Name); if (ver >= 1) f.serial(WomenName); f.serial(Desc); f.serial(Desc2); } }; static bool _SpecItem_MemoryCompressed; static std::map _SpecItem_TempMap; static std::vector _TitleWords; static std::map _DynStrings; static char *_SpecItem_Labels; static ucchar *_SpecItem_NameDesc; struct CItemLight { char *Label; ucchar *Name; ucchar *WomenName; ucchar *Desc; ucchar *Desc2; }; struct CItemLightComp { bool operator()(const CItemLight &x, const CItemLight &y) const { return strcmp(x.Label, y.Label) < 0; } }; static std::vector _SpecItems; static const ucchar *getSpecialWord(const std::string &label, bool women = false); static const ucchar *getSpecialDesc(const std::string &label); static const ucchar *getSpecialDesc2(const std::string &label); // Check Files for the Packed string. class CFileCheck { public: uint32 ReferenceDate; uint32 AdditionDate; CFileCheck() { ReferenceDate= 0; AdditionDate= 0; } bool operator==(const CFileCheck &o) const { return ReferenceDate==o.ReferenceDate && AdditionDate==o.AdditionDate; } void serial(NLMISC::IStream &f) { f.serialVersion(0); f.serial(ReferenceDate); f.serial(AdditionDate); } }; // The Header for the Packed String Client class CPackHeader { public: // The language code used std::string LanguageCode; // The Modification Dates of each word files std::vector FileChecks; // If must rebuild the packed version for any reason. uint32 PackedVersion; void serial(NLMISC::IStream &f) { f.serialCheck(NELID("_RTS")); f.serialCheck(NELID("KCAP")); f.serialVersion(0); f.serial(PackedVersion); f.serial(LanguageCode); f.serialCont(FileChecks); } }; // return true if OK (same). static bool checkWordFileDates(std::vector &fileChecks, const std::vector &fileNames, const std::string &languageCode); }; /** Class that want to register to wait for string * need to derive from this class. */ class IStringWaiterRemover { public: virtual ~IStringWaiterRemover() { // signal the string manager that this waiter is destroyed CStringManagerClient::instance()->removeStringWaiter(this); } }; /** Implement this class if you want to wait for * string to be delivered. */ class IStringWaitCallback { public: /// Overide this method to receive callback for string. virtual void onStringAvailable(uint /* stringId */, const ucstring &/* value */) {} /// Overide this method to receive callback for dynamic string. virtual void onDynStringAvailable(uint /* stringId */, const ucstring &/* value */) {} virtual ~IStringWaitCallback() { // signal the string manager that this waiter is destroyed CStringManagerClient::instance()->removeStringWaiter(this); } }; /** A proxy file loader for CI18N * The implementation will check if there is any * new content in the translation/work directory of ryzom * then overwrite the value found in data/gamedev/language */ class CLoadProxy : public NLMISC::CI18N::ILoadProxy, public TStringDiff::IDiffCallback { void loadStringFile(const std::string &filename, ucstring &text); void onEquivalent(uint addIndex, uint refIndex, TStringDiffContext &context); void onAdd(uint addIndex, uint refIndex, TStringDiffContext &context); void onRemove(uint addIndex, uint refIndex, TStringDiffContext &context); void onChanged(uint addIndex, uint refIndex, TStringDiffContext &context); void onSwap(uint newIndex, uint refIndex, TStringDiffContext &context); }; } // namespace STRING_MANAGER #endif //STRING_MANAGER_CLIENT_H