2012-05-29 13:31:11 +00:00
// 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