khanat-code-old/code/ryzom/client/src/net_manager.cpp
2012-02-29 23:12:07 +01:00

4327 lines
135 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
/////////////
// 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 "interface_v3/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 "interface_v3/view_text_id.h"
#include "interface_v3/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"
// Std.
#include <vector>
#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<CCharacterSummary> CharacterSummaries;
extern uint8 ServerPeopleActive;
extern uint8 ServerCareerActive;
extern vector<CMainlandSummary> 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 <class CInventoryCategoryTemplate>
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.getNodePtr()->resetBank( serverTick, (TCDBBank)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<string> 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("<impulseUserChar> 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("<impulseUserChar> 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<string, CClientConfig::SSysInfoParam>::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<string, CClientConfig::SSysInfoParam>::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("<CInterfaceChatDisplayer::displayChat> 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 = pIM->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("<BPFX>"));
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("<impulseChat> 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("<R2_INVITE>"), 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<CChatGroup::MaxDynChanPerPlayer)
PeopleInterraction.ChatInput.DynamicChat[dynChatDbIndex].clearMessages();
else
nlwarning("Dynamic chat %d not found for clearing", dynChatDbIndex);
}
// don't support other for now (NB: actually used only for dyn_chat)
}
// ***************************************************************************
void impulseChat(NLMISC::CBitMemStream &impulse)
{
ChatMngr.processChatString(impulse, InterfaceChatDisplayer);
}
void impulseChat2(NLMISC::CBitMemStream &impulse)
{
ChatMngr.processChatString2(impulse, InterfaceChatDisplayer);
}
void impulseTell(NLMISC::CBitMemStream &impulse)
{
ChatMngr.processTellString(impulse, InterfaceChatDisplayer);
}
void impulseFarTell(NLMISC::CBitMemStream &impulse)
{
ChatMngr.processFarTellString(impulse, InterfaceChatDisplayer);
}
void impulseTell2(NLMISC::CBitMemStream &impulse)
{
ChatMngr.processTellString2(impulse, InterfaceChatDisplayer);
}
void impulseDynString(NLMISC::CBitMemStream &impulse)
{
ChatMngr.processChatStringWithNoSender(impulse, CChatGroup::system, InterfaceChatDisplayer);
}
void inpulseDynStringInChatGroup(NLMISC::CBitMemStream &impulse)
{
CChatGroup::TGroupType type = CChatGroup::say;
impulse.serialEnum(type);
ChatMngr.processChatStringWithNoSender(impulse, type, InterfaceChatDisplayer);
}
// ***************************************************************************
//void impulseAddDynStr(NLMISC::CBitMemStream &impulse)
//{
// bool huff = false;
// impulse.serialBit(huff);
//
// uint32 index;
// ucstring ucstr;
//
// impulse.serial( index );
// impulse.serial( ucstr );
//
// vector<bool> 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 = CInterfaceManager::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 = CInterfaceManager::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 = CInterfaceManager::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<ucstring> 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();
im->getDbProp("SERVER:INVENTORY:20:0:SHEET")->setValue32(CSheetId("ai_flesh_poisson.item").asInt());
im->getDbProp("SERVER:INVENTORY:20:0:QUALITY")->setValue32(0);
im->getDbProp("SERVER:INVENTORY:20:1:SHEET")->setValue32(CSheetId("fyros_sword_lvl_01_05.item").asInt());
im->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<uint64> 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 = CInterfaceManager::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 = CInterfaceManager::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 = CInterfaceManager::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<uint32> 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();
iMngr->getDbProp("UI:VARIABLES:SPELL_CAST")->setValue32(1);
iMngr->getDbProp("UI:VARIABLES:CAST_BEGIN")->setValue32(begin);
iMngr->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<SQueuedTP> 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:
CInterfaceManager::getInstance()->runActionHandler("return_to_mainland", NULL);
break;
case R2::TPContext_Edit:
CInterfaceManager::getInstance()->runActionHandler("r2ed_stop_test", NULL);
break;
case R2::TPContext_IslandOwner:
CInterfaceManager::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<CGroupContainer*>( im->getElementFromId("ui:interface:team_share"));
if (!gc) return;
gc->setActive(true);
im->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<CCtrlTextButton*>(pIM->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<CGroupContainer*>(pIM->getElementFromId("ui:interface:team_share"));
if (pGC != NULL)
pGC->setActive(false);
CCtrlTextButton *pTB = dynamic_cast<CCtrlTextButton*>(pIM->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<uint32> vFriendListName;
vector<TCharConnectionState> vFriendListOnline;
vector<ucstring> vIgnoreListName;
impulse.serialCont(vFriendListName);
uint32 nbState;
impulse.serial(nbState);
vFriendListOnline.resize(nbState);
for (uint i=0; i<nbState; ++i)
{
impulse.serialShortEnum(vFriendListOnline[i]);
}
// impulse.serialCont(vFriendListOnline);
impulse.serialCont(vIgnoreListName);
if (PermanentlyBanned) return;
//nlinfo("impulseCallback : Received TEAM:CONTACT_INIT nbfriend:%d nbignore:%d", vFriendListName.size(), vIgnoreListName.size());
PeopleInterraction.initContactLists(vFriendListName, vFriendListOnline, vIgnoreListName);
}// impulseTeamContactInit //
//-----------------------------------------------
// impulseTeamContactCreate
// create one character from the friend or ignore list
//-----------------------------------------------
void impulseTeamContactCreate(NLMISC::CBitMemStream &impulse)
{
uint32 contactId;
uint32 nameId;
TCharConnectionState online = ccs_offline;
uint8 nList;
impulse.serial(contactId);
impulse.serial(nameId);
impulse.serialShortEnum(online);
impulse.serial(nList);
// client patch to resolve bad server response when requesting ignore list contact creation
if (nList == 1) // ignore list
{
// prevent adding an empty player to ignore list
if (nameId == 0) return;
}
if (PermanentlyBanned) return;
//nlinfo("impulseCallback : Received TEAM:CONTACT_CREATE %d %d %s %d", contactId, nameId, online?"true":"false", nList);
PeopleInterraction.addContactInList(contactId, nameId, online, nList);
}// impulseTeamContactStatus //
//-----------------------------------------------
// impulseTeamContactStatus
// update one of the character from the friend list
//-----------------------------------------------
void impulseTeamContactStatus(NLMISC::CBitMemStream &impulse)
{
uint32 contactId;
TCharConnectionState online = ccs_offline;
impulse.serial(contactId);
impulse.serialShortEnum(online);
if (PermanentlyBanned) return;
//nlinfo("impulseCallback : Received TEAM:CONTACT_STATUS %d %s", contactId, online == ccs_online ?"online": online==ccs_offline?"offline" : "foreign_online");
// 0<=FriendList (actually ignore list does not show online state)
PeopleInterraction.updateContactInList(contactId, online, 0);
// Resort the contact list if needed
CInterfaceManager* pIM= CInterfaceManager::getInstance();
CPeopleList::TSortOrder order = (CPeopleList::TSortOrder)(pIM->getDbProp("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<CGroupContainer *>( im->getElementFromId("ui:interface:join_guild_proposal"));
if (!gc) return;
CViewText *vt = dynamic_cast<CViewText*>(gc->getView("invitor_name"));
if (vt == NULL) return;
vt->setText(invitor);
gc->setActive(true);
im->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<CGroupContainer *>( im->getElementFromId("ui:interface:enter_crzone_proposal"));
if (!gc) return;
CViewTextID *vti = dynamic_cast<CViewTextID *>(gc->getView("phrase"));
if (!vti) return;
vti->setTextId(phraseID);
gc->setActive(true);
im->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*)pIM->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<CGroupContainer *>(iMngr->getElementFromId(PLAYER_EXCHANGE_INVITATION_DIALOG));
if (wnd)
{
wnd->setActive(true);
wnd->updateCoords();
wnd->center();
wnd->enableBlink(2);
iMngr->setTopWindow(wnd);
}
CViewTextID *vti = dynamic_cast<CViewTextID *>(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<CInterfaceGroup *>(iMngr->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<bool> 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 = pIM->getElementFromId(MC_M_CONTAINER);
CGroupContainer *pGCM = dynamic_cast<CGroupContainer*>(pIE);
if (pGCM == NULL) return NULL;
CGroupList *pList = pGCM->getList();
CGroupContainer *pGCS = dynamic_cast<CGroupContainer*>(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<pair<string, string> > vArgs;
vArgs.push_back(pair<string,string>("id", "mc"+NLMISC::toString(nNbMission)));
vArgs.push_back(pair<string,string>("mcid", NLMISC::toString(titleID)));
if (nNbMission == 0)
{
vArgs.push_back(pair<string,string>("posref", "TL TL"));
vArgs.push_back(pair<string,string>("posparent", "parent"));
vArgs.push_back(pair<string,string>("y", "0"));
}
else
{
vArgs.push_back(pair<string,string>("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<uint32> 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 = CInterfaceManager::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<std::string> &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<CBotChatPageCreateGuild*>(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();
pIM->getDbProp("UI:TEMP:INVENTORY_GUILD_OPENED")->setValue32(1);
}
//-----------------------------------------------
// impulseGuildCloseInventory
//-----------------------------------------------
void impulseGuildCloseInventory (NLMISC::CBitMemStream &impulse)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
pIM->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<uint16> 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<CSPhraseSlot> phrases;
// Read Known Phrases
impulse.serialCont(phrases);
CSPhraseManager *pPM= CSPhraseManager::getInstance();
for(uint i=0;i<phrases.size();i++)
{
if(phrases[i].PhraseSheetId != CSheetId::Unknown)
{
CSPhraseCom phraseCom;
pPM->buildPhraseFromSheet(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<CSPhraseMemorySlot> memorizedPhrases;
impulse.serialCont(memorizedPhrases);
if (PermanentlyBanned) return;
for(uint i=0;i<memorizedPhrases.size();i++)
{
pPM->memorizePhrase(
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 <class CInventoryCategoryTemplate>
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<CCDBNodeBranch*>(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<CCDBNodeBranch*>(inventoryNode->getNode( (uint16)itemSlot.getSlotIndex() ));
for ( uint i=0; i!=INVENTORIES::NbItemPropId; ++i )
{
CCDBNodeLeaf *leafNode = static_cast<CCDBNodeLeaf*>(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<CCDBNodeBranch*>(inventoryNode->getNode( (uint16)itemSlot.getSlotIndex() ));
CCDBNodeLeaf *leafNode = safe_cast<CCDBNodeLeaf*>(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<CCDBNodeBranch*>(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<CCDBNodeLeaf*>(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<CGroupMap*>(pIM->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<CGroupMap*>(pIM->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<CGroupContainer*>(pIM->getElementFromId("ui:interface:join_duel_proposal"));
if (pGC == NULL) return;
CViewTextID *pVTID = dynamic_cast<CViewTextID *>(pGC->getView("invitor_name"));
if (pVTID == NULL) return;
pVTID->setTextId(textID);
pGC->setActive(true);
pIM->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<CGroupContainer*>(pIM->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<CGroupContainer*>(pIM->getElementFromId("ui:interface:join_pvp_challenge_proposal"));
if (pGC == NULL) return;
CViewTextID *pVTID = dynamic_cast<CViewTextID *>(pGC->getView("invitor_name"));
if (pVTID == NULL) return;
pVTID->setTextId(textID);
pGC->setActive(true);
pIM->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<CGroupContainer*>(pIM->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; i<factionWars.FactionWarOccurs.size(); ++i )
{
CFactionWarManager::getInstance()->addFactionWar(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<CGroupContainer*>(pIM->getElementFromId("ui:interface:join_pvp_clan_proposal"));
if (pGC == NULL) return;
pGC->setActive(true);
CCtrlTextButton * butClan1 = dynamic_cast<CCtrlTextButton*>(pIM->getElementFromId("ui:interface:join_pvp_clan_proposal:content:clan1"));
if( butClan1 == NULL )
return;
butClan1->setText( ucstring(EGSPD::CPeople::toString( clan1 )) );
CCtrlTextButton * butClan2 = dynamic_cast<CCtrlTextButton*>(pIM->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();
pIM->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();
pIM->getDbProp("UI:TEMP:INVENTORY_ROOM_OPENED")->setValue32(0);
// deactivate the pop up window
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pIM->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= pIM->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_RECEIVED");
if(node)
node->setValueBool(true);
// set result of ACK
node= pIM->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_OK");
if(node)
node->setValueBool(canValidate);
node= pIM->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TEXTID");
if(node)
node->setValue32(docTextId);
node= pIM->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<contentStr.size() && i<digitMaxEnd;i++)
{
if(contentStr[i]=='}')
break;
}
if(i!=digitMaxEnd)
{
// get the width
ucstring digitStr= contentStr.substr(digitStart, i-digitStart);
fromString(digitStr.toString(), w);
// remove the first tag
contentStr= contentStr.substr(i+1);
}
}
// open the message box window or web ig
CInterfaceManager *pIM= CInterfaceManager::getInstance();
if (is_webig)
{
CGroupHTML *groupHtml;
string group = titleStr.toString();
// <missing:XXX>
group = group.substr(9, group.size()-10);
groupHtml = dynamic_cast<CGroupHTML*>(pIM->getElementFromId("ui:interface:"+group+":content:html"));
if (!groupHtml)
{
groupHtml = dynamic_cast<CGroupHTML*>(pIM->getElementFromId("ui:interface:webig:content:html"));
group = "webig";
}
if (groupHtml)
{
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pIM->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());
pIM->setTopWindow(pGC);
}
}
}
}
else
{
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pIM->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<CViewText*>(pIM->getElementFromId(pIM->getDefine("server_message_box_content_view_text")));
if(vt)
vt->setTextFormatTaged(contentStr);
// open
pIM->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<NumTextType;i++)
{
if(stringId==_TextId[i])
{
_TextReceived[i]= true;
}
}
// all received?
for(uint i=0;i<NumTextType;i++)
{
if(!_TextReceived[i])
return;
}
// Yes => 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= pIM->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<CChange> &changes = NetMngr.getChanges();
// Manage changes
vector<CChange>::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 = im->getDbProp("UI:VARIABLES:PING", false);
if (node)
node->setValue32(getPing());
node = im->getDbProp("UI:VARIABLES:UPLOAD", false);
if (node)
node->setValue32((sint32)(getMeanUpload()*1024.f/8.f));
node = im->getDbProp("UI:VARIABLES:DOWNLOAD", false);
if (node)
node->setValue32((sint32)(getMeanDownload()*1024.f/8.f));
node = im->getDbProp("UI:VARIABLES:PACKETLOST", false);
if (node)
node->setValue32((sint32)getMeanPacketLoss());
node = im->getDbProp("UI:VARIABLES:SERVERSTATE", false);
if (node)
node->setValue32((sint32)getConnectionState());
node = im->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<std::string> 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", "<people_name> <msg>")
{
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", "<people_name> <msg>")
{
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<uint32> 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, "","<num> <name>")
//{
// uint32 index;
// fromString(args[0], index);
// ucstring ucstr = args[1];
//
// vector<bool> 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