// 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 // ///////////// #include "stdpch.h" // Game Share #include "game_share/generic_xml_msg_mngr.h" #include "game_share/msg_client_server.h" #include "game_share/bot_chat_types.h" #include "game_share/news_types.h" #include "game_share/mode_and_behaviour.h" #include "game_share/chat_group.h" #include "game_share/character_summary.h" #include "game_share/sphrase_com.h" #include "game_share/msg_client_server.h" #include "game_share/ryzom_database_banks.h" #include "game_share/msg_encyclopedia.h" #include "game_share/prerequisit_infos.h" #include "game_share/permanent_ban_magic_number.h" #include "game_share/item_special_effect.h" #include "game_share/combat_flying_text.h" #include "game_share/shard_names.h" // Client. #include "nel/gui/group_list.h" #include "interface_v3/interface_manager.h" #include "net_manager.h" #include "client_cfg.h" #include "entities.h" #include "client_chat_manager.h" #include "world_database_manager.h" #include "continent_manager.h" #include "motion/user_controls.h" #include "interface_v3/bot_chat_manager.h" #include "interface_v3/bot_chat_page_all.h" #include "interface_v3/bot_chat_page_trade.h" #include "interface_v3/bot_chat_page_create_guild.h" #include "interface_v3/obs_huge_list.h" #include "string_manager_client.h" #include "interface_v3/people_interraction.h" #include "interface_v3/bot_chat_manager.h" #include "interface_v3/bot_chat_page_all.h" #include "nel/gui/view_text_id.h" #include "nel/gui/ctrl_text_button.h" #include "interface_v3/input_handler_manager.h" #include "interface_v3/guild_manager.h" #include "interface_v3/skill_manager.h" #include "misc.h" #include "interface_v3/inventory_manager.h" #include "interface_v3/sphrase_manager.h" #include "outpost_manager.h" #include "interface_v3/encyclopedia_manager.h" #include "user_entity.h" #include "init_main_loop.h" #include "interface_v3/group_map.h" #include "sound_manager.h" #include "interface_v3/group_compas.h" #include "interface_v3/group_html_webig.h" #include "interface_v3/bar_manager.h" #include "permanent_ban.h" #include "global.h" #include "connection.h" #include "faction_war_manager.h" #include "far_tp.h" #include "input.h" #include "r2/editor.h" #include "game_share/r2_share_itf.h" #include "game_share/r2_types.h" #include "npc_icon.h" #include "interface_v3/action_handler_base.h" // Std. #include #define OLD_STRING_SYSTEM #define BAR_STEP_TP 2 /////////// // USING // /////////// using namespace NLMISC; using namespace NL3D; using namespace std; extern bool FirstFrame; extern void selectTipsOfTheDay (uint tips); //////////// // GLOBAL // //////////// CGenericXmlMsgHeaderManager GenericMsgHeaderMngr; // Manage messages #ifdef CLIENT_MULTI CNetManagerMulti NetMngr; // Manage the connection. #else CNetManager NetMngr; // Manage the connection. #endif bool UseFemaleTitles = false; bool serverReceivedReady = false; static const std::string PLAYER_EXCHANGE_INVITATION_DIALOG = "ui:interface:accept_trade_invitation"; // Hierarchical timer H_AUTO_DECL ( RZ_Client_Net_Mngr_Update ) //////////// // EXTERN // //////////// extern bool noUserChar; // \todo GUIGUI : do this better. extern bool userChar; // \todo GUIGUI : do this better. extern std::vector CharacterSummaries; extern uint8 ServerPeopleActive; extern uint8 ServerCareerActive; extern vector Mainlands; extern bool UserCharPosReceived; extern CGenericXmlMsgHeaderManager GenericMsgHeaderMngr; extern CClientChatManager ChatMngr; extern bool CharNameValidArrived; extern bool CharNameValid; bool IsInRingSession = false; TSessionId HighestMainlandSessionId; // highest in the position stack extern const char *CDBBankNames[INVALID_CDB_BANK+1]; void cbImpulsionGatewayOpen(NLMISC::CBitMemStream &bms); void cbImpulsionGatewayMessage(NLMISC::CBitMemStream &bms); void cbImpulsionGatewayClose(NLMISC::CBitMemStream &bms); /////////////// // FUNCTIONS // /////////////// void impulseDatabaseInitPlayer(NLMISC::CBitMemStream &impulse) { try { sint32 p = impulse.getPos(); // get the egs tick of this change TGameCycle serverTick; impulse.serial(serverTick); // read delta IngameDbMngr.readDelta( serverTick, impulse, CDBPlayer ); IngameDbMngr.setInitPacketReceived(); nlinfo( "DB_INIT:PLR done (%u bytes)", impulse.getPos()-p ); } catch (const Exception &e) { BOMB( NLMISC::toString( "Problem while decoding a DB_INIT:PLR msg, skipped: %s", e.what() ), return ); } } void impulseDatabaseUpdatePlayer(NLMISC::CBitMemStream &impulse) { try { // get the egs tick of this change TGameCycle serverTick; impulse.serial(serverTick); // read delta IngameDbMngr.readDelta( serverTick, impulse, CDBPlayer ); // unlike on the server, here there is only one unified CCDBSynchronized object } catch (const Exception &e) { BOMB( NLMISC::toString( "Problem while decoding a DB_UPDATE_PLR msg, skipped: %s", e.what() ), return ); } } template void updateInventoryFromStream(NLMISC::CBitMemStream &impulse, const CInventoryCategoryTemplate *templ, bool notifyItemSheetChanges); void impulseDatabaseUpdateBank(NLMISC::CBitMemStream &impulse) { uint32 bank = INVALID_CDB_BANK; try { // get the egs tick of this change TGameCycle serverTick; impulse.serial(serverTick); // decode bank uint nbits; FILL_nbits_WITH_NB_BITS_FOR_CDBBANK impulse.serial( bank, nbits ); // read delta IngameDbMngr.readDelta( serverTick, impulse, (TCDBBank)bank ); // read guild inventory update if ( bank == CDBGuild ) { updateInventoryFromStream( impulse, (INVENTORIES::CInventoryCategoryForGuild*)NULL, false ); } } catch (const Exception &e) { BOMB( NLMISC::toString( "Problem while decoding a DB_GROUP:UPDATE_BANK %s msg, skipped: %s", CDBBankNames[bank], e.what() ), return ); } } void impulseDatabaseInitBank(NLMISC::CBitMemStream &impulse) { uint32 bank = INVALID_CDB_BANK; try { // get the egs tick of this change TGameCycle serverTick; impulse.serial(serverTick); // decode bank uint nbits; FILL_nbits_WITH_NB_BITS_FOR_CDBBANK impulse.serial( bank, nbits ); // read delta IngameDbMngr.readDelta( serverTick, impulse, (TCDBBank)bank ); nldebug( "CDB: DB_GROUP:INIT_BANK %s", CDBBankNames[bank] ); // read guild inventory update if ( bank == CDBGuild ) { updateInventoryFromStream( impulse, (INVENTORIES::CInventoryCategoryForGuild*)NULL, false ); } } catch (const Exception &e) { BOMB( NLMISC::toString( "Problem while decoding a DB_GROUP:INIT_BANK %s msg, skipped: %s", CDBBankNames[bank], e.what() ), return ); } } void impulseDatabaseResetBank(NLMISC::CBitMemStream &impulse) { uint32 bank = INVALID_CDB_BANK; try { // get the egs tick of this change TGameCycle serverTick; impulse.serial(serverTick); // read the bank to reset uint nbits; FILL_nbits_WITH_NB_BITS_FOR_CDBBANK impulse.serial( bank, nbits ); // reset the bank IngameDbMngr.resetBank( serverTick, bank ); nldebug( "CDB: DB_GROUP:RESET_BANK %s", CDBBankNames[bank] ); } catch (const Exception &e) { BOMB( NLMISC::toString( "Problem while decoding a DB_GROUP:RESET_BANK %s msg, skipped: %s", CDBBankNames[bank], e.what() ), return ); } } static void readPrivileges(NLMISC::CBitMemStream &impulse) { nlassert(impulse.isReading()); // nico : temporarily uses a try block here to avoid prb with people having updated client and not the server try { impulse.serial(UserPrivileges); } catch(const EStreamOverflow &) { nlwarning("User privileges not serialised, assuming none"); UserPrivileges = ""; } } void impulseNoUserChar(NLMISC::CBitMemStream &impulse) { // received NO_USER_CHAR //nlinfo("impulseCallBack : Received CONNECTION:NO_USER_CHAR"); impulse.serial(ServerPeopleActive); impulse.serial(ServerCareerActive); readPrivileges(impulse); impulse.serialCont(Mainlands); CharacterSummaries.clear(); noUserChar = true; LoginSM.pushEvent(CLoginStateMachine::ev_no_user_char); updatePatcherPriorityBasedOnCharacters(); } void impulseFarTP(NLMISC::CBitMemStream &impulse) { // received FAR_TP TSessionId sessionId; impulse.serial(sessionId); //nlinfo("impulseCallback : Received CONNECTION:FAR_TP %u", sessionId.asInt()); bool bailOutIfSessionVanished; impulse.serial(bailOutIfSessionVanished); FarTP.requestFarTPToSession(sessionId, PlayerSelectedSlot, CFarTP::JoinSession, bailOutIfSessionVanished); } static std::string lookupSrcKeyFile(const std::string &src) { if (CFile::isExists("save/" + src)) return "save/" + src; return CPath::lookup(src, false); } void copyKeySet(const std::string &srcPath, const std::string &destPath) { // can't use CFile copyFile here, because src may be in a bnp file std::string srcStr; srcStr.resize(CFile::getFileSize(srcPath)); if (srcStr.empty()) { nlwarning("Can't copy keys from %s : file not found or empty"); return; } try { CIFile ifile(srcPath); ifile.serialBuffer((uint8 *) &srcStr[0], (uint)srcStr.size()); COFile ofile(destPath); ofile.serialBuffer((uint8 *) &srcStr[0], (uint)srcStr.size()); } catch(const EStream &) { nlwarning("Couldn't copy %s to %s to create new character keyset", srcPath.c_str(), destPath.c_str()); } } void impulseUserChars(NLMISC::CBitMemStream &impulse) { // received USER_CHARS //nlinfo("impulseCallBack : Received CONNECTION:USER_CHARS"); impulse.serial(ServerPeopleActive); impulse.serial(ServerCareerActive); // read characters summary CharacterSummaries.clear(); impulse.serialCont (CharacterSummaries); // read shard name summaries std::vector shardNames; impulse.serialCont (shardNames); CShardNames::getInstance().loadShardNames(shardNames); // read privileges readPrivileges(impulse); impulse.serial(FreeTrial); FreeTrial = false; impulse.serialCont(Mainlands); userChar = true; LoginSM.pushEvent(CLoginStateMachine::ev_chars_received); // Create the message for the server to select the first character. /* CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream("CONNECTION:SELECT_CHAR", out)) { CSelectCharMsg SelectCharMsg; SelectCharMsg.c = 0; //TODO set here the character choosen by player out.serial( SelectCharMsg ); NetMngr.push(out); NetMngr.send(NetMngr.getCurrentServerTick()); // send CONNECTION:USER_CHARS nldebug("impulseCallBack : CONNECTION:SELECT_CHAR sent"); } else nlwarning("impulseCallBack : unknown message name : 'CONNECTION:SELECT_CHAR'."); noUserChar = true; */ if (!NewKeysCharNameValidated.empty()) { // if there's a new char for which a key set was wanted, create it now for (uint k = 0; k < CharacterSummaries.size(); ++k) { if (toLower(CharacterSummaries[k].Name) == toLower(NewKeysCharNameValidated)) { // first, stripes server name copyKeySet(lookupSrcKeyFile(GameKeySet), "save/keys_" + buildPlayerNameForSaveFile(NewKeysCharNameValidated) + ".xml"); copyKeySet(lookupSrcKeyFile(RingEditorKeySet), "save/keys_r2ed_" + buildPlayerNameForSaveFile(NewKeysCharNameValidated) + ".xml"); break; } } } updatePatcherPriorityBasedOnCharacters(); } void impulseUserChar(NLMISC::CBitMemStream &impulse) { // received USER_CHAR //nlinfo("impulseCallBack : Received CONNECTION:USER_CHAR"); // Serialize the message COfflineEntityState posState; extern uint8 ServerSeasonValue; extern bool ServerSeasonReceived; uint32 userRole; CUserCharMsg::read( impulse, posState, ServerSeasonValue, userRole, IsInRingSession, HighestMainlandSessionId, CharFirstConnectedTime, CharPlayedTime ); ServerSeasonReceived = true; // set the season that will be used when selecting the continent from the position if (UserEntity) { UserEntity->pos(CVectorD((float)posState.X/1000.0f, (float)posState.Y/1000.0f, (float)posState.Z/1000.0f)); UserEntity->front(CVector((float)cos(posState.Heading), (float)sin(posState.Heading), 0.f)); UserEntity->dir(UserEntity->front()); UserEntity->setHeadPitch(0); UserControls.resetCameraDeltaYaw(); //nldebug(" pos : %f %f %f heading : %f",UserEntity->pos().x,UserEntity->pos().y,UserEntity->pos().z,posState.Heading); // Update the position for the vision. NetMngr.setReferencePosition(UserEntity->pos()); } else { UserEntityInitPos = CVectorD((float)posState.X/1000.0f, (float)posState.Y/1000.0f, (float)posState.Z/1000.0f); UserEntityInitFront = CVector((float)cos(posState.Heading), (float)sin(posState.Heading), 0.f); //nldebug(" pos : %f %f %f heading : %f",UserEntityInitPos.x,UserEntityInitPos.y,UserEntityInitPos.z,posState.Heading); // Update the position for the vision. NetMngr.setReferencePosition(UserEntityInitPos); } UserCharPosReceived = true; // Configure the ring editor extern R2::TUserRole UserRoleInSession; UserRoleInSession = R2::TUserRole::TValues(userRole); ClientCfg.R2EDEnabled = IsInRingSession /*&& (UserRoleInSession.getValue() != R2::TUserRole::ur_player)*/; // !!!Do NOT uncomment the following line do the ClientCfg.R2EDEnabled = IsInRingSession && (UserRoleInSession != R2::TUserRole::ur_player); // even with UserRoleInSession R2::TUserRole::ur_player the ring features must be activated // because if the ring is not activated the dss do not know the existence of the player // So we can not kick him, tp to him, tp in to next act .... nldebug( "EnableR2Ed = %u, IsInRingSession = %u, UserRoleInSession = %u", (uint)ClientCfg.R2EDEnabled, (uint)IsInRingSession, userRole ); updatePatcherPriorityBasedOnCharacters(); } void impulseCharNameValid(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallBack : Received CONNECTION:VALID_NAME"); uint8 nTmp; impulse.serial(nTmp); CharNameValid = ((nTmp != 0) ? true : false); CharNameValidArrived = true; if (CharNameValid) NewKeysCharNameValidated = NewKeysCharNameWanted; } void checkHandshake( NLMISC::CBitMemStream &impulse ) { // Decode handshake to check versions uint16 handshakeVersion; uint16 itemSlotVersion; impulse.serial( handshakeVersion ); if ( handshakeVersion > 0 ) nlerror( "Server handshake version is more recent than client one" ); impulse.serial( itemSlotVersion ); if ( itemSlotVersion != INVENTORIES::CItemSlot::getVersion() ) nlerror( "Handshake: itemSlotVersion mismatch (S:%hu C:%hu)", itemSlotVersion, INVENTORIES::CItemSlot::getVersion() ); } void impulseServerReady(NLMISC::CBitMemStream &impulse) { // received CONNECTION:READY //nlinfo("impulseCallBack : Received CONNECTION:READY"); serverReceivedReady = true; checkHandshake( impulse ); LoginSM.pushEvent(CLoginStateMachine::ev_ready_received); } void impulseShardId(NLMISC::CBitMemStream &impulse) { // received SHARD_ID uint32 shardId; impulse.serial(shardId); ShardId = shardId; string webHost; impulse.serial(webHost); if (webHost != "") { WebServer = webHost; } nlinfo("WEB: Received SHARD_ID %d, web hosted at '%s', using '%s'", shardId, webHost.c_str(), WebServer.c_str()); } void impulseServerQuitOk(NLMISC::CBitMemStream &impulse) { // receive CONNECTION:SERVER_QUIT_OK if (FarTP.isFarTPInProgress()) { FarTP.onServerQuitOk(); } else { // ensure first a quit request is really asked if(game_exit_request) { // quit! game_exit= true; ryzom_exit= true; } } } void impulseServerQuitAbort(NLMISC::CBitMemStream &impulse) { // receive CONNECTION:SERVER_QUIT_ABORT if (FarTP.isFarTPInProgress()) { FarTP.onServerQuitAbort(); } else { // abort any quit request game_exit_request= false; ryzom_exit_request= false; } } void impulseMailNotification(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; // receive CONNECTION:MAIL_AVAILABLE CInterfaceManager::getInstance()->notifyMailAvailable(); } void impulseForumNotification(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; // receive CONNECTION:GUILD_MESSAGE_AVAILABLE CInterfaceManager::getInstance()->notifyForumUpdated(); } void impulsePermanentBan(NLMISC::CBitMemStream &impulse) { uint64 magicNumber; impulse.serial(magicNumber); if (magicNumber != PermanentBanMSGMagicNumber) return; // bad msg setPermanentBanMarkers(true); applyPermanentBanPunishment(); PermanentlyBanned = true; } void impulsePermanentUnban(NLMISC::CBitMemStream &impulse) { uint64 magicNumber; impulse.serial(magicNumber); if (magicNumber != PermanentUnbanMSGMagicNumber) return; // bad msg setPermanentBanMarkers(false); PermanentlyBanned = false; if (UserEntity) { // allows to walk / run again UserEntity->walkVelocity(ClientCfg.Walk); UserEntity->runVelocity(ClientCfg.Run); } } // *************************************************************************** class CInterfaceChatDisplayer : public CClientChatManager::IChatDisplayer { public: virtual void displayChat(TDataSetIndex compressedSenderIndex, const ucstring &ucstr, const ucstring &rawMessage, CChatGroup::TGroupType mode, NLMISC::CEntityId dynChatId, ucstring &senderName, uint bubbleTimer=0); virtual void displayTell(/*TDataSetIndex senderIndex, */const ucstring &ucstr, const ucstring &senderName); virtual void clearChannel(CChatGroup::TGroupType mode, uint32 dynChatDbIndex); private: // Add colorization tag for sender name void colorizeSender(ucstring &text, const ucstring &senderName, CRGBA baseColor); }; static CInterfaceChatDisplayer InterfaceChatDisplayer; void CInterfaceChatDisplayer::colorizeSender(ucstring &text, const ucstring &senderName, CRGBA baseColor) { // find the sender/text separator to put color tags ucstring::size_type pos = senderName.length() - 1; if (pos != ucstring::npos) { ucstring str; CInterfaceProperty prop; prop.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," "); CChatWindow::encodeColorTag(prop.getRGBA(), str, false); str += text.substr(0, pos+1); CChatWindow::encodeColorTag(baseColor, str, true); str += text.substr(pos+1); text.swap(str); } } // display a chat from network to interface void CInterfaceChatDisplayer::displayChat(TDataSetIndex compressedSenderIndex, const ucstring &ucstr, const ucstring &rawMessage, CChatGroup::TGroupType mode, NLMISC::CEntityId dynChatId, ucstring &senderName, uint bubbleTimer) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); ucstring finalString; string stringCategory = getStringCategory(ucstr, finalString); bool bubbleWanted = true; // Subtract rawMessage from ucstr so that the 'sender' part remains. ucstring senderPart = ucstr.luabind_substr(0, ucstr.length() - rawMessage.length()); // search a "{no_bubble}" tag { ucstring::size_type index = finalString.find(ucstring("{no_bubble}")); const size_t tokenSize= 11; // length of "{no_bubble}" if (index != ucstring::npos) { bubbleWanted = false; finalString = finalString.luabind_substr(0, index) + finalString.substr(index+tokenSize,finalString.size()); } } // **** get color CRGBA col; if (mode != CChatGroup::system) { // Remove all {break} for(;;) { ucstring::size_type index = finalString.find(ucstring("{break}")); if (index == ucstring::npos) break; finalString = finalString.luabind_substr(0, index) + finalString.luabind_substr(index+7,finalString.size()); } // select DB sint32 dbIndex = ChatMngr.getDynamicChannelDbIndexFromId(dynChatId); clamp(dbIndex, (sint32)0 , (sint32)CChatGroup::MaxDynChanPerPlayer); string entry="UI:SAVE:CHAT:COLORS:"; switch(mode) { case CChatGroup::dyn_chat: entry+="DYN:" + NLMISC::toString(dbIndex); break; case CChatGroup::say: entry+="SAY"; break; case CChatGroup::shout: entry+="SHOUT"; break; case CChatGroup::team: entry+="GROUP"; break; case CChatGroup::guild: entry+="CLADE"; break; case CChatGroup::civilization: entry+="CIVILIZATION"; break; case CChatGroup::territory: entry+="TERRITORY"; break; case CChatGroup::universe: entry+="UNIVERSE_NEW"; break; case CChatGroup::region: entry+="REGION"; break; case CChatGroup::tell: entry+="TELL"; break; default: nlwarning("unknown group type"); return; } // read DB CInterfaceProperty prop; prop.readRGBA(entry.c_str()," "); col = prop.getRGBA(); // Override color if the string contains the color if (!stringCategory.empty() && stringCategory != "SYS") { map::const_iterator it; it = ClientCfg.SystemInfoParams.find(strlwr(stringCategory)); if (it != ClientCfg.SystemInfoParams.end()) { col = it->second.Color; } } } if (stringCategory == "emt") { bubbleWanted = false; } if (mode != CChatGroup::system) { // find the sender/text separator to put color tags if (senderPart.empty() && stringCategory == "emt") { size_t pos = finalString.find(ucstring(": "), 0); if (pos != ucstring::npos) { senderPart = finalString.luabind_substr(0, pos + 2); } } colorizeSender(finalString, senderPart, col); } // play associated fx if any if( !stringCategory.empty() ) { map::const_iterator it; it = ClientCfg.SystemInfoParams.find( strlwr(stringCategory) ); if( it != ClientCfg.SystemInfoParams.end() ) { if( !(*it).second.SysInfoFxName.empty() ) { NL3D::UParticleSystemInstance sysInfoFx = FXMngr.instantFX((*it).second.SysInfoFxName); if( !sysInfoFx.empty() ) { sysInfoFx.setClusterSystem( UserEntity->getClusterSystem() ); sysInfoFx.setPos( UserEntity->pos() ); } else { nlwarning(" Can't set chat fx %s",(*it).second.SysInfoFxName.c_str()); } } } } // **** redirect to the correct interface output if( stringCategory != "bbl" ) { bool windowVisible; if (mode == CChatGroup::system) { pIM->displaySystemInfo(finalString, stringCategory); } else if (mode == CChatGroup::guild) { PeopleInterraction.ChatInput.Guild.displayMessage(finalString, col, 2, &windowVisible); } else if (mode == CChatGroup::team) { PeopleInterraction.ChatInput.Team.displayMessage(finalString, col, 2, &windowVisible); } else if (mode == CChatGroup::region) { PeopleInterraction.ChatInput.Region.displayMessage(finalString, col, 2, &windowVisible); } else if (mode == CChatGroup::universe) { PeopleInterraction.ChatInput.Universe.displayMessage(finalString, col, 2, &windowVisible); } else if (mode == CChatGroup::dyn_chat) { // retrieve the DBIndex from the dynamic chat id sint32 dbIndex= ChatMngr.getDynamicChannelDbIndexFromId(dynChatId); // if found, display, else discarded if(dbIndex >= 0 && dbIndex < CChatGroup::MaxDynChanPerPlayer) { PeopleInterraction.ChatInput.DynamicChat[dbIndex].displayMessage(finalString, col, 2, &windowVisible); // Add dynchannel info before text so that the chat log will show the correct string. CCDBNodeLeaf* node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_DYN_CHANNEL_NAME_IN_CHAT_CB", false); if (pIM->getLogState()) { // Add dyn chan number before string ucstring prefix("[" + NLMISC::toString(dbIndex) + "]"); // Find position to put the new string // After timestamp? size_t pos = finalString.find(ucstring("]")); size_t colonpos = finalString.find(ucstring(": @{")); // If no ] found or if found but after the colon (so part of the user chat) if (pos == ucstring::npos || (colonpos < pos)) { // No timestamp, so put it right after the color and add a space pos = finalString.find(ucstring("}"));; prefix += " "; } finalString = finalString.substr(0, pos + 1) + prefix + finalString.substr(pos + 1); if (node && node->getValueBool()) { uint32 textId = ChatMngr.getDynamicChannelNameFromDbIndex(dbIndex); ucstring title; STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId, title); prefix = title.empty() ? ucstring("") : ucstring(" ") + title; pos = finalString.find(ucstring("] ")); finalString = finalString.substr(0, pos) + prefix + finalString.substr(pos); } } } else { nlwarning("Dynamic chat %s not found for message: %s", dynChatId.toString().c_str(), finalString.toString().c_str()); } } else { ucstring::size_type index = finalString.find(ucstring("")); if (index != ucstring::npos) { bubbleWanted = false; finalString = finalString.substr(index+6,finalString.size()); ucstring::size_type index2 = finalString.find(ucstring(" ")); ucstring playerName; if (index2 < (finalString.size()-3)) { playerName = finalString.substr(0,index2); finalString = finalString.substr(index2+1,finalString.size()); } if (!senderName.empty()) { CEntityCL *senderEntity = EntitiesMngr.getEntityByName (CEntityCL::removeTitleAndShardFromName(senderName), true, true); if (senderEntity) { if (senderEntity->Type != CEntityCL::Player) { if (playerName.empty()) { senderEntity->removeStateFx(); senderEntity->setStateFx(finalString.toString()); nlinfo("empty"); } else { CEntityCL *destEntity = EntitiesMngr.getEntityByName (CEntityCL::removeTitleAndShardFromName(playerName), false, true); if (destEntity) { destEntity->removeStateFx(); destEntity->setStateFx(finalString.toString()); nlinfo("no empty"); } } } } } finalString = ""; } else { PeopleInterraction.ChatInput.AroundMe.displayMessage(finalString, col, 2, &windowVisible); } } // if tell, bkup sendername if (mode == CChatGroup::tell && windowVisible && !senderName.empty()) { PeopleInterraction.LastSenderName = CEntityCL::removeTitleAndShardFromName(senderName); } } // received CHAT //nldebug(" Received CHAT : %s with category %s",finalString.toString().c_str(),stringCategory.c_str()); // **** Process chat entry for the bubbles // todo hulud : registering a chat callback would be better than calling this hardcoded action handler ucstring finalRawMessage; // remove color qualifier from raw string getStringCategory(rawMessage, finalRawMessage); if (bubbleWanted) { InSceneBubbleManager.chatOpen(compressedSenderIndex, finalRawMessage, bubbleTimer); } // Log pIM->log (finalString); } // display a tell from network to interface void CInterfaceChatDisplayer::displayTell(/*TDataSetIndex senderIndex, */const ucstring &ucstr, const ucstring &senderName) { ucstring finalString = ucstr; // for now, '&' are removed by server so use another format until a special msg is made if (strFindReplace(finalString, ucstring(""), ucstring())) { CInterfaceManager::getInstance()->executeLuaScript("RingAccessPoint:forceRefresh()"); } CInterfaceProperty prop; prop.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," "); bool windowVisible; ucstring goodSenderName = CEntityCL::removeTitleAndShardFromName(senderName); // The sender part is up to and including the first ":" after the goodSenderName ucstring::size_type pos = finalString.find(goodSenderName); pos = finalString.find(':', pos); pos = finalString.find(' ', pos); ucstring senderPart = finalString.substr(0, pos+1); colorizeSender(finalString, senderPart, prop.getRGBA()); PeopleInterraction.ChatInput.Tell.displayTellMessage(/*senderIndex, */finalString, goodSenderName, prop.getRGBA(), 2, &windowVisible); CInterfaceManager::getInstance()->log(finalString); // Open the free teller window CChatGroupWindow *pCGW = PeopleInterraction.getChatGroupWindow(); if (pCGW != NULL) pCGW->setActiveFreeTeller(goodSenderName); if (windowVisible && !goodSenderName.empty()) PeopleInterraction.LastSenderName = goodSenderName; } // clear a channel void CInterfaceChatDisplayer::clearChannel(CChatGroup::TGroupType mode, uint32 dynChatDbIndex) { if (mode == CChatGroup::guild) PeopleInterraction.ChatInput.Guild.clearMessages(); else if (mode == CChatGroup::team) PeopleInterraction.ChatInput.Team.clearMessages(); else if (mode == CChatGroup::region) PeopleInterraction.ChatInput.Region.clearMessages(); else if (mode == CChatGroup::arround) PeopleInterraction.ChatInput.AroundMe.clearMessages(); else if (mode == CChatGroup::universe) PeopleInterraction.ChatInput.Universe.clearMessages(); else if (mode == CChatGroup::dyn_chat) { // if correct dbIndex, clear if(dynChatDbIndex code; // if( huff ) // { // impulse.serialCont( code ); // } // if (PermanentlyBanned) return; // #ifdef OLD_STRING_SYSTEM // ChatMngr.getDynamicDB().add( index, ucstr, code ); // #else // nlwarning( "// TRAP // WE MUST NEVER CALL THIS IMPULE ANYMORE : ALL IS HANDLED BY STRING_MANAGER NOW !!!" ); // #endif // // // received ADD_DYN_STR // nlinfo("impulseCallBack : Received ADD_DYN_STR : adding %s at index %d",ucstr.toString().c_str(),index); //} /* string getInterfaceNameFromId (sint botType, sint interfaceId) { string interfaceName = "ui:interface:bot_chat_"; switch (botType) { case 0: interfaceName += "figurant_"; break; case 1: interfaceName += "figurant_presse_"; break; case 2: interfaceName += "chef_village_"; break; default: interfaceName += "figurant_"; break; } switch (interfaceId) { case BOTCHATTYPE::Intro: interfaceName += "intro"; break; case BOTCHATTYPE::FriendlyMainPage: interfaceName += "friendly_main"; break; case BOTCHATTYPE::NeutralMainPage: interfaceName += "neutral_main"; break; case BOTCHATTYPE::NastyMainPage: interfaceName += "nasty_main"; break; case BOTCHATTYPE::MoreNewsPage: interfaceName += "more_news"; break; case BOTCHATTYPE::Done: nlinfo ("end of bot chat"); interfaceName = ""; break; } return interfaceName; } static char *shortNews[] = { "The wind is sour and brings only bad tidings...", "Kitins have been sighted near the village!", "", "The tribe of the Black Circle has recently", "increased its activities in our region.", "", "The Black Circle has made an incursion", "into our territory!", "", "The Black Circle has been sighted near one", "of our forward posts, deep in dangerous territory.", "", "The tide has washed up evil news, friend.", "The Black Circle is active in our region.", "", "Our people suffer from a debilitating shortage.", "We are in sore need of KamiBast.", "", "The economy is slow and our reserve of", "Live Seed low.", "", "We are in sore need of Live Seed", "If there is a Goo epidemic, we shall all perish!", "", "Our master mages have gotten wind of", "the growing Kami discontentment", "", }; static char *longNews[] = { "These powerful predators haven't come this near", "to the village since their devastating attack", "over 15 seasons ago!", "They are after more KamiBast", "for their occult practices.", "", "They have captured", "2 of our fortifications in the bush!", "", "They have taken over one of our richest sources", "of KamiBast, and are exploiting it", "for their own occult purposes.", "They now hold an important source", "of Live Seed hostage,", "close to one of our forward posts.", "We use the magical properties of KamiBast and", "its unusually rich fibers for all our crafts.", "", "If we don't harvest new Seed soon,", "we will have no way of purchasing goods", "and resources, beyond what we produce ourselves", "We use the rich Sap of Live Seed to produce", "an antidote that counters the disastrous", "effects of the Goo on all Atysian life forms.", "The Kamis are shaken by the Black Circle's", "presence. If the Circle continues it's occult", "practices, we will all suffer the Kamic anger.", }; */ /* void setFakeNews () { char *table[] = { "figurant", "chef_village", "garde", "commercant" }; sint rnd = rand ()%(sizeof(shortNews)/sizeof(shortNews[0])/3); rnd; for (uint i = 0; i < sizeof(table)/sizeof(table[0]); i++) { { // set test for the friendly main string iname; iname = "ui:interface:bot_chat_"; iname += table[i]; iname += "_friendly_main"; CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(iname); if (inter == NULL) { nlwarning ("cant find interface 's%'", iname.c_str()); continue; } CViewText *inter2 = (CViewText *)inter->getView("title0"); nlassert (inter2 != NULL); inter2->setText(ucstring(shortNews[rnd*3])); CViewText *inter3 = (CViewText *)inter->getView("title1"); nlassert (inter3 != NULL); inter3->setText(ucstring(shortNews[rnd*3+1])); CViewText *inter4 = (CViewText *)inter->getView("title2"); nlassert (inter4 != NULL); inter4->setText(ucstring(shortNews[rnd*3+2])); } { // set test for the neutral main string iname; iname = "ui:interface:bot_chat_"; iname += table[i]; iname += "_neutral_main"; CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(iname); if (inter == NULL) { nlwarning ("cant find interface 's%'", iname.c_str()); continue; } CViewText *inter2 = (CViewText *)inter->getView("title0"); nlassert (inter2 != NULL); inter2->setText(ucstring(shortNews[rnd*3])); CViewText *inter3 = (CViewText *)inter->getView("title1"); nlassert (inter3 != NULL); inter3->setText(ucstring(shortNews[rnd*3+1])); } { // set test for the more news string iname; iname = "ui:interface:bot_chat_"; iname += table[i]; iname += "_more_news"; CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(iname); if (inter == NULL) { nlwarning ("cant find interface 's%'", iname.c_str()); continue; } CViewText *inter2 = (CViewText *)inter->getView("title0"); nlassert (inter2 != NULL); inter2->setText(ucstring(longNews[rnd*3])); CViewText *inter3 = (CViewText *)inter->getView("title1"); nlassert (inter3 != NULL); inter3->setText(ucstring(longNews[rnd*3+1])); CViewText *inter4 = (CViewText *)inter->getView("title2"); nlassert (inter4 != NULL); inter4->setText(ucstring(longNews[rnd*3+2])); } } } */ //========================================= /** Temp setup for choice list */ /* static void setupBotChatChoiceList(CInterfaceGroup *botChatGroup) { // Temp for test. Should then be read from server msg std::vector choices; for(uint k = 0; k < 90; ++k) { choices.push_back("Choice " + toString(k)); } CBotChat::setChoiceList(botChatGroup, choices, false); } */ //========================================= /** Temp setup for description list */ /* static void setupBotChatDescription(CInterfaceGroup *botChatGroup) { ucstring desc; for(uint k = 0; k < 90; ++k) { desc += "This is a multi line description. "; } CBotChat::setDescription(botChatGroup, desc); } */ //========================================= /** Temp setup for bot chat gift */ /* static void setupBotChatBotGift(CInterfaceGroup *botChatGroup) { // create dummy item in the db CInterfaceManager *im = CInterfaceManager::getInstance(); NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:0:SHEET")->setValue32(CSheetId("ai_flesh_poisson.item").asInt()); NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:0:QUALITY")->setValue32(0); NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:1:SHEET")->setValue32(CSheetId("fyros_sword_lvl_01_05.item").asInt()); NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:1:QUALITY")->setValue32(2); CBotChat::setBotGift(botChatGroup, ucstring("Thanks to have succeeded the mission"), ucstring("Here's your reward"), ucstring("The bot has taken the object quest from your inventory")); } */ //----------------------------------------------- // impulseBotChatSetInterface : //----------------------------------------------- #if 0 void impulseBotChatSetInterface(NLMISC::CBitMemStream &impulse) { // received ADD_DYN_STR CEntityId user; uint32 happyness; BOTCHATTYPE::TBotChatInterfaceId interfaceId; bool hasNews; impulse.serial (user); impulse.serial (happyness); // impulse.serialEnum (interfaceId); uint16 interfId; impulse.serial(interfId); interfaceId = (BOTCHATTYPE::TBotChatInterfaceId)(interfId&0xff); uint8 botType = (interfId>>8) & 0xff; impulse.serial (hasNews); nldebug("impulseCallBack : Received BOT_CHAT:SET_INTERFACE interface %d, have news %s, happy %d, bottype %hu", interfaceId, hasNews?"yes":"no", happyness,(uint16)botType); string stringId; vector args; if (hasNews) { /* impulse.serial (stringId); impulse.serialCont (args); nlinfo ("receive the news '%s' with %d args", stringId.c_str(), args.size()); */ // TEMP FOR THE DEMO, DON'T USE THE NETWORK NEW BUT SELECT A NEWS HERE /* CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId("ui:interface:bot_chat_intro"); nlassert (inter != NULL); inter->setActive(true); CViewText *inter2 = (CViewText *)inter->getView("hi"); nlassert (inter2 != NULL); inter2->NetworkTextId.setString("IOS_NEWS_FOOTBALL_SHORT_EEII", &ChatMngr); inter2->NetworkTextId.Args.push_back(10); inter2->NetworkTextId.Args.push_back(20); inter2->NetworkTextId.Args.push_back(1); inter2->NetworkTextId.Args.push_back(2); */ } // FOR THE DEMO, find and set a fake news: // setFakeNews (); string interfaceName = getInterfaceNameFromId (botType, interfaceId); if(interfaceName.empty()) { nlwarning ("Received an unknown bot chat interface %d", interfaceId); } else { CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(interfaceName); if (inter == NULL) { nlwarning ("Can't find interface name '%s' %d", interfaceName.c_str(), interfaceId); } else { CInterfaceManager::getInstance()->setBotChatWin(inter); if (inter->getActive()) { nlwarning ("Interface %s is already active, not normal!", interfaceName.c_str()); } else { nlinfo ("server want to me display the bot chat interface %s %d", interfaceName.c_str(), interfaceId); inter->setActive(true); } } } } #endif //----------------------------------------------- // impulseBeginTrade : //----------------------------------------------- void impulseBeginTrade(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; //open trade window CInterfaceGroup* win = CWidgetManager::getInstance()->getWindowFromId("ui:interface:trade"); if (!win) { nlwarning("invalid interface ui:interface:trade"); return; } win->setActive(true); } //----------------------------------------------- // impulseBuyPrice : //----------------------------------------------- void impulseBuyPrice(NLMISC::CBitMemStream &impulse) { uint16 botChatSession; uint32 sheetID; uint16 quality; uint64 price; impulse.serial(botChatSession); impulse.serial(price); impulse.serial(sheetID); impulse.serial(quality); // no more used } //----------------------------------------------- // impulseDynChatOpen //----------------------------------------------- void impulseDynChatOpen(NLMISC::CBitMemStream &impulse) { uint32 BotUID; // Compressed Index uint32 BotName; // Server string vector DynStrs; // 0 - Desc, 1 - Option0, 2 - Option1, etc.... impulse.serial(BotUID); impulse.serial(BotName); impulse.serialCont(DynStrs); if (PermanentlyBanned) return; /* string sTmp = "impulseCallback : Received BOTCHAT:DYNCHAT_OPEN BotUID:"; sTmp += toString(BotUID) + " BotName:"; sTmp += toString(BotName) + " DynStrs:"; for (uint32 i = 0; i < DynStrs.size(); ++i) { sTmp += toString(DynStrs[i]); if (i != DynStrs.size()-1) sTmp += ","; } nlinfo(sTmp.c_str());*/ InSceneBubbleManager.dynChatOpen(BotUID, BotName, DynStrs); } //----------------------------------------------- // impulseDynChatClose //----------------------------------------------- void impulseDynChatClose(NLMISC::CBitMemStream &impulse) { uint32 BotUID; // Compressed Index impulse.serial(BotUID); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received BOTCHAT:DYNCHAT_CLOSE BotUID:"+toString(BotUID)); InSceneBubbleManager.dynChatClose(BotUID); } //----------------------------------------------- // impulseBeginCast: //----------------------------------------------- void impulseBeginCast(NLMISC::CBitMemStream &impulse) { //open cast window uint32 begin,end; impulse.serial(begin); impulse.serial(end); if (PermanentlyBanned) return; CInterfaceManager* iMngr = CInterfaceManager::getInstance(); NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SPELL_CAST")->setValue32(1); NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CAST_BEGIN")->setValue32(begin); NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CAST_END")->setValue32(end); } //----------------------------------------------- // impulseCorrectPos : // Message from the server to correct the user position because he is not at the same position on the server.. //----------------------------------------------- void impulseCorrectPos(NLMISC::CBitMemStream &impulse) { // TP:CORRECT //nlinfo("impulseCallback : Received TP:CORRECT"); sint32 x, y, z; impulse.serial(x); impulse.serial(y); impulse.serial(z); nlinfo("impulseCorrectPos: new user position %d %d %d", x, y, z); if(UserEntity->mode() != MBEHAV::COMBAT_FLOAT) { // Compute the destination. CVectorD dest = CVectorD((float)x/1000.0f, (float)y/1000.0f, (float)z/1000.0f); // Update the position for the vision. NetMngr.setReferencePosition(dest); // Change the user poisition. UserEntity->correctPos(dest); } }// impulseCorrectPos // class CDummyProgress : public IProgressCallback { void progress (float /* value */) {} }; //----------------------------------------------- // impulseTP : // Message from the server to teleport the user. // \warning This function remove the current target. Do no use to correct a position. //----------------------------------------------- void impulseTPCommon(NLMISC::CBitMemStream &impulse, bool hasSeason); void impulseTPCommon2(NLMISC::CBitMemStream &impulse, bool hasSeason); void impulseTP(NLMISC::CBitMemStream &impulse) { impulseTPCommon(impulse, false); } void impulseTPWithSeason(NLMISC::CBitMemStream &impulse) { impulseTPCommon(impulse, true); } struct SQueuedTP { NLMISC::CBitMemStream Impulse; bool HasSeason; SQueuedTP(const NLMISC::CBitMemStream &impulse, bool hasSeason) :Impulse(impulse), HasSeason(hasSeason) { } }; // note - this method added by Sadge and Hamster to deal with unexplained recursive calls to impulseTPCommon // these calls are provoked by the net manager update which is called during loading void impulseTPCommon(NLMISC::CBitMemStream &impulse, bool hasSeason) { CNiceInputAuto niceInputs; static std::list queuedTPs; SQueuedTP thisTP(impulse,hasSeason); queuedTPs.push_back(thisTP); BOMB_IF(queuedTPs.size()!=1,NLMISC::toString("Queueing recursive TPs depth=%u",queuedTPs.size()),return); while(!queuedTPs.empty()) { impulseTPCommon2(queuedTPs.front().Impulse,queuedTPs.front().HasSeason); queuedTPs.pop_front(); }; } void impulseTPCommon2(NLMISC::CBitMemStream &impulse, bool hasSeason) { // choose a default screen if not setuped if( LoadingBackground!=ResurectKamiBackground && LoadingBackground!=ResurectKaravanBackground && LoadingBackground!=TeleportKamiBackground && LoadingBackground!=TeleportKaravanBackground) LoadingBackground= TeleportKaravanBackground; // if resurect but user not dead, choose default. NB: this is a bug, the tp impulse should tell // which background to choose. \todo yoyo: this is a temp fix if( UserEntity && !UserEntity->isDead() && (LoadingBackground==ResurectKamiBackground || LoadingBackground==ResurectKaravanBackground) ) LoadingBackground= TeleportKaravanBackground; // Play music according to the background if(SoundMngr) { LoadingMusic.clear(); if(LoadingBackground==TeleportKamiBackground) LoadingMusic= "Kami Teleport.ogg"; else if(LoadingBackground==TeleportKaravanBackground) LoadingMusic= "Karavan Teleport.ogg"; // if resurection, continue to play death music else if(LoadingBackground==ResurectKamiBackground || LoadingBackground==ResurectKaravanBackground) { // noop } // default: loading music else { LoadingMusic= "Loading Music Loop.ogg"; } // start to play SoundMngr->playEventMusic(LoadingMusic, CSoundManager::LoadingMusicXFade, true); } // Create the loading texture. beginLoading (LoadingBackground); // No ESCAPE key UseEscapeDuringLoading = false; // Change the tips selectTipsOfTheDay (rand()); // start progress bar and display background ProgressBar.reset (BAR_STEP_TP); ucstring nmsg("Loading..."); ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) ); // received ADD_DYN_STR nlinfo("impulseTP: received a request for a TP."); sint32 x, y, z; impulse.serial(x); impulse.serial(y); impulse.serial(z); bool useHeading; impulse.serialBit( useHeading ); // Is there an orientation too ? if( useHeading ) { float angle; impulse.serial(angle); nlinfo("impulseTP: to %d %d %d %f", x, y, z, angle); CVector ori = CVector((float)cos(angle), (float)sin(angle), 0.0f); ori.normalize(); UserEntity->dir(ori, false, false); UserEntity->front(ori, false, false); UserEntity->setHeadPitch(0); UserControls.resetCameraDeltaYaw(); } else nlinfo("impulseTP: to %d %d %d", x, y, z); if (hasSeason) { extern uint8 ServerSeasonValue; extern bool ServerSeasonReceived; impulse.serial(ServerSeasonValue); ServerSeasonReceived = true; } if (ClientCfg.R2EDEnabled) { R2::getEditor().tpReceived(); } // Compute the destination. CVectorD dest = CVectorD((float)x/1000.0f, (float)y/1000.0f, (float)z/1000.0f); // Update the position for the vision. NetMngr.setReferencePosition(dest); // Change the position of the entity and in Pacs. UserEntity->pos(dest); // Fade out the Game Sound if(SoundMngr) SoundMngr->fadeOutGameSound(ClientCfg.SoundTPFade); R2::TTeleportContext tpContext = R2::TPContext_Unknown; ucstring tpReason; ucstring tpCancelText; try { R2::TR2TpInfos tpInfos; impulse.serial(tpInfos); if ( tpInfos.UseTpMessage) { tpReason = CI18N::get(tpInfos.TpReasonId); uint32 size = (uint32)tpInfos.TpReasonParams.size(); uint32 first = 0; CSString str(tpReason.toString()); for (;first != size ; ++first) { std::string value = tpInfos.TpReasonParams[first]; std::string key = NLMISC::toString("%%%u", first +1); str = str.replace( key.c_str(), value.c_str()); } tpReason = ucstring(str); tpCancelText = CI18N::get(tpInfos.TpCancelTextId); tpContext = tpInfos.TpContext; } } catch (const EStream &) { tpReason = ucstring("TP Reason"); tpCancelText = ucstring("Cancel TP"); // for test // try to deduce tp context from current editor mode switch (R2::getEditor().getMode()) { case R2::CEditor::EditionMode: case R2::CEditor::NotInitialized: tpContext = R2::TPContext_Unknown; tpReason = ucstring(); tpCancelText = ucstring(); break; case R2::CEditor::GoingToDMMode: case R2::CEditor::TestMode: case R2::CEditor::DMMode: tpContext = R2::TPContext_Edit; break; case R2::CEditor::AnimationModeLoading: case R2::CEditor::AnimationModeWaitingForLoading: case R2::CEditor::AnimationModeDm: case R2::CEditor::AnimationModeGoingToDm: tpContext = R2::TPContext_IslandOwner; break; case R2::CEditor::AnimationModePlay: case R2::CEditor::AnimationModeGoingToPlay: default: tpContext = R2::TPContext_Mainland; break; } } if (!tpReason.empty()) { std::string tpIcon; switch(tpContext) { case R2::TPContext_Mainland: tpIcon = "cancel_tp_main_land.tga"; break; case R2::TPContext_Edit: tpIcon = "cancel_tp_edit.tga"; break; case R2::TPContext_IslandOwner: tpIcon = "cancel_tp_island_owner.tga"; break; default: break; } ProgressBar.setTPMessages(tpReason, tpCancelText, tpIcon); } ProgressBar.progress(0); // enable hardware mouse to allow to click the buttons //bool oldHardwareCursor = IsMouseCursorHardware(); //InitMouseWithCursor(true); // Select the closest continent from the new position. ContinentMngr.select(dest, ProgressBar); // //InitMouseWithCursor(oldHardwareCursor); // reset 'cancel' button ProgressBar.setTPMessages(ucstring(), ucstring(), ""); // ProgressBar.enableQuitButton(false); // TMP TMP ProgressBar.progress(1.f); // do a last display without the buttons because first frame may take a while to draw, and the buttons have no more effect at this point. ProgressBar.finish(); // ProgressBar.enableQuitButton(true); // TMP TMP // Teleport the User. UserEntity->tp(dest); // Msg Received, send an acknowledge after the landscape has been loaded. CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream("TP:ACK", out)) { NetMngr.push(out); nlinfo("impulseTP: teleport acknowledge 'TP:ACK' sent."); } else nlwarning("impulseTP: unknown message name : 'TP:ACK'."); // First frame FirstFrame = true; // if tp canceling was asked, act accordingly if (ProgressBar.getTPCancelFlag(true)) { switch(tpContext) { case R2::TPContext_Mainland: CAHManager::getInstance()->runActionHandler("return_to_mainland", NULL); break; case R2::TPContext_Edit: CAHManager::getInstance()->runActionHandler("r2ed_stop_test", NULL); break; case R2::TPContext_IslandOwner: CAHManager::getInstance()->runActionHandler("r2_stop_live", NULL); break; default: break; } } initHardwareCursor(true); }// impulseTP // //----------------------------------------------- // impulseCombatEngageFailed : //----------------------------------------------- void impulseCombatEngageFailed(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; nlinfo("impulseCombatEngageFailed: Combat Engage Failed."); // Unlock the motion. UserControls.locked(false); }// impulseCombatEngageFailed // //----------------------------------------------- // impulseTeamInvitation : //----------------------------------------------- void impulseTeamInvitation(NLMISC::CBitMemStream &impulse) { nlinfo("impulseTeamInvitation: received an invitation"); uint32 textID; impulse.serial(textID); if (PermanentlyBanned) return; CInterfaceManager *pIM = CInterfaceManager::getInstance(); pIM->executeLuaScript("game:onTeamInvation("+toString(textID)+")", 0); }// impulseTeamInvitation // //----------------------------------------------- // impulseTeamShareOpen // The server request that the client opens the team sharing system //----------------------------------------------- void impulseTeamShareOpen(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; CInterfaceManager *im = CInterfaceManager::getInstance(); CGroupContainer *gc = dynamic_cast( CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share")); if (!gc) return; gc->setActive(true); CWidgetManager::getInstance()->setTopWindow(gc); gc->updateCoords(); gc->center(); }// impulseTeamShareOpen // //----------------------------------------------- // impulseTeamShareInvalid // invalidate the player validation. If someone has choosen an item/phrase after the player has validated // the player receive this message to let him know that the chance percentage to obtain a specific item has // changed and so the player can update its own settings to fit better to what he wants. // On the client side we have just to show the valid button. All the resets are done on the server side. //----------------------------------------------- void impulseTeamShareInvalid(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; CInterfaceManager *pIM = CInterfaceManager::getInstance(); CCtrlTextButton *pTB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share:content:ok")); if (pTB != NULL) pTB->setActive(true); }// impulseTeamShareInvalid // //----------------------------------------------- // impulseTeamShareClose // The server wants to close the team sharing interface (if the sharing has been validated or other reasons) //----------------------------------------------- void impulseTeamShareClose(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share")); if (pGC != NULL) pGC->setActive(false); CCtrlTextButton *pTB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share:content:ok")); if (pTB != NULL) pTB->setActive(true); }// impulseTeamShareClose // //----------------------------------------------- // impulseTeamContactInit // initialize friend list and ignore list from the contact list //----------------------------------------------- void impulseTeamContactInit(NLMISC::CBitMemStream &impulse) { vector vFriendListName; vector vFriendListOnline; vector vIgnoreListName; impulse.serialCont(vFriendListName); uint32 nbState; impulse.serial(nbState); vFriendListOnline.resize(nbState); for (uint i=0; igetDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32()); if (order == CPeopleList::sort_online) { PeopleInterraction.FriendList.sortEx(order); } }// impulseTeamContactStatus // //----------------------------------------------- // impulseTeamContactRemove // Remove a contact by the server //----------------------------------------------- void impulseTeamContactRemove(NLMISC::CBitMemStream &impulse) { uint32 contactId; uint8 nList; impulse.serial(contactId); impulse.serial(nList); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received TEAM:CONTACT_REMOVE %d %d", contactId, nList); PeopleInterraction.removeContactFromList(contactId, nList); }// impulseTeamContactRemove // //----------------------------------------------- // servers sets information of a guild member: // u16 ( member index ) u32 (player name ), u8 ( player grade + last bit set if player online ). //----------------------------------------------- /*void impulseGuildSetMemberInfo(NLMISC::CBitMemStream &impulse) { uint16 index; impulse.serial(index); uint32 guildMemberName; impulse.serial(guildMemberName); uint8 grade; impulse.serial(grade); bool online = ((grade&0x80) != 0); grade = (grade & 0x7F); CGuildManager::getInstance()->set(index, guildMemberName, grade, online); }*/ //----------------------------------------------- // vector of pair( u32 (player name ), u8 ( player grade + last bit set if player online ) ) //----------------------------------------------- /*void impulseGuildInitMemberInfo(NLMISC::CBitMemStream &impulse) { vector < pair < uint32, uint8 > > AllMembers; uint16 nbEntries; impulse.serial(nbEntries); AllMembers.resize(nbEntries); for (uint32 i = 0; i < nbEntries; ++i) { uint32 name; impulse.serial(name); uint8 gradeNonline; impulse.serial(gradeNonline); AllMembers[i].first = name; AllMembers[i].second = gradeNonline; } CGuildManager::getInstance()->init(AllMembers); }*/ //----------------------------------------------- // impulseGuildInvitation //----------------------------------------------- /*void impulseGuildInvitation(NLMISC::CBitMemStream &impulse) { nlinfo("impulseGuildInvitation"); }*/ //----------------------------------------------- // impulseGuildJoinProposal // server sent to client invitation (uint32 invitorNameId, uint32 guildNameId //----------------------------------------------- void impulseGuildJoinProposal(NLMISC::CBitMemStream &impulse) { uint32 phraseID; impulse.serial(phraseID); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received GUILD:JOIN_PROPOSAL %d", phraseID); CGuildManager::getInstance()->launchJoinProposal(phraseID); /*//activate the pop up window CInterfaceManager *im = CInterfaceManager::getInstance(); CGroupContainer *gc = dynamic_cast( CWidgetManager::getInstance()->getElementFromId("ui:interface:join_guild_proposal")); if (!gc) return; CViewText *vt = dynamic_cast(gc->getView("invitor_name")); if (vt == NULL) return; vt->setText(invitor); gc->setActive(true); CWidgetManager::getInstance()->setTopWindow(gc); gc->updateCoords(); gc->center(); gc->enableBlink(2);*/ }// impulseGuildJoinProposal // //----------------------------------------------- // impulseCloseTempInv //----------------------------------------------- void impulseCloseTempInv(NLMISC::CBitMemStream &impulse) { CTempInvManager::getInstance()->close(); } //----------------------------------------------- // impulseAscencorTeleport //----------------------------------------------- void impulseAscencorTeleport(NLMISC::CBitMemStream &impulse) { } // impulseAscencorTeleport // //----------------------------------------------- // impulseEnterCrZoneProposal // server sent to client invitation (uint32 invitorNameId, uint32 guildNameId //----------------------------------------------- void impulseEnterCrZoneProposal(NLMISC::CBitMemStream &impulse) { uint32 phraseID; impulse.serial(phraseID); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received MISSION:ASK_ENTER_CRITICAL %d", phraseID); //activate the pop up window CInterfaceManager *im = CInterfaceManager::getInstance(); CGroupContainer *gc = dynamic_cast( CWidgetManager::getInstance()->getElementFromId("ui:interface:enter_crzone_proposal")); if (!gc) return; CViewTextID *vti = dynamic_cast(gc->getView("phrase")); if (!vti) return; vti->setTextId(phraseID); gc->setActive(true); CWidgetManager::getInstance()->setTopWindow(gc); gc->updateCoords(); gc->center(); gc->enableBlink(2); }// impulseEnterCrZoneProposal // //----------------------------------------------- // impulseCloseEnterCrZoneProposal // server close proposal interface //----------------------------------------------- void impulseCloseEnterCrZoneProposal(NLMISC::CBitMemStream &impulse) { // hide interface CInterfaceManager* pIM = CInterfaceManager::getInstance(); CInterfaceGroup *pIG = (CInterfaceGroup*)CWidgetManager::getInstance()->getElementFromId ("ui:interface:enter_crzone_proposal"); if(pIG) pIG->setActive(false); }// impulseCloseEnterCrZoneProposal // //----------------------------------------------- // impulseExchangeInvitation : //----------------------------------------------- void impulseExchangeInvitation(NLMISC::CBitMemStream &impulse) { uint32 textID; impulse.serial(textID); if (PermanentlyBanned) return; CInterfaceManager* iMngr = CInterfaceManager::getInstance(); // show the modal window that allow the player to accept / decline the invitation CGroupContainer *wnd = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(PLAYER_EXCHANGE_INVITATION_DIALOG)); if (wnd) { wnd->setActive(true); wnd->updateCoords(); wnd->center(); wnd->enableBlink(2); CWidgetManager::getInstance()->setTopWindow(wnd); } CViewTextID *vti = dynamic_cast(wnd->getView("invite_phrase")); if (vti) { vti->setTextId(textID); } }// impulseExchangeInvitation // //----------------------------------------------- // impulseExchangeCloseInvitation : //----------------------------------------------- void impulseExchangeCloseInvitation(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; CInterfaceManager* iMngr = CInterfaceManager::getInstance(); // hide the modal window that allow the player to accept / decline the invitation CInterfaceGroup *wnd = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(PLAYER_EXCHANGE_INVITATION_DIALOG)); if (wnd) wnd->setActive(false); } //----------------------------------------------- // impulseMountAbort : //----------------------------------------------- void impulseMountAbort(NLMISC::CBitMemStream &impulse) { nlwarning("impulseMountAbort: Received ANIMALS:MOUNT_ABORT => no more used"); }// impulseMountAbort // //----------------------------------------------- // impulseRyzomTime : // Synchronize the ryzom time with the server. //----------------------------------------------- /* void impulseRyzomTime(NLMISC::CBitMemStream &impulse) { nlinfo("impulseRyzomTime: Ryzom Time Received"); uint32 serverTick; float ryzomTime; uint32 ryzomDay; impulse.serial(serverTick); impulse.serial(ryzomTime); impulse.serial(ryzomDay); nlinfo("impulseRyzomTime: Day '%d' Time '%f'.", ryzomDay, ryzomTime); // Initialize RT.setOrigin( serverTick, ryzomDay, ryzomTime ); }// impulseRyzomTime // */ //----------------------------------------------- // impulseWhere : // Display server position //----------------------------------------------- void impulseWhere(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received DEBUG:REPLY_WHERE"); sint32 x,y,z; impulse.serial(x); impulse.serial(y); impulse.serial(z); if (PermanentlyBanned) return; char buf[128]; double xf = ((double)x)/1000.0f; double yf = ((double)y)/1000.0f; double zf = ((double)z)/1000.0f; sprintf(buf,"Your server position is : X= %g Y= %g Z= %g",xf,yf,zf); nlinfo(buf); CInterfaceManager::getInstance()->displaySystemInfo(ucstring(buf)); }// impulseWhere // //----------------------------------------------- // impulseWho : // Display server position //----------------------------------------------- /* void impulseWho(NLMISC::CBitMemStream &impulse) { nlinfo("impulseWho Received"); CInterfaceManager::getInstance()->displaySystemInfo(ucstring("Players currently in the game :")); ucstring name; uint32 loginId; uint16 dist; uint8 dirshort; string str; while( impulse.getPos() < (sint32)impulse.length() ) { impulse.serial(name); impulse.serial(loginId); impulse.serial(dist); impulse.serial(dirshort); double angle = dirshort * 2.0 * NLMISC::Pi / 255.0; angle -= NLMISC::Pi; nlinfo ("name %s uid %u dist %hu dirshort %hu angle %f", name.toString().c_str(),loginId, dist, (uint16)dirshort, angle); sint direction =(sint) floor( 0.5 + ( 8.0 * (angle + NLMISC::Pi)/(NLMISC::Pi) ) ); direction = ((direction%16)+16)%16; static const string txts[]= { "uiW", "uiWSW", "uiSW", "uiSSW", "uiS", "uiSSE", "uiSE", "uiESE", "uiE", "uiENE", "uiNE", "uiNNE", "uiN", "uiNNW", "uiNW", "uiWNW", }; str = toString (" - uid %d - distance %hu meters - direction ", loginId, dist); CInterfaceManager::getInstance()->displaySystemInfo(ucstring(name + ucstring(str) + CI18N::get(txts[direction]))); } }// impulseWho // */ /* void impulseWhoGM(NLMISC::CBitMemStream &impulse) { nlinfo("impulseWhoGM Received"); CInterfaceManager::getInstance()->displaySystemInfo(ucstring("Players currently in the game :")); ucstring name; uint32 loginId; uint16 dist; uint8 dirshort; string str; while( impulse.getPos() < (sint32)impulse.length() ) { impulse.serial(name); impulse.serial(loginId); impulse.serial(dist); impulse.serial(dirshort); double angle = dirshort * 2.0 * NLMISC::Pi / 255.0; angle -= NLMISC::Pi; nlinfo ("name %s uid %u dist %hu dirshort %hu angle %f", name.toString().c_str(),loginId, dist, (uint16)dirshort, angle); sint direction =(sint) floor( 0.5 + ( 8.0 * (angle + NLMISC::Pi)/(NLMISC::Pi) ) ); direction = ((direction%16)+16)%16; static const string txts[]= { "uiW", "uiWSW", "uiSW", "uiSSW", "uiS", "uiSSE", "uiSE", "uiESE", "uiE", "uiENE", "uiNE", "uiNNE", "uiN", "uiNNW", "uiNW", "uiWNW", }; str = toString (" - uid %d - distance %hu meters - direction ", loginId, dist); CInterfaceManager::getInstance()->displaySystemInfo(ucstring(name + ucstring(str) + CI18N::get(txts[direction]))); } }// impulseWho // */ //----------------------------------------------- // impulseCounter : // check UDP validity //----------------------------------------------- void impulseCounter(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallBack : Received DEBUG:COUNTER"); try { uint32 counter; impulse.serial(counter); static uint queueTop = 0; static deque queue; if (counter > queueTop) { queue.resize(queue.size()+counter-queueTop, false); queueTop = counter; } if (queueTop-counter+1 > queue.size()) { nlinfo("COUNTER: counter %d arrived too late...", counter); } else { if (queue[queue.size()-1-(queueTop-counter)]) { nlwarning("COUNTER: Received counter %d more than once !", counter); } else { nldebug("COUNTER: set counter %d", counter); queue[queue.size()-1-(queueTop-counter)] = true; } while (queue.size() > 128) { if (!queue.front()) { nlwarning("COUNTER: counter %d not received !", queueTop-queue.size()-1); } queue.pop_front(); } } } catch (const Exception &e) { nlwarning ("Problem while decoding a COUTNER msg, skipped: %s", e.what()); } } //----------------------------------------------- // impulsePhraseSend : // A dyn string (or phrase) is send (so, we receive it) //----------------------------------------------- void impulsePhraseSend(NLMISC::CBitMemStream &impulse) { STRING_MANAGER::CStringManagerClient::instance()->receiveDynString(impulse); } //----------------------------------------------- // impulseStringResp : // Update the local string set //----------------------------------------------- void impulseStringResp(NLMISC::CBitMemStream &impulse) { uint32 stringId; string strUtf8; impulse.serial(stringId); impulse.serial(strUtf8); ucstring str; str.fromUtf8(strUtf8); if (PermanentlyBanned) return; STRING_MANAGER::CStringManagerClient::instance()->receiveString(stringId, str); } //----------------------------------------------- // impulseReloadCache : // reload the string cache //----------------------------------------------- void impulseReloadCache(NLMISC::CBitMemStream &impulse) { uint32 timestamp;; impulse.serial(timestamp); if (PermanentlyBanned) return; STRING_MANAGER::CStringManagerClient::instance()->loadCache(timestamp); } //----------------------------------------------- // impulseBotChatEnd // ForceThe end of the bot chat //----------------------------------------------- void impulseBotChatForceEnd(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; CBotChatManager::getInstance()->setCurrPage(NULL); } //----------------------------------------------- // MISSION COMPLETED JOURNAL //----------------------------------------------- /* #define MC_M_CONTAINER "ui:interface:info_player_journal" #define MC_S_CONTAINER "ui:interface:ipj_com_missions" #define MC_TEMPLATE "tipj_mission_complete" //----------------------------------------------- CGroupContainer *getMissionCompletedContainer() { CInterfaceManager *pIM = CInterfaceManager::getInstance(); CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(MC_M_CONTAINER); CGroupContainer *pGCM = dynamic_cast(pIE); if (pGCM == NULL) return NULL; CGroupList *pList = pGCM->getList(); CGroupContainer *pGCS = dynamic_cast(pList->getGroup(MC_S_CONTAINER)); return pGCS; } //----------------------------------------------- void clearMissions() { CGroupContainer *pGCMC = getMissionCompletedContainer(); CInterfaceGroup *pContent = pGCMC->getGroup("content"); pContent->clearGroups(); } //----------------------------------------------- void addMission(uint32 titleID) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGCMC = getMissionCompletedContainer(); if (pGCMC == NULL) { nlwarning("cannot get container for missions completed"); return; } CInterfaceGroup *pContent = pGCMC->getGroup("content"); uint32 nNbMission = pContent->getGroups().size(); vector > vArgs; vArgs.push_back(pair("id", "mc"+NLMISC::toString(nNbMission))); vArgs.push_back(pair("mcid", NLMISC::toString(titleID))); if (nNbMission == 0) { vArgs.push_back(pair("posref", "TL TL")); vArgs.push_back(pair("posparent", "parent")); vArgs.push_back(pair("y", "0")); } else { vArgs.push_back(pair("posref", "BL TL")); } CInterfaceGroup *pIG = pIM->createGroupInstance(MC_TEMPLATE, pContent->getId(), vArgs); if (pIG == NULL) { nlwarning("cannot create a mission completed"); return; } pIG->setParent(pContent); if (nNbMission == 0) pIG->setParentPos(pContent); else pIG->setParentPos(pContent->getGroups()[nNbMission-1]); pContent->addGroup(pIG); } */ //----------------------------------------------- // impulseJournalInitCompletedMissions : // initialize the player journal missions for completed missions //----------------------------------------------- void impulseJournalInitCompletedMissions (NLMISC::CBitMemStream &impulse) { /* vector vMissionCompleted; impulse.serialCont(vMissionCompleted); clearMissions(); for (uint32 i = 0; i < vMissionCompleted.size(); ++i) addMission (vMissionCompleted[i]); */ } //----------------------------------------------- // impulseJournalInitCompletedMissions : // initialize the player journal missions for completed missions //----------------------------------------------- void impulseJournalUpdateCompletedMissions (NLMISC::CBitMemStream &impulse) { /* uint32 nNewCompletedMission; impulse.serial(nNewCompletedMission); addMission (nNewCompletedMission); */ } //----------------------------------------------- // impulseJournalCantAbandon : // server refuses mission abandon //----------------------------------------------- void impulseJournalCantAbandon (NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; /// reactivate abandon button CCDBNodeLeaf *pNL = NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MISSION_ABANDON_BUTTON",false); if (pNL != NULL) pNL->setValue64(1); } //----------------------------------------------- // server add a compass target //----------------------------------------------- void impulseJournalAddCompass(NLMISC::CBitMemStream &impulse) { sint32 x; sint32 y; uint32 text; impulse.serial(x); impulse.serial(y); impulse.serial(text); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received JOURNAL:ADD_COMPASS %d %d %d", x, y, text); CCompassDialogsManager::getInstance().addEntry( x,y,text ); } //----------------------------------------------- // server removes a compass target //----------------------------------------------- void impulseJournalRemoveCompass(NLMISC::CBitMemStream &impulse) { uint32 text; impulse.serial(text); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received JOURNAL:REMOVE_COMPASS %d", text); CCompassDialogsManager::getInstance().removeEntry( text ); } // // the server ask me to execute a command // void impulseRemoteAdmin (NLMISC::CBitMemStream &impulse) { CLog logDisplayVars; CLightMemDisplayer mdDisplayVars; logDisplayVars.addDisplayer (&mdDisplayVars); mdDisplayVars.setParam (10); uint32 rid; impulse.serial (rid); string cmd; impulse.serial (cmd); // remove the 2 first rc character if exists, only there to say to the EGS that is a remote command if (cmd.size()>2 && tolower(cmd[0])=='r' && tolower(cmd[1])=='c') cmd = cmd.substr(2); mdDisplayVars.clear (); ICommand::execute(cmd, logDisplayVars, !ICommand::isCommand(cmd)); const std::deque &strs = mdDisplayVars.lockStrings(); string str; if (ICommand::isCommand(cmd)) { for (uint k = 0; k < strs.size(); k++) { str += strs[k]; } } else { if (strs.size()>0) { str = strs[0].substr(0,strs[0].size()-1); // replace all spaces into underscore because space is a reserved char for (uint i = 0; i < str.size(); i++) if (str[i] == ' ') str[i] = '_'; } else { str = "???"; } } mdDisplayVars.unlockStrings(); //nlinfo("impulseCallback : Received COMMAND:REMOTE_ADMIN : Server asked me to execute '%s', result is '%s'", cmd.c_str(), str.c_str()); CBitMemStream out; if(GenericMsgHeaderMngr.pushNameToStream("COMMAND:REMOTE_ADMIN_ANSWER", out)) { out.serial (rid); out.serial (cmd); out.serial (str); NetMngr.push (out); //nlinfo("impulseCallback : COMMAND:REMOTE_ADMIN_ANSWER %d %s %s sent", rid, cmd.c_str(), str.c_str()); } } //----------------------------------------------- // impulseGuildAscensor : // server request that the client launch the ascensor interface //----------------------------------------------- void impulseGuildAscensor (NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received GUILD:ASCENSOR"); CGuildManager::getInstance()->launchAscensor(); } //----------------------------------------------- //impulseGuildLeaveAscensor //----------------------------------------------- void impulseGuildLeaveAscensor (NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received GUILD:LEAVE_ASCENSOR"); CGuildManager::getInstance()->quitAscensor(); } //----------------------------------------------- //impulseGuildAbortCreation //----------------------------------------------- void impulseGuildAbortCreation (NLMISC::CBitMemStream &impulse) { CBotChatPage *pPage = CBotChatManager::getInstance()->getCurrPage(); CBotChatPageCreateGuild *pPageCG = dynamic_cast(pPage); if (pPageCG == BotChatPageAll->CreateGuild) CBotChatManager::getInstance()->setCurrPage(NULL); } void impulseGuildOpenGuildWindow(NLMISC::CBitMemStream &impulse) { CGuildManager::getInstance()->openGuildWindow(); } //----------------------------------------------- // impulseGuildOpenInventory //----------------------------------------------- void impulseGuildOpenInventory (NLMISC::CBitMemStream &impulse) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_GUILD_OPENED")->setValue32(1); } //----------------------------------------------- // impulseGuildCloseInventory //----------------------------------------------- void impulseGuildCloseInventory (NLMISC::CBitMemStream &impulse) { CInterfaceManager *pIM = CInterfaceManager::getInstance(); NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_GUILD_OPENED")->setValue32(0); } //----------------------------------------------- // impulseGuildUpdatePlayerTitle // server block/unblock some reserved titles //----------------------------------------------- void impulseGuildUpdatePlayerTitle(NLMISC::CBitMemStream &impulse) { CSkillManager *pSM = CSkillManager::getInstance(); bool bUnblock; impulse.serial(bUnblock); vector vTitles; impulse.serialCont(vTitles); if (PermanentlyBanned) return; if (bUnblock) { for (uint32 i = 0; i < vTitles.size(); ++i) pSM->unblockTitleFromServer((CHARACTER_TITLE::ECharacterTitle)vTitles[i]); } else { for (uint32 i = 0; i < vTitles.size(); ++i) pSM->blockTitleFromServer((CHARACTER_TITLE::ECharacterTitle)vTitles[i]); } } //----------------------------------------------- // impulseGuildUseFemaleTitles // server activates/deactivates use of female titles //----------------------------------------------- void impulseGuildUseFemaleTitles(NLMISC::CBitMemStream &impulse) { impulse.serial( UseFemaleTitles ); } //----------------------------------------------- // impulsePhraseDownLoad // server upload the phrases. //----------------------------------------------- void impulsePhraseDownLoad (NLMISC::CBitMemStream &impulse) { std::vector phrases; // Read Known Phrases impulse.serialCont(phrases); CSPhraseManager *pPM= CSPhraseManager::getInstance(); for(uint i=0;ibuildPhraseFromSheet(phraseCom, phrases[i].PhraseSheetId.asInt()); pPM->setPhraseNoUpdateDB(phrases[i].KnownSlot, phraseCom); } else { pPM->setPhraseNoUpdateDB(phrases[i].KnownSlot, phrases[i].Phrase); } } // must update the DB (NB: if initInGameDone) after all phrase set. pPM->updateBookDB(); // Then Read Memorized Phrases std::vector memorizedPhrases; impulse.serialCont(memorizedPhrases); if (PermanentlyBanned) return; for(uint i=0;imemorizePhrase( memorizedPhrases[i].MemoryLineId, memorizedPhrases[i].MemorySlotId, memorizedPhrases[i].PhraseId); } // OK. extern bool SabrinaPhraseBookLoaded; SabrinaPhraseBookLoaded= true; // update gray state, if game inited. pPM->updateMemoryBar(); } //----------------------------------------------- // impulsePhraseConfirmBuy // server confirm/infirm the buy of botchat phrase. //----------------------------------------------- void impulsePhraseConfirmBuy (NLMISC::CBitMemStream &impulse) { uint16 phraseId; bool confirm; impulse.serial(phraseId); impulse.serial(confirm); if (PermanentlyBanned) return; CSPhraseManager *pSM= CSPhraseManager::getInstance(); pSM->receiveBotChatConfirmBuy(phraseId, confirm); } //----------------------------------------------- // impulsePhraseAckExecuteCyclic // server confirm/infirm the cyclic execution of a phrase //----------------------------------------------- void impulsePhraseAckExecuteCyclic (NLMISC::CBitMemStream &impulse) { uint8 counter; bool ok; impulse.serial(ok); impulse.serial(counter); if (PermanentlyBanned) return; CSPhraseManager *pSM= CSPhraseManager::getInstance(); pSM->receiveAckExecuteFromServer(true, counter, ok); } //----------------------------------------------- // impulsePhraseAckExecuteCyclic // server confirm/infirm the execution of a phrase //----------------------------------------------- void impulsePhraseAckExecuteNext (NLMISC::CBitMemStream &impulse) { uint8 counter; bool ok; impulse.serial(ok); impulse.serial(counter); if (PermanentlyBanned) return; CSPhraseManager *pSM= CSPhraseManager::getInstance(); pSM->receiveAckExecuteFromServer(false, counter, ok); } // Same params as in BOMB_IF #ifdef FINAL_VERSION #define SKIP_IF(condition,msg,skipAction) if (!(condition)); else skipAction; #else #define SKIP_IF(condition,msg,skipAction) if (!(condition)) WARN(msg); else skipAction; #endif template void updateInventoryFromStream (NLMISC::CBitMemStream &impulse, const CInventoryCategoryTemplate *templ, bool notifyItemSheetChanges) { try { // get the egs tick of this change TGameCycle serverTick; impulse.serial(serverTick); // For All inventories for ( uint invId=0; invId!=CInventoryCategoryTemplate::NbInventoryIds; ++invId ) { // Presence bit bool hasContent; impulse.serialBit( hasContent ); if ( ! hasContent ) continue; // Number field uint32 nbChanges; impulse.serial( nbChanges, INVENTORIES::LowNumberBits ); if ( nbChanges == INVENTORIES::LowNumberBound ) impulse.serial( nbChanges, 32 ); const string invBranchStr = CInventoryCategoryTemplate::getDbStr( (typename CInventoryCategoryTemplate::TInventoryId)invId ); ICDBNode::CTextId textId( invBranchStr ); ICDBNode *inventoryNode = IngameDbMngr.getNodePtr()->getNode( textId, false ); BOMB_IF( !inventoryNode, "Inventory missing in database", return ) // List of updates for ( uint c=0; c!=nbChanges; ++c ) { // Unpack (the bitmemstream is written from high-order to low-order) uint32 iuInfoVersion; impulse.serial( iuInfoVersion, 1 ); if ( iuInfoVersion == 1 ) { uint32 slotIndex; impulse.serial( slotIndex, CInventoryCategoryTemplate::SlotBitSize ); // Access the database leaf CCDBNodeBranch *slotNode = static_cast(inventoryNode->getNode( (uint16)slotIndex )); ICDBNode *leafNode = slotNode->find( INVENTORIES::InfoVersionStr ); BOMB_IF( !leafNode, "Inventory slot property missing in database", continue ); // Apply or increment Info Version in database if ( CInventoryCategoryTemplate::needPlainInfoVersionTransfer() ) { uint32 infoVersion; impulse.serial( infoVersion, INVENTORIES::InfoVersionBitSize ); ((CCDBNodeLeaf*)leafNode)->setPropCheckGC( serverTick, infoVersion ); } else { // NB: don't need to check GC on a info version upgrade, since this is always a delta of +1 // the order of received of this impulse is not important ((CCDBNodeLeaf*)leafNode)->setValue64( ((CCDBNodeLeaf*)leafNode)->getValue64() + 1 ); } } else { uint32 iuAll; impulse.serial( iuAll, 1 ); if ( iuAll == 1 ) { INVENTORIES::CItemSlot itemSlot; itemSlot.serialAll( impulse, templ ); //nldebug( "Inv %s Update %u", CInventoryCategoryTemplate::InventoryStr[invId], itemSlot.getSlotIndex() ); // Apply all properties to database CCDBNodeBranch *slotNode = static_cast(inventoryNode->getNode( (uint16)itemSlot.getSlotIndex() )); for ( uint i=0; i!=INVENTORIES::NbItemPropId; ++i ) { CCDBNodeLeaf *leafNode = static_cast(slotNode->find( string(INVENTORIES::CItemSlot::ItemPropStr[i]) )); SKIP_IF( !leafNode, "Inventory slot property missing in database", continue ); leafNode->setPropCheckGC( serverTick, (sint64)itemSlot.getItemProp( ( INVENTORIES::TItemPropId)i ) ); } } else { uint32 iuOneProp; impulse.serial( iuOneProp, 1 ); if ( iuOneProp == 1 ) { INVENTORIES::CItemSlot itemSlot; itemSlot.serialOneProp( impulse, templ ); //nldebug( "Inv %s Prop %u %s", CInventoryCategoryTemplate::InventoryStr[invId], itemSlot.getSlotIndex(), INVENTORIES::CItemSlot::ItemPropStr[itemSlot.getOneProp().ItemPropId] ); // Apply property to database CCDBNodeBranch *slotNode = static_cast(inventoryNode->getNode( (uint16)itemSlot.getSlotIndex() )); CCDBNodeLeaf *leafNode = safe_cast(slotNode->find( string(INVENTORIES::CItemSlot::ItemPropStr[itemSlot.getOneProp().ItemPropId]) )); SKIP_IF( !leafNode, "Inventory slot property missing in database", continue ); leafNode->setPropCheckGC( serverTick, (sint64)itemSlot.getOneProp().ItemPropValue ); } else // iuReset { uint32 slotIndex; impulse.serial( slotIndex, CInventoryCategoryTemplate::SlotBitSize ); //nldebug( "Inv %s Reset %u", CInventoryCategoryTemplate::InventoryStr[invId], slotIndex ); // Reset all properties in database CCDBNodeBranch *slotNode = static_cast(inventoryNode->getNode( (uint16)slotIndex )); for ( uint i=0; i!=INVENTORIES::NbItemPropId; ++i ) { // Instead of clearing all leaves (by index), we must find and clear only the // properties in TItemPropId, because the actual database leaves may have // less properties, and because we must not clear the leaf INFO_VERSION. CCDBNodeLeaf *leafNode = safe_cast(slotNode->find( string(INVENTORIES::CItemSlot::ItemPropStr[i]) )); SKIP_IF( !leafNode, "Inventory slot property missing in database", continue ); leafNode->setPropCheckGC( serverTick, 0 ); } } } } } } CInventoryManager::getInstance()->sortBag(); } catch (const Exception &e) { nlwarning ("Problem while decoding a DB_UPD_INV msg, skipped: %s", e.what()); } } //----------------------------------------------- // impulseUpdateInventory: //----------------------------------------------- void impulseUpdateInventory (NLMISC::CBitMemStream &impulse) { updateInventoryFromStream( impulse, (INVENTORIES::CInventoryCategoryForCharacter*)NULL, true ); }; //----------------------------------------------- // impulseInitInventory: //----------------------------------------------- void impulseInitInventory (NLMISC::CBitMemStream &impulse) { sint32 p = impulse.getPos(); impulseUpdateInventory( impulse ); IngameDbMngr.setInitPacketReceived(); nlinfo( "DB_INIT:INV done (%u bytes)", impulse.getPos()-p ); } //----------------------------------------------- // impulseItemInfoSet: //----------------------------------------------- void impulseItemInfoSet (NLMISC::CBitMemStream &impulse) { CItemInfos itemInfos; impulse.serial(itemInfos); getInventory().onReceiveItemInfo(itemInfos); } //----------------------------------------------- // impulseItemInfoRefreshVersion: //----------------------------------------------- void impulseItemInfoRefreshVersion (NLMISC::CBitMemStream &impulse) { uint16 slotId; uint8 infoVersion; impulse.serial(slotId); impulse.serial(infoVersion); getInventory().onRefreshItemInfoVersion(slotId, infoVersion); } //----------------------------------------------- // impulsePrereqInfoSet: //----------------------------------------------- void impulsePrereqInfoSet (NLMISC::CBitMemStream &impulse) { CPrerequisitInfos prereqInfos; uint8 index; impulse.serial(prereqInfos); impulse.serial(index); //write infos in interface CBotChatManager::getInstance()->onReceiveMissionInfo(index, prereqInfos); } //----------------------------------------------- //----------------------------------------------- void impulseDeathRespawnPoint (NLMISC::CBitMemStream &impulse) { CRespawnPointsMsg msg; impulse.serial(msg); if (PermanentlyBanned) return; CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupMap *pMap = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:respawn_map:content:map_content:actual_map")); if (pMap == NULL) { nlwarning("problem cannot find ui:interface:respawn_map:content:map_content:actual_map"); return; } pMap->addRespawnPoints(msg); pMap = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:map:content:map_content:actual_map")); if (pMap == NULL) { nlwarning("problem cannot find ui:interface:map:content:map_content:actual_map"); return; } pMap->addRespawnPoints(msg); } //----------------------------------------------- //----------------------------------------------- void impulseDeathRespawn (NLMISC::CBitMemStream &impulse) { // TODO : Bring me to life !!! } //----------------------------------------------- // impulseDuelInvitation : //----------------------------------------------- void impulseDuelInvitation(NLMISC::CBitMemStream &impulse) { uint32 textID; impulse.serial(textID); //nlinfo("impulseCallback : Received DUEL:INVITATION %d", textID); if (PermanentlyBanned) return; //activate the pop up window CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_duel_proposal")); if (pGC == NULL) return; CViewTextID *pVTID = dynamic_cast(pGC->getView("invitor_name")); if (pVTID == NULL) return; pVTID->setTextId(textID); pGC->setActive(true); CWidgetManager::getInstance()->setTopWindow(pGC); pGC->updateCoords(); pGC->center(); pGC->enableBlink(2); }// impulseDuelInvitation // //----------------------------------------------- // impulseDuelCancelInvitation: //----------------------------------------------- void impulseDuelCancelInvitation(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received DUEL:CANCEL_INVITATION"); //activate the pop up window CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_duel_proposal")); if (pGC == NULL) return; pGC->setActive(false); }// impulseDuelCancelInvitation // //----------------------------------------------- // impulsePVPChallengeInvitation : //----------------------------------------------- void impulsePVPChallengeInvitation(NLMISC::CBitMemStream &impulse) { uint32 textID; impulse.serial(textID); if (PermanentlyBanned) return; //nlinfo("impulseCallback : Received PVP_CHALLENGE:INVITATION %d", textID); //activate the pop up window CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_challenge_proposal")); if (pGC == NULL) return; CViewTextID *pVTID = dynamic_cast(pGC->getView("invitor_name")); if (pVTID == NULL) return; pVTID->setTextId(textID); pGC->setActive(true); CWidgetManager::getInstance()->setTopWindow(pGC); pGC->updateCoords(); pGC->center(); pGC->enableBlink(2); }// impulsePVPChallengeInvitation // //----------------------------------------------- // impulsePVPChallengeCancelInvitation: //----------------------------------------------- void impulsePVPChallengeCancelInvitation(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received PVP_CHALLENGE:CANCEL_INVITATION"); //activate the pop up window CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_challenge_proposal")); if (pGC == NULL) return; pGC->setActive(false); }// impulsePVPChallengeCancelInvitation // //----------------------------------------------- // impulsePVPFactionPushFactionWar: //----------------------------------------------- void impulsePVPFactionPushFactionWar(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received PVP_FACTION:PUSH_FACTION_WAR"); PVP_CLAN::CFactionWar factionWar; impulse.serialEnum(factionWar.Clan1); impulse.serialEnum(factionWar.Clan2); CFactionWarManager::getInstance()->addFactionWar(factionWar); } //----------------------------------------------- // impulsePVPFactionPopFactionWar: //----------------------------------------------- void impulsePVPFactionPopFactionWar(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received PVP_FACTION:POP_FACTION_WAR"); PVP_CLAN::CFactionWar factionWar; impulse.serialEnum(factionWar.Clan1); impulse.serialEnum(factionWar.Clan2); CFactionWarManager::getInstance()->stopFactionWar(factionWar); } //----------------------------------------------- // impulsePVPFactionFactionWars: //----------------------------------------------- void impulsePVPFactionFactionWars(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received PVP_FACTION:FACTION_WARS"); CFactionWarsMsg factionWars; impulse.serial(factionWars); for( uint i=0; iaddFactionWar(factionWars.FactionWarOccurs[i]); } } //----------------------------------------------- // impulsePVPChooseClan //----------------------------------------------- /* void impulsePVPChooseClan(NLMISC::CBitMemStream &impulse) { nlinfo("impulsePVPChooseClan : Received PVP_CLAN:CHOOSE_CLAN"); EGSPD::CPeople::TPeople clan1= EGSPD::CPeople::Unknown, clan2= EGSPD::CPeople::Unknown; impulse.serialEnum( clan1 ); impulse.serialEnum( clan2 ); if (PermanentlyBanned) return; //activate the pop up window CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_clan_proposal")); if (pGC == NULL) return; pGC->setActive(true); CCtrlTextButton * butClan1 = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_clan_proposal:content:clan1")); if( butClan1 == NULL ) return; butClan1->setText( ucstring(EGSPD::CPeople::toString( clan1 )) ); CCtrlTextButton * butClan2 = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_clan_proposal:content:clan2")); if( butClan2 == NULL ) return; butClan2->setText( ucstring(EGSPD::CPeople::toString( clan2 )) ); } */ //----------------------------------------------- // impulseEncyclopediaUpdate //----------------------------------------------- void impulseEncyclopediaUpdate(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received ENCYCLOPEDIA:UPDATE"); CEncyclopediaUpdateMsg msg; impulse.serial(msg); if (PermanentlyBanned) return; CEncyclopediaManager::getInstance()->update(msg); }// impulseEncyclopediaUpdate // //----------------------------------------------- // impulseEncyclopediaInit //----------------------------------------------- void impulseEncyclopediaInit(NLMISC::CBitMemStream &impulse) { //nlinfo("impulseCallback : Received ENCYCLOPEDIA:INIT"); CEncyclopediaUpdateMsg msg; impulse.serial(msg); if (PermanentlyBanned) return; CEncyclopediaManager::getInstance()->update(msg); }// impulseEncyclopediaInit // //----------------------------------------------- //----------------------------------------------- void impulseItemOpenRoomInventory(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; // This is a message because we may do other things there CInterfaceManager *pIM = CInterfaceManager::getInstance(); NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_ROOM_OPENED")->setValue32(1); } //----------------------------------------------- //----------------------------------------------- void impulseItemCloseRoomInventory(NLMISC::CBitMemStream &impulse) { if (PermanentlyBanned) return; // This is a message because we may do other things there CInterfaceManager *pIM = CInterfaceManager::getInstance(); NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_ROOM_OPENED")->setValue32(0); // deactivate the pop up window CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:inv_room")); if (pGC == NULL) return; pGC->setActive(false); } //----------------------------------------------- //----------------------------------------------- void impulseUserBars(NLMISC::CBitMemStream &impulse) { uint8 msgNumber; sint32 hp, sap, sta, focus; impulse.serial(msgNumber); impulse.serial(hp); impulse.serial(sap); impulse.serial(sta); impulse.serial(focus); if (PermanentlyBanned) return; // Setup the user Bars CBarManager::CBarInfo bi; CBarManager::getInstance()->setupUserBarInfo(msgNumber, hp, sap, sta, focus); } //----------------------------------------------- //----------------------------------------------- void impulseOutpostChooseSide(NLMISC::CBitMemStream &impulse) { // read message bool playerGuildInConflict; bool playerGuildIsAttacker; impulse.serial(playerGuildInConflict); impulse.serial(playerGuildIsAttacker); uint32 ownerGuildNameId; impulse.serial( ownerGuildNameId ); uint32 attackerGuildNameId; impulse.serial( attackerGuildNameId ); uint32 declTimer; impulse.serial( declTimer ); // start OutpostManager.startPvpJoinProposal(playerGuildInConflict, playerGuildIsAttacker, ownerGuildNameId, attackerGuildNameId, declTimer); } //----------------------------------------------- //----------------------------------------------- void impulseOutpostDeclareWarAck(NLMISC::CBitMemStream &impulse) { bool canValidate; uint32 docTextId; uint32 timeStartAttack; impulse.serial(canValidate); impulse.serial(docTextId); impulse.serial(timeStartAttack); // write result in Local DB. CInterfaceManager *pIM= CInterfaceManager::getInstance(); // ack reception CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_RECEIVED"); if(node) node->setValueBool(true); // set result of ACK node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_OK"); if(node) node->setValueBool(canValidate); node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TEXTID"); if(node) node->setValue32(docTextId); node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TIME_RANGE_ATT"); if(node) node->setValue32(timeStartAttack); } extern void addWebIGParams(string &url, bool trustedDomain); //----------------------------------------------- //----------------------------------------------- class CServerMessageBoxOnReceiveTextId : public STRING_MANAGER::IStringWaitCallback { private: enum TTextType {TitleType= 0, ContentType, NumTextType}; uint32 _TextId[NumTextType]; bool _TextReceived[NumTextType]; bool _AlreadyDisplayed; // show the window void activateMsgBoxWindow() { STRING_MANAGER::CStringManagerClient *pSMC= STRING_MANAGER::CStringManagerClient::instance(); // get the content string (should have been received!) ucstring contentStr; ucstring titleStr; if(!pSMC->getDynString(_TextId[ContentType], contentStr)) return; if(!pSMC->getDynString(_TextId[TitleType], titleStr)) return; // if the string start with a @{Wxxxx} code, remove it and get the wanted window size sint w = 256; // default size to 256 !! bool is_webig = false; if(contentStr.size()>=6 && contentStr[0]=='W' && contentStr[1]=='E' && contentStr[2]=='B' && contentStr[3]==' ' && contentStr[4]==':' && contentStr[5]==' ' ) { uint i; const uint digitStart= 6; const uint digitMaxEnd= (uint)contentStr.size(); is_webig = true; for(i = digitStart; i < digitMaxEnd; i++) { if(contentStr[i] == ' ') break; } if(i != digitMaxEnd) { ucstring web_app = contentStr.substr(digitStart, i-digitStart); contentStr = ucstring("http://"+ClientCfg.WebIgMainDomain+"/start/")+web_app+ucstring(".php?")+contentStr.substr(i+1); } else { contentStr = ""; i = digitStart; } } else if(contentStr.size()>=5 && contentStr[0]=='@' && contentStr[1]=='{' && contentStr[2]=='W') { uint i; const uint digitStart= 3; const uint digitMaxEnd= 8; for(i=digitStart;i group = group.substr(9, group.size()-10); groupHtml = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:"+group+":content:html")); if (!groupHtml) { groupHtml = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:webig:content:html")); group = "webig"; } if (groupHtml) { CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:"+group)); if (pGC) { if (contentStr.empty()) { pGC->setActive(false); } else { if (group == "webig") pGC->setActive(true); string url = contentStr.toString(); addWebIGParams(url, true); groupHtml->browse(url.c_str()); CWidgetManager::getInstance()->setTopWindow(pGC); } } } } else { CGroupContainer *pGC = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:server_message_box")); if (pGC) { // show the window with correct width pGC->setW(w); pGC->setActive(true); // must set the text by hand CViewText *vt= dynamic_cast(CWidgetManager::getInstance()->getElementFromId(pIM->getDefine("server_message_box_content_view_text"))); if(vt) vt->setTextFormatTaged(contentStr); // open CWidgetManager::getInstance()->setTopWindow(pGC); pGC->invalidateCoords(); // Yoyo: because of buggued group container, I found that 6 times is a good number.... for(uint i=0;i<6;i++) pGC->updateCoords(); pGC->center(); pGC->enableBlink(2); } } } public: // called when the string is available virtual void onDynStringAvailable(uint stringId, const ucstring &value) { // don't care if already displayed if(_AlreadyDisplayed) return; // check if one of waited text for(uint i=0;i display window _AlreadyDisplayed= true; activateMsgBoxWindow(); } // start the waiter void startWaitTexts(uint32 titleTextId, uint32 docTextId) { // reset _TextId[TitleType]= titleTextId; _TextId[ContentType]= docTextId; _TextReceived[TitleType]= false; _TextReceived[ContentType]= false; _AlreadyDisplayed= false; // start to wait receive of those string (NB: they may be already here, but waitDynStrings calls directly the callback in this case) STRING_MANAGER::CStringManagerClient *pSMC= STRING_MANAGER::CStringManagerClient::instance(); pSMC->waitDynString(titleTextId, this); pSMC->waitDynString(docTextId, this); } }; CServerMessageBoxOnReceiveTextId ServerMessageBoxOnReceiveTextId; void impulseUserPopup(NLMISC::CBitMemStream &impulse) { uint32 titleTextId; uint32 docTextId; impulse.serial(titleTextId); impulse.serial(docTextId); // setup TEMP DB for title CInterfaceManager *pIM= CInterfaceManager::getInstance(); CCDBNodeLeaf *node= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:SERVER_POPUP:TITLE"); if(node) node->setValue32(titleTextId); // Open the Popup only when the 2 dyn strings are available ServerMessageBoxOnReceiveTextId.startWaitTexts(titleTextId, docTextId); } //----------------------------------------------- //----------------------------------------------- //extern void impulseCombatFlyingHpDelta(NLMISC::CBitMemStream &impulse); void impulseCombatFlyingHpDelta(NLMISC::CBitMemStream &impulse) { uint32 entityID; uint32 rgba; sint16 hpDelta; impulse.serial(entityID); impulse.serial(rgba); impulse.serial(hpDelta); CRGBA color((uint8)(rgba>>24&255), (uint8)(rgba>>16&255), (uint8)(rgba>>8&255), (uint8)(rgba&255)); CEntityCL *entity = EntitiesMngr.getEntityByCompressedIndex(entityID); if (entity) entity->addHPOutput(ucstring(toString("%d", hpDelta)), color); } void impulseCombatFlyingTextItemSpecialEffectProc(NLMISC::CBitMemStream &impulse) { uint32 entityID; uint32 rgba; uint8 effect; sint32 param; impulse.serial(entityID); impulse.serial(rgba); impulse.serial(effect); impulse.serial(param); CRGBA color((uint8)(rgba>>24&255), (uint8)(rgba>>16&255), (uint8)(rgba>>8&255), (uint8)(rgba&255)); ucstring text = CI18N::get(toString("uiItemSpecialEffectFlyingText%s", ITEM_SPECIAL_EFFECT::toString((ITEM_SPECIAL_EFFECT::TItemSpecialEffect)effect).c_str())); strFindReplace(text, "%param", toString("%d", param)); CEntityCL *entity = EntitiesMngr.getEntityByCompressedIndex(entityID); if (entity) entity->addHPOutput(text, color); } void impulseCombatFlyingText(NLMISC::CBitMemStream &impulse) { uint32 entityID; uint8 tmp; impulse.serial(entityID); impulse.serial(tmp); COMBAT_FLYING_TEXT::TCombatFlyingText type = (COMBAT_FLYING_TEXT::TCombatFlyingText)tmp; CRGBA color(255, 255, 255); ucstring text(""); float dt = 0.0f; switch (type) { case COMBAT_FLYING_TEXT::TargetDodge: // The target dodged color = CRGBA(255, 128, 64); text = CI18N::get("uiDodge"); break; case COMBAT_FLYING_TEXT::TargetParry: // The target parried color = CRGBA(255, 128, 64); text = CI18N::get("uiParry"); break; case COMBAT_FLYING_TEXT::TargetEvade: // Actually the user miss his hit color = CRGBA(255, 128, 64); text = CI18N::get("uiEvade"); break; case COMBAT_FLYING_TEXT::SelfEvade: // Actually the target miss his hit color = CRGBA(255, 255, 0); text = CI18N::get("uiEvade"); break; case COMBAT_FLYING_TEXT::TargetResist: // The target resisted magic color = CRGBA(255, 128, 64); text = CI18N::get("uiResist"); break; case COMBAT_FLYING_TEXT::SelfResist: // The user resisted magic color = CRGBA(255, 255, 0); text = CI18N::get("uiResist"); break; case COMBAT_FLYING_TEXT::SelfInterrupt: // the user cast was interupted color = CRGBA(200, 0, 0); text = CI18N::get("uiInterrupt"); dt = 0.4f; break; case COMBAT_FLYING_TEXT::SelfFailure: // The user failed to cast color = CRGBA(200, 0, 0); text = CI18N::get("uiFailure"); break; default: // bad type nlwarning("Bad type for COMBAT_FLYING_TEXT:TCombatFlyingText enum"); break; } CEntityCL *entity = EntitiesMngr.getEntityByCompressedIndex(entityID); if (entity) entity->addHPOutput(text, color, dt); } void impulseSetSeason(NLMISC::CBitMemStream &impulse) { extern uint8 ServerSeasonValue; extern bool ServerSeasonReceived; impulse.serial(ServerSeasonValue); ServerSeasonReceived = true; } void impulseDssDown(NLMISC::CBitMemStream &impulse) { FarTP.onDssDown(); } void impulseSetNpcIconDesc(NLMISC::CBitMemStream &impulse) { uint8 nb8; impulse.serial(nb8); bool hasChanged = false; for (uint i=0; i!=(uint)nb8; ++i) { TNPCIconCacheKey npcIconCacheKey; impulse.serial(npcIconCacheKey); uint32 state; impulse.serial(state); hasChanged = CNPCIconCache::getInstance().onReceiveMissionAvailabilityForThisChar(npcIconCacheKey, (NPC_ICON::TNPCMissionGiverState)state) || hasChanged; // mind the order to avoid partial evaluation } if (hasChanged) CNPCIconCache::getInstance().refreshIconsOfScene(); } void impulseServerEventForMissionAvailability(NLMISC::CBitMemStream &impulse) { CNPCIconCache::getInstance().onEventForMissionAvailabilityForThisChar(); } void impulseSetNpcIconTimer(NLMISC::CBitMemStream &impulse) { NLMISC::TGameCycle delay; impulse.serial(delay); CNPCIconCache::getInstance().setMissionGiverTimer(delay); } //----------------------------------------------- // initializeNetwork : //----------------------------------------------- void initializeNetwork() { GenericMsgHeaderMngr.setCallback("DB_UPD_PLR", impulseDatabaseUpdatePlayer); GenericMsgHeaderMngr.setCallback("DB_INIT:PLR", impulseDatabaseInitPlayer); GenericMsgHeaderMngr.setCallback("DB_UPD_INV", impulseUpdateInventory); GenericMsgHeaderMngr.setCallback("DB_INIT:INV", impulseInitInventory); GenericMsgHeaderMngr.setCallback("DB_GROUP:UPDATE_BANK", impulseDatabaseUpdateBank); GenericMsgHeaderMngr.setCallback("DB_GROUP:INIT_BANK", impulseDatabaseInitBank); GenericMsgHeaderMngr.setCallback("DB_GROUP:RESET_BANK", impulseDatabaseResetBank); GenericMsgHeaderMngr.setCallback("CONNECTION:NO_USER_CHAR", impulseNoUserChar); GenericMsgHeaderMngr.setCallback("CONNECTION:USER_CHARS", impulseUserChars); GenericMsgHeaderMngr.setCallback("CONNECTION:USER_CHAR", impulseUserChar); GenericMsgHeaderMngr.setCallback("CONNECTION:FAR_TP", impulseFarTP); GenericMsgHeaderMngr.setCallback("CONNECTION:READY", impulseServerReady); GenericMsgHeaderMngr.setCallback("CONNECTION:VALID_NAME", impulseCharNameValid); GenericMsgHeaderMngr.setCallback("CONNECTION:SHARD_ID", impulseShardId); GenericMsgHeaderMngr.setCallback("CONNECTION:SERVER_QUIT_OK", impulseServerQuitOk); GenericMsgHeaderMngr.setCallback("CONNECTION:SERVER_QUIT_ABORT", impulseServerQuitAbort); GenericMsgHeaderMngr.setCallback("CONNECTION:MAIL_AVAILABLE", impulseMailNotification); GenericMsgHeaderMngr.setCallback("CONNECTION:GUILD_MESSAGE_AVAILABLE", impulseForumNotification); GenericMsgHeaderMngr.setCallback("CONNECTION:PERMANENT_BAN", impulsePermanentBan); GenericMsgHeaderMngr.setCallback("CONNECTION:UNBAN", impulsePermanentUnban); GenericMsgHeaderMngr.setCallback("STRING:CHAT", impulseChat); GenericMsgHeaderMngr.setCallback("STRING:TELL", impulseTell); GenericMsgHeaderMngr.setCallback("STRING:FAR_TELL", impulseFarTell); GenericMsgHeaderMngr.setCallback("STRING:CHAT2", impulseChat2); GenericMsgHeaderMngr.setCallback("STRING:DYN_STRING", impulseDynString); GenericMsgHeaderMngr.setCallback("STRING:DYN_STRING_GROUP", inpulseDynStringInChatGroup); GenericMsgHeaderMngr.setCallback("STRING:TELL2", impulseTell2); // GenericMsgHeaderMngr.setCallback("STRING:ADD_DYN_STR", impulseAddDynStr); GenericMsgHeaderMngr.setCallback("TP:DEST", impulseTP); GenericMsgHeaderMngr.setCallback("TP:DEST_WITH_SEASON", impulseTPWithSeason); GenericMsgHeaderMngr.setCallback("TP:CORRECT", impulseCorrectPos); GenericMsgHeaderMngr.setCallback("COMBAT:ENGAGE_FAILED", impulseCombatEngageFailed); GenericMsgHeaderMngr.setCallback("BOTCHAT:DYNCHAT_OPEN", impulseDynChatOpen); GenericMsgHeaderMngr.setCallback("BOTCHAT:DYNCHAT_CLOSE", impulseDynChatClose); GenericMsgHeaderMngr.setCallback("CASTING:BEGIN", impulseBeginCast); GenericMsgHeaderMngr.setCallback("TEAM:INVITATION", impulseTeamInvitation); GenericMsgHeaderMngr.setCallback("TEAM:SHARE_OPEN", impulseTeamShareOpen); GenericMsgHeaderMngr.setCallback("TEAM:SHARE_INVALID", impulseTeamShareInvalid); GenericMsgHeaderMngr.setCallback("TEAM:SHARE_CLOSE", impulseTeamShareClose); GenericMsgHeaderMngr.setCallback("TEAM:CONTACT_INIT", impulseTeamContactInit); GenericMsgHeaderMngr.setCallback("TEAM:CONTACT_CREATE", impulseTeamContactCreate); GenericMsgHeaderMngr.setCallback("TEAM:CONTACT_STATUS", impulseTeamContactStatus); GenericMsgHeaderMngr.setCallback("TEAM:CONTACT_REMOVE", impulseTeamContactRemove); GenericMsgHeaderMngr.setCallback("EXCHANGE:INVITATION", impulseExchangeInvitation); GenericMsgHeaderMngr.setCallback("EXCHANGE:CLOSE_INVITATION", impulseExchangeCloseInvitation); GenericMsgHeaderMngr.setCallback("ANIMALS:MOUNT_ABORT", impulseMountAbort); GenericMsgHeaderMngr.setCallback("DEBUG:REPLY_WHERE", impulseWhere); GenericMsgHeaderMngr.setCallback("DEBUG:COUNTER", impulseCounter); // GenericMsgHeaderMngr.setCallback("STRING_MANAGER:PHRASE_SEND", impulsePhraseSend); GenericMsgHeaderMngr.setCallback("STRING_MANAGER:STRING_RESP", impulseStringResp); GenericMsgHeaderMngr.setCallback("STRING_MANAGER:RELOAD_CACHE", impulseReloadCache); // GenericMsgHeaderMngr.setCallback("BOTCHAT:FORCE_END", impulseBotChatForceEnd); GenericMsgHeaderMngr.setCallback("JOURNAL:INIT_COMPLETED_MISSIONS", impulseJournalInitCompletedMissions); GenericMsgHeaderMngr.setCallback("JOURNAL:UPDATE_COMPLETED_MISSIONS", impulseJournalUpdateCompletedMissions); // GenericMsgHeaderMngr.setCallback("JOURNAL:CANT_ABANDON", impulseJournalCantAbandon); GenericMsgHeaderMngr.setCallback("JOURNAL:ADD_COMPASS", impulseJournalAddCompass); GenericMsgHeaderMngr.setCallback("JOURNAL:REMOVE_COMPASS", impulseJournalRemoveCompass); //GenericMsgHeaderMngr.setCallback("GUILD:SET_MEMBER_INFO", impulseGuildSetMemberInfo); //GenericMsgHeaderMngr.setCallback("GUILD:INIT_MEMBER_INFO", impulseGuildInitMemberInfo); GenericMsgHeaderMngr.setCallback("GUILD:JOIN_PROPOSAL", impulseGuildJoinProposal); GenericMsgHeaderMngr.setCallback("GUILD:ASCENSOR", impulseGuildAscensor); GenericMsgHeaderMngr.setCallback("GUILD:LEAVE_ASCENSOR", impulseGuildLeaveAscensor); GenericMsgHeaderMngr.setCallback("GUILD:ABORT_CREATION", impulseGuildAbortCreation); GenericMsgHeaderMngr.setCallback("GUILD:OPEN_GUILD_WINDOW", impulseGuildOpenGuildWindow); GenericMsgHeaderMngr.setCallback("GUILD:OPEN_INVENTORY", impulseGuildOpenInventory); GenericMsgHeaderMngr.setCallback("GUILD:CLOSE_INVENTORY", impulseGuildCloseInventory); GenericMsgHeaderMngr.setCallback("GUILD:UPDATE_PLAYER_TITLE", impulseGuildUpdatePlayerTitle); GenericMsgHeaderMngr.setCallback("GUILD:USE_FEMALE_TITLES", impulseGuildUseFemaleTitles); //GenericMsgHeaderMngr.setCallback("GUILD:INVITATION", impulseGuildInvitation); GenericMsgHeaderMngr.setCallback("HARVEST:CLOSE_TEMP_INVENTORY", impulseCloseTempInv); GenericMsgHeaderMngr.setCallback("COMMAND:REMOTE_ADMIN", impulseRemoteAdmin); GenericMsgHeaderMngr.setCallback("PHRASE:DOWNLOAD", impulsePhraseDownLoad); GenericMsgHeaderMngr.setCallback("PHRASE:CONFIRM_BUY", impulsePhraseConfirmBuy); GenericMsgHeaderMngr.setCallback("PHRASE:EXEC_CYCLIC_ACK", impulsePhraseAckExecuteCyclic); GenericMsgHeaderMngr.setCallback("PHRASE:EXEC_NEXT_ACK", impulsePhraseAckExecuteNext); GenericMsgHeaderMngr.setCallback("ITEM_INFO:SET", impulseItemInfoSet); GenericMsgHeaderMngr.setCallback("ITEM_INFO:REFRESH_VERSION", impulseItemInfoRefreshVersion); GenericMsgHeaderMngr.setCallback("MISSION_PREREQ:SET", impulsePrereqInfoSet); GenericMsgHeaderMngr.setCallback("ITEM:OPEN_ROOM_INVENTORY", impulseItemOpenRoomInventory); GenericMsgHeaderMngr.setCallback("ITEM:CLOSE_ROOM_INVENTORY", impulseItemCloseRoomInventory); GenericMsgHeaderMngr.setCallback("DEATH:RESPAWN_POINT", impulseDeathRespawnPoint); GenericMsgHeaderMngr.setCallback("DEATH:RESPAWN", impulseDeathRespawn); GenericMsgHeaderMngr.setCallback("DUEL:INVITATION", impulseDuelInvitation); GenericMsgHeaderMngr.setCallback("DUEL:CANCEL_INVITATION", impulseDuelCancelInvitation); GenericMsgHeaderMngr.setCallback("PVP_CHALLENGE:INVITATION", impulsePVPChallengeInvitation); GenericMsgHeaderMngr.setCallback("PVP_CHALLENGE:CANCEL_INVITATION", impulsePVPChallengeCancelInvitation); GenericMsgHeaderMngr.setCallback("PVP_FACTION:PUSH_FACTION_WAR", impulsePVPFactionPushFactionWar); GenericMsgHeaderMngr.setCallback("PVP_FACTION:POP_FACTION_WAR", impulsePVPFactionPopFactionWar); GenericMsgHeaderMngr.setCallback("PVP_FACTION:FACTION_WARS", impulsePVPFactionFactionWars); // GenericMsgHeaderMngr.setCallback("PVP_VERSUS:CHOOSE_CLAN", impulsePVPChooseClan); GenericMsgHeaderMngr.setCallback("ENCYCLOPEDIA:UPDATE", impulseEncyclopediaUpdate); GenericMsgHeaderMngr.setCallback("ENCYCLOPEDIA:INIT", impulseEncyclopediaInit); GenericMsgHeaderMngr.setCallback("USER:BARS", impulseUserBars); GenericMsgHeaderMngr.setCallback("USER:POPUP", impulseUserPopup); GenericMsgHeaderMngr.setCallback("MISSION:ASK_ENTER_CRITICAL", impulseEnterCrZoneProposal); GenericMsgHeaderMngr.setCallback("MISSION:CLOSE_ENTER_CRITICAL", impulseCloseEnterCrZoneProposal); // Module gateway message GenericMsgHeaderMngr.setCallback( "MODULE_GATEWAY:FEOPEN", cbImpulsionGatewayOpen); GenericMsgHeaderMngr.setCallback( "MODULE_GATEWAY:GATEWAY_MSG", cbImpulsionGatewayMessage ); GenericMsgHeaderMngr.setCallback( "MODULE_GATEWAY:FECLOSE", cbImpulsionGatewayClose ); GenericMsgHeaderMngr.setCallback( "OUTPOST:CHOOSE_SIDE", impulseOutpostChooseSide ); GenericMsgHeaderMngr.setCallback( "OUTPOST:DECLARE_WAR_ACK", impulseOutpostDeclareWarAck ); GenericMsgHeaderMngr.setCallback( "COMBAT:FLYING_HP_DELTA", impulseCombatFlyingHpDelta ); GenericMsgHeaderMngr.setCallback( "COMBAT:FLYING_TEXT_ISE", impulseCombatFlyingTextItemSpecialEffectProc ); GenericMsgHeaderMngr.setCallback( "COMBAT:FLYING_TEXT", impulseCombatFlyingText ); GenericMsgHeaderMngr.setCallback( "SEASON:SET", impulseSetSeason ); GenericMsgHeaderMngr.setCallback( "RING_MISSION:DSS_DOWN", impulseDssDown ); GenericMsgHeaderMngr.setCallback( "NPC_ICON:SET_DESC", impulseSetNpcIconDesc ); GenericMsgHeaderMngr.setCallback( "NPC_ICON:SVR_EVENT_MIS_AVL", impulseServerEventForMissionAvailability ); GenericMsgHeaderMngr.setCallback( "NPC_ICON:SET_TIMER", impulseSetNpcIconTimer ); } //----------------------------------------------- // impulseCallBack : // The impulse callback to receive all msg from the frontend. //----------------------------------------------- void impulseCallBack(NLMISC::CBitMemStream &impulse, sint32 packet, void *arg) { GenericMsgHeaderMngr.execute(impulse); } //////////// // METHOD // //////////// //----------------------------------------------- // CNetManager : // Constructor. //----------------------------------------------- CNetManager::CNetManager() : CNetworkConnection() { #ifdef ENABLE_INCOMING_MSG_RECORDER _IsReplayStarting = false; #endif }// CNetManager // //----------------------------------------------- // update : // Updates the whole connection with the frontend. // Call this method evently. // \return bool : 'true' if data were sent/received. //----------------------------------------------- bool CNetManager::update() { H_AUTO_USE ( RZ_Client_Net_Mngr_Update ) #ifdef ENABLE_INCOMING_MSG_RECORDER if(_IsReplayStarting) return; #endif // If the client is in Local Mode -> no network. if(ClientCfg.Local) { // Init if(_CurrentServerTick == 0) { if(T1 >= _LCT) { _MachineTimeAtTick = T1; _CurrentClientTime = _MachineTimeAtTick - _LCT; _CurrentClientTick = 0; _CurrentServerTick = 10; } return false; } if((T1 - _MachineTimeAtTick) >= _MsPerTick) { NLMISC::TGameCycle nbTick = (NLMISC::TGameCycle)((T1 - _MachineTimeAtTick)/_MsPerTick); _CurrentClientTick += nbTick; _CurrentServerTick += nbTick; _MachineTimeAtTick += nbTick*_MsPerTick; } // update the smooth server tick for debug CNetworkConnection::updateSmoothServerTick(); // emulation done #ifdef ENABLE_INCOMING_MSG_RECORDER return false; #endif } // Update the base class. bool result = CNetworkConnection::update(); // Get changes with the update. const vector &changes = NetMngr.getChanges(); // Manage changes vector::const_iterator it; for(it = changes.begin(); it < changes.end(); ++it) { const CChange &change = *it; // Update a property. if(change.Property < AddNewEntity) { if (!IgnoreEntityDbUpdates || change.ShortId == 0) { // Update the visual property for the slot. EntitiesMngr.updateVisualProperty(change.GameCycle, change.ShortId, change.Property, change.PositionInfo.PredictedInterval); } else { nlwarning("CNetManager::update : Skipping EntitiesMngr.updateVisualProperty() because IgnoreEntityDbUpdates=%s and change.ShortId=%d", (IgnoreEntityDbUpdates?"true":"false"), change.ShortId); } } // Add New Entity (and remove the old one in the slot). else if(change.Property == AddNewEntity) { if (!IgnoreEntityDbUpdates || change.ShortId == 0) { // Remove the old entity. EntitiesMngr.remove(change.ShortId, false); // Create the new entity. if(EntitiesMngr.create(change.ShortId, get(change.ShortId), change.NewEntityInfo) == 0) nlwarning("CNetManager::update : entity in the slot '%u' has not been created.", change.ShortId); } else { nlwarning("CNetManager::update : Skipping EntitiesMngr.create() because IgnoreEntityDbUpdates=%s and change.ShortId=%d", (IgnoreEntityDbUpdates?"true":"false"), change.ShortId); } } // Delete an entity else if(change.Property == RemoveOldEntity) { if (!IgnoreEntityDbUpdates || change.ShortId == 0) { // Remove the old entity. EntitiesMngr.remove(change.ShortId, true); } else { nlwarning("CNetManager::update : Skipping EntitiesMngr.remove() because IgnoreEntityDbUpdates=%s and change.ShortId=%d", (IgnoreEntityDbUpdates?"true":"false"), change.ShortId); } } // Lag detected. else if(change.Property == LagDetected) { nldebug("CNetManager::update : Lag detected."); } // Probe received. else if(change.Property == ProbeReceived) { nldebug("CNetManager::update : Probe Received."); } // Connection ready. else if(change.Property == ConnectionReady) { nldebug("CNetManager::update : Connection Ready."); } // Property unknown. else nlwarning("CNetManager::update : The property '%d' is unknown.", change.Property); } ChatMngr.flushBuffer(InterfaceChatDisplayer); // Clear all changes. clearChanges(); // Update data base server state if (IngameDbMngr.getNodePtr()) { CInterfaceManager *im = CInterfaceManager::getInstance(); if (im) { CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:PING", false); if (node) node->setValue32(getPing()); node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:UPLOAD", false); if (node) node->setValue32((sint32)(getMeanUpload()*1024.f/8.f)); node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DOWNLOAD", false); if (node) node->setValue32((sint32)(getMeanDownload()*1024.f/8.f)); node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:PACKETLOST", false); if (node) node->setValue32((sint32)getMeanPacketLoss()); node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SERVERSTATE", false); if (node) node->setValue32((sint32)getConnectionState()); node = NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CONNECTION_QUALITY", false); if (node) node->setValue32((sint32)getConnectionQuality()); } } // Return 'true' if data were sent/received. return result; }// update // //----------------------------------------------- // getConnectionQuality : //----------------------------------------------- bool CNetManager::getConnectionQuality() { // If the client is in Local Mode -> no network. if(ClientCfg.Local) return true; return CNetworkConnection::getConnectionQuality(); }// getConnectionQuality // /** * Buffers a bitmemstream, that will be converted into a generic action, to be sent later to the server (at next update). */ void CNetManager::push(NLMISC::CBitMemStream &msg) { // If the client is in Local Mode -> no network. if(ClientCfg.Local) return; if (PermanentlyBanned) return; CNetworkConnection::push(msg); } /** * Buffers a target action */ void CNetManager::pushTarget(CLFECOMMON::TCLEntityId slot) { // If the client is in Local Mode -> no network. if(ClientCfg.Local) { if(UserEntity->mode() != MBEHAV::COMBAT && UserEntity->mode() != MBEHAV::COMBAT_FLOAT) { UserEntity->targetSlot(slot); } return; } CNetworkConnection::pushTarget(slot, LHSTATE::NONE); } /** * Buffers a pick-up action */ void CNetManager::pushPickup(CLFECOMMON::TCLEntityId slot, LHSTATE::TLHState lootOrHarvest) { // If the client is in Local Mode -> no network. if(ClientCfg.Local) { return; } CNetworkConnection::pushTarget(slot, lootOrHarvest); } /** * Send */ void CNetManager::send(NLMISC::TGameCycle gameCycle) { // If the client is in Local Mode -> no network. if(ClientCfg.Local) return; // wait till next server is received if (_LastSentCycle >= gameCycle) { //nlinfo ("Try to CNetManager::send(%d) _LastSentCycle=%d more than one time with the same game cycle, so we wait new game cycle to send", gameCycle, _LastSentCycle); while (_LastSentCycle >= gameCycle) { // Update network. update(); // Send dummy info send(); // Do not take all the CPU. nlSleep(100); gameCycle = getCurrentServerTick(); } } CNetworkConnection::send(gameCycle); } /** * Send */ void CNetManager::send() { // If the client is in Local Mode -> no network. if(ClientCfg.Local) return; CNetworkConnection::send(); } /** * Disconnects the current connection */ void CNetManager::disconnect() { // If the client is in Local Mode -> no need to disconnect. if(ClientCfg.Local) return; CNetworkConnection::disconnect(); }// disconnect // /** * Reset data and init the socket */ void CNetManager::reinit() { if(ClientCfg.Local) return; IngameDbMngr.resetInitState(); CNetworkConnection::reinit(); } void CNetManager::waitForServer() { sint LastGameCycle = getCurrentServerTick(); for(;;) { // Event server get events CInputHandlerManager::getInstance()->pumpEventsNoIM(); // Update Network. update(); if (LastGameCycle != (sint) getCurrentServerTick()) break; nlSleep(100); send(); } }// waitForServer // #ifdef ENABLE_INCOMING_MSG_RECORDER //----------------------------------------------- // setReplayingMode : //----------------------------------------------- void CNetManager::setReplayingMode( bool onOff, const std::string& filename ) { CNetworkConnection::setReplayingMode(onOff, filename); _IsReplayStarting = onOff; }// setReplayingMode // //----------------------------------------------- // startReplay : //----------------------------------------------- void CNetManager::startReplay() { // Init Replay _MachineTimeAtTick = T1; if(_MachineTimeAtTick >= _LCT) _CurrentClientTime = _MachineTimeAtTick - _LCT; else _CurrentClientTime = 0; // Replay now in progress. _IsReplayStarting = false; }// startReplay // #endif /* * Create the net managers in CLIENT_MULTI mode */ void CNetManagerMulti::init( const std::string& cookie, const std::string& addr ) { uint nb, baseCookie; NLMISC::CConfigFile::CVar *var = ClientCfg.ConfigFile.getVarPtr( "NbConnections" ); if ( var ) nb = var->asInt(); else nb = 1; var = ClientCfg.ConfigFile.getVarPtr( "UserId" ); if ( var ) baseCookie = var->asInt(); else baseCookie = 0; std::vector fsAddrs; fsAddrs.push_back( addr ); string portString = addr.substr( addr.find( ':' ) ); var = ClientCfg.ConfigFile.getVarPtr( "AdditionalFSList" ); if ( var ) { for ( uint i=0; i!=var->size(); ++i ) fsAddrs.push_back( var->asString( i ) + portString ); } nlinfo( "CNetManagerMulti: Creating %u connections to %u front-ends, baseCookie=%u...", nb, fsAddrs.size(), baseCookie ); for ( uint i=0; i!=nb; ++i ) { CNetManager *nm = new CNetManager(); string multicook = NLMISC::toString( "%8x|%8x|%8x", 0, 0, baseCookie + i ); nm->init( multicook, fsAddrs[i % fsAddrs.size()] ); _NetManagers.push_back( nm ); } } // uint32 ShardId = 0; std::string WebServer = ""; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /////////// COMMANDS after should NOT appear IN the FINAL VERSION /////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// #if !FINAL_VERSION // temp : simulate a team msg in local mode NLMISC_COMMAND(localTellTeam, "Temp : simulate a tell in local mode", " ") { if (args.empty()) return false; ucstring player = args[0]; std::string msg; if (args.size() >= 2) { msg = args[1]; for(uint k = 2; k < args.size(); ++k) { msg += " " + args[k]; } } TDataSetIndex dsi = INVALID_DATASET_INDEX; InterfaceChatDisplayer.displayChat(dsi, ucstring(msg), ucstring(msg), CChatGroup::team, NLMISC::CEntityId::Unknown, player); return true; } // temp : simulate a tell in local mode NLMISC_COMMAND(localTell, "Temp : simulate a tell in local mode", " ") { if (args.empty()) return false; ucstring player = args[0]; std::string msg; if (args.size() >= 2) { msg = args[1]; for(uint k = 2; k < args.size(); ++k) { msg += " " + args[k]; } } // TDataSetIndex dsi = INVALID_DATASET_ROW; InterfaceChatDisplayer.displayTell(/*dsi, */ucstring(msg), player); return true; } NLMISC_COMMAND(testDynChatOpen, "", "") { NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 BotUID = 22; // Compressed Index uint32 BotName = 654; // Server string vector DynStrs; // 0 - Desc, 1 - Option0, 2 - Option1, etc.... DynStrs.push_back(16540); DynStrs.push_back(11465); DynStrs.push_back(12654); bm.serial(BotUID); bm.serial(BotName); bm.serialCont(DynStrs); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseDynChatOpen(bm); return true; } NLMISC_COMMAND(testDynChatClose, "", "") { NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 BotUID = 22; // Compressed Index bm.serial(BotUID); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseDynChatClose(bm); return true; } NLMISC_COMMAND(testCloseTempInv, "","") { NLMISC::CBitMemStream bm; impulseCloseTempInv(bm); return true; } NLMISC_COMMAND(testTeamInvite, "","") { NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 index = 10; bm.serial(index); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseTeamInvitation(bm); return true; } NLMISC_COMMAND(testGuildInvite, "","") { NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 index = 10; bm.serial(index); bm.serial(index); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseGuildJoinProposal(bm); return true; } NLMISC_COMMAND( testExchangeInvitation, "Test the modal window for invitation exchange", "" ) { CBitMemStream impulse; uint32 nameIndex = 0; impulse.serial(nameIndex); impulse.invert(); impulseExchangeInvitation(impulse); return true; } NLMISC_COMMAND(testAscensor, "Temp : Simulate a GUILD:ASCENSOR message coming from server","") { NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 index = 10; bm.serial(index); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseGuildAscensor(bm); return true; } NLMISC_COMMAND(testDuelInvite, "","") { NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 index = 10; bm.serial(index); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseDuelInvitation(bm); return true; } //NLMISC_COMMAND(receiveId, ""," ") //{ // uint32 index; // fromString(args[0], index); // ucstring ucstr = args[1]; // // vector code; // //#ifdef OLD_STRING_SYSTEM // ChatMngr.getDynamicDB().add( index, ucstr, code ); //#else // // TRAP // WE MUST NEVER CALL THIS COMMAND ANYMORE : ALL IS HANDLED BY STRING_MANAGER NOW !!! // nlstop; //#endif // // return true; //} NLMISC_COMMAND(testOutpostChooseSide, "","b b u32 u32") { if(args.size()<4) return false; NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); bool playerGuildInConflict; fromString(args[0], playerGuildInConflict); bool playerGuildIsAttacker; fromString(args[1], playerGuildIsAttacker); bm.serial(playerGuildInConflict); bm.serial(playerGuildIsAttacker); uint32 ownerGuildNameId; fromString(args[2], ownerGuildNameId); bm.serial( ownerGuildNameId ); uint32 attackerGuildNameId; fromString(args[3], attackerGuildNameId); bm.serial( attackerGuildNameId ); uint32 declTimer= 100; bm.serial( declTimer ); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseOutpostChooseSide(bm); return true; } NLMISC_COMMAND(testUserPopup, "","u32 u32") { if(args.size()<2) return false; NLMISC::CBitMemStream bm; if (bm.isReading()) bm.invert(); uint32 titleId; fromString(args[0], titleId); bm.serial( titleId ); uint32 textId; fromString(args[1], textId); bm.serial( textId ); bm.invert(); bm.seek(0, NLMISC::IStream::begin); impulseUserPopup(bm); return true; } #endif