1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #include "game_share/generic_xml_msg_mngr.h"
30 #include "game_share/msg_client_server.h"
31 #include "game_share/bot_chat_types.h"
32 #include "game_share/mode_and_behaviour.h"
33 #include "game_share/chat_group.h"
34 #include "game_share/character_summary.h"
35 #include "game_share/sphrase_com.h"
36 #include "game_share/outpost.h"
37 #include "game_share/msg_client_server.h"
38 #include "game_share/ryzom_database_banks.h"
39 #include "game_share/msg_encyclopedia.h"
40 #include "game_share/prerequisit_infos.h"
41 #include "game_share/permanent_ban_magic_number.h"
42 #include "game_share/item_special_effect.h"
43 #include "game_share/combat_flying_text.h"
44 #include "game_share/shard_names.h"
46 #include "nel/gui/group_list.h"
47 #include "interface_v3/interface_manager.h"
48 #include "net_manager.h"
49 #include "client_cfg.h"
51 #include "client_chat_manager.h"
52 #include "world_database_manager.h"
53 #include "continent_manager.h"
54 #include "motion/user_controls.h"
55 #include "interface_v3/bot_chat_manager.h"
56 #include "interface_v3/bot_chat_page_all.h"
57 #include "interface_v3/bot_chat_page_trade.h"
58 #include "interface_v3/bot_chat_page_create_guild.h"
59 #include "interface_v3/obs_huge_list.h"
60 #include "string_manager_client.h"
61 #include "interface_v3/people_interraction.h"
62 #include "interface_v3/bot_chat_manager.h"
63 #include "interface_v3/bot_chat_page_all.h"
64 #include "nel/gui/view_text_id.h"
65 #include "nel/gui/ctrl_text_button.h"
66 #include "interface_v3/input_handler_manager.h"
67 #include "interface_v3/guild_manager.h"
68 #include "interface_v3/skill_manager.h"
70 #include "interface_v3/inventory_manager.h"
71 #include "interface_v3/sphrase_manager.h"
72 #include "outpost_manager.h"
73 #include "interface_v3/encyclopedia_manager.h"
74 #include "user_entity.h"
75 #include "init_main_loop.h"
76 #include "interface_v3/group_map.h"
77 #include "sound_manager.h"
78 #include "interface_v3/group_compas.h"
79 #include "interface_v3/group_html_webig.h"
80 #include "interface_v3/bar_manager.h"
81 #include "permanent_ban.h"
83 #include "connection.h"
84 #include "faction_war_manager.h"
87 #include "r2/editor.h"
88 #include "game_share/r2_share_itf.h"
89 #include "game_share/r2_types.h"
91 #include "interface_v3/action_handler_base.h"
100 #define OLD_STRING_SYSTEM
101 #define BAR_STEP_TP 2
106 using namespace NLMISC
;
107 using namespace NL3D
;
111 extern bool FirstFrame
;
112 extern void selectTipsOfTheDay (uint tips
);
118 CGenericXmlMsgHeaderManager GenericMsgHeaderMngr
; // Manage messages
120 CNetManagerMulti NetMngr
; // Manage the connection.
122 CNetManager NetMngr
; // Manage the connection.
125 bool UseFemaleTitles
= false;
127 bool serverReceivedReady
= false;
129 static const std::string PLAYER_EXCHANGE_INVITATION_DIALOG
= "ui:interface:accept_trade_invitation";
131 // Hierarchical timer
132 H_AUTO_DECL ( RZ_Client_Net_Mngr_Update
)
137 extern bool noUserChar
; // \todo GUIGUI : do this better.
138 extern bool userChar
; // \todo GUIGUI : do this better.
139 extern std::vector
<CCharacterSummary
> CharacterSummaries
;
140 extern uint8 ServerPeopleActive
;
141 extern uint8 ServerCareerActive
;
142 extern vector
<CMainlandSummary
> Mainlands
;
143 extern bool UserCharPosReceived
;
144 extern CGenericXmlMsgHeaderManager GenericMsgHeaderMngr
;
145 extern CClientChatManager ChatMngr
;
147 extern bool CharNameValidArrived
;
148 extern bool CharNameValid
;
149 bool IsInRingSession
= false;
150 TSessionId HighestMainlandSessionId
; // highest in the position stack
151 std::string lastUniversMessage
;
153 extern const char *CDBBankNames
[INVALID_CDB_BANK
+1];
155 void cbImpulsionGatewayOpen(NLMISC::CBitMemStream
&bms
);
156 void cbImpulsionGatewayMessage(NLMISC::CBitMemStream
&bms
);
157 void cbImpulsionGatewayClose(NLMISC::CBitMemStream
&bms
);
165 void impulseDatabaseInitPlayer(NLMISC::CBitMemStream
&impulse
)
169 sint32 p
= impulse
.getPos();
171 // get the egs tick of this change
172 TGameCycle serverTick
;
173 impulse
.serial(serverTick
);
176 IngameDbMngr
.readDelta( serverTick
, impulse
, CDBPlayer
);
177 IngameDbMngr
.setInitPacketReceived();
178 nlinfo( "DB_INIT:PLR done (%u bytes)", impulse
.getPos()-p
);
180 catch (const Exception
&e
)
182 BOMB( NLMISC::toString( "Problem while decoding a DB_INIT:PLR msg, skipped: %s", e
.what() ), return );
186 void impulseDatabaseUpdatePlayer(NLMISC::CBitMemStream
&impulse
)
190 // get the egs tick of this change
191 TGameCycle serverTick
;
192 impulse
.serial(serverTick
);
195 IngameDbMngr
.readDelta( serverTick
, impulse
, CDBPlayer
); // unlike on the server, here there is only one unified CCDBSynchronized object
197 catch (const Exception
&e
)
200 BOMB( NLMISC::toString( "Problem while decoding a DB_UPDATE_PLR msg, skipped: %s", e
.what() ), return );
204 template <class CInventoryCategoryTemplate
>
205 void updateInventoryFromStream(NLMISC::CBitMemStream
&impulse
, const CInventoryCategoryTemplate
*templ
, bool notifyItemSheetChanges
);
207 void impulseDatabaseUpdateBank(NLMISC::CBitMemStream
&impulse
)
209 uint32 bank
= INVALID_CDB_BANK
;
212 // get the egs tick of this change
213 TGameCycle serverTick
;
214 impulse
.serial(serverTick
);
218 FILL_nbits_WITH_NB_BITS_FOR_CDBBANK
219 impulse
.serial( bank
, nbits
);
222 IngameDbMngr
.readDelta( serverTick
, impulse
, (TCDBBank
)bank
);
224 // read guild inventory update
225 if ( bank
== CDBGuild
)
227 updateInventoryFromStream( impulse
, (INVENTORIES::CInventoryCategoryForGuild
*)NULL
, false );
230 catch (const Exception
&e
)
232 BOMB( NLMISC::toString( "Problem while decoding a DB_GROUP:UPDATE_BANK %s msg, skipped: %s", CDBBankNames
[bank
], e
.what() ), return );
236 void impulseDatabaseInitBank(NLMISC::CBitMemStream
&impulse
)
238 uint32 bank
= INVALID_CDB_BANK
;
241 // get the egs tick of this change
242 TGameCycle serverTick
;
243 impulse
.serial(serverTick
);
247 FILL_nbits_WITH_NB_BITS_FOR_CDBBANK
248 impulse
.serial( bank
, nbits
);
251 IngameDbMngr
.readDelta( serverTick
, impulse
, (TCDBBank
)bank
);
252 nldebug( "CDB: DB_GROUP:INIT_BANK %s", CDBBankNames
[bank
] );
254 // read guild inventory update
255 if ( bank
== CDBGuild
)
257 updateInventoryFromStream( impulse
, (INVENTORIES::CInventoryCategoryForGuild
*)NULL
, false );
260 catch (const Exception
&e
)
262 BOMB( NLMISC::toString( "Problem while decoding a DB_GROUP:INIT_BANK %s msg, skipped: %s", CDBBankNames
[bank
], e
.what() ), return );
266 void impulseDatabaseResetBank(NLMISC::CBitMemStream
&impulse
)
268 uint32 bank
= INVALID_CDB_BANK
;
271 // get the egs tick of this change
272 TGameCycle serverTick
;
273 impulse
.serial(serverTick
);
275 // read the bank to reset
277 FILL_nbits_WITH_NB_BITS_FOR_CDBBANK
278 impulse
.serial( bank
, nbits
);
281 IngameDbMngr
.resetBank( serverTick
, bank
);
282 nldebug( "CDB: DB_GROUP:RESET_BANK %s", CDBBankNames
[bank
] );
284 catch (const Exception
&e
)
286 BOMB( NLMISC::toString( "Problem while decoding a DB_GROUP:RESET_BANK %s msg, skipped: %s", CDBBankNames
[bank
], e
.what() ), return );
290 static void readPrivileges(NLMISC::CBitMemStream
&impulse
)
292 nlassert(impulse
.isReading());
293 // nico : temporarily uses a try block here to avoid prb with people having updated client and not the server
296 impulse
.serial(UserPrivileges
);
298 catch(const EStreamOverflow
&)
300 nlwarning("User privileges not serialised, assuming none");
301 UserPrivileges
.clear();
305 void impulseNoUserChar(NLMISC::CBitMemStream
&impulse
)
307 // received NO_USER_CHAR
308 //nlinfo("impulseCallBack : Received CONNECTION:NO_USER_CHAR");
310 impulse
.serial(ServerPeopleActive
);
311 impulse
.serial(ServerCareerActive
);
312 readPrivileges(impulse
);
313 impulse
.serialCont(Mainlands
);
314 CharacterSummaries
.clear();
317 LoginSM
.pushEvent(CLoginStateMachine::ev_no_user_char
);
319 updatePatcherPriorityBasedOnCharacters();
322 void impulseFarTP(NLMISC::CBitMemStream
&impulse
)
325 TSessionId sessionId
;
326 impulse
.serial(sessionId
);
327 //nlinfo("impulseCallback : Received CONNECTION:FAR_TP %u", sessionId.asInt());
328 bool bailOutIfSessionVanished
;
329 impulse
.serial(bailOutIfSessionVanished
);
330 FarTP
.requestFarTPToSession(sessionId
, PlayerSelectedSlot
, CFarTP::JoinSession
, bailOutIfSessionVanished
);
334 static std::string
lookupSrcKeyFile(const std::string
&src
)
336 if (CFile::isExists("save/" + src
)) return "save/" + src
;
337 return CPath::lookup(src
, false);
340 void copyKeySet(const std::string
&srcPath
, const std::string
&destPath
)
342 // can't use CFile copyFile here, because src may be in a bnp file
344 srcStr
.resize(CFile::getFileSize(srcPath
));
347 nlwarning("Can't copy keys from %s : file not found or empty");
352 CIFile
ifile(srcPath
);
353 ifile
.serialBuffer((uint8
*) &srcStr
[0], (uint
)srcStr
.size());
354 COFile
ofile(destPath
);
355 ofile
.serialBuffer((uint8
*) &srcStr
[0], (uint
)srcStr
.size());
357 catch(const EStream
&)
359 nlwarning("Couldn't copy %s to %s to create new character keyset", srcPath
.c_str(), destPath
.c_str());
363 void impulseUserChars(NLMISC::CBitMemStream
&impulse
)
365 // received USER_CHARS
366 //nlinfo("impulseCallBack : Received CONNECTION:USER_CHARS");
368 impulse
.serial(ServerPeopleActive
);
369 impulse
.serial(ServerCareerActive
);
370 // read characters summary
371 CharacterSummaries
.clear();
372 impulse
.serialCont (CharacterSummaries
);
373 // read shard name summaries
374 std::vector
<string
> shardNames
;
375 impulse
.serialCont (shardNames
);
376 CShardNames::getInstance().loadShardNames(shardNames
);
378 readPrivileges(impulse
);
379 impulse
.serial(FreeTrial
);
381 impulse
.serialCont(Mainlands
);
384 LoginSM
.pushEvent(CLoginStateMachine::ev_chars_received
);
386 // Create the message for the server to select the first character.
387 /* CBitMemStream out;
388 if(GenericMsgHeaderMngr.pushNameToStream("CONNECTION:SELECT_CHAR", out))
390 CSelectCharMsg SelectCharMsg;
391 SelectCharMsg.c = 0; //TODO set here the character choosen by player
392 out.serial( SelectCharMsg );
394 NetMngr.send(NetMngr.getCurrentServerTick());
395 // send CONNECTION:USER_CHARS
396 nldebug("impulseCallBack : CONNECTION:SELECT_CHAR sent");
399 nlwarning("impulseCallBack : unknown message name : 'CONNECTION:SELECT_CHAR'.");
404 if (!NewKeysCharNameValidated
.empty())
406 // if there's a new char for which a key set was wanted, create it now
407 for (uint k
= 0; k
< CharacterSummaries
.size(); ++k
)
409 if (toLower(CharacterSummaries
[k
].Name
.toUtf8()) == toLower(NewKeysCharNameValidated
))
411 // first, stripes server name
412 copyKeySet(lookupSrcKeyFile(GameKeySet
), "save/keys_" + buildPlayerNameForSaveFile(NewKeysCharNameValidated
) + ".xml");
413 copyKeySet(lookupSrcKeyFile(RingEditorKeySet
), "save/keys_r2ed_" + buildPlayerNameForSaveFile(NewKeysCharNameValidated
) + ".xml");
418 updatePatcherPriorityBasedOnCharacters();
421 void impulseUserChar(NLMISC::CBitMemStream
&impulse
)
423 // received USER_CHAR
424 //nlinfo("impulseCallBack : Received CONNECTION:USER_CHAR");
426 // Serialize the message
427 COfflineEntityState posState
;
428 extern uint8 ServerSeasonValue
;
429 extern bool ServerSeasonReceived
;
431 CUserCharMsg::read( impulse
, posState
, ServerSeasonValue
, userRole
, IsInRingSession
, HighestMainlandSessionId
, CharFirstConnectedTime
, CharPlayedTime
);
432 ServerSeasonReceived
= true; // set the season that will be used when selecting the continent from the position
436 UserEntity
->pos(CVectorD((float)posState
.X
/1000.0f
, (float)posState
.Y
/1000.0f
, (float)posState
.Z
/1000.0f
));
437 UserEntity
->front(CVector((float)cos(posState
.Heading
), (float)sin(posState
.Heading
), 0.f
));
438 UserEntity
->dir(UserEntity
->front());
439 UserEntity
->setHeadPitch(0);
440 UserControls
.resetCameraDeltaYaw();
441 //nldebug("<impulseUserChar> pos : %f %f %f heading : %f",UserEntity->pos().x,UserEntity->pos().y,UserEntity->pos().z,posState.Heading);
443 // Update the position for the vision.
444 NetMngr
.setReferencePosition(UserEntity
->pos());
448 UserEntityInitPos
= CVectorD((float)posState
.X
/1000.0f
, (float)posState
.Y
/1000.0f
, (float)posState
.Z
/1000.0f
);
449 UserEntityInitFront
= CVector((float)cos(posState
.Heading
), (float)sin(posState
.Heading
), 0.f
);
450 //nldebug("<impulseUserChar> pos : %f %f %f heading : %f",UserEntityInitPos.x,UserEntityInitPos.y,UserEntityInitPos.z,posState.Heading);
452 // Update the position for the vision.
453 NetMngr
.setReferencePosition(UserEntityInitPos
);
456 UserCharPosReceived
= true;
458 // Configure the ring editor
459 extern R2::TUserRole UserRoleInSession
;
460 UserRoleInSession
= R2::TUserRole::TValues(userRole
);
461 ClientCfg
.R2EDEnabled
= IsInRingSession
/*&& (UserRoleInSession.getValue() != R2::TUserRole::ur_player)*/;
462 // !!!Do NOT uncomment the following line do the ClientCfg.R2EDEnabled = IsInRingSession && (UserRoleInSession != R2::TUserRole::ur_player);
463 // even with UserRoleInSession R2::TUserRole::ur_player the ring features must be activated
464 // because if the ring is not activated the dss do not know the existence of the player
465 // So we can not kick him, tp to him, tp in to next act ....
466 nldebug( "EnableR2Ed = %u, IsInRingSession = %u, UserRoleInSession = %u", (uint
)ClientCfg
.R2EDEnabled
, (uint
)IsInRingSession
, userRole
);
468 updatePatcherPriorityBasedOnCharacters();
471 void impulseCharNameValid(NLMISC::CBitMemStream
&impulse
)
473 //nlinfo("impulseCallBack : Received CONNECTION:VALID_NAME");
475 impulse
.serial(nTmp
);
476 CharNameValid
= ((nTmp
!= 0) ? true : false);
477 CharNameValidArrived
= true;
478 if (CharNameValid
) NewKeysCharNameValidated
= NewKeysCharNameWanted
;
482 void checkHandshake( NLMISC::CBitMemStream
&impulse
)
484 // Decode handshake to check versions
485 uint16 handshakeVersion
;
486 uint16 itemSlotVersion
;
487 impulse
.serial( handshakeVersion
);
488 if ( handshakeVersion
> 0 )
489 nlerror( "Server handshake version is more recent than client one" );
490 impulse
.serial( itemSlotVersion
);
491 if ( itemSlotVersion
!= INVENTORIES::CItemSlot::getVersion() )
492 nlerror( "Handshake: itemSlotVersion mismatch (S:%hu C:%hu)", itemSlotVersion
, INVENTORIES::CItemSlot::getVersion() );
496 void impulseServerReady(NLMISC::CBitMemStream
&impulse
)
498 // received CONNECTION:READY
499 //nlinfo("impulseCallBack : Received CONNECTION:READY");
501 serverReceivedReady
= true;
503 checkHandshake( impulse
);
505 LoginSM
.pushEvent(CLoginStateMachine::ev_ready_received
);
508 void impulseShardId(NLMISC::CBitMemStream
&impulse
)
513 impulse
.serial(shardId
);
517 impulse
.serial(webHost
);
518 if (!webHost
.empty())
523 nlinfo("WEB: Received SHARD_ID %d, web hosted at '%s', using '%s'", shardId
, webHost
.c_str(), WebServer
.c_str());
526 void impulseServerQuitOk(NLMISC::CBitMemStream
&impulse
)
528 // receive CONNECTION:SERVER_QUIT_OK
529 if (FarTP
.isFarTPInProgress())
531 FarTP
.onServerQuitOk();
535 // ensure first a quit request is really asked
536 if(game_exit_request
)
545 void impulseServerQuitAbort(NLMISC::CBitMemStream
&impulse
)
547 // receive CONNECTION:SERVER_QUIT_ABORT
548 if (FarTP
.isFarTPInProgress())
550 FarTP
.onServerQuitAbort();
554 // abort any quit request
555 game_exit_request
= false;
556 ryzom_exit_request
= false;
560 void impulseMailNotification(NLMISC::CBitMemStream
&impulse
)
562 if (PermanentlyBanned
) return;
563 // receive CONNECTION:MAIL_AVAILABLE
564 CInterfaceManager::getInstance()->notifyMailAvailable();
567 void impulseForumNotification(NLMISC::CBitMemStream
&impulse
)
569 if (PermanentlyBanned
) return;
570 // receive CONNECTION:GUILD_MESSAGE_AVAILABLE
571 CInterfaceManager::getInstance()->notifyForumUpdated();
575 void impulsePermanentBan(NLMISC::CBitMemStream
&impulse
)
578 impulse
.serial(magicNumber
);
579 if (magicNumber
!= PermanentBanMSGMagicNumber
) return; // bad msg
580 setPermanentBanMarkers(true);
581 applyPermanentBanPunishment();
582 PermanentlyBanned
= true;
585 void impulsePermanentUnban(NLMISC::CBitMemStream
&impulse
)
588 impulse
.serial(magicNumber
);
589 if (magicNumber
!= PermanentUnbanMSGMagicNumber
) return; // bad msg
590 setPermanentBanMarkers(false);
591 PermanentlyBanned
= false;
594 // allows to walk / run again
595 UserEntity
->walkVelocity(ClientCfg
.Walk
);
596 UserEntity
->runVelocity(ClientCfg
.Run
);
601 // ***************************************************************************
602 class CInterfaceChatDisplayer
: public CClientChatManager::IChatDisplayer
605 virtual void displayChat(TDataSetIndex compressedSenderIndex
, const std::string
&ucstr
, const std::string
&rawMessage
, CChatGroup::TGroupType mode
, NLMISC::CEntityId dynChatId
, std::string
&senderName
, uint bubbleTimer
=0);
606 virtual void displayTell(/*TDataSetIndex senderIndex, */const std::string
&ucstr
, const std::string
&senderName
);
607 virtual void clearChannel(CChatGroup::TGroupType mode
, uint32 dynChatDbIndex
);
610 // Add colorization tag for sender name
611 void colorizeSender(string
&text
, const string
&senderName
, CRGBA baseColor
);
614 static CInterfaceChatDisplayer InterfaceChatDisplayer
;
616 void CInterfaceChatDisplayer::colorizeSender(string
&text
, const string
&senderName
, CRGBA baseColor
)
618 // find the sender/text separator to put color tags
619 string::size_type pos
= senderName
.length() - 1;
620 if (pos
!= string::npos
)
624 CInterfaceProperty prop
;
625 prop
.readRGBA("UI:SAVE:CHAT:COLORS:SPEAKER"," ");
627 CChatWindow::encodeColorTag(prop
.getRGBA(), str
, false);
629 str
+= text
.substr(0, pos
+1);
631 CChatWindow::encodeColorTag(baseColor
, str
, true);
633 str
+= text
.substr(pos
+1);
639 // display a chat from network to interface
640 void CInterfaceChatDisplayer::displayChat(TDataSetIndex compressedSenderIndex
, const std::string
&ucstr
, const std::string
&rawMessage
, CChatGroup::TGroupType mode
, NLMISC::CEntityId dynChatId
, std::string
&senderName
, uint bubbleTimer
)
642 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
644 string stringCategory
= getStringCategory(ucstr
, finalString
);
646 bool bubbleWanted
= true;
648 // Subtract rawMessage from ucstr so that the 'sender' part remains.
649 string senderPart
= ucstr
.substr(0, ucstr
.length() - rawMessage
.length());
651 // search a "{no_bubble}" tag
653 string::size_type index
= finalString
.find("{no_bubble}");
654 const size_t tokenSize
= 11; // length of "{no_bubble}"
655 if (index
!= string::npos
)
657 bubbleWanted
= false;
658 finalString
= finalString
.substr(0, index
) + finalString
.substr(index
+tokenSize
,finalString
.size());
665 if (mode
!= CChatGroup::system
)
667 // Remove all {break}
670 string::size_type index
= finalString
.find("{break}");
671 if (index
== string::npos
) break;
672 finalString
= finalString
.substr(0, index
) + finalString
.substr(index
+7,finalString
.size());
676 sint32 dbIndex
= ChatMngr
.getDynamicChannelDbIndexFromId(dynChatId
);
677 clamp(dbIndex
, (sint32
)0 , (sint32
)CChatGroup::MaxDynChanPerPlayer
);
678 string entry
="UI:SAVE:CHAT:COLORS:";
681 case CChatGroup::dyn_chat
: entry
+="DYN:" + NLMISC::toString(dbIndex
); break;
682 case CChatGroup::say
: entry
+="SAY"; break;
683 case CChatGroup::shout
: entry
+="SHOUT"; break;
684 case CChatGroup::team
: entry
+="GROUP"; break;
685 case CChatGroup::guild
: entry
+="CLADE"; break;
686 case CChatGroup::civilization
: entry
+="CIVILIZATION"; break;
687 case CChatGroup::territory
: entry
+="TERRITORY"; break;
688 case CChatGroup::universe
: entry
+="UNIVERSE_NEW"; break;
689 case CChatGroup::region
: entry
+="REGION"; break;
690 case CChatGroup::tell
: entry
+="TELL"; break;
691 default: nlwarning("unknown group type"); return;
695 CInterfaceProperty prop
;
696 prop
.readRGBA(entry
.c_str()," ");
697 col
= prop
.getRGBA();
699 // Override color if the string contains the color
700 if (!stringCategory
.empty() && stringCategory
!= "SYS")
702 map
<string
, CClientConfig::SSysInfoParam
>::const_iterator it
;
703 it
= ClientCfg
.SystemInfoParams
.find(toLowerAscii(stringCategory
));
704 if (it
!= ClientCfg
.SystemInfoParams
.end())
706 col
= it
->second
.Color
;
711 if (stringCategory
== "emt")
713 bubbleWanted
= false;
716 if (mode
!= CChatGroup::system
)
718 // find the sender/text separator to put color tags
719 if (senderPart
.empty() && stringCategory
== "emt")
721 size_t pos
= finalString
.find(": ", 0);
722 if (pos
!= string::npos
)
724 senderPart
= finalString
.substr(0, pos
+ 2);
727 colorizeSender(finalString
, senderPart
, col
);
730 // play associated fx if any
731 if( !stringCategory
.empty() )
733 map
<string
, CClientConfig::SSysInfoParam
>::const_iterator it
;
734 it
= ClientCfg
.SystemInfoParams
.find( toLowerAscii(stringCategory
) );
735 if( it
!= ClientCfg
.SystemInfoParams
.end() )
737 if( !(*it
).second
.SysInfoFxName
.empty() )
739 NL3D::UParticleSystemInstance sysInfoFx
= FXMngr
.instantFX((*it
).second
.SysInfoFxName
);
740 if( !sysInfoFx
.empty() )
742 sysInfoFx
.setClusterSystem( UserEntity
->getClusterSystem() );
743 sysInfoFx
.setPos( UserEntity
->pos() );
747 nlwarning("<CInterfaceChatDisplayer::displayChat> Can't set chat fx %s",(*it
).second
.SysInfoFxName
.c_str());
753 // **** redirect to the correct interface output
754 if( stringCategory
!= "bbl" )
757 if (mode
== CChatGroup::system
)
759 pIM
->displaySystemInfo(finalString
, stringCategory
);
761 else if (mode
== CChatGroup::guild
)
763 PeopleInterraction
.ChatInput
.Guild
.displayMessage(finalString
, col
, 2, &windowVisible
);
765 else if (mode
== CChatGroup::team
)
767 PeopleInterraction
.ChatInput
.Team
.displayMessage(finalString
, col
, 2, &windowVisible
);
769 else if (mode
== CChatGroup::region
)
771 PeopleInterraction
.ChatInput
.Region
.displayMessage(finalString
, col
, 2, &windowVisible
);
773 else if (mode
== CChatGroup::universe
)
775 if (lastUniversMessage
!= finalString
)
777 PeopleInterraction
.ChatInput
.Universe
.displayMessage(finalString
, col
, 2, &windowVisible
);
778 lastUniversMessage
= finalString
;
781 else if (mode
== CChatGroup::dyn_chat
)
783 // retrieve the DBIndex from the dynamic chat id
784 sint32 dbIndex
= ChatMngr
.getDynamicChannelDbIndexFromId(dynChatId
);
785 // if found, display, else discarded
786 if(dbIndex
>= 0 && dbIndex
< CChatGroup::MaxDynChanPerPlayer
)
788 PeopleInterraction
.ChatInput
.DynamicChat
[dbIndex
].displayMessage(finalString
, col
, 2, &windowVisible
);
790 // Add dynchannel info before text so that the chat log will show the correct string.
791 CCDBNodeLeaf
* node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHAT:SHOW_DYN_CHANNEL_NAME_IN_CHAT_CB", false);
792 if (pIM
->getLogState())
794 // Add dyn chan number before string
795 string prefix
= "[" + NLMISC::toString(dbIndex
) + "]";
796 // Find position to put the new string
798 size_t pos
= finalString
.find("]");
799 size_t colonpos
= finalString
.find(": @{");
800 // If no ] found or if found but after the colon (so part of the user chat)
801 if (pos
== string::npos
|| (colonpos
< pos
))
803 // No timestamp, so put it right after the color and add a space
804 pos
= finalString
.find("}");;
807 finalString
= finalString
.substr(0, pos
+ 1) + prefix
+ finalString
.substr(pos
+ 1);
809 if (node
&& node
->getValueBool())
811 uint32 textId
= ChatMngr
.getDynamicChannelNameFromDbIndex(dbIndex
);
813 STRING_MANAGER::CStringManagerClient::instance()->getDynString(textId
, title
);
814 prefix
= (title
.empty() ? "" : " ") + title
;
815 pos
= finalString
.find("] ");
816 finalString
= finalString
.substr(0, pos
) + prefix
+ finalString
.substr(pos
);
822 nlwarning("Dynamic chat %s not found for message: %s", dynChatId
.toString().c_str(), finalString
.c_str());
827 string::size_type index
= finalString
.find("<BPFX>");
828 if (index
!= string::npos
)
830 bubbleWanted
= false;
831 finalString
= finalString
.substr(index
+6,finalString
.size());
832 string::size_type index2
= finalString
.find(string(" "));
834 if (index2
< (finalString
.size()-3))
836 playerName
= finalString
.substr(0,index2
);
837 finalString
= finalString
.substr(index2
+1,finalString
.size());
839 if (!senderName
.empty())
841 CEntityCL
*senderEntity
= EntitiesMngr
.getEntityByName (CEntityCL::removeTitleAndShardFromName(senderName
), true, true);
844 if (senderEntity
->Type
!= CEntityCL::Player
)
846 if (playerName
.empty())
848 senderEntity
->removeStateFx();
849 senderEntity
->setStateFx(finalString
);
854 CEntityCL
*destEntity
= EntitiesMngr
.getEntityByName (CEntityCL::removeTitleAndShardFromName(playerName
), false, true);
857 destEntity
->removeStateFx();
858 destEntity
->setStateFx(finalString
);
869 PeopleInterraction
.ChatInput
.AroundMe
.displayMessage(finalString
, col
, 2, &windowVisible
);
872 // if tell, bkup sendername
873 if (mode
== CChatGroup::tell
&& windowVisible
&& !senderName
.empty())
875 PeopleInterraction
.LastSenderName
= CEntityCL::removeTitleAndShardFromName(senderName
);
880 //nldebug("<impulseChat> Received CHAT : %s with category %s",finalString.toString().c_str(),stringCategory.c_str());
883 // **** Process chat entry for the bubbles
884 // todo hulud : registering a chat callback would be better than calling this hardcoded action handler
885 string finalRawMessage
;
886 // remove color qualifier from raw string
887 getStringCategory(rawMessage
, finalRawMessage
);
890 InSceneBubbleManager
.chatOpen(compressedSenderIndex
, finalRawMessage
, bubbleTimer
);
896 if (mode
== CChatGroup::dyn_chat
)
898 sint32 dbIndex
= ChatMngr
.getDynamicChannelDbIndexFromId(dynChatId
);
899 clamp(dbIndex
, (sint32
)0 , (sint32
)CChatGroup::MaxDynChanPerPlayer
);
901 channel
= "dyn" + toString(dbIndex
);
905 channel
= CChatGroup::groupTypeToString(mode
);
908 channel
= "#" + toString((uint32
)mode
);
911 if (!stringCategory
.empty() && NLMISC::compareCaseInsensitive(stringCategory
.c_str(), "SYS")) // Not empty and not 'SYS'
913 channel
= channel
+ "/" + stringCategory
;
915 pIM
->log (finalString
, channel
);
920 // display a tell from network to interface
921 void CInterfaceChatDisplayer::displayTell(/*TDataSetIndex senderIndex, */const std::string
&ucstr
, const std::string
&senderName
)
924 string finalString
= ucstr
;
926 // for now, '&' are removed by server so use another format until a special msg is made
927 if (strFindReplace(finalString
, "<R2_INVITE>", string()))
929 CLuaManager::getInstance().executeLuaScript("RingAccessPoint:forceRefresh()");
933 CInterfaceProperty prop
;
934 prop
.readRGBA("UI:SAVE:CHAT:COLORS:TELL"," ");
937 string goodSenderName
= CEntityCL::removeTitleAndShardFromName(senderName
);
939 // The sender part is up to and including the first ":" after the goodSenderName
940 string::size_type pos
= finalString
.find(goodSenderName
);
941 pos
= finalString
.find(':', pos
);
942 pos
= finalString
.find(' ', pos
);
943 string senderPart
= finalString
.substr(0, pos
+1);
944 colorizeSender(finalString
, senderPart
, prop
.getRGBA());
946 PeopleInterraction
.ChatInput
.Tell
.displayTellMessage(/*senderIndex, */finalString
, goodSenderName
, prop
.getRGBA(), 2, &windowVisible
);
947 CInterfaceManager::getInstance()->log(finalString
, CChatGroup::groupTypeToString(CChatGroup::tell
));
949 // Open the free teller window
950 CChatGroupWindow
*pCGW
= PeopleInterraction
.getChatGroupWindow();
952 pCGW
->setActiveFreeTeller(goodSenderName
);
954 if (windowVisible
&& !goodSenderName
.empty())
955 PeopleInterraction
.LastSenderName
= goodSenderName
;
959 void CInterfaceChatDisplayer::clearChannel(CChatGroup::TGroupType mode
, uint32 dynChatDbIndex
)
961 if (mode
== CChatGroup::guild
) PeopleInterraction
.ChatInput
.Guild
.clearMessages();
962 else if (mode
== CChatGroup::team
) PeopleInterraction
.ChatInput
.Team
.clearMessages();
963 else if (mode
== CChatGroup::region
) PeopleInterraction
.ChatInput
.Region
.clearMessages();
964 else if (mode
== CChatGroup::arround
) PeopleInterraction
.ChatInput
.AroundMe
.clearMessages();
965 else if (mode
== CChatGroup::universe
) PeopleInterraction
.ChatInput
.Universe
.clearMessages();
966 else if (mode
== CChatGroup::dyn_chat
)
968 // if correct dbIndex, clear
969 if(dynChatDbIndex
<CChatGroup::MaxDynChanPerPlayer
)
970 PeopleInterraction
.ChatInput
.DynamicChat
[dynChatDbIndex
].clearMessages();
972 nlwarning("Dynamic chat %d not found for clearing", dynChatDbIndex
);
975 // don't support other for now (NB: actually used only for dyn_chat)
979 // ***************************************************************************
980 void impulseChat(NLMISC::CBitMemStream
&impulse
)
982 ChatMngr
.processChatString(impulse
, InterfaceChatDisplayer
);
985 void impulseChat2(NLMISC::CBitMemStream
&impulse
)
987 ChatMngr
.processChatString2(impulse
, InterfaceChatDisplayer
);
990 void impulseTell(NLMISC::CBitMemStream
&impulse
)
992 ChatMngr
.processTellString(impulse
, InterfaceChatDisplayer
);
995 void impulseFarTell(NLMISC::CBitMemStream
&impulse
)
997 ChatMngr
.processFarTellString(impulse
, InterfaceChatDisplayer
);
1000 void impulseTell2(NLMISC::CBitMemStream
&impulse
)
1002 ChatMngr
.processTellString2(impulse
, InterfaceChatDisplayer
);
1005 void impulseDynString(NLMISC::CBitMemStream
&impulse
)
1007 ChatMngr
.processChatStringWithNoSender(impulse
, CChatGroup::system
, InterfaceChatDisplayer
);
1010 void inpulseDynStringInChatGroup(NLMISC::CBitMemStream
&impulse
)
1012 CChatGroup::TGroupType type
= CChatGroup::say
;
1013 impulse
.serialEnum(type
);
1014 ChatMngr
.processChatStringWithNoSender(impulse
, type
, InterfaceChatDisplayer
);
1017 // ***************************************************************************
1018 //void impulseAddDynStr(NLMISC::CBitMemStream &impulse)
1020 // bool huff = false;
1021 // impulse.serialBit(huff);
1024 // ucstring ucstr; // OLD
1026 // impulse.serial( index );
1027 // impulse.serial( ucstr );
1029 // vector<bool> code;
1032 // impulse.serialCont( code );
1034 // if (PermanentlyBanned) return;
1035 // #ifdef OLD_STRING_SYSTEM
1036 // ChatMngr.getDynamicDB().add( index, ucstr, code );
1038 // nlwarning( "// TRAP // WE MUST NEVER CALL THIS IMPULE ANYMORE : ALL IS HANDLED BY STRING_MANAGER NOW !!!" );
1041 // // received ADD_DYN_STR
1042 // nlinfo("impulseCallBack : Received ADD_DYN_STR : adding %s at index %d",ucstr.toString().c_str(),index);
1045 string getInterfaceNameFromId (sint botType, sint interfaceId)
1047 string interfaceName = "ui:interface:bot_chat_";
1051 case 0: interfaceName += "figurant_"; break;
1052 case 1: interfaceName += "figurant_presse_"; break;
1053 case 2: interfaceName += "chef_village_"; break;
1054 default: interfaceName += "figurant_"; break;
1057 switch (interfaceId)
1059 case BOTCHATTYPE::Intro: interfaceName += "intro"; break;
1060 case BOTCHATTYPE::FriendlyMainPage: interfaceName += "friendly_main"; break;
1061 case BOTCHATTYPE::NeutralMainPage: interfaceName += "neutral_main"; break;
1062 case BOTCHATTYPE::NastyMainPage: interfaceName += "nasty_main"; break;
1063 case BOTCHATTYPE::MoreNewsPage: interfaceName += "more_news"; break;
1064 case BOTCHATTYPE::Done: nlinfo ("end of bot chat"); interfaceName.clear(); break;
1066 return interfaceName;
1069 static char *shortNews[] = {
1070 "The wind is sour and brings only bad tidings...", "Kitins have been sighted near the village!", "",
1071 "The tribe of the Black Circle has recently", "increased its activities in our region.", "",
1072 "The Black Circle has made an incursion", "into our territory!", "",
1073 "The Black Circle has been sighted near one", "of our forward posts, deep in dangerous territory.", "",
1074 "The tide has washed up evil news, friend.", "The Black Circle is active in our region.", "",
1075 "Our people suffer from a debilitating shortage.", "We are in sore need of KamiBast.", "",
1076 "The economy is slow and our reserve of", "Live Seed low.", "",
1077 "We are in sore need of Live Seed", "If there is a Goo epidemic, we shall all perish!", "",
1078 "Our master mages have gotten wind of", "the growing Kami discontentment", "",
1081 static char *longNews[] = {
1082 "These powerful predators haven't come this near", "to the village since their devastating attack", "over 15 seasons ago!",
1083 "They are after more KamiBast", "for their occult practices.", "",
1084 "They have captured", "2 of our fortifications in the bush!", "",
1085 "They have taken over one of our richest sources", "of KamiBast, and are exploiting it", "for their own occult purposes.",
1086 "They now hold an important source", "of Live Seed hostage,", "close to one of our forward posts.",
1087 "We use the magical properties of KamiBast and", "its unusually rich fibers for all our crafts.", "",
1088 "If we don't harvest new Seed soon,", "we will have no way of purchasing goods", "and resources, beyond what we produce ourselves",
1089 "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.",
1090 "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.",
1096 char *table[] = { "figurant", "chef_village", "garde", "commercant" };
1098 sint rnd = rand ()%(sizeof(shortNews)/sizeof(shortNews[0])/3);
1101 for (uint i = 0; i < sizeof(table)/sizeof(table[0]); i++)
1103 { // set test for the friendly main
1105 iname = "ui:interface:bot_chat_";
1107 iname += "_friendly_main";
1109 CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(iname);
1112 nlwarning ("cant find interface 's%'", iname.c_str());
1116 CViewText *inter2 = (CViewText *)inter->getView("title0");
1117 nlassert (inter2 != NULL);
1118 inter2->setText(ucstring(shortNews[rnd*3])); // OLD
1120 CViewText *inter3 = (CViewText *)inter->getView("title1");
1121 nlassert (inter3 != NULL);
1122 inter3->setText(ucstring(shortNews[rnd*3+1])); // OLD
1124 CViewText *inter4 = (CViewText *)inter->getView("title2");
1125 nlassert (inter4 != NULL);
1126 inter4->setText(ucstring(shortNews[rnd*3+2])); // OLD
1128 { // set test for the neutral main
1130 iname = "ui:interface:bot_chat_";
1132 iname += "_neutral_main";
1134 CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(iname);
1137 nlwarning ("cant find interface 's%'", iname.c_str());
1141 CViewText *inter2 = (CViewText *)inter->getView("title0");
1142 nlassert (inter2 != NULL);
1143 inter2->setText(ucstring(shortNews[rnd*3])); // OLD
1145 CViewText *inter3 = (CViewText *)inter->getView("title1");
1146 nlassert (inter3 != NULL);
1147 inter3->setText(ucstring(shortNews[rnd*3+1])); // OLD
1149 { // set test for the more news
1151 iname = "ui:interface:bot_chat_";
1153 iname += "_more_news";
1155 CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId(iname);
1158 nlwarning ("cant find interface 's%'", iname.c_str());
1162 CViewText *inter2 = (CViewText *)inter->getView("title0");
1163 nlassert (inter2 != NULL);
1164 inter2->setText(ucstring(longNews[rnd*3])); // OLD
1166 CViewText *inter3 = (CViewText *)inter->getView("title1");
1167 nlassert (inter3 != NULL);
1168 inter3->setText(ucstring(longNews[rnd*3+1])); // OLD
1170 CViewText *inter4 = (CViewText *)inter->getView("title2");
1171 nlassert (inter4 != NULL);
1172 inter4->setText(ucstring(longNews[rnd*3+2])); // OLD
1182 //=========================================
1183 /** Temp setup for choice list
1186 static void setupBotChatChoiceList(CInterfaceGroup *botChatGroup)
1188 // Temp for test. Should then be read from server msg
1189 std::vector<string> choices;
1190 for(uint k = 0; k < 90; ++k)
1192 choices.push_back("Choice " + toString(k));
1194 CBotChat::setChoiceList(botChatGroup, choices, false);
1198 //=========================================
1199 /** Temp setup for description list
1202 static void setupBotChatDescription(CInterfaceGroup *botChatGroup)
1205 for(uint k = 0; k < 90; ++k)
1207 desc += "This is a multi line description. ";
1209 CBotChat::setDescription(botChatGroup, desc);
1213 //=========================================
1214 /** Temp setup for bot chat gift
1217 static void setupBotChatBotGift(CInterfaceGroup *botChatGroup)
1219 // create dummy item in the db
1220 CInterfaceManager *im = CInterfaceManager::getInstance();
1221 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:0:SHEET")->setValue32(CSheetId("ai_flesh_poisson.item").asInt());
1222 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:0:QUALITY")->setValue32(0);
1223 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:1:SHEET")->setValue32(CSheetId("fyros_sword_lvl_01_05.item").asInt());
1224 NLGUI::CDBManager::getInstance()->getDbProp("SERVER:INVENTORY:20:1:QUALITY")->setValue32(2);
1225 CBotChat::setBotGift(botChatGroup, "Thanks to have succeeded the mission", "Here's your reward", "The bot has taken the object quest from your inventory");
1229 //-----------------------------------------------
1230 // impulseBotChatSetInterface :
1231 //-----------------------------------------------
1233 void impulseBotChatSetInterface(NLMISC::CBitMemStream
&impulse
)
1235 // received ADD_DYN_STR
1239 BOTCHATTYPE::TBotChatInterfaceId interfaceId
;
1242 impulse
.serial (user
);
1243 impulse
.serial (happyness
);
1245 // impulse.serialEnum (interfaceId);
1247 impulse
.serial(interfId
);
1248 interfaceId
= (BOTCHATTYPE::TBotChatInterfaceId
)(interfId
&0xff);
1249 uint8 botType
= (interfId
>>8) & 0xff;
1251 impulse
.serial (hasNews
);
1253 nldebug("impulseCallBack : Received BOT_CHAT:SET_INTERFACE interface %d, have news %s, happy %d, bottype %hu", interfaceId
, hasNews
?"yes":"no", happyness
,(uint16
)botType
);
1256 vector
<uint64
> args
;
1260 /* impulse.serial (stringId);
1261 impulse.serialCont (args);
1262 nlinfo ("receive the news '%s' with %d args", stringId.c_str(), args.size());
1264 // TEMP FOR THE DEMO, DON'T USE THE NETWORK NEW BUT SELECT A NEWS HERE
1266 CInterfaceGroup *inter = CWidgetManager::getInstance()->getWindowFromId("ui:interface:bot_chat_intro");
1267 nlassert (inter != NULL);
1268 inter->setActive(true);
1270 CViewText *inter2 = (CViewText *)inter->getView("hi");
1271 nlassert (inter2 != NULL);
1272 inter2->NetworkTextId.setString("IOS_NEWS_FOOTBALL_SHORT_EEII", &ChatMngr);
1273 inter2->NetworkTextId.Args.push_back(10);
1274 inter2->NetworkTextId.Args.push_back(20);
1275 inter2->NetworkTextId.Args.push_back(1);
1276 inter2->NetworkTextId.Args.push_back(2);
1279 // FOR THE DEMO, find and set a fake news:
1282 string interfaceName
= getInterfaceNameFromId (botType
, interfaceId
);
1284 if(interfaceName
.empty())
1286 nlwarning ("Received an unknown bot chat interface %d", interfaceId
);
1290 CInterfaceGroup
*inter
= CWidgetManager::getInstance()->getWindowFromId(interfaceName
);
1293 nlwarning ("Can't find interface name '%s' %d", interfaceName
.c_str(), interfaceId
);
1297 CInterfaceManager::getInstance()->setBotChatWin(inter
);
1298 if (inter
->getActive())
1300 nlwarning ("Interface %s is already active, not normal!", interfaceName
.c_str());
1304 nlinfo ("server want to me display the bot chat interface %s %d", interfaceName
.c_str(), interfaceId
);
1305 inter
->setActive(true);
1314 //-----------------------------------------------
1315 // impulseBeginTrade :
1316 //-----------------------------------------------
1317 void impulseBeginTrade(NLMISC::CBitMemStream
&impulse
)
1319 if (PermanentlyBanned
) return;
1321 CInterfaceGroup
* win
= CWidgetManager::getInstance()->getWindowFromId("ui:interface:trade");
1324 nlwarning("invalid interface ui:interface:trade");
1327 win
->setActive(true);
1330 //-----------------------------------------------
1331 // impulseBuyPrice :
1332 //-----------------------------------------------
1333 void impulseBuyPrice(NLMISC::CBitMemStream
&impulse
)
1335 uint16 botChatSession
;
1339 impulse
.serial(botChatSession
);
1340 impulse
.serial(price
);
1341 impulse
.serial(sheetID
);
1342 impulse
.serial(quality
);
1346 //-----------------------------------------------
1347 // impulseDynChatOpen
1348 //-----------------------------------------------
1349 void impulseDynChatOpen(NLMISC::CBitMemStream
&impulse
)
1351 uint32 BotUID
; // Compressed Index
1352 uint32 BotName
; // Server string
1353 vector
<uint32
> DynStrs
; // 0 - Desc, 1 - Option0, 2 - Option1, etc....
1354 impulse
.serial(BotUID
);
1355 impulse
.serial(BotName
);
1356 impulse
.serialCont(DynStrs
);
1358 if (PermanentlyBanned
) return;
1360 /* string sTmp = "impulseCallback : Received BOTCHAT:DYNCHAT_OPEN BotUID:";
1361 sTmp += toString(BotUID) + " BotName:";
1362 sTmp += toString(BotName) + " DynStrs:";
1363 for (uint32 i = 0; i < DynStrs.size(); ++i)
1365 sTmp += toString(DynStrs[i]);
1366 if (i != DynStrs.size()-1) sTmp += ",";
1368 nlinfo(sTmp.c_str());*/
1370 InSceneBubbleManager
.dynChatOpen(BotUID
, BotName
, DynStrs
);
1373 //-----------------------------------------------
1374 // impulseDynChatClose
1375 //-----------------------------------------------
1376 void impulseDynChatClose(NLMISC::CBitMemStream
&impulse
)
1378 uint32 BotUID
; // Compressed Index
1379 impulse
.serial(BotUID
);
1380 if (PermanentlyBanned
) return;
1381 //nlinfo("impulseCallback : Received BOTCHAT:DYNCHAT_CLOSE BotUID:"+toString(BotUID));
1382 InSceneBubbleManager
.dynChatClose(BotUID
);
1385 //-----------------------------------------------
1386 // impulseBeginCast:
1387 //-----------------------------------------------
1388 void impulseBeginCast(NLMISC::CBitMemStream
&impulse
)
1392 impulse
.serial(begin
);
1393 impulse
.serial(end
);
1394 if (PermanentlyBanned
) return;
1395 CInterfaceManager
* iMngr
= CInterfaceManager::getInstance();
1396 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SPELL_CAST")->setValue32(1);
1397 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CAST_BEGIN")->setValue32(begin
);
1398 NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CAST_END")->setValue32(end
);
1403 //-----------------------------------------------
1404 // impulseCorrectPos :
1405 // Message from the server to correct the user position because he is not at the same position on the server..
1406 //-----------------------------------------------
1407 void impulseCorrectPos(NLMISC::CBitMemStream
&impulse
)
1410 //nlinfo("impulseCallback : Received TP:CORRECT");
1415 nlinfo("impulseCorrectPos: new user position %d %d %d", x
, y
, z
);
1417 if(UserEntity
->mode() != MBEHAV::COMBAT_FLOAT
)
1419 if (x
== 0) // Get SpeedAdjustement
1421 UserEntity
->setSpeedServerAdjust(-0.2f
);
1425 // Compute the destination.
1426 CVectorD dest
= CVectorD((float)x
/1000.0f
, (float)y
/1000.0f
, (float)z
/1000.0f
);
1427 // Update the position for the vision.
1428 NetMngr
.setReferencePosition(dest
);
1429 // Change the user poisition.
1430 UserEntity
->correctPos(dest
);
1433 }// impulseCorrectPos //
1435 class CDummyProgress
: public IProgressCallback
1437 void progress (float /* value */) {}
1440 //-----------------------------------------------
1442 // Message from the server to teleport the user.
1443 // \warning This function remove the current target. Do no use to correct a position.
1444 //-----------------------------------------------
1445 void impulseTPCommon(NLMISC::CBitMemStream
&impulse
, bool hasSeason
);
1446 void impulseTPCommon2(NLMISC::CBitMemStream
&impulse
, bool hasSeason
);
1448 void impulseTP(NLMISC::CBitMemStream
&impulse
)
1450 impulseTPCommon(impulse
, false);
1453 void impulseTPWithSeason(NLMISC::CBitMemStream
&impulse
)
1455 impulseTPCommon(impulse
, true);
1460 NLMISC::CBitMemStream Impulse
;
1463 SQueuedTP(const NLMISC::CBitMemStream
&impulse
, bool hasSeason
)
1464 :Impulse(impulse
), HasSeason(hasSeason
)
1469 // note - this method added by Sadge and Hamster to deal with unexplained recursive calls to impulseTPCommon
1470 // these calls are provoked by the net manager update which is called during loading
1471 void impulseTPCommon(NLMISC::CBitMemStream
&impulse
, bool hasSeason
)
1473 CNiceInputAuto niceInputs
;
1474 static std::list
<SQueuedTP
> queuedTPs
;
1475 SQueuedTP
thisTP(impulse
,hasSeason
);
1476 queuedTPs
.push_back(thisTP
);
1478 BOMB_IF(queuedTPs
.size()!=1,NLMISC::toString("Queueing recursive TPs depth=%u",queuedTPs
.size()),return);
1480 while(!queuedTPs
.empty())
1482 impulseTPCommon2(queuedTPs
.front().Impulse
,queuedTPs
.front().HasSeason
);
1483 queuedTPs
.pop_front();
1489 void impulseTPCommon2(NLMISC::CBitMemStream
&impulse
, bool hasSeason
)
1491 // choose a default screen if not setuped
1492 if (LoadingBackground
!= ResurectKamiBackground
&& LoadingBackground
!= ResurectKaravanBackground
1493 && LoadingBackground
!= TeleportKamiBackground
&& LoadingBackground
!= TeleportKaravanBackground
)
1494 LoadingBackground
= ElevatorBackground
;
1495 // if resurect but user not dead, choose default. NB: this is a bug, the tp impulse should tell
1496 // which background to choose. \todo yoyo: this is a temp fix
1497 if (UserEntity
&& !UserEntity
->isDead() && (LoadingBackground
== ResurectKamiBackground
|| LoadingBackground
== ResurectKaravanBackground
))
1498 LoadingBackground
= ElevatorBackground
;
1500 // Play music according to the background
1503 LoadingMusic
.clear();
1504 switch (LoadingBackground
)
1506 case TeleportKamiBackground
:
1507 LoadingMusic
= ClientCfg
.KamiTeleportMusic
;
1509 case TeleportKaravanBackground
:
1510 LoadingMusic
= ClientCfg
.KaravanTeleportMusic
;
1512 case ResurectKamiBackground
:
1513 case ResurectKaravanBackground
:
1514 // TODO: Resurrect music
1517 LoadingMusic
= ClientCfg
.TeleportLoadingMusic
;
1522 SoundMngr
->playEventMusic(LoadingMusic
, CSoundManager::LoadingMusicXFade
, true);
1525 // Create the loading texture.
1526 beginLoading (LoadingBackground
);
1529 UseEscapeDuringLoading
= false;
1532 selectTipsOfTheDay (rand());
1534 // start progress bar and display background
1535 ProgressBar
.reset (BAR_STEP_TP
);
1536 string
nmsg("Loading...");
1537 ProgressBar
.newMessage ( ClientCfg
.buildLoadingString(nmsg
) );
1540 // received ADD_DYN_STR
1541 nlinfo("impulseTP: received a request for a TP.");
1547 impulse
.serialBit( useHeading
);
1548 // Is there an orientation too ?
1552 impulse
.serial(angle
);
1553 nlinfo("impulseTP: to %d %d %d %f", x
, y
, z
, angle
);
1554 CVector ori
= CVector((float)cos(angle
), (float)sin(angle
), 0.0f
);
1556 UserEntity
->dir(ori
, false, false);
1557 UserEntity
->front(ori
, false, false);
1558 UserEntity
->setHeadPitch(0);
1559 UserControls
.resetCameraDeltaYaw();
1562 nlinfo("impulseTP: to %d %d %d", x
, y
, z
);
1566 extern uint8 ServerSeasonValue
;
1567 extern bool ServerSeasonReceived
;
1568 impulse
.serial(ServerSeasonValue
);
1569 ServerSeasonReceived
= true;
1572 if (ClientCfg
.R2EDEnabled
)
1574 R2::getEditor().tpReceived();
1577 // Compute the destination.
1578 CVectorD dest
= CVectorD((float)x
/1000.0f
, (float)y
/1000.0f
, (float)z
/1000.0f
);
1579 // Update the position for the vision.
1580 NetMngr
.setReferencePosition(dest
);
1581 // Change the position of the entity and in Pacs.
1582 UserEntity
->pos(dest
);
1584 // Fade out the Game Sound
1586 SoundMngr
->fadeOutGameSound(ClientCfg
.SoundTPFade
);
1589 R2::TTeleportContext tpContext
= R2::TPContext_Unknown
;
1592 string tpCancelText
;
1596 R2::TR2TpInfos tpInfos
;
1597 impulse
.serial(tpInfos
);
1600 if ( tpInfos
.UseTpMessage
)
1602 tpReason
= CI18N::get(tpInfos
.TpReasonId
);
1604 uint32 size
= (uint32
)tpInfos
.TpReasonParams
.size();
1606 CSString
str(tpReason
);
1607 for (;first
!= size
; ++first
)
1609 std::string value
= tpInfos
.TpReasonParams
[first
];
1610 std::string key
= NLMISC::toString("%%%u", first
+1);
1611 str
= str
.replace( key
.c_str(), value
.c_str());
1613 tpReason
= string(str
);
1614 tpCancelText
= CI18N::get(tpInfos
.TpCancelTextId
);
1615 tpContext
= tpInfos
.TpContext
;
1619 catch (const EStream
&)
1621 tpReason
= "TP Reason";
1622 tpCancelText
= "Cancel TP"; // for test
1623 // try to deduce tp context from current editor mode
1624 switch (R2::getEditor().getMode())
1626 case R2::CEditor::EditionMode
:
1627 case R2::CEditor::NotInitialized
:
1628 tpContext
= R2::TPContext_Unknown
;
1629 tpReason
= string();
1630 tpCancelText
= string();
1632 case R2::CEditor::GoingToDMMode
:
1633 case R2::CEditor::TestMode
:
1634 case R2::CEditor::DMMode
:
1635 tpContext
= R2::TPContext_Edit
;
1637 case R2::CEditor::AnimationModeLoading
:
1638 case R2::CEditor::AnimationModeWaitingForLoading
:
1639 case R2::CEditor::AnimationModeDm
:
1640 case R2::CEditor::AnimationModeGoingToDm
:
1641 tpContext
= R2::TPContext_IslandOwner
;
1643 case R2::CEditor::AnimationModePlay
:
1644 case R2::CEditor::AnimationModeGoingToPlay
:
1646 tpContext
= R2::TPContext_Mainland
;
1653 if (!tpReason
.empty())
1658 case R2::TPContext_Mainland
: tpIcon
= "cancel_tp_main_land.tga"; break;
1659 case R2::TPContext_Edit
: tpIcon
= "cancel_tp_edit.tga"; break;
1660 case R2::TPContext_IslandOwner
: tpIcon
= "cancel_tp_island_owner.tga"; break;
1663 ProgressBar
.setTPMessages(tpReason
, tpCancelText
, tpIcon
);
1666 ProgressBar
.progress(0);
1667 // enable hardware mouse to allow to click the buttons
1668 //bool oldHardwareCursor = IsMouseCursorHardware();
1669 //InitMouseWithCursor(true);
1670 // Select the closest continent from the new position.
1671 ContinentMngr
.select(dest
, ProgressBar
);
1673 //InitMouseWithCursor(oldHardwareCursor);
1675 // reset 'cancel' button
1676 ProgressBar
.setTPMessages(string(), string(), "");
1679 // ProgressBar.enableQuitButton(false); // TMP TMP
1680 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.
1681 ProgressBar
.finish();
1682 // ProgressBar.enableQuitButton(true); // TMP TMP
1684 // Teleport the User.
1685 UserEntity
->tp(dest
);
1687 // Msg Received, send an acknowledge after the landscape has been loaded.
1689 if(GenericMsgHeaderMngr
.pushNameToStream("TP:ACK", out
))
1692 nlinfo("impulseTP: teleport acknowledge 'TP:ACK' sent.");
1695 nlwarning("impulseTP: unknown message name : 'TP:ACK'.");
1702 // if tp canceling was asked, act accordingly
1703 if (ProgressBar
.getTPCancelFlag(true))
1707 case R2::TPContext_Mainland
:
1708 CAHManager::getInstance()->runActionHandler("return_to_mainland", NULL
);
1710 case R2::TPContext_Edit
:
1711 CAHManager::getInstance()->runActionHandler("r2ed_stop_test", NULL
);
1713 case R2::TPContext_IslandOwner
:
1714 CAHManager::getInstance()->runActionHandler("r2_stop_live", NULL
);
1721 initHardwareCursor(true);
1724 //-----------------------------------------------
1725 // impulseCombatEngageFailed :
1726 //-----------------------------------------------
1727 void impulseCombatEngageFailed(NLMISC::CBitMemStream
&impulse
)
1729 if (PermanentlyBanned
) return;
1730 nlinfo("impulseCombatEngageFailed: Combat Engage Failed.");
1732 // Unlock the motion.
1733 UserControls
.locked(false);
1734 }// impulseCombatEngageFailed //
1736 //-----------------------------------------------
1737 // impulseTeamInvitation :
1738 //-----------------------------------------------
1739 void impulseTeamInvitation(NLMISC::CBitMemStream
&impulse
)
1741 nlinfo("impulseTeamInvitation: received an invitation");
1744 impulse
.serial(textID
);
1745 if (PermanentlyBanned
) return;
1747 CLuaManager::getInstance().executeLuaScript("game:onTeamInvation("+toString(textID
)+")", 0);
1748 }// impulseTeamInvitation //
1750 //-----------------------------------------------
1751 // impulseTeamShareOpen
1752 // The server request that the client opens the team sharing system
1753 //-----------------------------------------------
1754 void impulseTeamShareOpen(NLMISC::CBitMemStream
&impulse
)
1756 if (PermanentlyBanned
) return;
1757 CInterfaceManager
*im
= CInterfaceManager::getInstance();
1758 CGroupContainer
*gc
= dynamic_cast<CGroupContainer
*>( CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share"));
1760 gc
->setActive(true);
1761 CWidgetManager::getInstance()->setTopWindow(gc
);
1764 }// impulseTeamShareOpen //
1766 //-----------------------------------------------
1767 // impulseTeamShareInvalid
1768 // invalidate the player validation. If someone has choosen an item/phrase after the player has validated
1769 // the player receive this message to let him know that the chance percentage to obtain a specific item has
1770 // changed and so the player can update its own settings to fit better to what he wants.
1771 // On the client side we have just to show the valid button. All the resets are done on the server side.
1772 //-----------------------------------------------
1773 void impulseTeamShareInvalid(NLMISC::CBitMemStream
&impulse
)
1775 if (PermanentlyBanned
) return;
1776 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1777 CCtrlTextButton
*pTB
= dynamic_cast<CCtrlTextButton
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share:content:ok"));
1779 pTB
->setActive(true);
1780 }// impulseTeamShareInvalid //
1782 //-----------------------------------------------
1783 // impulseTeamShareClose
1784 // The server wants to close the team sharing interface (if the sharing has been validated or other reasons)
1785 //-----------------------------------------------
1786 void impulseTeamShareClose(NLMISC::CBitMemStream
&impulse
)
1788 if (PermanentlyBanned
) return;
1789 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1791 *pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share"));
1793 pGC
->setActive(false);
1794 CCtrlTextButton
*pTB
= dynamic_cast<CCtrlTextButton
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:team_share:content:ok"));
1796 pTB
->setActive(true);
1797 }// impulseTeamShareClose //
1799 //-----------------------------------------------
1800 // impulseTeamContactInit
1801 // initialize friend list and ignore list from the contact list
1802 //-----------------------------------------------
1803 void impulseTeamContactInit(NLMISC::CBitMemStream
&impulse
)
1805 vector
<uint32
> vFriendListName
;
1806 vector
<TCharConnectionState
> vFriendListOnline
;
1807 vector
<ucstring
> vIgnoreListName
; // TODO: UTF-8 (serial)
1809 impulse
.serialCont(vFriendListName
);
1811 impulse
.serial(nbState
);
1812 vFriendListOnline
.resize(nbState
);
1813 for (uint i
=0; i
<nbState
; ++i
)
1815 impulse
.serialShortEnum(vFriendListOnline
[i
]);
1817 // impulse.serialCont(vFriendListOnline);
1818 impulse
.serialCont(vIgnoreListName
);
1820 if (PermanentlyBanned
) return;
1822 //nlinfo("impulseCallback : Received TEAM:CONTACT_INIT nbfriend:%d nbignore:%d", vFriendListName.size(), vIgnoreListName.size());
1824 PeopleInterraction
.initContactLists(vFriendListName
, vFriendListOnline
, vIgnoreListName
);
1825 }// impulseTeamContactInit //
1827 //-----------------------------------------------
1828 // impulseTeamContactCreate
1829 // create one character from the friend or ignore list
1830 //-----------------------------------------------
1831 void impulseTeamContactCreate(NLMISC::CBitMemStream
&impulse
)
1835 TCharConnectionState online
= ccs_offline
;
1838 impulse
.serial(contactId
);
1839 impulse
.serial(nameId
);
1840 impulse
.serialShortEnum(online
);
1841 impulse
.serial(nList
);
1843 // client patch to resolve bad server response when requesting ignore list contact creation
1844 if (nList
== 1) // ignore list
1846 // prevent adding an empty player to ignore list
1847 if (nameId
== 0) return;
1850 if (PermanentlyBanned
) return;
1852 //nlinfo("impulseCallback : Received TEAM:CONTACT_CREATE %d %d %s %d", contactId, nameId, online?"true":"false", nList);
1854 PeopleInterraction
.addContactInList(contactId
, nameId
, online
, nList
);
1856 }// impulseTeamContactStatus //
1858 //-----------------------------------------------
1859 // impulseTeamContactStatus
1860 // update one of the character from the friend list
1861 //-----------------------------------------------
1862 void impulseTeamContactStatus(NLMISC::CBitMemStream
&impulse
)
1865 TCharConnectionState online
= ccs_offline
;
1867 impulse
.serial(contactId
);
1868 impulse
.serialShortEnum(online
);
1870 if (PermanentlyBanned
) return;
1872 //nlinfo("impulseCallback : Received TEAM:CONTACT_STATUS %d %s", contactId, online == ccs_online ?"online": online==ccs_offline?"offline" : "foreign_online");
1874 // 0<=FriendList (actually ignore list does not show online state)
1875 PeopleInterraction
.updateContactInList(contactId
, online
, 0);
1877 // Resort the contact list if needed
1878 CInterfaceManager
* pIM
= CInterfaceManager::getInstance();
1879 CPeopleList::TSortOrder order
= (CPeopleList::TSortOrder
)(NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CONTACT_LIST:SORT_ORDER")->getValue32());
1881 if (order
== CPeopleList::sort_online
)
1883 PeopleInterraction
.FriendList
.sortEx(order
);
1885 }// impulseTeamContactStatus //
1888 //-----------------------------------------------
1889 // impulseTeamContactRemove
1890 // Remove a contact by the server
1891 //-----------------------------------------------
1892 void impulseTeamContactRemove(NLMISC::CBitMemStream
&impulse
)
1897 impulse
.serial(contactId
);
1898 impulse
.serial(nList
);
1900 if (PermanentlyBanned
) return;
1902 //nlinfo("impulseCallback : Received TEAM:CONTACT_REMOVE %d %d", contactId, nList);
1904 PeopleInterraction
.removeContactFromList(contactId
, nList
);
1906 }// impulseTeamContactRemove //
1909 //-----------------------------------------------
1910 // servers sets information of a guild member:
1911 // u16 ( member index ) u32 (player name ), u8 ( player grade + last bit set if player online ).
1912 //-----------------------------------------------
1913 /*void impulseGuildSetMemberInfo(NLMISC::CBitMemStream &impulse)
1916 impulse.serial(index);
1917 uint32 guildMemberName;
1918 impulse.serial(guildMemberName);
1920 impulse.serial(grade);
1921 bool online = ((grade&0x80) != 0);
1922 grade = (grade & 0x7F);
1923 CGuildManager::getInstance()->set(index, guildMemberName, grade, online);
1926 //-----------------------------------------------
1927 // vector of pair( u32 (player name ), u8 ( player grade + last bit set if player online ) )
1928 //-----------------------------------------------
1929 /*void impulseGuildInitMemberInfo(NLMISC::CBitMemStream &impulse)
1931 vector < pair < uint32, uint8 > > AllMembers;
1933 impulse.serial(nbEntries);
1934 AllMembers.resize(nbEntries);
1935 for (uint32 i = 0; i < nbEntries; ++i)
1938 impulse.serial(name);
1940 impulse.serial(gradeNonline);
1941 AllMembers[i].first = name;
1942 AllMembers[i].second = gradeNonline;
1945 CGuildManager::getInstance()->init(AllMembers);
1949 //-----------------------------------------------
1950 // impulseGuildInvitation
1951 //-----------------------------------------------
1952 /*void impulseGuildInvitation(NLMISC::CBitMemStream &impulse)
1954 nlinfo("impulseGuildInvitation");
1958 //-----------------------------------------------
1959 // impulseGuildJoinProposal
1960 // server sent to client invitation (uint32 invitorNameId, uint32 guildNameId
1961 //-----------------------------------------------
1962 void impulseGuildJoinProposal(NLMISC::CBitMemStream
&impulse
)
1966 impulse
.serial(phraseID
);
1968 if (PermanentlyBanned
) return;
1970 //nlinfo("impulseCallback : Received GUILD:JOIN_PROPOSAL %d", phraseID);
1972 CGuildManager::getInstance()->launchJoinProposal(phraseID
);
1973 /*//activate the pop up window
1974 CInterfaceManager *im = CInterfaceManager::getInstance();
1975 CGroupContainer *gc = dynamic_cast<CGroupContainer *>( CWidgetManager::getInstance()->getElementFromId("ui:interface:join_guild_proposal"));
1977 CViewText *vt = dynamic_cast<CViewText*>(gc->getView("invitor_name"));
1978 if (vt == NULL) return;
1979 vt->setText(invitor);
1980 gc->setActive(true);
1981 CWidgetManager::getInstance()->setTopWindow(gc);
1984 gc->enableBlink(2);*/
1985 }// impulseGuildJoinProposal //
1988 //-----------------------------------------------
1989 // impulseCloseTempInv
1990 //-----------------------------------------------
1991 void impulseCloseTempInv(NLMISC::CBitMemStream
&impulse
)
1993 CTempInvManager::getInstance()->close();
1996 //-----------------------------------------------
1997 // impulseAscencorTeleport
1998 //-----------------------------------------------
1999 void impulseAscencorTeleport(NLMISC::CBitMemStream
&impulse
)
2002 } // impulseAscencorTeleport //
2004 //-----------------------------------------------
2005 // impulseEnterCrZoneProposal
2006 // server sent to client invitation (uint32 invitorNameId, uint32 guildNameId
2007 //-----------------------------------------------
2008 void impulseEnterCrZoneProposal(NLMISC::CBitMemStream
&impulse
)
2011 impulse
.serial(phraseID
);
2012 if (PermanentlyBanned
) return;
2014 //nlinfo("impulseCallback : Received MISSION:ASK_ENTER_CRITICAL %d", phraseID);
2016 //activate the pop up window
2017 CInterfaceManager
*im
= CInterfaceManager::getInstance();
2018 CGroupContainer
*gc
= dynamic_cast<CGroupContainer
*>( CWidgetManager::getInstance()->getElementFromId("ui:interface:enter_crzone_proposal"));
2020 CViewTextID
*vti
= dynamic_cast<CViewTextID
*>(gc
->getView("phrase"));
2022 vti
->setTextId(phraseID
);
2023 gc
->setActive(true);
2024 CWidgetManager::getInstance()->setTopWindow(gc
);
2028 }// impulseEnterCrZoneProposal //
2030 //-----------------------------------------------
2031 // impulseCloseEnterCrZoneProposal
2032 // server close proposal interface
2033 //-----------------------------------------------
2034 void impulseCloseEnterCrZoneProposal(NLMISC::CBitMemStream
&impulse
)
2037 CInterfaceManager
* pIM
= CInterfaceManager::getInstance();
2038 CInterfaceGroup
*pIG
= (CInterfaceGroup
*)CWidgetManager::getInstance()->getElementFromId ("ui:interface:enter_crzone_proposal");
2040 pIG
->setActive(false);
2041 }// impulseCloseEnterCrZoneProposal //
2044 //-----------------------------------------------
2045 // impulseExchangeInvitation :
2046 //-----------------------------------------------
2047 void impulseExchangeInvitation(NLMISC::CBitMemStream
&impulse
)
2050 impulse
.serial(textID
);
2051 if (PermanentlyBanned
) return;
2052 CInterfaceManager
* iMngr
= CInterfaceManager::getInstance();
2054 // show the modal window that allow the player to accept / decline the invitation
2055 CGroupContainer
*wnd
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(PLAYER_EXCHANGE_INVITATION_DIALOG
));
2058 wnd
->setActive(true);
2059 wnd
->updateCoords();
2061 wnd
->enableBlink(2);
2062 CWidgetManager::getInstance()->setTopWindow(wnd
);
2065 CViewTextID
*vti
= dynamic_cast<CViewTextID
*>(wnd
->getView("invite_phrase"));
2068 vti
->setTextId(textID
);
2071 }// impulseExchangeInvitation //
2073 //-----------------------------------------------
2074 // impulseExchangeCloseInvitation :
2075 //-----------------------------------------------
2076 void impulseExchangeCloseInvitation(NLMISC::CBitMemStream
&impulse
)
2078 if (PermanentlyBanned
) return;
2079 CInterfaceManager
* iMngr
= CInterfaceManager::getInstance();
2080 // hide the modal window that allow the player to accept / decline the invitation
2081 CInterfaceGroup
*wnd
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(PLAYER_EXCHANGE_INVITATION_DIALOG
));
2082 if (wnd
) wnd
->setActive(false);
2085 //-----------------------------------------------
2086 // impulseMountAbort :
2087 //-----------------------------------------------
2088 void impulseMountAbort(NLMISC::CBitMemStream
&impulse
)
2090 nlwarning("impulseMountAbort: Received ANIMALS:MOUNT_ABORT => no more used");
2091 }// impulseMountAbort //
2093 //-----------------------------------------------
2094 // impulseRyzomTime :
2095 // Synchronize the ryzom time with the server.
2096 //-----------------------------------------------
2098 void impulseRyzomTime(NLMISC::CBitMemStream &impulse)
2100 nlinfo("impulseRyzomTime: Ryzom Time Received");
2104 impulse.serial(serverTick);
2105 impulse.serial(ryzomTime);
2106 impulse.serial(ryzomDay);
2107 nlinfo("impulseRyzomTime: Day '%d' Time '%f'.", ryzomDay, ryzomTime);
2110 RT.setOrigin( serverTick, ryzomDay, ryzomTime );
2111 }// impulseRyzomTime //
2113 //-----------------------------------------------
2115 // Display server position
2116 //-----------------------------------------------
2117 void impulseWhere(NLMISC::CBitMemStream
&impulse
)
2119 //nlinfo("impulseCallback : Received DEBUG:REPLY_WHERE");
2125 if (PermanentlyBanned
) return;
2128 double xf
= ((double)x
)/1000.0f
;
2129 double yf
= ((double)y
)/1000.0f
;
2130 double zf
= ((double)z
)/1000.0f
;
2132 sprintf(buf
,"Your server position is : X= %g Y= %g Z= %g",xf
,yf
,zf
);
2134 CInterfaceManager::getInstance()->displaySystemInfo(buf
);
2137 //-----------------------------------------------
2139 // Display server position
2140 //-----------------------------------------------
2142 void impulseWho(NLMISC::CBitMemStream &impulse)
2144 nlinfo("impulseWho Received");
2145 CInterfaceManager::getInstance()->displaySystemInfo("Players currently in the game :");
2147 ucstring name; // OLD
2152 while( impulse.getPos() < (sint32)impulse.length() )
2154 impulse.serial(name);
2155 impulse.serial(loginId);
2156 impulse.serial(dist);
2157 impulse.serial(dirshort);
2159 double angle = dirshort * 2.0 * NLMISC::Pi / 255.0;
2160 angle -= NLMISC::Pi;
2161 nlinfo ("name %s uid %u dist %hu dirshort %hu angle %f", name.toString().c_str(),loginId, dist, (uint16)dirshort, angle);
2162 sint direction =(sint) floor( 0.5 + ( 8.0 * (angle + NLMISC::Pi)/(NLMISC::Pi) ) );
2163 direction = ((direction%16)+16)%16;
2164 static const string txts[]=
2184 str = toString (" - uid %d - distance %hu meters - direction ", loginId, dist);
2185 CInterfaceManager::getInstance()->displaySystemInfo(name + str + CI18N::get(txts[direction]));
2191 void impulseWhoGM(NLMISC::CBitMemStream &impulse)
2193 nlinfo("impulseWhoGM Received");
2194 CInterfaceManager::getInstance()->displaySystemInfo("Players currently in the game :");
2196 ucstring name; // OLD
2201 while( impulse.getPos() < (sint32)impulse.length() )
2203 impulse.serial(name);
2204 impulse.serial(loginId);
2205 impulse.serial(dist);
2206 impulse.serial(dirshort);
2208 double angle = dirshort * 2.0 * NLMISC::Pi / 255.0;
2209 angle -= NLMISC::Pi;
2210 nlinfo ("name %s uid %u dist %hu dirshort %hu angle %f", name.toString().c_str(),loginId, dist, (uint16)dirshort, angle);
2211 sint direction =(sint) floor( 0.5 + ( 8.0 * (angle + NLMISC::Pi)/(NLMISC::Pi) ) );
2212 direction = ((direction%16)+16)%16;
2213 static const string txts[]=
2233 str = toString (" - uid %d - distance %hu meters - direction ", loginId, dist);
2234 CInterfaceManager::getInstance()->displaySystemInfo(name + str + CI18N::get(txts[direction]));
2238 //-----------------------------------------------
2240 // check UDP validity
2241 //-----------------------------------------------
2242 void impulseCounter(NLMISC::CBitMemStream
&impulse
)
2244 //nlinfo("impulseCallBack : Received DEBUG:COUNTER");
2248 impulse
.serial(counter
);
2250 static uint queueTop
= 0;
2251 static deque
<bool> queue
;
2253 if (counter
> queueTop
)
2255 queue
.resize(queue
.size()+counter
-queueTop
, false);
2259 if (queueTop
-counter
+1 > queue
.size())
2261 nlinfo("COUNTER: counter %d arrived too late...", counter
);
2265 if (queue
[queue
.size()-1-(queueTop
-counter
)])
2267 nlwarning("COUNTER: Received counter %d more than once !", counter
);
2271 nldebug("COUNTER: set counter %d", counter
);
2272 queue
[queue
.size()-1-(queueTop
-counter
)] = true;
2275 while (queue
.size() > 128)
2279 nlwarning("COUNTER: counter %d not received !", queueTop
-queue
.size()-1);
2286 catch (const Exception
&e
)
2288 nlwarning ("Problem while decoding a COUTNER msg, skipped: %s", e
.what());
2292 //-----------------------------------------------
2293 // impulsePhraseSend :
2294 // A dyn string (or phrase) is send (so, we receive it)
2295 //-----------------------------------------------
2296 void impulsePhraseSend(NLMISC::CBitMemStream
&impulse
)
2298 STRING_MANAGER::CStringManagerClient::instance()->receiveDynString(impulse
);
2301 //-----------------------------------------------
2302 // impulseStringResp :
2303 // Update the local string set
2304 //-----------------------------------------------
2305 void impulseStringResp(NLMISC::CBitMemStream
&impulse
)
2309 impulse
.serial(stringId
);
2310 impulse
.serial(str
);
2312 if (PermanentlyBanned
) return;
2314 STRING_MANAGER::CStringManagerClient::instance()->receiveString(stringId
, str
);
2317 //-----------------------------------------------
2318 // impulseReloadCache :
2319 // reload the string cache
2320 //-----------------------------------------------
2321 void impulseReloadCache(NLMISC::CBitMemStream
&impulse
)
2324 impulse
.serial(timestamp
);
2325 if (PermanentlyBanned
) return;
2326 STRING_MANAGER::CStringManagerClient::instance()->loadCache(timestamp
);
2329 //-----------------------------------------------
2330 // impulseBotChatEnd
2331 // ForceThe end of the bot chat
2332 //-----------------------------------------------
2333 void impulseBotChatForceEnd(NLMISC::CBitMemStream
&impulse
)
2335 if (PermanentlyBanned
) return;
2336 CBotChatManager::getInstance()->setCurrPage(NULL
);
2340 //-----------------------------------------------
2341 // MISSION COMPLETED JOURNAL
2342 //-----------------------------------------------
2344 #define MC_M_CONTAINER "ui:interface:info_player_journal"
2345 #define MC_S_CONTAINER "ui:interface:ipj_com_missions"
2346 #define MC_TEMPLATE "tipj_mission_complete"
2347 //-----------------------------------------------
2348 CGroupContainer *getMissionCompletedContainer()
2350 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2351 CInterfaceElement *pIE = CWidgetManager::getInstance()->getElementFromId(MC_M_CONTAINER);
2352 CGroupContainer *pGCM = dynamic_cast<CGroupContainer*>(pIE);
2353 if (pGCM == NULL) return NULL;
2355 CGroupList *pList = pGCM->getList();
2356 CGroupContainer *pGCS = dynamic_cast<CGroupContainer*>(pList->getGroup(MC_S_CONTAINER));
2360 //-----------------------------------------------
2361 void clearMissions()
2363 CGroupContainer *pGCMC = getMissionCompletedContainer();
2364 CInterfaceGroup *pContent = pGCMC->getGroup("content");
2365 pContent->clearGroups();
2367 //-----------------------------------------------
2368 void addMission(uint32 titleID)
2370 CInterfaceManager *pIM = CInterfaceManager::getInstance();
2371 CGroupContainer *pGCMC = getMissionCompletedContainer();
2374 nlwarning("cannot get container for missions completed");
2377 CInterfaceGroup *pContent = pGCMC->getGroup("content");
2379 uint32 nNbMission = pContent->getGroups().size();
2380 vector<pair<string, string> > vArgs;
2382 vArgs.push_back(pair<string,string>("id", "mc"+NLMISC::toString(nNbMission)));
2383 vArgs.push_back(pair<string,string>("mcid", NLMISC::toString(titleID)));
2385 if (nNbMission == 0)
2387 vArgs.push_back(pair<string,string>("posref", "TL TL"));
2388 vArgs.push_back(pair<string,string>("posparent", "parent"));
2389 vArgs.push_back(pair<string,string>("y", "0"));
2393 vArgs.push_back(pair<string,string>("posref", "BL TL"));
2396 CInterfaceGroup *pIG = pIM->createGroupInstance(MC_TEMPLATE, pContent->getId(), vArgs);
2399 nlwarning("cannot create a mission completed");
2402 pIG->setParent(pContent);
2403 if (nNbMission == 0)
2404 pIG->setParentPos(pContent);
2406 pIG->setParentPos(pContent->getGroups()[nNbMission-1]);
2407 pContent->addGroup(pIG);
2410 //-----------------------------------------------
2411 // impulseJournalInitCompletedMissions :
2412 // initialize the player journal missions for completed missions
2413 //-----------------------------------------------
2414 void impulseJournalInitCompletedMissions (NLMISC::CBitMemStream
&impulse
)
2417 vector<uint32> vMissionCompleted;
2418 impulse.serialCont(vMissionCompleted);
2422 for (uint32 i = 0; i < vMissionCompleted.size(); ++i)
2423 addMission (vMissionCompleted[i]);
2427 //-----------------------------------------------
2428 // impulseJournalInitCompletedMissions :
2429 // initialize the player journal missions for completed missions
2430 //-----------------------------------------------
2431 void impulseJournalUpdateCompletedMissions (NLMISC::CBitMemStream
&impulse
)
2434 uint32 nNewCompletedMission;
2435 impulse.serial(nNewCompletedMission);
2437 addMission (nNewCompletedMission);
2442 //-----------------------------------------------
2443 // impulseJournalCantAbandon :
2444 // server refuses mission abandon
2445 //-----------------------------------------------
2446 void impulseJournalCantAbandon (NLMISC::CBitMemStream
&impulse
)
2448 if (PermanentlyBanned
) return;
2449 /// reactivate abandon button
2450 CCDBNodeLeaf
*pNL
= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MISSION_ABANDON_BUTTON",false);
2457 //-----------------------------------------------
2458 // server add a compass target
2459 //-----------------------------------------------
2460 void impulseJournalAddCompass(NLMISC::CBitMemStream
&impulse
)
2467 impulse
.serial(text
);
2468 if (PermanentlyBanned
) return;
2469 //nlinfo("impulseCallback : Received JOURNAL:ADD_COMPASS %d %d %d", x, y, text);
2470 CCompassDialogsManager::getInstance().addEntry( x
,y
,text
);
2473 //-----------------------------------------------
2474 // server removes a compass target
2475 //-----------------------------------------------
2476 void impulseJournalRemoveCompass(NLMISC::CBitMemStream
&impulse
)
2479 impulse
.serial(text
);
2480 if (PermanentlyBanned
) return;
2481 //nlinfo("impulseCallback : Received JOURNAL:REMOVE_COMPASS %d", text);
2482 CCompassDialogsManager::getInstance().removeEntry( text
);
2488 // the server ask me to execute a command
2490 void impulseRemoteAdmin (NLMISC::CBitMemStream
&impulse
)
2492 CLog logDisplayVars
;
2493 CLightMemDisplayer mdDisplayVars
;
2494 logDisplayVars
.addDisplayer (&mdDisplayVars
);
2495 mdDisplayVars
.setParam (10);
2498 impulse
.serial (rid
);
2500 impulse
.serial (cmd
);
2502 // remove the 2 first rc character if exists, only there to say to the EGS that is a remote command
2503 if (cmd
.size()>2 && tolower(cmd
[0])=='r' && tolower(cmd
[1])=='c') // FIXME: toLowerAscii
2504 cmd
= cmd
.substr(2);
2506 mdDisplayVars
.clear ();
2507 ICommand::execute(cmd
, logDisplayVars
, !ICommand::isCommand(cmd
));
2508 const std::deque
<std::string
> &strs
= mdDisplayVars
.lockStrings();
2511 if (ICommand::isCommand(cmd
))
2513 for (uint k
= 0; k
< strs
.size(); k
++)
2522 str
= strs
[0].substr(0,strs
[0].size()-1);
2523 // replace all spaces into underscore because space is a reserved char
2524 for (uint i
= 0; i
< str
.size(); i
++) if (str
[i
] == ' ') str
[i
] = '_';
2531 mdDisplayVars
.unlockStrings();
2533 //nlinfo("impulseCallback : Received COMMAND:REMOTE_ADMIN : Server asked me to execute '%s', result is '%s'", cmd.c_str(), str.c_str());
2536 if(GenericMsgHeaderMngr
.pushNameToStream("COMMAND:REMOTE_ADMIN_ANSWER", out
))
2542 //nlinfo("impulseCallback : COMMAND:REMOTE_ADMIN_ANSWER %d %s %s sent", rid, cmd.c_str(), str.c_str());
2547 //-----------------------------------------------
2548 // impulseGuildAscensor :
2549 // server request that the client launch the ascensor interface
2550 //-----------------------------------------------
2552 void impulseGuildAscensor (NLMISC::CBitMemStream
&impulse
)
2554 if (PermanentlyBanned
) return;
2555 //nlinfo("impulseCallback : Received GUILD:ASCENSOR");
2556 CGuildManager::getInstance()->launchAscensor();
2559 //-----------------------------------------------
2560 //impulseGuildLeaveAscensor
2561 //-----------------------------------------------
2562 void impulseGuildLeaveAscensor (NLMISC::CBitMemStream
&impulse
)
2564 if (PermanentlyBanned
) return;
2565 //nlinfo("impulseCallback : Received GUILD:LEAVE_ASCENSOR");
2566 CGuildManager::getInstance()->quitAscensor();
2569 //-----------------------------------------------
2570 //impulseGuildAbortCreation
2571 //-----------------------------------------------
2572 void impulseGuildAbortCreation (NLMISC::CBitMemStream
&impulse
)
2574 CBotChatPage
*pPage
= CBotChatManager::getInstance()->getCurrPage();
2575 CBotChatPageCreateGuild
*pPageCG
= dynamic_cast<CBotChatPageCreateGuild
*>(pPage
);
2576 if (pPageCG
== BotChatPageAll
->CreateGuild
)
2577 CBotChatManager::getInstance()->setCurrPage(NULL
);
2580 void impulseGuildOpenGuildWindow(NLMISC::CBitMemStream
&impulse
)
2582 CGuildManager::getInstance()->openGuildWindow();
2586 //-----------------------------------------------
2587 // impulseGuildOpenInventory
2588 //-----------------------------------------------
2589 void impulseGuildOpenInventory (NLMISC::CBitMemStream
&impulse
)
2591 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2592 NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_GUILD_OPENED")->setValue32(1);
2595 //-----------------------------------------------
2596 // impulseGuildCloseInventory
2597 //-----------------------------------------------
2598 void impulseGuildCloseInventory (NLMISC::CBitMemStream
&impulse
)
2600 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2601 NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_GUILD_OPENED")->setValue32(0);
2604 //-----------------------------------------------
2605 // impulseGuildUpdatePlayerTitle
2606 // server block/unblock some reserved titles
2607 //-----------------------------------------------
2608 void impulseGuildUpdatePlayerTitle(NLMISC::CBitMemStream
&impulse
)
2610 CSkillManager
*pSM
= CSkillManager::getInstance();
2612 impulse
.serial(bUnblock
);
2613 vector
<uint16
> vTitles
;
2614 impulse
.serialCont(vTitles
);
2615 if (PermanentlyBanned
) return;
2618 for (uint32 i
= 0; i
< vTitles
.size(); ++i
)
2619 pSM
->unblockTitleFromServer((CHARACTER_TITLE::ECharacterTitle
)vTitles
[i
]);
2623 for (uint32 i
= 0; i
< vTitles
.size(); ++i
)
2624 pSM
->blockTitleFromServer((CHARACTER_TITLE::ECharacterTitle
)vTitles
[i
]);
2628 //-----------------------------------------------
2629 // impulseGuildUseFemaleTitles
2630 // server activates/deactivates use of female titles
2631 //-----------------------------------------------
2632 void impulseGuildUseFemaleTitles(NLMISC::CBitMemStream
&impulse
)
2634 impulse
.serial( UseFemaleTitles
);
2637 //-----------------------------------------------
2638 // impulsePhraseDownLoad
2639 // server upload the phrases.
2640 //-----------------------------------------------
2641 void impulsePhraseDownLoad (NLMISC::CBitMemStream
&impulse
)
2643 std::vector
<CSPhraseSlot
> phrases
;
2645 // Read Known Phrases
2646 impulse
.serialCont(phrases
);
2647 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
2648 for(uint i
=0;i
<phrases
.size();i
++)
2650 if(phrases
[i
].PhraseSheetId
!= CSheetId::Unknown
)
2652 CSPhraseCom phraseCom
;
2653 pPM
->buildPhraseFromSheet(phraseCom
, phrases
[i
].PhraseSheetId
.asInt());
2654 pPM
->setPhraseNoUpdateDB(phrases
[i
].KnownSlot
, phraseCom
);
2658 pPM
->setPhraseNoUpdateDB(phrases
[i
].KnownSlot
, phrases
[i
].Phrase
);
2661 // must update the DB (NB: if initInGameDone) after all phrase set.
2662 pPM
->updateBookDB();
2664 // Then Read Memorized Phrases
2665 std::vector
<CSPhraseMemorySlot
> memorizedPhrases
;
2666 impulse
.serialCont(memorizedPhrases
);
2667 if (PermanentlyBanned
) return;
2668 for(uint i
=0;i
<memorizedPhrases
.size();i
++)
2670 pPM
->memorizePhrase(
2671 memorizedPhrases
[i
].MemoryLineId
,
2672 memorizedPhrases
[i
].MemorySlotId
,
2673 memorizedPhrases
[i
].PhraseId
);
2677 extern bool SabrinaPhraseBookLoaded
;
2678 SabrinaPhraseBookLoaded
= true;
2680 // update gray state, if game inited.
2681 pPM
->updateMemoryBar();
2684 //-----------------------------------------------
2685 // impulsePhraseConfirmBuy
2686 // server confirm/infirm the buy of botchat phrase.
2687 //-----------------------------------------------
2688 void impulsePhraseConfirmBuy (NLMISC::CBitMemStream
&impulse
)
2693 impulse
.serial(phraseId
);
2694 impulse
.serial(confirm
);
2696 if (PermanentlyBanned
) return;
2698 CSPhraseManager
*pSM
= CSPhraseManager::getInstance();
2699 pSM
->receiveBotChatConfirmBuy(phraseId
, confirm
);
2703 //-----------------------------------------------
2704 // impulsePhraseAckExecuteCyclic
2705 // server confirm/infirm the cyclic execution of a phrase
2706 //-----------------------------------------------
2707 void impulsePhraseAckExecuteCyclic (NLMISC::CBitMemStream
&impulse
)
2713 impulse
.serial(counter
);
2715 if (PermanentlyBanned
) return;
2718 CSPhraseManager
*pSM
= CSPhraseManager::getInstance();
2719 pSM
->receiveAckExecuteFromServer(true, counter
, ok
);
2723 //-----------------------------------------------
2724 // impulsePhraseAckExecuteCyclic
2725 // server confirm/infirm the execution of a phrase
2726 //-----------------------------------------------
2727 void impulsePhraseAckExecuteNext (NLMISC::CBitMemStream
&impulse
)
2733 impulse
.serial(counter
);
2735 if (PermanentlyBanned
) return;
2737 CSPhraseManager
*pSM
= CSPhraseManager::getInstance();
2738 pSM
->receiveAckExecuteFromServer(false, counter
, ok
);
2741 // Same params as in BOMB_IF
2742 #ifdef FINAL_VERSION
2743 #define SKIP_IF(condition,msg,skipAction) if (!(condition)); else skipAction;
2745 #define SKIP_IF(condition,msg,skipAction) if (!(condition)) WARN(msg); else skipAction;
2748 template <class CInventoryCategoryTemplate
>
2749 void updateInventoryFromStream (NLMISC::CBitMemStream
&impulse
, const CInventoryCategoryTemplate
*templ
, bool notifyItemSheetChanges
)
2753 // get the egs tick of this change
2754 TGameCycle serverTick
;
2755 impulse
.serial(serverTick
);
2757 // For All inventories
2758 for ( uint invId
=0; invId
!=CInventoryCategoryTemplate::NbInventoryIds
; ++invId
)
2762 impulse
.serialBit( hasContent
);
2768 impulse
.serial( nbChanges
, INVENTORIES::LowNumberBits
);
2769 if ( nbChanges
== INVENTORIES::LowNumberBound
)
2770 impulse
.serial( nbChanges
, 32 );
2772 const string invBranchStr
= CInventoryCategoryTemplate::getDbStr( (typename
CInventoryCategoryTemplate::TInventoryId
)invId
);
2773 ICDBNode::CTextId
textId( invBranchStr
);
2774 ICDBNode
*inventoryNode
= IngameDbMngr
.getNodePtr()->getNode( textId
, false );
2775 BOMB_IF(!inventoryNode
, "Inventory missing in database", return);
2778 for ( uint c
=0; c
!=nbChanges
; ++c
)
2780 // Unpack (the bitmemstream is written from high-order to low-order)
2781 uint32 iuInfoVersion
;
2782 impulse
.serial( iuInfoVersion
, 1 );
2783 if ( iuInfoVersion
== 1 )
2786 impulse
.serial( slotIndex
, CInventoryCategoryTemplate::SlotBitSize
);
2788 // Access the database leaf
2789 CCDBNodeBranch
*slotNode
= safe_cast
<CCDBNodeBranch
*>(inventoryNode
->getNode( (uint16
)slotIndex
));
2790 CCDBNodeLeaf
*leafNode
= type_cast
<CCDBNodeLeaf
*>(slotNode
->find( INVENTORIES::InfoVersionStr
));
2791 BOMB_IF( !leafNode
, "Inventory slot property missing in database", continue );
2793 // Apply or increment Info Version in database
2794 if ( CInventoryCategoryTemplate::needPlainInfoVersionTransfer() )
2797 impulse
.serial( infoVersion
, INVENTORIES::InfoVersionBitSize
);
2798 leafNode
->setPropCheckGC( serverTick
, infoVersion
);
2802 // NB: don't need to check GC on a info version upgrade, since this is always a delta of +1
2803 // the order of received of this impulse is not important
2804 leafNode
->setValue64( leafNode
->getValue64() + 1 );
2811 impulse
.serial( iuAll
, 1 );
2814 INVENTORIES::CItemSlot itemSlot
;
2815 itemSlot
.serialAll( impulse
, templ
);
2816 //nldebug( "Inv %s Update %u", CInventoryCategoryTemplate::InventoryStr[invId], itemSlot.getSlotIndex() );
2818 // Apply all properties to database
2819 CCDBNodeBranch
*slotNode
= safe_cast
<CCDBNodeBranch
*>(inventoryNode
->getNode( (uint16
)itemSlot
.getSlotIndex() ));
2820 for ( uint i
=0; i
!=INVENTORIES::NbItemPropId
; ++i
)
2822 CCDBNodeLeaf
*leafNode
= type_cast
<CCDBNodeLeaf
*>(slotNode
->find( string(INVENTORIES::CItemSlot::ItemPropStr
[i
]) ));
2823 SKIP_IF( !leafNode
, "Inventory slot property missing in database", continue );
2824 leafNode
->setPropCheckGC( serverTick
, (sint64
)itemSlot
.getItemProp( ( INVENTORIES::TItemPropId
)i
) );
2830 impulse
.serial( iuOneProp
, 1 );
2831 if ( iuOneProp
== 1 )
2833 INVENTORIES::CItemSlot itemSlot
;
2834 itemSlot
.serialOneProp( impulse
, templ
);
2835 //nldebug( "Inv %s Prop %u %s", CInventoryCategoryTemplate::InventoryStr[invId], itemSlot.getSlotIndex(), INVENTORIES::CItemSlot::ItemPropStr[itemSlot.getOneProp().ItemPropId] );
2837 // Apply property to database
2838 CCDBNodeBranch
*slotNode
= safe_cast
<CCDBNodeBranch
*>(inventoryNode
->getNode( (uint16
)itemSlot
.getSlotIndex() ));
2839 CCDBNodeLeaf
*leafNode
= type_cast
<CCDBNodeLeaf
*>(slotNode
->find( string(INVENTORIES::CItemSlot::ItemPropStr
[itemSlot
.getOneProp().ItemPropId
]) ));
2840 SKIP_IF( !leafNode
, "Inventory slot property missing in database", continue );
2841 leafNode
->setPropCheckGC( serverTick
, (sint64
)itemSlot
.getOneProp().ItemPropValue
);
2847 impulse
.serial( slotIndex
, CInventoryCategoryTemplate::SlotBitSize
);
2848 //nldebug( "Inv %s Reset %u", CInventoryCategoryTemplate::InventoryStr[invId], slotIndex );
2850 // Reset all properties in database
2851 CCDBNodeBranch
*slotNode
= safe_cast
<CCDBNodeBranch
*>(inventoryNode
->getNode( (uint16
)slotIndex
));
2852 for ( uint i
=0; i
!=INVENTORIES::NbItemPropId
; ++i
)
2854 // Instead of clearing all leaves (by index), we must find and clear only the
2855 // properties in TItemPropId, because the actual database leaves may have
2856 // less properties, and because we must not clear the leaf INFO_VERSION.
2857 // NOTE: For example, only player BAG inventory has WORNED leaf.
2858 CCDBNodeLeaf
*leafNode
= type_cast
<CCDBNodeLeaf
*>(slotNode
->find( string(INVENTORIES::CItemSlot::ItemPropStr
[i
]) ));
2859 SKIP_IF( !leafNode
, "Inventory slot property missing in database", continue );
2860 leafNode
->setPropCheckGC( serverTick
, 0 );
2868 CInventoryManager::getInstance()->sortBag();
2870 catch (const Exception
&e
)
2872 nlwarning ("Problem while decoding a DB_UPD_INV msg, skipped: %s", e
.what());
2876 //-----------------------------------------------
2877 // impulseUpdateInventory:
2878 //-----------------------------------------------
2879 void impulseUpdateInventory (NLMISC::CBitMemStream
&impulse
)
2881 updateInventoryFromStream( impulse
, (INVENTORIES::CInventoryCategoryForCharacter
*)NULL
, true );
2884 //-----------------------------------------------
2885 // impulseInitInventory:
2886 //-----------------------------------------------
2887 void impulseInitInventory (NLMISC::CBitMemStream
&impulse
)
2889 sint32 p
= impulse
.getPos();
2890 impulseUpdateInventory( impulse
);
2891 IngameDbMngr
.setInitPacketReceived();
2892 nlinfo( "DB_INIT:INV done (%u bytes)", impulse
.getPos()-p
);
2894 getInventory().onUpdateEquipHands();
2897 //-----------------------------------------------
2898 // impulseItemInfoSet:
2899 //-----------------------------------------------
2900 void impulseItemInfoSet (NLMISC::CBitMemStream
&impulse
)
2902 CItemInfos itemInfos
;
2903 impulse
.serial(itemInfos
);
2905 getInventory().onReceiveItemInfo(itemInfos
);
2908 //-----------------------------------------------
2909 // impulseItemInfoRefreshVersion:
2910 //-----------------------------------------------
2911 void impulseItemInfoRefreshVersion (NLMISC::CBitMemStream
&impulse
)
2915 impulse
.serial(slotId
);
2916 impulse
.serial(infoVersion
);
2918 getInventory().onRefreshItemInfoVersion(slotId
, infoVersion
);
2921 //-----------------------------------------------
2922 // impulsePrereqInfoSet:
2923 //-----------------------------------------------
2924 void impulsePrereqInfoSet (NLMISC::CBitMemStream
&impulse
)
2926 CPrerequisitInfos prereqInfos
;
2928 impulse
.serial(prereqInfos
);
2929 impulse
.serial(index
);
2931 //write infos in interface
2932 CBotChatManager::getInstance()->onReceiveMissionInfo(index
, prereqInfos
);
2935 //-----------------------------------------------
2936 //-----------------------------------------------
2937 void impulseDeathRespawnPoint (NLMISC::CBitMemStream
&impulse
)
2939 CRespawnPointsMsg msg
;
2940 impulse
.serial(msg
);
2941 if (PermanentlyBanned
) return;
2942 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2943 CGroupMap
*pMap
= dynamic_cast<CGroupMap
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:respawn_map:content:map_content:actual_map"));
2946 nlwarning("problem cannot find ui:interface:respawn_map:content:map_content:actual_map");
2949 pMap
->addRespawnPoints(msg
);
2952 pMap
= dynamic_cast<CGroupMap
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:map:content:map_content:actual_map"));
2955 nlwarning("problem cannot find ui:interface:map:content:map_content:actual_map");
2958 pMap
->addRespawnPoints(msg
);
2961 //-----------------------------------------------
2962 //-----------------------------------------------
2963 void impulseDeathRespawn (NLMISC::CBitMemStream
&impulse
)
2965 // TODO : Bring me to life !!!
2968 //-----------------------------------------------
2969 // impulseDuelInvitation :
2970 //-----------------------------------------------
2971 void impulseDuelInvitation(NLMISC::CBitMemStream
&impulse
)
2974 impulse
.serial(textID
);
2976 //nlinfo("impulseCallback : Received DUEL:INVITATION %d", textID);
2978 if (PermanentlyBanned
) return;
2980 //activate the pop up window
2981 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
2982 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_duel_proposal"));
2983 if (pGC
== NULL
) return;
2984 CViewTextID
*pVTID
= dynamic_cast<CViewTextID
*>(pGC
->getView("invitor_name"));
2985 if (pVTID
== NULL
) return;
2986 pVTID
->setTextId(textID
);
2987 pGC
->setActive(true);
2988 CWidgetManager::getInstance()->setTopWindow(pGC
);
2989 pGC
->updateCoords();
2991 pGC
->enableBlink(2);
2993 }// impulseDuelInvitation //
2995 //-----------------------------------------------
2996 // impulseDuelCancelInvitation:
2997 //-----------------------------------------------
2998 void impulseDuelCancelInvitation(NLMISC::CBitMemStream
&impulse
)
3000 if (PermanentlyBanned
) return;
3001 //nlinfo("impulseCallback : Received DUEL:CANCEL_INVITATION");
3003 //activate the pop up window
3004 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3005 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_duel_proposal"));
3006 if (pGC
== NULL
) return;
3007 pGC
->setActive(false);
3009 }// impulseDuelCancelInvitation //
3011 //-----------------------------------------------
3012 // impulsePVPChallengeInvitation :
3013 //-----------------------------------------------
3014 void impulsePVPChallengeInvitation(NLMISC::CBitMemStream
&impulse
)
3017 impulse
.serial(textID
);
3019 if (PermanentlyBanned
) return;
3021 //nlinfo("impulseCallback : Received PVP_CHALLENGE:INVITATION %d", textID);
3023 //activate the pop up window
3024 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3025 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_challenge_proposal"));
3026 if (pGC
== NULL
) return;
3027 CViewTextID
*pVTID
= dynamic_cast<CViewTextID
*>(pGC
->getView("invitor_name"));
3028 if (pVTID
== NULL
) return;
3029 pVTID
->setTextId(textID
);
3030 pGC
->setActive(true);
3031 CWidgetManager::getInstance()->setTopWindow(pGC
);
3032 pGC
->updateCoords();
3034 pGC
->enableBlink(2);
3036 }// impulsePVPChallengeInvitation //
3038 //-----------------------------------------------
3039 // impulsePVPChallengeCancelInvitation:
3040 //-----------------------------------------------
3041 void impulsePVPChallengeCancelInvitation(NLMISC::CBitMemStream
&impulse
)
3043 //nlinfo("impulseCallback : Received PVP_CHALLENGE:CANCEL_INVITATION");
3045 //activate the pop up window
3046 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3047 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_challenge_proposal"));
3048 if (pGC
== NULL
) return;
3049 pGC
->setActive(false);
3051 }// impulsePVPChallengeCancelInvitation //
3055 //-----------------------------------------------
3056 // impulsePVPFactionPushFactionWar:
3057 //-----------------------------------------------
3058 void impulsePVPFactionPushFactionWar(NLMISC::CBitMemStream
&impulse
)
3060 //nlinfo("impulseCallback : Received PVP_FACTION:PUSH_FACTION_WAR");
3062 PVP_CLAN::CFactionWar factionWar
;
3063 impulse
.serialEnum(factionWar
.Clan1
);
3064 impulse
.serialEnum(factionWar
.Clan2
);
3066 CFactionWarManager::getInstance()->addFactionWar(factionWar
);
3070 //-----------------------------------------------
3071 // impulsePVPFactionPopFactionWar:
3072 //-----------------------------------------------
3073 void impulsePVPFactionPopFactionWar(NLMISC::CBitMemStream
&impulse
)
3075 //nlinfo("impulseCallback : Received PVP_FACTION:POP_FACTION_WAR");
3077 PVP_CLAN::CFactionWar factionWar
;
3078 impulse
.serialEnum(factionWar
.Clan1
);
3079 impulse
.serialEnum(factionWar
.Clan2
);
3081 CFactionWarManager::getInstance()->stopFactionWar(factionWar
);
3085 //-----------------------------------------------
3086 // impulsePVPFactionFactionWars:
3087 //-----------------------------------------------
3088 void impulsePVPFactionFactionWars(NLMISC::CBitMemStream
&impulse
)
3090 //nlinfo("impulseCallback : Received PVP_FACTION:FACTION_WARS");
3092 CFactionWarsMsg factionWars
;
3093 impulse
.serial(factionWars
);
3095 for( uint i
=0; i
<factionWars
.FactionWarOccurs
.size(); ++i
)
3097 CFactionWarManager::getInstance()->addFactionWar(factionWars
.FactionWarOccurs
[i
]);
3103 //-----------------------------------------------
3104 // impulsePVPChooseClan
3105 //-----------------------------------------------
3107 void impulsePVPChooseClan(NLMISC::CBitMemStream &impulse)
3109 nlinfo("impulsePVPChooseClan : Received PVP_CLAN:CHOOSE_CLAN");
3111 EGSPD::CPeople::TPeople clan1= EGSPD::CPeople::Unknown, clan2= EGSPD::CPeople::Unknown;
3112 impulse.serialEnum( clan1 );
3113 impulse.serialEnum( clan2 );
3115 if (PermanentlyBanned) return;
3117 //activate the pop up window
3118 CInterfaceManager *pIM = CInterfaceManager::getInstance();
3119 CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_clan_proposal"));
3120 if (pGC == NULL) return;
3121 pGC->setActive(true);
3123 CCtrlTextButton * butClan1 = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_clan_proposal:content:clan1"));
3124 if( butClan1 == NULL )
3126 butClan1->setText( EGSPD::CPeople::toString( clan1 ) );
3128 CCtrlTextButton * butClan2 = dynamic_cast<CCtrlTextButton*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:join_pvp_clan_proposal:content:clan2"));
3129 if( butClan2 == NULL )
3131 butClan2->setText( EGSPD::CPeople::toString( clan2 ) );
3135 //-----------------------------------------------
3136 // impulseEncyclopediaUpdate
3137 //-----------------------------------------------
3138 void impulseEncyclopediaUpdate(NLMISC::CBitMemStream
&impulse
)
3140 //nlinfo("impulseCallback : Received ENCYCLOPEDIA:UPDATE");
3142 CEncyclopediaUpdateMsg msg
;
3143 impulse
.serial(msg
);
3144 if (PermanentlyBanned
) return;
3145 CEncyclopediaManager::getInstance()->update(msg
);
3146 }// impulseEncyclopediaUpdate //
3148 //-----------------------------------------------
3149 // impulseEncyclopediaInit
3150 //-----------------------------------------------
3151 void impulseEncyclopediaInit(NLMISC::CBitMemStream
&impulse
)
3153 //nlinfo("impulseCallback : Received ENCYCLOPEDIA:INIT");
3155 CEncyclopediaUpdateMsg msg
;
3156 impulse
.serial(msg
);
3157 if (PermanentlyBanned
) return;
3158 CEncyclopediaManager::getInstance()->update(msg
);
3159 }// impulseEncyclopediaInit //
3161 //-----------------------------------------------
3162 //-----------------------------------------------
3163 void impulseItemOpenRoomInventory(NLMISC::CBitMemStream
&impulse
)
3165 if (PermanentlyBanned
) return;
3166 // This is a message because we may do other things there
3167 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3168 NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_ROOM_OPENED")->setValue32(1);
3171 //-----------------------------------------------
3172 //-----------------------------------------------
3173 void impulseItemCloseRoomInventory(NLMISC::CBitMemStream
&impulse
)
3175 if (PermanentlyBanned
) return;
3176 // This is a message because we may do other things there
3177 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3178 NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:INVENTORY_ROOM_OPENED")->setValue32(0);
3180 // deactivate the pop up window
3181 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:inv_room"));
3182 if (pGC
== NULL
) return;
3183 pGC
->setActive(false);
3186 //-----------------------------------------------
3187 //-----------------------------------------------
3188 void impulseUserBars(NLMISC::CBitMemStream
&impulse
)
3191 sint32 hp
, sap
, sta
, focus
;
3192 impulse
.serial(msgNumber
);
3194 impulse
.serial(sap
);
3195 impulse
.serial(sta
);
3196 impulse
.serial(focus
);
3198 if (PermanentlyBanned
) return;
3200 // Setup the user Bars
3201 CBarManager::CBarInfo bi
;
3202 CBarManager::getInstance()->setupUserBarInfo(msgNumber
, hp
, sap
, sta
, focus
);
3205 //-----------------------------------------------
3206 //-----------------------------------------------
3207 void impulseOutpostChooseSide(NLMISC::CBitMemStream
&impulse
)
3212 bool playerGuildInConflict
;
3213 bool playerGuildIsAttacker
;
3214 impulse
.serial(type
);
3215 impulse
.serial(outpostInFire
);
3216 impulse
.serial(playerGuildInConflict
);
3217 impulse
.serial(playerGuildIsAttacker
);
3218 uint32 ownerGuildNameId
;
3219 impulse
.serial( ownerGuildNameId
);
3220 uint32 attackerGuildNameId
;
3221 impulse
.serial( attackerGuildNameId
);
3223 impulse
.serial( declTimer
);
3226 OutpostManager
.startPvpJoinProposal((OUTPOSTENUMS::TPVPType
)type
, outpostInFire
, playerGuildInConflict
, playerGuildIsAttacker
,
3227 ownerGuildNameId
, attackerGuildNameId
, declTimer
);
3230 //-----------------------------------------------
3231 //-----------------------------------------------
3232 void impulseOutpostDeclareWarAck(NLMISC::CBitMemStream
&impulse
)
3236 uint32 timeStartAttack
;
3238 impulse
.serial(canValidate
);
3239 impulse
.serial(docTextId
);
3240 impulse
.serial(timeStartAttack
);
3242 // write result in Local DB.
3243 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3246 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_RECEIVED");
3248 node
->setValueBool(true);
3249 // set result of ACK
3250 node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_OK");
3252 node
->setValueBool(canValidate
);
3253 node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TEXTID");
3255 node
->setValue32(docTextId
);
3256 node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TIME_RANGE_ATT");
3258 node
->setValue32(timeStartAttack
);
3261 extern void addWebIGParams(string
&url
, bool trustedDomain
);
3263 //-----------------------------------------------
3264 //-----------------------------------------------
3265 class CServerMessageBoxOnReceiveTextId
: public STRING_MANAGER::IStringWaitCallback
3268 enum TTextType
{TitleType
= 0, ContentType
, NumTextType
};
3269 uint32 _TextId
[NumTextType
];
3270 bool _TextReceived
[NumTextType
];
3271 bool _AlreadyDisplayed
;
3274 void activateMsgBoxWindow()
3276 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
3278 // get the content string (should have been received!)
3281 if(!pSMC
->getDynString(_TextId
[ContentType
], contentStr
))
3284 if(!pSMC
->getDynString(_TextId
[TitleType
], titleStr
))
3287 // if the string start with a @{Wxxxx} code, remove it and get the wanted window size
3288 sint w
= 256; // default size to 256 !!
3289 bool is_webig
= false;
3291 if(contentStr
.size()>=6 && contentStr
[0]=='W' && contentStr
[1]=='E' && contentStr
[2]=='B'
3292 && contentStr
[3]==' ' && contentStr
[4]==':' && contentStr
[5]==' ' )
3295 const uint digitStart
= 6;
3296 const uint digitMaxEnd
= (uint
)contentStr
.size();
3300 for(i
= digitStart
; i
< digitMaxEnd
; i
++)
3302 if(contentStr
[i
] == ' ')
3305 if(i
!= digitMaxEnd
)
3307 string web_app
= contentStr
.substr(digitStart
, i
-digitStart
);
3308 contentStr
= string(ClientCfg
.WebIgMainDomain
+ "/") + web_app
+ string("/index.php?") + contentStr
.substr((size_t)i
+ 1);
3316 else if(contentStr
.size()>=5 && contentStr
[0]=='@' && contentStr
[1]=='{' && contentStr
[2]=='W')
3319 const uint digitStart
= 3;
3320 const uint digitMaxEnd
= 8;
3321 for(i
=digitStart
;i
<contentStr
.size() && i
<digitMaxEnd
;i
++)
3323 if(contentStr
[i
]=='}')
3329 string digitStr
= contentStr
.substr(digitStart
, i
-digitStart
);
3330 fromString(digitStr
, w
);
3331 // remove the first tag
3332 contentStr
= contentStr
.substr(i
+1);
3336 // open the message box window or web ig
3337 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3341 CGroupHTML
*groupHtml
;
3342 string group
= titleStr
;
3344 group
= group
.substr(9, group
.size()-10);
3345 groupHtml
= dynamic_cast<CGroupHTML
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:"+group
+":content:html"));
3348 groupHtml
= dynamic_cast<CGroupHTML
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:webig:content:html"));
3354 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:"+group
));
3357 if (contentStr
.empty())
3359 pGC
->setActive(false);
3363 if (group
== "webig")
3364 pGC
->setActive(true);
3365 string url
= contentStr
;
3366 addWebIGParams(url
, true);
3367 groupHtml
->browse(url
.c_str());
3368 CWidgetManager::getInstance()->setTopWindow(pGC
);
3375 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:server_message_box"));
3378 // show the window with correct width
3380 pGC
->setActive(true);
3382 // must set the text by hand
3383 CViewText
*vt
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId(CWidgetManager::getInstance()->getParser()->getDefine("server_message_box_content_view_text")));
3385 vt
->setTextFormatTaged(contentStr
);
3388 CWidgetManager::getInstance()->setTopWindow(pGC
);
3389 pGC
->invalidateCoords();
3390 // Yoyo: because of buggued group container, I found that 6 times is a good number....
3391 for(uint i
=0;i
<6;i
++)
3392 pGC
->updateCoords();
3394 pGC
->enableBlink(2);
3400 // called when the string is available
3401 virtual void onDynStringAvailable(uint stringId
, const std::string
&value
)
3403 // don't care if already displayed
3404 if(_AlreadyDisplayed
)
3407 // check if one of waited text
3408 for(uint i
=0;i
<NumTextType
;i
++)
3410 if(stringId
==_TextId
[i
])
3412 _TextReceived
[i
]= true;
3417 for(uint i
=0;i
<NumTextType
;i
++)
3419 if(!_TextReceived
[i
])
3422 // Yes => display window
3423 _AlreadyDisplayed
= true;
3424 activateMsgBoxWindow();
3428 void startWaitTexts(uint32 titleTextId
, uint32 docTextId
)
3431 _TextId
[TitleType
]= titleTextId
;
3432 _TextId
[ContentType
]= docTextId
;
3433 _TextReceived
[TitleType
]= false;
3434 _TextReceived
[ContentType
]= false;
3435 _AlreadyDisplayed
= false;
3437 // start to wait receive of those string (NB: they may be already here, but waitDynStrings calls directly the callback in this case)
3438 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
3439 pSMC
->waitDynString(titleTextId
, this);
3440 pSMC
->waitDynString(docTextId
, this);
3443 CServerMessageBoxOnReceiveTextId ServerMessageBoxOnReceiveTextId
;
3446 void impulseUserPopup(NLMISC::CBitMemStream
&impulse
)
3450 impulse
.serial(titleTextId
);
3451 impulse
.serial(docTextId
);
3453 // setup TEMP DB for title
3454 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3455 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:SERVER_POPUP:TITLE");
3456 if(node
) node
->setValue32(titleTextId
);
3458 // Open the Popup only when the 2 dyn strings are available
3459 ServerMessageBoxOnReceiveTextId
.startWaitTexts(titleTextId
, docTextId
);
3462 //-----------------------------------------------
3463 //-----------------------------------------------
3464 //extern void impulseCombatFlyingHpDelta(NLMISC::CBitMemStream &impulse);
3465 void impulseCombatFlyingHpDelta(NLMISC::CBitMemStream
&impulse
)
3470 impulse
.serial(entityID
);
3471 impulse
.serial(rgba
);
3472 impulse
.serial(hpDelta
);
3473 CRGBA
color((uint8
)(rgba
>>24&255), (uint8
)(rgba
>>16&255), (uint8
)(rgba
>>8&255), (uint8
)(rgba
&255));
3474 CEntityCL
*entity
= EntitiesMngr
.getEntityByCompressedIndex(entityID
);
3476 entity
->addHPOutput(toString("%d", hpDelta
), color
);
3479 void impulseCombatFlyingTextItemSpecialEffectProc(NLMISC::CBitMemStream
&impulse
)
3485 impulse
.serial(entityID
);
3486 impulse
.serial(rgba
);
3487 impulse
.serial(effect
);
3488 impulse
.serial(param
);
3489 CRGBA
color((uint8
)(rgba
>>24&255), (uint8
)(rgba
>>16&255), (uint8
)(rgba
>>8&255), (uint8
)(rgba
&255));
3490 string text
= CI18N::get(toString("uiItemSpecialEffectFlyingText%s", ITEM_SPECIAL_EFFECT::toString((ITEM_SPECIAL_EFFECT::TItemSpecialEffect
)effect
).c_str()));
3491 strFindReplace(text
, "%param", toString("%d", param
));
3492 CEntityCL
*entity
= EntitiesMngr
.getEntityByCompressedIndex(entityID
);
3494 entity
->addHPOutput(text
, color
);
3497 void impulseCombatFlyingText(NLMISC::CBitMemStream
&impulse
)
3501 impulse
.serial(entityID
);
3502 impulse
.serial(tmp
);
3503 COMBAT_FLYING_TEXT::TCombatFlyingText type
= (COMBAT_FLYING_TEXT::TCombatFlyingText
)tmp
;
3505 CRGBA
color(255, 255, 255);
3511 case COMBAT_FLYING_TEXT::TargetDodge
: // The target dodged
3512 color
= CRGBA(255, 128, 64);
3513 text
= CI18N::get("uiDodge");
3516 case COMBAT_FLYING_TEXT::TargetParry
: // The target parried
3517 color
= CRGBA(255, 128, 64);
3518 text
= CI18N::get("uiParry");
3521 case COMBAT_FLYING_TEXT::TargetEvade
: // Actually the user miss his hit
3522 color
= CRGBA(255, 128, 64);
3523 text
= CI18N::get("uiEvade");
3526 case COMBAT_FLYING_TEXT::SelfEvade
: // Actually the target miss his hit
3527 color
= CRGBA(255, 255, 0);
3528 text
= CI18N::get("uiEvade");
3531 case COMBAT_FLYING_TEXT::TargetResist
: // The target resisted magic
3532 color
= CRGBA(255, 128, 64);
3533 text
= CI18N::get("uiResist");
3536 case COMBAT_FLYING_TEXT::SelfResist
: // The user resisted magic
3537 color
= CRGBA(255, 255, 0);
3538 text
= CI18N::get("uiResist");
3541 case COMBAT_FLYING_TEXT::SelfInterrupt
: // the user cast was interupted
3542 color
= CRGBA(200, 0, 0);
3543 text
= CI18N::get("uiInterrupt");
3547 case COMBAT_FLYING_TEXT::SelfFailure
: // The user failed to cast
3548 color
= CRGBA(200, 0, 0);
3549 text
= CI18N::get("uiFailure");
3552 default: // bad type
3553 nlwarning("Bad type for COMBAT_FLYING_TEXT:TCombatFlyingText enum");
3557 CEntityCL
*entity
= EntitiesMngr
.getEntityByCompressedIndex(entityID
);
3559 entity
->addHPOutput(text
, color
, dt
);
3562 void impulseSetSeason(NLMISC::CBitMemStream
&impulse
)
3564 extern uint8 ServerSeasonValue
;
3565 extern bool ServerSeasonReceived
;
3566 impulse
.serial(ServerSeasonValue
);
3567 ServerSeasonReceived
= true;
3570 void impulseDssDown(NLMISC::CBitMemStream
&impulse
)
3575 void impulseSetNpcIconDesc(NLMISC::CBitMemStream
&impulse
)
3578 impulse
.serial(nb8
);
3579 bool hasChanged
= false;
3580 for (uint i
=0; i
!=(uint
)nb8
; ++i
)
3582 TNPCIconCacheKey npcIconCacheKey
;
3583 impulse
.serial(npcIconCacheKey
);
3585 impulse
.serial(state
);
3586 hasChanged
= CNPCIconCache::getInstance().onReceiveMissionAvailabilityForThisChar(npcIconCacheKey
, (NPC_ICON::TNPCMissionGiverState
)state
) || hasChanged
; // mind the order to avoid partial evaluation
3589 CNPCIconCache::getInstance().refreshIconsOfScene();
3592 void impulseServerEventForMissionAvailability(NLMISC::CBitMemStream
&impulse
)
3594 CNPCIconCache::getInstance().onEventForMissionAvailabilityForThisChar();
3597 void impulseSetNpcIconTimer(NLMISC::CBitMemStream
&impulse
)
3599 NLMISC::TGameCycle delay
;
3600 impulse
.serial(delay
);
3601 CNPCIconCache::getInstance().setMissionGiverTimer(delay
);
3604 //-----------------------------------------------
3605 // initializeNetwork :
3606 //-----------------------------------------------
3607 void initializeNetwork()
3609 GenericMsgHeaderMngr
.setCallback("DB_UPD_PLR", impulseDatabaseUpdatePlayer
);
3610 GenericMsgHeaderMngr
.setCallback("DB_INIT:PLR", impulseDatabaseInitPlayer
);
3611 GenericMsgHeaderMngr
.setCallback("DB_UPD_INV", impulseUpdateInventory
);
3612 GenericMsgHeaderMngr
.setCallback("DB_INIT:INV", impulseInitInventory
);
3613 GenericMsgHeaderMngr
.setCallback("DB_GROUP:UPDATE_BANK", impulseDatabaseUpdateBank
);
3614 GenericMsgHeaderMngr
.setCallback("DB_GROUP:INIT_BANK", impulseDatabaseInitBank
);
3615 GenericMsgHeaderMngr
.setCallback("DB_GROUP:RESET_BANK", impulseDatabaseResetBank
);
3616 GenericMsgHeaderMngr
.setCallback("CONNECTION:NO_USER_CHAR", impulseNoUserChar
);
3617 GenericMsgHeaderMngr
.setCallback("CONNECTION:USER_CHARS", impulseUserChars
);
3618 GenericMsgHeaderMngr
.setCallback("CONNECTION:USER_CHAR", impulseUserChar
);
3619 GenericMsgHeaderMngr
.setCallback("CONNECTION:FAR_TP", impulseFarTP
);
3620 GenericMsgHeaderMngr
.setCallback("CONNECTION:READY", impulseServerReady
);
3621 GenericMsgHeaderMngr
.setCallback("CONNECTION:VALID_NAME", impulseCharNameValid
);
3622 GenericMsgHeaderMngr
.setCallback("CONNECTION:SHARD_ID", impulseShardId
);
3623 GenericMsgHeaderMngr
.setCallback("CONNECTION:SERVER_QUIT_OK", impulseServerQuitOk
);
3624 GenericMsgHeaderMngr
.setCallback("CONNECTION:SERVER_QUIT_ABORT", impulseServerQuitAbort
);
3625 GenericMsgHeaderMngr
.setCallback("CONNECTION:MAIL_AVAILABLE", impulseMailNotification
);
3626 GenericMsgHeaderMngr
.setCallback("CONNECTION:GUILD_MESSAGE_AVAILABLE", impulseForumNotification
);
3627 GenericMsgHeaderMngr
.setCallback("CONNECTION:PERMANENT_BAN", impulsePermanentBan
);
3628 GenericMsgHeaderMngr
.setCallback("CONNECTION:UNBAN", impulsePermanentUnban
);
3630 GenericMsgHeaderMngr
.setCallback("STRING:CHAT", impulseChat
);
3631 GenericMsgHeaderMngr
.setCallback("STRING:TELL", impulseTell
);
3632 GenericMsgHeaderMngr
.setCallback("STRING:FAR_TELL", impulseFarTell
);
3633 GenericMsgHeaderMngr
.setCallback("STRING:CHAT2", impulseChat2
);
3634 GenericMsgHeaderMngr
.setCallback("STRING:DYN_STRING", impulseDynString
);
3635 GenericMsgHeaderMngr
.setCallback("STRING:DYN_STRING_GROUP", inpulseDynStringInChatGroup
);
3636 GenericMsgHeaderMngr
.setCallback("STRING:TELL2", impulseTell2
);
3637 // GenericMsgHeaderMngr.setCallback("STRING:ADD_DYN_STR", impulseAddDynStr);
3638 GenericMsgHeaderMngr
.setCallback("TP:DEST", impulseTP
);
3639 GenericMsgHeaderMngr
.setCallback("TP:DEST_WITH_SEASON", impulseTPWithSeason
);
3640 GenericMsgHeaderMngr
.setCallback("TP:CORRECT", impulseCorrectPos
);
3641 GenericMsgHeaderMngr
.setCallback("COMBAT:ENGAGE_FAILED", impulseCombatEngageFailed
);
3642 GenericMsgHeaderMngr
.setCallback("BOTCHAT:DYNCHAT_OPEN", impulseDynChatOpen
);
3643 GenericMsgHeaderMngr
.setCallback("BOTCHAT:DYNCHAT_CLOSE", impulseDynChatClose
);
3645 GenericMsgHeaderMngr
.setCallback("CASTING:BEGIN", impulseBeginCast
);
3646 GenericMsgHeaderMngr
.setCallback("TEAM:INVITATION", impulseTeamInvitation
);
3647 GenericMsgHeaderMngr
.setCallback("TEAM:SHARE_OPEN", impulseTeamShareOpen
);
3648 GenericMsgHeaderMngr
.setCallback("TEAM:SHARE_INVALID", impulseTeamShareInvalid
);
3649 GenericMsgHeaderMngr
.setCallback("TEAM:SHARE_CLOSE", impulseTeamShareClose
);
3650 GenericMsgHeaderMngr
.setCallback("TEAM:CONTACT_INIT", impulseTeamContactInit
);
3651 GenericMsgHeaderMngr
.setCallback("TEAM:CONTACT_CREATE", impulseTeamContactCreate
);
3652 GenericMsgHeaderMngr
.setCallback("TEAM:CONTACT_STATUS", impulseTeamContactStatus
);
3653 GenericMsgHeaderMngr
.setCallback("TEAM:CONTACT_REMOVE", impulseTeamContactRemove
);
3655 GenericMsgHeaderMngr
.setCallback("EXCHANGE:INVITATION", impulseExchangeInvitation
);
3656 GenericMsgHeaderMngr
.setCallback("EXCHANGE:CLOSE_INVITATION", impulseExchangeCloseInvitation
);
3657 GenericMsgHeaderMngr
.setCallback("ANIMALS:MOUNT_ABORT", impulseMountAbort
);
3659 GenericMsgHeaderMngr
.setCallback("DEBUG:REPLY_WHERE", impulseWhere
);
3660 GenericMsgHeaderMngr
.setCallback("DEBUG:COUNTER", impulseCounter
);
3663 GenericMsgHeaderMngr
.setCallback("STRING_MANAGER:PHRASE_SEND", impulsePhraseSend
);
3664 GenericMsgHeaderMngr
.setCallback("STRING_MANAGER:STRING_RESP", impulseStringResp
);
3665 GenericMsgHeaderMngr
.setCallback("STRING_MANAGER:RELOAD_CACHE", impulseReloadCache
);
3667 GenericMsgHeaderMngr
.setCallback("BOTCHAT:FORCE_END", impulseBotChatForceEnd
);
3669 GenericMsgHeaderMngr
.setCallback("JOURNAL:INIT_COMPLETED_MISSIONS", impulseJournalInitCompletedMissions
);
3670 GenericMsgHeaderMngr
.setCallback("JOURNAL:UPDATE_COMPLETED_MISSIONS", impulseJournalUpdateCompletedMissions
);
3671 // GenericMsgHeaderMngr.setCallback("JOURNAL:CANT_ABANDON", impulseJournalCantAbandon);
3673 GenericMsgHeaderMngr
.setCallback("JOURNAL:ADD_COMPASS", impulseJournalAddCompass
);
3674 GenericMsgHeaderMngr
.setCallback("JOURNAL:REMOVE_COMPASS", impulseJournalRemoveCompass
);
3677 //GenericMsgHeaderMngr.setCallback("GUILD:SET_MEMBER_INFO", impulseGuildSetMemberInfo);
3678 //GenericMsgHeaderMngr.setCallback("GUILD:INIT_MEMBER_INFO", impulseGuildInitMemberInfo);
3680 GenericMsgHeaderMngr
.setCallback("GUILD:JOIN_PROPOSAL", impulseGuildJoinProposal
);
3682 GenericMsgHeaderMngr
.setCallback("GUILD:ASCENSOR", impulseGuildAscensor
);
3683 GenericMsgHeaderMngr
.setCallback("GUILD:LEAVE_ASCENSOR", impulseGuildLeaveAscensor
);
3684 GenericMsgHeaderMngr
.setCallback("GUILD:ABORT_CREATION", impulseGuildAbortCreation
);
3685 GenericMsgHeaderMngr
.setCallback("GUILD:OPEN_GUILD_WINDOW", impulseGuildOpenGuildWindow
);
3687 GenericMsgHeaderMngr
.setCallback("GUILD:OPEN_INVENTORY", impulseGuildOpenInventory
);
3688 GenericMsgHeaderMngr
.setCallback("GUILD:CLOSE_INVENTORY", impulseGuildCloseInventory
);
3690 GenericMsgHeaderMngr
.setCallback("GUILD:UPDATE_PLAYER_TITLE", impulseGuildUpdatePlayerTitle
);
3691 GenericMsgHeaderMngr
.setCallback("GUILD:USE_FEMALE_TITLES", impulseGuildUseFemaleTitles
);
3692 //GenericMsgHeaderMngr.setCallback("GUILD:INVITATION", impulseGuildInvitation);
3694 GenericMsgHeaderMngr
.setCallback("HARVEST:CLOSE_TEMP_INVENTORY", impulseCloseTempInv
);
3696 GenericMsgHeaderMngr
.setCallback("COMMAND:REMOTE_ADMIN", impulseRemoteAdmin
);
3698 GenericMsgHeaderMngr
.setCallback("PHRASE:DOWNLOAD", impulsePhraseDownLoad
);
3699 GenericMsgHeaderMngr
.setCallback("PHRASE:CONFIRM_BUY", impulsePhraseConfirmBuy
);
3700 GenericMsgHeaderMngr
.setCallback("PHRASE:EXEC_CYCLIC_ACK", impulsePhraseAckExecuteCyclic
);
3701 GenericMsgHeaderMngr
.setCallback("PHRASE:EXEC_NEXT_ACK", impulsePhraseAckExecuteNext
);
3703 GenericMsgHeaderMngr
.setCallback("ITEM_INFO:SET", impulseItemInfoSet
);
3704 GenericMsgHeaderMngr
.setCallback("ITEM_INFO:REFRESH_VERSION", impulseItemInfoRefreshVersion
);
3705 GenericMsgHeaderMngr
.setCallback("MISSION_PREREQ:SET", impulsePrereqInfoSet
);
3706 GenericMsgHeaderMngr
.setCallback("ITEM:OPEN_ROOM_INVENTORY", impulseItemOpenRoomInventory
);
3707 GenericMsgHeaderMngr
.setCallback("ITEM:CLOSE_ROOM_INVENTORY", impulseItemCloseRoomInventory
);
3709 GenericMsgHeaderMngr
.setCallback("DEATH:RESPAWN_POINT", impulseDeathRespawnPoint
);
3710 GenericMsgHeaderMngr
.setCallback("DEATH:RESPAWN", impulseDeathRespawn
);
3712 GenericMsgHeaderMngr
.setCallback("DUEL:INVITATION", impulseDuelInvitation
);
3713 GenericMsgHeaderMngr
.setCallback("DUEL:CANCEL_INVITATION", impulseDuelCancelInvitation
);
3715 GenericMsgHeaderMngr
.setCallback("PVP_CHALLENGE:INVITATION", impulsePVPChallengeInvitation
);
3716 GenericMsgHeaderMngr
.setCallback("PVP_CHALLENGE:CANCEL_INVITATION", impulsePVPChallengeCancelInvitation
);
3718 GenericMsgHeaderMngr
.setCallback("PVP_FACTION:PUSH_FACTION_WAR", impulsePVPFactionPushFactionWar
);
3719 GenericMsgHeaderMngr
.setCallback("PVP_FACTION:POP_FACTION_WAR", impulsePVPFactionPopFactionWar
);
3720 GenericMsgHeaderMngr
.setCallback("PVP_FACTION:FACTION_WARS", impulsePVPFactionFactionWars
);
3723 // GenericMsgHeaderMngr.setCallback("PVP_VERSUS:CHOOSE_CLAN", impulsePVPChooseClan);
3725 GenericMsgHeaderMngr
.setCallback("ENCYCLOPEDIA:UPDATE", impulseEncyclopediaUpdate
);
3726 GenericMsgHeaderMngr
.setCallback("ENCYCLOPEDIA:INIT", impulseEncyclopediaInit
);
3728 GenericMsgHeaderMngr
.setCallback("USER:BARS", impulseUserBars
);
3729 GenericMsgHeaderMngr
.setCallback("USER:POPUP", impulseUserPopup
);
3732 GenericMsgHeaderMngr
.setCallback("MISSION:ASK_ENTER_CRITICAL", impulseEnterCrZoneProposal
);
3733 GenericMsgHeaderMngr
.setCallback("MISSION:CLOSE_ENTER_CRITICAL", impulseCloseEnterCrZoneProposal
);
3735 // Module gateway message
3736 GenericMsgHeaderMngr
.setCallback( "MODULE_GATEWAY:FEOPEN", cbImpulsionGatewayOpen
);
3737 GenericMsgHeaderMngr
.setCallback( "MODULE_GATEWAY:GATEWAY_MSG", cbImpulsionGatewayMessage
);
3738 GenericMsgHeaderMngr
.setCallback( "MODULE_GATEWAY:FECLOSE", cbImpulsionGatewayClose
);
3740 GenericMsgHeaderMngr
.setCallback( "OUTPOST:CHOOSE_SIDE", impulseOutpostChooseSide
);
3741 GenericMsgHeaderMngr
.setCallback( "OUTPOST:DECLARE_WAR_ACK", impulseOutpostDeclareWarAck
);
3743 GenericMsgHeaderMngr
.setCallback( "COMBAT:FLYING_HP_DELTA", impulseCombatFlyingHpDelta
);
3744 GenericMsgHeaderMngr
.setCallback( "COMBAT:FLYING_TEXT_ISE", impulseCombatFlyingTextItemSpecialEffectProc
);
3745 GenericMsgHeaderMngr
.setCallback( "COMBAT:FLYING_TEXT", impulseCombatFlyingText
);
3747 GenericMsgHeaderMngr
.setCallback( "SEASON:SET", impulseSetSeason
);
3748 GenericMsgHeaderMngr
.setCallback( "RING_MISSION:DSS_DOWN", impulseDssDown
);
3750 GenericMsgHeaderMngr
.setCallback( "NPC_ICON:SET_DESC", impulseSetNpcIconDesc
);
3751 GenericMsgHeaderMngr
.setCallback( "NPC_ICON:SVR_EVENT_MIS_AVL", impulseServerEventForMissionAvailability
);
3752 GenericMsgHeaderMngr
.setCallback( "NPC_ICON:SET_TIMER", impulseSetNpcIconTimer
);
3756 //-----------------------------------------------
3757 // impulseCallBack :
3758 // The impulse callback to receive all msg from the frontend.
3759 //-----------------------------------------------
3760 void impulseCallBack(NLMISC::CBitMemStream
&impulse
, sint32 packet
, void *arg
)
3762 GenericMsgHeaderMngr
.execute(impulse
);
3769 //-----------------------------------------------
3772 //-----------------------------------------------
3773 CNetManager::CNetManager() : CNetworkConnection()
3775 #ifdef ENABLE_INCOMING_MSG_RECORDER
3776 _IsReplayStarting
= false;
3780 //-----------------------------------------------
3782 // Updates the whole connection with the frontend.
3783 // Call this method evently.
3784 // \return bool : 'true' if data were sent/received.
3785 //-----------------------------------------------
3786 bool CNetManager::update()
3788 H_AUTO_USE ( RZ_Client_Net_Mngr_Update
)
3790 #ifdef ENABLE_INCOMING_MSG_RECORDER
3791 if(_IsReplayStarting
)
3795 // If the client is in Local Mode -> no network.
3799 if(_CurrentServerTick
== 0)
3803 _MachineTimeAtTick
= T1
;
3804 _CurrentClientTime
= _MachineTimeAtTick
- _LCT
;
3805 _CurrentClientTick
= 0;
3806 _CurrentServerTick
= 10;
3812 if((T1
- _MachineTimeAtTick
) >= _MsPerTick
)
3814 NLMISC::TGameCycle nbTick
= (NLMISC::TGameCycle
)((T1
- _MachineTimeAtTick
)/_MsPerTick
);
3815 _CurrentClientTick
+= nbTick
;
3816 _CurrentServerTick
+= nbTick
;
3817 _MachineTimeAtTick
+= nbTick
*_MsPerTick
;
3820 // update the smooth server tick for debug
3821 CNetworkConnection::updateSmoothServerTick();
3824 #ifdef ENABLE_INCOMING_MSG_RECORDER
3829 // Update the base class.
3830 bool result
= CNetworkConnection::update();
3831 // Get changes with the update.
3832 const vector
<CChange
> &changes
= NetMngr
.getChanges();
3835 vector
<CChange
>::const_iterator it
;
3836 for(it
= changes
.begin(); it
< changes
.end(); ++it
)
3838 const CChange
&change
= *it
;
3839 // Update a property.
3840 if(change
.Property
< AddNewEntity
)
3842 if (!IgnoreEntityDbUpdates
|| change
.ShortId
== 0)
3844 // Update the visual property for the slot.
3845 EntitiesMngr
.updateVisualProperty(change
.GameCycle
, change
.ShortId
, change
.Property
, change
.PositionInfo
.PredictedInterval
);
3849 nlwarning("CNetManager::update : Skipping EntitiesMngr.updateVisualProperty() because IgnoreEntityDbUpdates=%s and change.ShortId=%d", (IgnoreEntityDbUpdates
?"true":"false"), change
.ShortId
);
3852 // Add New Entity (and remove the old one in the slot).
3853 else if(change
.Property
== AddNewEntity
)
3855 if (!IgnoreEntityDbUpdates
|| change
.ShortId
== 0)
3857 // Remove the old entity.
3858 EntitiesMngr
.remove(change
.ShortId
, false);
3859 // Create the new entity.
3860 if(EntitiesMngr
.create(change
.ShortId
, get(change
.ShortId
), change
.NewEntityInfo
) == 0)
3861 nlwarning("CNetManager::update : entity in the slot '%u' has not been created.", change
.ShortId
);
3865 nlwarning("CNetManager::update : Skipping EntitiesMngr.create() because IgnoreEntityDbUpdates=%s and change.ShortId=%d", (IgnoreEntityDbUpdates
?"true":"false"), change
.ShortId
);
3869 else if(change
.Property
== RemoveOldEntity
)
3871 if (!IgnoreEntityDbUpdates
|| change
.ShortId
== 0)
3873 // Remove the old entity.
3874 EntitiesMngr
.remove(change
.ShortId
, true);
3878 nlwarning("CNetManager::update : Skipping EntitiesMngr.remove() because IgnoreEntityDbUpdates=%s and change.ShortId=%d", (IgnoreEntityDbUpdates
?"true":"false"), change
.ShortId
);
3882 else if(change
.Property
== LagDetected
)
3884 nldebug("CNetManager::update : Lag detected.");
3887 else if(change
.Property
== ProbeReceived
)
3889 nldebug("CNetManager::update : Probe Received.");
3891 // Connection ready.
3892 else if(change
.Property
== ConnectionReady
)
3894 nldebug("CNetManager::update : Connection Ready.");
3896 // Property unknown.
3898 nlwarning("CNetManager::update : The property '%d' is unknown.", change
.Property
);
3900 ChatMngr
.flushBuffer(InterfaceChatDisplayer
);
3901 // Clear all changes.
3904 // Update data base server state
3905 if (IngameDbMngr
.getNodePtr())
3907 CInterfaceManager
*im
= CInterfaceManager::getInstance();
3910 CCDBNodeLeaf
*node
= NULL
;
3913 m_PingLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:PING", false);
3917 node
= &*m_PingLeaf
;
3919 node
->setValue32(getPing());
3923 m_UploadLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:UPLOAD", false);
3927 node
= &*m_UploadLeaf
;
3929 node
->setValue32((sint32
)(getMeanUpload()*1024.f
/8.f
));
3932 if (!m_DownloadLeaf
)
3933 m_DownloadLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:DOWNLOAD", false);
3937 node
= &*m_DownloadLeaf
;
3939 node
->setValue32((sint32
)(getMeanDownload()*1024.f
/8.f
));
3942 if (!m_PacketLostLeaf
)
3943 m_PacketLostLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:PACKETLOST", false);
3945 if (m_PacketLostLeaf
)
3947 node
= &*m_PacketLostLeaf
;
3949 node
->setValue32((sint32
)getMeanPacketLoss());
3952 if (!m_ServerStateLeaf
)
3953 m_ServerStateLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:SERVERSTATE", false);
3955 if (m_ServerStateLeaf
)
3957 node
= &*m_ServerStateLeaf
;
3959 node
->setValue32((sint32
)getConnectionState());
3962 if (!m_ConnectionQualityLeaf
)
3963 m_ConnectionQualityLeaf
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:CONNECTION_QUALITY", false);
3965 if (m_ConnectionQualityLeaf
)
3967 node
= &*m_ConnectionQualityLeaf
;
3969 node
->setValue32((sint32
)getConnectionQuality());
3974 // Return 'true' if data were sent/received.
3980 //-----------------------------------------------
3981 // getConnectionQuality :
3982 //-----------------------------------------------
3983 bool CNetManager::getConnectionQuality()
3985 // If the client is in Local Mode -> no network.
3989 return CNetworkConnection::getConnectionQuality();
3990 }// getConnectionQuality //
3994 * Buffers a bitmemstream, that will be converted into a generic action, to be sent later to the server (at next update).
3996 void CNetManager::push(NLMISC::CBitMemStream
&msg
)
3998 // If the client is in Local Mode -> no network.
4002 if (PermanentlyBanned
) return;
4004 CNetworkConnection::push(msg
);
4008 * Buffers a target action
4010 void CNetManager::pushTarget(CLFECOMMON::TCLEntityId slot
)
4012 // If the client is in Local Mode -> no network.
4015 if(UserEntity
->mode() != MBEHAV::COMBAT
4016 && UserEntity
->mode() != MBEHAV::COMBAT_FLOAT
)
4018 UserEntity
->targetSlot(slot
);
4023 CNetworkConnection::pushTarget(slot
, LHSTATE::NONE
);
4028 * Buffers a pick-up action
4030 void CNetManager::pushPickup(CLFECOMMON::TCLEntityId slot
, LHSTATE::TLHState lootOrHarvest
)
4032 // If the client is in Local Mode -> no network.
4038 CNetworkConnection::pushTarget(slot
, lootOrHarvest
);
4045 void CNetManager::send(NLMISC::TGameCycle gameCycle
)
4047 // If the client is in Local Mode -> no network.
4051 // wait till next server is received
4052 if (_LastSentCycle
>= gameCycle
)
4054 //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);
4055 while (_LastSentCycle
>= gameCycle
)
4061 // Do not take all the CPU.
4064 gameCycle
= getCurrentServerTick();
4068 CNetworkConnection::send(gameCycle
);
4074 void CNetManager::send()
4076 // If the client is in Local Mode -> no network.
4080 CNetworkConnection::send();
4084 * Disconnects the current connection
4086 void CNetManager::disconnect()
4088 // If the client is in Local Mode -> no need to disconnect.
4092 CNetworkConnection::disconnect();
4097 * Reset data and init the socket
4099 void CNetManager::reinit()
4104 IngameDbMngr
.resetInitState();
4105 CNetworkConnection::reinit();
4108 void CNetManager::waitForServer()
4110 sint LastGameCycle
= getCurrentServerTick();
4114 // Event server get events
4115 CInputHandlerManager::getInstance()->pumpEventsNoIM();
4119 if (LastGameCycle
!= (sint
) getCurrentServerTick())
4126 }// waitForServer //
4129 #ifdef ENABLE_INCOMING_MSG_RECORDER
4130 //-----------------------------------------------
4131 // setReplayingMode :
4132 //-----------------------------------------------
4133 void CNetManager::setReplayingMode( bool onOff
, const std::string
& filename
)
4135 CNetworkConnection::setReplayingMode(onOff
, filename
);
4136 _IsReplayStarting
= onOff
;
4137 }// setReplayingMode //
4139 //-----------------------------------------------
4141 //-----------------------------------------------
4142 void CNetManager::startReplay()
4145 _MachineTimeAtTick
= T1
;
4146 if(_MachineTimeAtTick
>= _LCT
)
4147 _CurrentClientTime
= _MachineTimeAtTick
- _LCT
;
4149 _CurrentClientTime
= 0;
4150 // Replay now in progress.
4151 _IsReplayStarting
= false;
4157 * Create the net managers in CLIENT_MULTI mode
4159 void CNetManagerMulti::init( const std::string
& cookie
, const std::string
& addr
)
4161 uint nb
, baseCookie
;
4162 NLMISC::CConfigFile::CVar
*var
= ClientCfg
.ConfigFile
.getVarPtr( "NbConnections" );
4167 var
= ClientCfg
.ConfigFile
.getVarPtr( "UserId" );
4169 baseCookie
= var
->asInt();
4172 std::vector
<std::string
> fsAddrs
;
4173 fsAddrs
.push_back( addr
);
4174 string portString
= addr
.substr( addr
.find( ':' ) );
4175 var
= ClientCfg
.ConfigFile
.getVarPtr( "AdditionalFSList" );
4178 for ( uint i
=0; i
!=var
->size(); ++i
)
4179 fsAddrs
.push_back( var
->asString( i
) + portString
);
4181 nlinfo( "CNetManagerMulti: Creating %u connections to %u front-ends, baseCookie=%u...", nb
, fsAddrs
.size(), baseCookie
);
4183 for ( uint i
=0; i
!=nb
; ++i
)
4185 CNetManager
*nm
= new CNetManager();
4186 string multicook
= NLMISC::toString( "%8x|%8x|%8x", 0, 0, baseCookie
+ i
);
4187 nm
->init( multicook
, fsAddrs
[i
% fsAddrs
.size()] );
4188 _NetManagers
.push_back( nm
);
4194 std::string WebServer
;
4199 /////////////////////////////////////////////////////////////////////////////
4200 /////////////////////////////////////////////////////////////////////////////
4201 /////////////////////////////////////////////////////////////////////////////
4202 /////////////////////////////////////////////////////////////////////////////
4203 /////////// COMMANDS after should NOT appear IN the FINAL VERSION ///////////
4204 /////////////////////////////////////////////////////////////////////////////
4205 /////////////////////////////////////////////////////////////////////////////
4206 /////////////////////////////////////////////////////////////////////////////
4207 /////////////////////////////////////////////////////////////////////////////
4208 /////////////////////////////////////////////////////////////////////////////
4213 // temp : simulate a team msg in local mode
4214 NLMISC_COMMAND(localTellTeam
, "Temp : simulate a tell in local mode", "<people_name> <msg>")
4216 if (args
.empty()) return false;
4217 string player
= args
[0];
4219 if (args
.size() >= 2)
4222 for(uint k
= 2; k
< args
.size(); ++k
)
4224 msg
+= " " + args
[k
];
4227 TDataSetIndex dsi
= INVALID_DATASET_INDEX
;
4228 InterfaceChatDisplayer
.displayChat(dsi
, msg
, msg
, CChatGroup::team
, NLMISC::CEntityId::Unknown
, player
);
4232 // temp : simulate a tell in local mode
4233 NLMISC_COMMAND(localTell
, "Temp : simulate a tell in local mode", "<people_name> <msg>")
4235 if (args
.empty()) return false;
4236 string player
= args
[0];
4238 if (args
.size() >= 2)
4241 for(uint k
= 2; k
< args
.size(); ++k
)
4243 msg
+= " " + args
[k
];
4246 // TDataSetIndex dsi = INVALID_DATASET_ROW;
4247 InterfaceChatDisplayer
.displayTell(/*dsi, */msg
, player
);
4251 NLMISC_COMMAND(testDynChatOpen
, "", "")
4253 NLMISC::CBitMemStream bm
;
4254 if (bm
.isReading()) bm
.invert();
4255 uint32 BotUID
= 22; // Compressed Index
4256 uint32 BotName
= 654; // Server string
4257 vector
<uint32
> DynStrs
; // 0 - Desc, 1 - Option0, 2 - Option1, etc....
4258 DynStrs
.push_back(16540);
4259 DynStrs
.push_back(11465);
4260 DynStrs
.push_back(12654);
4263 bm
.serialCont(DynStrs
);
4265 bm
.seek(0, NLMISC::IStream::begin
);
4266 impulseDynChatOpen(bm
);
4270 NLMISC_COMMAND(testDynChatClose
, "", "")
4272 NLMISC::CBitMemStream bm
;
4273 if (bm
.isReading()) bm
.invert();
4274 uint32 BotUID
= 22; // Compressed Index
4277 bm
.seek(0, NLMISC::IStream::begin
);
4278 impulseDynChatClose(bm
);
4283 NLMISC_COMMAND(testCloseTempInv
, "","")
4285 NLMISC::CBitMemStream bm
;
4286 impulseCloseTempInv(bm
);
4290 NLMISC_COMMAND(testTeamInvite
, "","")
4292 NLMISC::CBitMemStream bm
;
4293 if (bm
.isReading()) bm
.invert();
4297 bm
.seek(0, NLMISC::IStream::begin
);
4298 impulseTeamInvitation(bm
);
4301 NLMISC_COMMAND(testGuildInvite
, "","")
4303 NLMISC::CBitMemStream bm
;
4304 if (bm
.isReading()) bm
.invert();
4309 bm
.seek(0, NLMISC::IStream::begin
);
4310 impulseGuildJoinProposal(bm
);
4314 NLMISC_COMMAND( testExchangeInvitation
, "Test the modal window for invitation exchange", "" )
4316 CBitMemStream impulse
;
4317 uint32 nameIndex
= 0;
4318 impulse
.serial(nameIndex
);
4320 impulseExchangeInvitation(impulse
);
4325 NLMISC_COMMAND(testAscensor
, "Temp : Simulate a GUILD:ASCENSOR message coming from server","")
4327 NLMISC::CBitMemStream bm
;
4328 if (bm
.isReading()) bm
.invert();
4332 bm
.seek(0, NLMISC::IStream::begin
);
4333 impulseGuildAscensor(bm
);
4337 NLMISC_COMMAND(testDuelInvite
, "","")
4339 NLMISC::CBitMemStream bm
;
4340 if (bm
.isReading()) bm
.invert();
4344 bm
.seek(0, NLMISC::IStream::begin
);
4345 impulseDuelInvitation(bm
);
4349 //NLMISC_COMMAND(receiveId, "","<num> <name>")
4352 // fromString(args[0], index);
4353 // ucstring ucstr = args[1]; // OLD
4355 // vector<bool> code;
4357 //#ifdef OLD_STRING_SYSTEM
4358 // ChatMngr.getDynamicDB().add( index, ucstr, code );
4360 // // TRAP // WE MUST NEVER CALL THIS COMMAND ANYMORE : ALL IS HANDLED BY STRING_MANAGER NOW !!!
4367 NLMISC_COMMAND(testOutpostChooseSide
, "","b b u32 u32")
4371 NLMISC::CBitMemStream bm
;
4372 if (bm
.isReading()) bm
.invert();
4373 bool playerGuildInConflict
;
4374 fromString(args
[0], playerGuildInConflict
);
4375 bool playerGuildIsAttacker
;
4376 fromString(args
[1], playerGuildIsAttacker
);
4377 bm
.serial(playerGuildInConflict
);
4378 bm
.serial(playerGuildIsAttacker
);
4379 uint32 ownerGuildNameId
;
4380 fromString(args
[2], ownerGuildNameId
);
4381 bm
.serial( ownerGuildNameId
);
4382 uint32 attackerGuildNameId
;
4383 fromString(args
[3], attackerGuildNameId
);
4384 bm
.serial( attackerGuildNameId
);
4385 uint32 declTimer
= 100;
4386 bm
.serial( declTimer
);
4389 bm
.seek(0, NLMISC::IStream::begin
);
4390 impulseOutpostChooseSide(bm
);
4394 NLMISC_COMMAND(testUserPopup
, "","u32 u32")
4398 NLMISC::CBitMemStream bm
;
4399 if (bm
.isReading()) bm
.invert();
4401 fromString(args
[0], titleId
);
4402 bm
.serial( titleId
);
4404 fromString(args
[1], textId
);
4405 bm
.serial( textId
);
4408 bm
.seek(0, NLMISC::IStream::begin
);
4409 impulseUserPopup(bm
);