WOLChatMgr.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * $Archive: /Commando/Code/Commando/WOLChatMgr.cpp $
  22. *
  23. * DESCRIPTION
  24. *
  25. * PROGRAMMER
  26. * Denzil E. Long, Jr.
  27. * $Author: Denzil_l $
  28. *
  29. * VERSION INFO
  30. * $Revision: 36 $
  31. * $Modtime: 2/25/02 5:05p $
  32. *
  33. ******************************************************************************/
  34. #include "WOLChatMgr.h"
  35. #include "WOLBuddyMgr.h"
  36. #include "MPSettingsMgr.h"
  37. #include "DlgWOLWait.h"
  38. #include <WWOnline\WOLSession.h>
  39. #include <WWOnline\WOLServer.h>
  40. #include <WWOnline\WOLChannel.h>
  41. #include <WWOnline\WOLProduct.h>
  42. #include "String_IDs.h"
  43. #include <WWTranslateDB\TranslateDB.h>
  44. #include <WWDebug\WWDebug.h>
  45. using namespace WWOnline;
  46. WOLChatMgr* WOLChatMgr::_mInstance = NULL;
  47. // Local prototypes
  48. typedef void (*SlashCommandFunc)(const wchar_t*);
  49. static void SlashCmdPage(const wchar_t*);
  50. static void SlashCmdR(const wchar_t*);
  51. static void SlashCmdLocate(const wchar_t*);
  52. static void SlashCmdMsg(const wchar_t*);
  53. static void SlashCmdInvite(const wchar_t*);
  54. static void SlashCmdKick(const wchar_t*);
  55. static void SlashCmdJoin(const wchar_t*);
  56. static const wchar_t* Get_Parameter_From_String(const wchar_t* command_string, WideStringClass& parameter);
  57. /******************************************************************************
  58. *
  59. * NAME
  60. * WOLChatMgr::GetInstance
  61. *
  62. * DESCRIPTION
  63. * Obtain Chat manager instance
  64. *
  65. * INPUTS
  66. * Create - Okay to create chat manager if not already instantiated.
  67. *
  68. * RESULT
  69. * Instance - Pointer to the chat manager.
  70. *
  71. ******************************************************************************/
  72. WOLChatMgr* WOLChatMgr::GetInstance(bool createOK)
  73. {
  74. if (_mInstance == NULL)
  75. {
  76. new WOLChatMgr;
  77. if (_mInstance)
  78. {
  79. if (_mInstance->FinalizeCreate() == false)
  80. {
  81. _mInstance->Release_Ref();
  82. }
  83. }
  84. }
  85. else
  86. {
  87. _mInstance->Add_Ref();
  88. }
  89. return _mInstance;
  90. }
  91. /******************************************************************************
  92. *
  93. * NAME
  94. * WOLChatMgr::WOLChatMgr
  95. *
  96. * DESCRIPTION
  97. * Constructor
  98. *
  99. * INPUTS
  100. * NONE
  101. *
  102. * RESULT
  103. * NONE
  104. *
  105. ******************************************************************************/
  106. WOLChatMgr::WOLChatMgr()
  107. {
  108. WWDEBUG_SAY(("WOLChatMgr: Instantiated\n"));
  109. _mInstance = this;
  110. }
  111. /******************************************************************************
  112. *
  113. * NAME
  114. * WOLChatMgr::~WOLChatMgr
  115. *
  116. * DESCRIPTION
  117. * Destructor
  118. *
  119. * INPUTS
  120. * NONE
  121. *
  122. * RESULT
  123. * NONE
  124. *
  125. ******************************************************************************/
  126. WOLChatMgr::~WOLChatMgr()
  127. {
  128. WWDEBUG_SAY(("WOLChatMgr: Destroyed\n"));
  129. _mInstance = NULL;
  130. }
  131. /******************************************************************************
  132. *
  133. * NAME
  134. * WOLChatMgr::FinalizeCreate
  135. *
  136. * DESCRIPTION
  137. * Finalize object creation.
  138. *
  139. * INPUTS
  140. * NONE
  141. *
  142. * RESULT
  143. * True if successful
  144. *
  145. ******************************************************************************/
  146. bool WOLChatMgr::FinalizeCreate(void)
  147. {
  148. // Get reference to WWOnline session
  149. mWOLSession = Session::GetInstance(false);
  150. if (!mWOLSession.IsValid())
  151. {
  152. return false;
  153. }
  154. // Generate chat lobby prefex
  155. RefPtr<Product> product = Product::Current();
  156. if (!product.IsValid())
  157. {
  158. return false;
  159. }
  160. mLobbyPrefix.Format(L"Lob_%d_", product->GetGameCode());
  161. return true;
  162. }
  163. /******************************************************************************
  164. *
  165. * NAME
  166. * WOLChatMgr::Start
  167. *
  168. * DESCRIPTION
  169. * Start receiving and processing chat messages.
  170. *
  171. * INPUTS
  172. * NONE
  173. *
  174. * RESULT
  175. * NONE
  176. *
  177. ******************************************************************************/
  178. void WOLChatMgr::Start(void)
  179. {
  180. if (mWOLSession.IsValid())
  181. {
  182. Observer<ServerError>::NotifyMe(*mWOLSession);
  183. Observer<ChannelListEvent>::NotifyMe(*mWOLSession);
  184. Observer<ChannelEvent>::NotifyMe(*mWOLSession);
  185. Observer<UserEvent>::NotifyMe(*mWOLSession);
  186. Observer<UserList>::NotifyMe(*mWOLSession);
  187. Observer<ChatMessage>::NotifyMe(*mWOLSession);
  188. }
  189. }
  190. /******************************************************************************
  191. *
  192. * NAME
  193. * WOLChatMgr::Stop
  194. *
  195. * DESCRIPTION
  196. * Suspend receiving and processing of chat messages.
  197. *
  198. * INPUTS
  199. * NONE
  200. *
  201. * RESULT
  202. * NONE
  203. *
  204. ******************************************************************************/
  205. void WOLChatMgr::Stop(void)
  206. {
  207. if (mWOLSession.IsValid())
  208. {
  209. Observer<ServerError>::StopObserving();
  210. Observer<ChannelListEvent>::StopObserving();
  211. Observer<ChannelEvent>::StopObserving();
  212. Observer<UserEvent>::StopObserving();
  213. Observer<UserList>::StopObserving();
  214. Observer<ChatMessage>::StopObserving();
  215. }
  216. }
  217. /******************************************************************************
  218. *
  219. * NAME
  220. * WOLChatMgr::RefreshLobbyList
  221. *
  222. * DESCRIPTION
  223. * Request an updated list of chat channels.
  224. *
  225. * INPUTS
  226. * NONE
  227. *
  228. * RESULT
  229. * NONE
  230. *
  231. ******************************************************************************/
  232. void WOLChatMgr::RefreshLobbyList(void)
  233. {
  234. mWOLSession->RequestChannelList(0, false);
  235. }
  236. /******************************************************************************
  237. *
  238. * NAME
  239. * WOLChatMgr::GetLobbyList
  240. *
  241. * DESCRIPTION
  242. * Get a list of available chat channels.
  243. *
  244. * INPUTS
  245. * NONE
  246. *
  247. * RESULT
  248. * Lobbies - List of valid chat channels.
  249. *
  250. ******************************************************************************/
  251. const LobbyList& WOLChatMgr::GetLobbyList(void)
  252. {
  253. return mLobbyList;
  254. }
  255. /******************************************************************************
  256. *
  257. * NAME
  258. * WOLChatMgr::GetCurrentLobby
  259. *
  260. * DESCRIPTION
  261. * Get the lobby we are currently joined.
  262. *
  263. * INPUTS
  264. * NONE
  265. *
  266. * RESULT
  267. * Lobby - Lobby currently joined to.
  268. *
  269. ******************************************************************************/
  270. const RefPtr<ChannelData>& WOLChatMgr::GetCurrentLobby(void)
  271. {
  272. return mWOLSession->GetCurrentChannel();
  273. }
  274. /******************************************************************************
  275. *
  276. * NAME
  277. * WOLChatMgr::FindLobby
  278. *
  279. * DESCRIPTION
  280. * Find a chat lobby with the specified name.
  281. *
  282. * INPUTS
  283. * Name - Name of lobby to find.
  284. *
  285. * RESULT
  286. * Lobby -
  287. *
  288. ******************************************************************************/
  289. const RefPtr<ChannelData> WOLChatMgr::FindLobby(const wchar_t* name)
  290. {
  291. return mWOLSession->FindChatChannel(name);
  292. }
  293. /******************************************************************************
  294. *
  295. * NAME
  296. * WOLChatMgr::CreateLobby
  297. *
  298. * DESCRIPTION
  299. * Create a channel lobby
  300. *
  301. * INPUTS
  302. * Name - New lobby name
  303. * Password - Password required to join lobby.
  304. *
  305. * RESULT
  306. * NONE
  307. *
  308. ******************************************************************************/
  309. void WOLChatMgr::CreateLobby(const wchar_t* name, const wchar_t* password)
  310. {
  311. RefPtr<WaitCondition> wait = mWOLSession->CreateChannel(name, password, 0);
  312. if (wait.IsValid())
  313. {
  314. WideStringClass message(255, true);
  315. message.Format(TRANSLATE(IDS_CHAT_LOBBYCREATE), name);
  316. DlgWOLWait::DoDialog((const wchar_t*)message, wait);
  317. }
  318. }
  319. /******************************************************************************
  320. *
  321. * NAME
  322. * WOLChatMgr::JoinLobby
  323. *
  324. * DESCRIPTION
  325. * Join a channel lobby
  326. *
  327. * INPUTS
  328. * Channel - Channel lobby to join
  329. *
  330. * RESULT
  331. * NONE
  332. *
  333. ******************************************************************************/
  334. void WOLChatMgr::JoinLobby(const RefPtr<ChannelData>& channel)
  335. {
  336. if (channel.IsValid())
  337. {
  338. RefPtr<Product> product = Product::Current();
  339. WWASSERT_PRINT(product.IsValid(), "WWOnline product not initialized.");
  340. RefPtr<WaitCondition> wait = mWOLSession->JoinChannel(channel, product->GetChannelPassword());
  341. if (wait.IsValid())
  342. {
  343. WideStringClass displayName(0, true);
  344. GetLobbyDisplayName(channel, displayName);
  345. WideStringClass message(0, true);
  346. message.Format(TRANSLATE(IDS_CHAT_LOBBYJOIN), displayName);
  347. DlgWOLWait::DoDialog((const wchar_t*)message, wait);
  348. }
  349. }
  350. }
  351. /******************************************************************************
  352. *
  353. * NAME
  354. * WOLChatMgr::LeaveLobby
  355. *
  356. * DESCRIPTION
  357. * Leave the current channel lobby.
  358. *
  359. * INPUTS
  360. * NONE
  361. *
  362. * RESULT
  363. * NONE
  364. *
  365. ******************************************************************************/
  366. void WOLChatMgr::LeaveLobby(void)
  367. {
  368. RefPtr<WaitCondition> wait = mWOLSession->LeaveChannel();
  369. if (wait.IsValid())
  370. {
  371. const RefPtr<ChannelData>& channel = GetCurrentLobby();
  372. WideStringClass lobbyName(0, true);
  373. GetLobbyDisplayName(channel, lobbyName);
  374. WideStringClass title(0, true);
  375. title.Format(TRANSLATE(IDS_CHAT_LOBBYLEAVE), lobbyName);
  376. DlgWOLWait::DoDialog(title, wait);
  377. }
  378. }
  379. /******************************************************************************
  380. *
  381. * NAME
  382. * WOLChatMgr::IsLobbyValid
  383. *
  384. * DESCRIPTION
  385. * Check if the channel is a valid chat lobby.
  386. *
  387. * INPUTS
  388. * Lobby - Lobby to validate
  389. *
  390. * RESULT
  391. * True if lobby is a valid chat lobby.
  392. *
  393. ******************************************************************************/
  394. bool WOLChatMgr::IsLobbyValid(const RefPtr<ChannelData>& lobby)
  395. {
  396. if (lobby.IsValid())
  397. {
  398. const int unwantedFlags = CHAN_MODE_SECRET | CHAN_MODE_INVITEONLY | CHAN_MODE_BAN;
  399. unsigned int lobbyFlags = lobby->GetFlags();
  400. // Lobbies without these flags are valid chat lobbies.
  401. if ((lobbyFlags & unwantedFlags) == 0)
  402. {
  403. // Lobbies that have the matching prefix are valid.
  404. const wchar_t* lobbyName = lobby->GetName();
  405. return (wcsnicmp(mLobbyPrefix, lobbyName, mLobbyPrefix.Get_Length()) == 0);
  406. }
  407. }
  408. return false;
  409. }
  410. /******************************************************************************
  411. *
  412. * NAME
  413. * WOLChatMgr::GetLobbyDisplayName
  414. *
  415. * DESCRIPTION
  416. * Get the display name for the given lobby.
  417. *
  418. * INPUTS
  419. * Lobby - Lobby to get display name for.
  420. * Name - On return; display name for the lobby.
  421. *
  422. * RESULT
  423. * NONE
  424. *
  425. ******************************************************************************/
  426. void WOLChatMgr::GetLobbyDisplayName(const RefPtr<ChannelData>& lobby, WideStringClass& outName)
  427. {
  428. if (lobby.IsValid() == false)
  429. {
  430. outName = L"";
  431. return;
  432. }
  433. const wchar_t* name = lobby->GetName();
  434. int prefixLength = mLobbyPrefix.Get_Length();
  435. if (wcsnicmp(name, mLobbyPrefix, prefixLength) == 0)
  436. {
  437. const wchar_t* extName = (name + prefixLength);
  438. // If the extended portion of the lobby name is a number then select a name
  439. // from the Renegade lobby names provided. Otherwise use the extended portion
  440. // as given.
  441. if (*extName >= L'0' && *extName <= L'9')
  442. {
  443. static const wchar_t* _lobbies[8] =
  444. {
  445. TRANSLATE (IDS_MENU_LOBBY_NAME_01),
  446. TRANSLATE (IDS_MENU_LOBBY_NAME_02),
  447. TRANSLATE (IDS_MENU_LOBBY_NAME_03),
  448. TRANSLATE (IDS_MENU_LOBBY_NAME_04),
  449. TRANSLATE (IDS_MENU_LOBBY_NAME_05),
  450. TRANSLATE (IDS_MENU_LOBBY_NAME_06),
  451. TRANSLATE (IDS_MENU_LOBBY_NAME_07),
  452. TRANSLATE (IDS_MENU_LOBBY_NAME_08),
  453. };
  454. int channelNumber = _wtol(extName);
  455. int subnum = (channelNumber / 8);
  456. int nameNumber = (channelNumber % 8);
  457. const wchar_t* displayName = _lobbies[nameNumber];
  458. if (subnum == 0)
  459. {
  460. outName = displayName;
  461. }
  462. else
  463. {
  464. outName.Format(L"%s_%d", displayName, (subnum + 1));
  465. }
  466. }
  467. else
  468. {
  469. outName = extName;
  470. }
  471. }
  472. }
  473. /******************************************************************************
  474. *
  475. * NAME
  476. * WOLChatMgr::FindUser
  477. *
  478. * DESCRIPTION
  479. * Find a user with the specified name.
  480. *
  481. * INPUTS
  482. * Name - Name of user to look for.
  483. *
  484. * RESULT
  485. * User -
  486. *
  487. ******************************************************************************/
  488. const RefPtr<UserData> WOLChatMgr::FindUser(const wchar_t* name)
  489. {
  490. return mWOLSession->FindUser(name);
  491. }
  492. /******************************************************************************
  493. *
  494. * NAME
  495. * WOLChatMgr::ClearUserInList
  496. *
  497. * DESCRIPTION
  498. * Clear the list of users who have joined.
  499. *
  500. * INPUTS
  501. * NONE
  502. *
  503. * RESULT
  504. * NONE
  505. *
  506. ******************************************************************************/
  507. void WOLChatMgr::ClearUserInList(void)
  508. {
  509. mUserInList.clear();
  510. }
  511. /******************************************************************************
  512. *
  513. * NAME
  514. * WOLChatMgr::ClearUserOutList
  515. *
  516. * DESCRIPTION
  517. * Clear the list of users who have left.
  518. *
  519. * INPUTS
  520. * NONE
  521. *
  522. * RESULT
  523. * NONE
  524. *
  525. ******************************************************************************/
  526. void WOLChatMgr::ClearUserOutList(void)
  527. {
  528. mUserOutList.clear();
  529. }
  530. /******************************************************************************
  531. *
  532. * NAME
  533. * WOLChatMgr::SquelchUser
  534. *
  535. * DESCRIPTION
  536. * Enable / Disable receipt of messages from the specified user.
  537. *
  538. * INPUTS
  539. * Name - Name of user
  540. * Squelch - True to enable; false to disable
  541. *
  542. * RESULT
  543. * True if request was successful.
  544. *
  545. ******************************************************************************/
  546. bool WOLChatMgr::SquelchUser(const RefPtr<UserData>& user, bool onoff)
  547. {
  548. bool success = mWOLSession->SquelchUser(user, onoff);
  549. if (success)
  550. {
  551. int stringID = (onoff ? IDS_CHAT_SQUELCH_ON : IDS_CHAT_SQUELCH_OFF);
  552. const wchar_t* text = TRANSLATE(stringID);
  553. WideStringClass message(0, true);
  554. message.Format(text, user->GetName());
  555. AddMessage(NULL, message, true, true);
  556. }
  557. return success;
  558. }
  559. /******************************************************************************
  560. *
  561. * NAME
  562. * WOLChatMgr::LocateUser
  563. *
  564. * DESCRIPTION
  565. * Request the location status of a user.
  566. *
  567. * INPUTS
  568. * Name - Name of user to locate
  569. *
  570. * RESULT
  571. * NONE
  572. *
  573. ******************************************************************************/
  574. void WOLChatMgr::LocateUser(const wchar_t* name)
  575. {
  576. mLocatingUserName = name;
  577. mLocatingUserName.Trim();
  578. if (mLocatingUserName.Is_Empty() == false)
  579. {
  580. mWOLSession->RequestLocateUser(mLocatingUserName);
  581. }
  582. }
  583. /******************************************************************************
  584. *
  585. * NAME
  586. * WOLChatMgr::SendPublicMessage
  587. *
  588. * DESCRIPTION
  589. * Send a message that everyone can see.
  590. *
  591. * INPUTS
  592. * Message - Message to send
  593. * IsAction - Is this message and action.
  594. *
  595. * RESULT
  596. * NONE
  597. *
  598. ******************************************************************************/
  599. void WOLChatMgr::SendPublicMessage(const wchar_t* message, bool isAction)
  600. {
  601. if (ProcessCommand(message))
  602. {
  603. return;
  604. }
  605. if (isAction)
  606. {
  607. mWOLSession->SendPublicAction(message);
  608. }
  609. else
  610. {
  611. mWOLSession->SendPublicMessage(message);
  612. }
  613. const wchar_t* sender = NULL;
  614. RefPtr<UserData> me = mWOLSession->GetCurrentUser();
  615. if (me.IsValid())
  616. {
  617. sender = me->GetName();
  618. }
  619. AddMessage(sender, message, false, isAction);
  620. }
  621. /******************************************************************************
  622. *
  623. * NAME
  624. * WOLChatMgr::SendPrivateMessage
  625. *
  626. * DESCRIPTION
  627. * Send a message that only the specified user can see.
  628. *
  629. * INPUTS
  630. * User - Users to send message to.
  631. * Message - Message to send.
  632. * IsAction - True if this is an emote action.
  633. *
  634. * RESULT
  635. * NONE
  636. *
  637. ******************************************************************************/
  638. void WOLChatMgr::SendPrivateMessage(const RefPtr<UserData>& user,
  639. const wchar_t* message, bool isAction)
  640. {
  641. if (ProcessCommand(message))
  642. {
  643. return;
  644. }
  645. UserList userList;
  646. userList.push_back(user);
  647. SendPrivateMessage(userList, message, isAction);
  648. }
  649. /******************************************************************************
  650. *
  651. * NAME
  652. * WOLChatMgr::SendPrivateMessage
  653. *
  654. * DESCRIPTION
  655. * Send a message that only a selected group of users can see.
  656. *
  657. * INPUTS
  658. * User - List of users to send message to.
  659. * Message - Message to send.
  660. * IsAction - True if this is an emote action.
  661. *
  662. * RESULT
  663. * NONE
  664. *
  665. ******************************************************************************/
  666. void WOLChatMgr::SendPrivateMessage(UserList& users, const wchar_t* message, bool isAction)
  667. {
  668. if (ProcessCommand(message))
  669. {
  670. return;
  671. }
  672. if (isAction)
  673. {
  674. mWOLSession->SendPrivateAction(users, message);
  675. }
  676. else
  677. {
  678. mWOLSession->SendPrivateMessage(users, message);
  679. }
  680. const wchar_t* sender = NULL;
  681. RefPtr<UserData> me = mWOLSession->GetCurrentUser();
  682. if (me.IsValid())
  683. {
  684. sender = me->GetName();
  685. }
  686. AddMessage(sender, message, true, isAction);
  687. }
  688. /******************************************************************************
  689. *
  690. * NAME
  691. * WOLChatMgr::AddMessage
  692. *
  693. * DESCRIPTION
  694. * Add a message to the chat messages pool.
  695. *
  696. * INPUTS
  697. * Sender - User message originated from.
  698. * Message - Text message
  699. * IsPrivate - True if the message is private.
  700. * IsAction - True if the message is an action.
  701. *
  702. * RESULT
  703. * NONE
  704. *
  705. ******************************************************************************/
  706. void WOLChatMgr::AddMessage(const wchar_t* sender, const wchar_t* message, bool isPrivate, bool isAction)
  707. {
  708. ChatMessage msg(sender, message, isPrivate, isAction);
  709. mMessageList.push_back(msg);
  710. WOLChatMgrEvent event = MessageListChanged;
  711. NotifyObservers(event);
  712. }
  713. /******************************************************************************
  714. *
  715. * NAME
  716. * WOLChatMgr::PassesFilters
  717. *
  718. * DESCRIPTION
  719. * Check message against user specified text filters.
  720. *
  721. * INPUTS
  722. * Message - Chat message to filter.
  723. *
  724. * RESULT
  725. * True if message should be displayed; False if it should be hidden.
  726. *
  727. ******************************************************************************/
  728. bool WOLChatMgr::PassesFilters(const ChatMessage& msg)
  729. {
  730. // Messages from the user and channel owners are never filtered.
  731. if (msg.IsSenderMyself() || msg.IsSenderChannelOwner())
  732. {
  733. return true;
  734. }
  735. // All messages from squelched users are filtered
  736. if (msg.IsSenderSquelched())
  737. {
  738. WWDEBUG_SAY(("WOLChatMgr: Filtered squelched message from %S\n",
  739. (const WCHAR*)msg.GetSendersName()));
  740. return false;
  741. }
  742. //---------------------------------------------------------------------------
  743. // Buddy and Clan filtering
  744. //---------------------------------------------------------------------------
  745. bool testClan = MPSettingsMgrClass::Get_Option_Flag(MPSettingsMgrClass::OPTION_CLAN_CHAT_ONLY);
  746. bool testBuddy = MPSettingsMgrClass::Get_Option_Flag(MPSettingsMgrClass::OPTION_BUDDY_CHAT_ONLY);
  747. // If only interested in messages from clan members then filter out all
  748. // messages from everybody else.
  749. bool passesClan = true;
  750. if (testClan)
  751. {
  752. RefPtr<UserData> user = mWOLSession->GetCurrentUser();
  753. if (user.IsValid())
  754. {
  755. unsigned long clanID = user->GetSquadID();
  756. passesClan = ((clanID == 0) || msg.IsSenderInClan(clanID));
  757. }
  758. }
  759. // If only interested in messages from buddies then filter out all the
  760. // messages that are not from users in the buddy list.
  761. bool passesBuddy = true;
  762. if (testBuddy)
  763. {
  764. WOLBuddyMgr* buddyMgr = WOLBuddyMgr::GetInstance(false);
  765. if (buddyMgr)
  766. {
  767. passesBuddy = buddyMgr->IsBuddy(msg.GetSendersName());
  768. buddyMgr->Release_Ref();
  769. }
  770. }
  771. if (testClan && testBuddy)
  772. {
  773. if (!passesClan && !passesBuddy)
  774. {
  775. return false;
  776. }
  777. }
  778. else if (testClan && !passesClan)
  779. {
  780. return false;
  781. }
  782. else if (testBuddy && !passesBuddy)
  783. {
  784. return false;
  785. }
  786. //---------------------------------------------------------------------------
  787. // Western and Asian filtering
  788. //---------------------------------------------------------------------------
  789. // If we are filtering western text and the message is western then
  790. // filter out the message.
  791. bool showLatin = MPSettingsMgrClass::Get_Option_Flag(MPSettingsMgrClass::OPTION_DISPLAY_NONASIAN);
  792. if (!showLatin && IsAnsiText(msg.GetMessage()))
  793. {
  794. WWDEBUG_SAY(("WOLChatMgr: Filtered latin text message\n"));
  795. return false;
  796. }
  797. // If we are filtering asian text and the message is asian then filter out
  798. // the message.
  799. bool showAsian = MPSettingsMgrClass::Get_Option_Flag(MPSettingsMgrClass::OPTION_DISPLAY_ASIAN);
  800. if (!showAsian && !IsAnsiText(msg.GetMessage()))
  801. {
  802. WWDEBUG_SAY(("WOLChatMgr: Filtered Asian text message\n"));
  803. return false;
  804. }
  805. return true;
  806. }
  807. /******************************************************************************
  808. *
  809. * NAME
  810. * WOLChatMgr::ClearMessageList
  811. *
  812. * DESCRIPTION
  813. * Clear all the messages.
  814. *
  815. * INPUTS
  816. * NONE
  817. *
  818. * RESULT
  819. * NONE
  820. *
  821. ******************************************************************************/
  822. void WOLChatMgr::ClearMessageList(void)
  823. {
  824. mMessageList.clear();
  825. }
  826. /******************************************************************************
  827. *
  828. * NAME
  829. * WOLChatMgr::HandleNotification(ServerError)
  830. *
  831. * DESCRIPTION
  832. * Handle error conditions from the server.
  833. *
  834. * INPUTS
  835. *
  836. * RESULT
  837. * NONE
  838. *
  839. ******************************************************************************/
  840. void WOLChatMgr::HandleNotification(ServerError& error)
  841. {
  842. switch (error.GetErrorCode())
  843. {
  844. case CHAT_E_NOT_OPER:
  845. break;
  846. case CHAT_E_BANNED:
  847. {
  848. Add_Ref();
  849. WOLChatMgrEvent event = BannedFromChannel;
  850. NotifyObservers(event);
  851. Release_Ref();
  852. }
  853. break;
  854. default:
  855. {
  856. const wchar_t* msg = error.GetDescription();
  857. AddMessage(TRANSLATE(IDS_CHAT_SERVERERROR), msg, true, false);
  858. }
  859. break;
  860. }
  861. }
  862. /******************************************************************************
  863. *
  864. * NAME
  865. * WOLChatMgr::HandleNotification(ChannelListEvent)
  866. *
  867. * DESCRIPTION
  868. * Handle channel list events.
  869. *
  870. * INPUTS
  871. *
  872. * RESULT
  873. * NONE
  874. *
  875. ******************************************************************************/
  876. void WOLChatMgr::HandleNotification(ChannelListEvent& event)
  877. {
  878. if (event.GetEvent() == ChannelListEvent::NewList && event.GetChannelType() == 0)
  879. {
  880. mLobbyList.clear();
  881. const ChannelList& channelList = event.Subject();
  882. ChannelList::const_iterator iter = channelList.begin();
  883. while (iter != channelList.end())
  884. {
  885. const RefPtr<ChannelData>& channel = (*iter);
  886. // If this is a valid public chat lobby then add it to the list.
  887. if (IsLobbyValid(channel))
  888. {
  889. mLobbyList.push_back(channel);
  890. }
  891. iter++;
  892. }
  893. Add_Ref();
  894. WOLChatMgrEvent event = LobbyListChanged;
  895. NotifyObservers(event);
  896. Release_Ref();
  897. }
  898. }
  899. /******************************************************************************
  900. *
  901. * NAME
  902. * WOLChatMgr::HandleNotification(ChannelEvent)
  903. *
  904. * DESCRIPTION
  905. * Handle channel events such as response to leaving or joining.
  906. *
  907. * INPUTS
  908. *
  909. * RESULT
  910. * NONE
  911. *
  912. ******************************************************************************/
  913. void WOLChatMgr::HandleNotification(ChannelEvent& event)
  914. {
  915. ChannelStatus status = event.GetStatus();
  916. switch (status)
  917. {
  918. case ChannelJoined:
  919. case ChannelLeft:
  920. {
  921. const RefPtr<ChannelData>& channel = event.Subject();
  922. WideStringClass displayName(0, true);
  923. GetLobbyDisplayName(channel, displayName);
  924. WideStringClass message(0, true);
  925. if (status == ChannelJoined)
  926. {
  927. message.Format(TRANSLATE(IDS_CHAT_LOBBYJOINED), displayName);
  928. }
  929. else
  930. {
  931. message.Format(TRANSLATE(IDS_CHAT_LOBBYLEFT), displayName);
  932. }
  933. AddMessage(NULL, message, true, true);
  934. Add_Ref();
  935. WOLChatMgrEvent event = LobbyChanged;
  936. NotifyObservers(event);
  937. Release_Ref();
  938. }
  939. break;
  940. case ChannelBanned:
  941. {
  942. Add_Ref();
  943. WOLChatMgrEvent event = BannedFromChannel;
  944. NotifyObservers(event);
  945. Release_Ref();
  946. }
  947. break;
  948. case ChannelKicked:
  949. {
  950. Add_Ref();
  951. WOLChatMgrEvent event = KickedFromChannel;
  952. NotifyObservers(event);
  953. Release_Ref();
  954. }
  955. break;
  956. default:
  957. break;
  958. }
  959. }
  960. /******************************************************************************
  961. *
  962. * NAME
  963. * WOLChatMgr::HandleNotification(UserEvent)
  964. *
  965. * DESCRIPTION
  966. * Handle user related events
  967. *
  968. * INPUTS
  969. *
  970. * RESULT
  971. * NONE
  972. *
  973. ******************************************************************************/
  974. void WOLChatMgr::HandleNotification(UserEvent& userEvent)
  975. {
  976. UserEvent::Event event = userEvent.GetEvent();
  977. switch (event)
  978. {
  979. case UserEvent::Join:
  980. {
  981. WWDEBUG_SAY(("WOLChatMgr: Received User Join Event\n"));
  982. const RefPtr<UserData>& user = userEvent.Subject();
  983. mUserInList.push_back(user);
  984. mWOLSession->RequestUserDetails(user, (REQUEST_LOCALE|REQUEST_SQUADINFO));
  985. Add_Ref();
  986. WOLChatMgrEvent event = UserInListChanged;
  987. NotifyObservers(event);
  988. Release_Ref();
  989. }
  990. break;
  991. case UserEvent::Kicked:
  992. {
  993. const RefPtr<UserData>& user = userEvent.Subject();
  994. mUserOutList.push_back(user);
  995. WideStringClass kickMsg(0, true);
  996. kickMsg.Format(TRANSLATE(IDS_CHAT_USERKICKED), user->GetName());
  997. AddMessage(NULL, kickMsg, true, true);
  998. Add_Ref();
  999. WOLChatMgrEvent event = UserOutListChanged;
  1000. NotifyObservers(event);
  1001. Release_Ref();
  1002. }
  1003. break;
  1004. case UserEvent::Leave:
  1005. {
  1006. mUserOutList.push_back(userEvent.Subject());
  1007. Add_Ref();
  1008. WOLChatMgrEvent event = UserOutListChanged;
  1009. NotifyObservers(event);
  1010. Release_Ref();
  1011. }
  1012. break;
  1013. case UserEvent::Banned:
  1014. {
  1015. WideStringClass banMsg(0, true);
  1016. banMsg.Format(TRANSLATE(IDS_CHAT_USERBANNED), userEvent.Subject()->GetName());
  1017. AddMessage(NULL, banMsg, true, true);
  1018. }
  1019. break;
  1020. case UserEvent::Located:
  1021. {
  1022. WWDEBUG_SAY(("WOLChatMgr: Received User Located Event\n"));
  1023. const RefPtr<UserData>& user = userEvent.Subject();
  1024. // Is this the user we were looking for?
  1025. if (mLocatingUserName.Compare_No_Case(user->GetName()) == 0)
  1026. {
  1027. // Build a string containing the user's name
  1028. WideStringClass message(0, true);
  1029. message.Format(TRANSLATE(IDS_CHAT_LOCATEDUSER), user->GetName());
  1030. // Append the description of the user's location
  1031. WideStringClass location(64, true);
  1032. WOLBuddyMgr::GetLocationDescription(user, location);
  1033. message += L" - ";
  1034. message += location;
  1035. // Add this message to the UI
  1036. AddMessage(NULL, message, true, false);
  1037. mLocatingUserName = L"";
  1038. }
  1039. }
  1040. break;
  1041. }
  1042. }
  1043. /******************************************************************************
  1044. *
  1045. * NAME
  1046. * WOLChatMgr::HandleNotification(UserList)
  1047. *
  1048. * DESCRIPTION
  1049. *
  1050. * INPUTS
  1051. *
  1052. * RESULT
  1053. * NONE
  1054. *
  1055. ******************************************************************************/
  1056. void WOLChatMgr::HandleNotification(WWOnline::UserList& users)
  1057. {
  1058. mUserInList.clear();
  1059. mUserOutList.clear();
  1060. int count = users.size();
  1061. for (int index = 0; index < count; index++)
  1062. {
  1063. mWOLSession->RequestUserDetails(users[index], (REQUEST_LOCALE|REQUEST_SQUADINFO));
  1064. mUserInList.push_back(users[index]);
  1065. }
  1066. Add_Ref();
  1067. WOLChatMgrEvent event = UserInListChanged;
  1068. NotifyObservers(event);
  1069. Release_Ref();
  1070. }
  1071. /******************************************************************************
  1072. *
  1073. * NAME
  1074. * WOLChatMgr::HandleNotification(ChatMessage)
  1075. *
  1076. * DESCRIPTION
  1077. *
  1078. * INPUTS
  1079. *
  1080. * RESULT
  1081. * NONE
  1082. *
  1083. ******************************************************************************/
  1084. void WOLChatMgr::HandleNotification(ChatMessage& chatMsg)
  1085. {
  1086. if (PassesFilters(chatMsg))
  1087. {
  1088. mMessageList.push_back(chatMsg);
  1089. Add_Ref();
  1090. WOLChatMgrEvent event = MessageListChanged;
  1091. NotifyObservers(event);
  1092. Release_Ref();
  1093. }
  1094. }
  1095. /******************************************************************************
  1096. *
  1097. * NAME
  1098. * WOLChatMgr::ProcessCommand(const wchar_t* message)
  1099. *
  1100. * DESCRIPTION
  1101. *
  1102. * INPUTS
  1103. *
  1104. * RESULT
  1105. * NONE
  1106. *
  1107. ******************************************************************************/
  1108. bool WOLChatMgr::ProcessCommand(const wchar_t* message)
  1109. {
  1110. // Does this look like a command?
  1111. if (message && message[0] == L'/')
  1112. {
  1113. // Separate the parameters into individual strings
  1114. WideStringClass command(255, true);
  1115. const wchar_t* params = Get_Parameter_From_String(&message[1], command);
  1116. if (command.Get_Length() > 0)
  1117. {
  1118. static struct {const wchar_t* Token; SlashCommandFunc Dispatch;} _cmdDispatch[] =
  1119. {
  1120. {L"page", SlashCmdPage},
  1121. {L"r", SlashCmdR},
  1122. {L"locate", SlashCmdLocate},
  1123. {L"msg", SlashCmdMsg},
  1124. {L"invite", SlashCmdInvite},
  1125. {L"kick", SlashCmdKick},
  1126. {L"join", SlashCmdJoin},
  1127. {NULL, NULL},
  1128. };
  1129. int index = 0;
  1130. const wchar_t* token = _cmdDispatch[index].Token;
  1131. while (token)
  1132. {
  1133. if (command.Compare_No_Case(token) == 0)
  1134. {
  1135. _cmdDispatch[index].Dispatch(params);
  1136. return true;
  1137. }
  1138. ++index;
  1139. token = _cmdDispatch[index].Token;
  1140. }
  1141. }
  1142. }
  1143. return false;
  1144. }
  1145. // Page a user
  1146. void SlashCmdPage(const wchar_t* param)
  1147. {
  1148. // Get the name parameter from the string
  1149. WideStringClass name(64, true);
  1150. WideStringClass pageMsg(0, true);
  1151. pageMsg = Get_Parameter_From_String(param, name);
  1152. pageMsg.Trim();
  1153. if (!name.Is_Empty() && !pageMsg.Is_Empty())
  1154. {
  1155. WOLBuddyMgr* buddyMgr = WOLBuddyMgr::GetInstance(false);
  1156. if (buddyMgr)
  1157. {
  1158. // Page the requested user
  1159. buddyMgr->PageUser(name, pageMsg);
  1160. buddyMgr->Release_Ref();
  1161. }
  1162. }
  1163. }
  1164. // Send a page reply
  1165. void SlashCmdR(const wchar_t* param)
  1166. {
  1167. WideStringClass reply(0, true);
  1168. reply = param;
  1169. reply.Trim();
  1170. if (reply.Is_Empty() == false)
  1171. {
  1172. WOLBuddyMgr* buddyMgr = WOLBuddyMgr::GetInstance(false);
  1173. if (buddyMgr)
  1174. {
  1175. const wchar_t* name = buddyMgr->GetLastPagersName();
  1176. if (name && wcslen(name))
  1177. {
  1178. // Reply to the last user who paged.
  1179. buddyMgr->PageUser(name, reply);
  1180. }
  1181. buddyMgr->Release_Ref();
  1182. }
  1183. }
  1184. }
  1185. // Locate a user
  1186. void SlashCmdLocate(const wchar_t* param)
  1187. {
  1188. // Try to find the specified user
  1189. WideStringClass name(64, true);
  1190. Get_Parameter_From_String(param, name);
  1191. if (name.Is_Empty() == false)
  1192. {
  1193. WOLChatMgr* chat = WOLChatMgr::GetInstance(false);
  1194. if (chat)
  1195. {
  1196. chat->LocateUser(name);
  1197. chat->Release_Ref();
  1198. }
  1199. }
  1200. }
  1201. // Send private message
  1202. void SlashCmdMsg(const wchar_t* param)
  1203. {
  1204. // Get the name parameter from the string
  1205. WideStringClass name(64, true);
  1206. WideStringClass message(0, true);
  1207. message = Get_Parameter_From_String(param, name);
  1208. message.Trim();
  1209. if (!name.Is_Empty() && !message.Is_Empty())
  1210. {
  1211. WOLChatMgr* chat = WOLChatMgr::GetInstance(false);
  1212. if (chat)
  1213. {
  1214. RefPtr<UserData> user = chat->FindUser(name);
  1215. if (user.IsValid())
  1216. {
  1217. chat->SendPrivateMessage(user, message, false);
  1218. }
  1219. chat->Release_Ref();
  1220. }
  1221. }
  1222. }
  1223. // Invite a user to our location
  1224. void SlashCmdInvite(const wchar_t* param)
  1225. {
  1226. // Get the name parameter from the string
  1227. WideStringClass name(64, true);
  1228. const wchar_t* msg = Get_Parameter_From_String(param, name);
  1229. if (name.Is_Empty() == false)
  1230. {
  1231. WOLBuddyMgr* buddyMgr = WOLBuddyMgr::GetInstance(false);
  1232. if (buddyMgr)
  1233. {
  1234. buddyMgr->InviteUser(name, msg);
  1235. buddyMgr->Release_Ref();
  1236. }
  1237. }
  1238. }
  1239. // Kick a user
  1240. void SlashCmdKick(const wchar_t* param)
  1241. {
  1242. // Get the name parameter from the string
  1243. WideStringClass name(64, true);
  1244. Get_Parameter_From_String(param, name);
  1245. if (name.Is_Empty() == false)
  1246. {
  1247. RefPtr<Session> wolSession = Session::GetInstance(false);
  1248. if (wolSession.IsValid())
  1249. {
  1250. wolSession->KickUser(name);
  1251. }
  1252. }
  1253. }
  1254. // Join a user
  1255. void SlashCmdJoin(const wchar_t* param)
  1256. {
  1257. // Get the name parameter from the string
  1258. WideStringClass name(64, true);
  1259. Get_Parameter_From_String(param, name);
  1260. if (name.Is_Empty() == false)
  1261. {
  1262. RefPtr<UserData> user;
  1263. RefPtr<Session> wolSession = Session::GetInstance(false);
  1264. if (wolSession.IsValid())
  1265. {
  1266. user = wolSession->FindUser(name);
  1267. }
  1268. // If the user we want to join is already in our user list then no need to join
  1269. if (user.IsValid() == false)
  1270. {
  1271. WOLBuddyMgr* buddyMgr = WOLBuddyMgr::GetInstance(false);
  1272. if (buddyMgr)
  1273. {
  1274. user = UserData::Create(name);
  1275. buddyMgr->JoinUser(user);
  1276. buddyMgr->Release_Ref();
  1277. }
  1278. }
  1279. }
  1280. }
  1281. /******************************************************************************
  1282. *
  1283. * NAME
  1284. * Get_Parameter_From_String
  1285. *
  1286. * DESCRIPTION
  1287. *
  1288. * INPUTS
  1289. * Command - Command string
  1290. * Param -
  1291. *
  1292. * RESULT
  1293. * NONE
  1294. *
  1295. ******************************************************************************/
  1296. const wchar_t* Get_Parameter_From_String(const wchar_t* command, WideStringClass& param)
  1297. {
  1298. #define LOCAL_STRIP_WHITESPACE(str) \
  1299. while (str[0] != 0 && str[0] == L' ') {++str;}
  1300. // Strip off whitespace
  1301. LOCAL_STRIP_WHITESPACE(command);
  1302. const wchar_t* curr_pos = command;
  1303. // Look for the first whitespace break
  1304. while (curr_pos[0] != 0 && curr_pos[0] != L' ')
  1305. {
  1306. ++curr_pos;
  1307. }
  1308. // Return the string contents to the caller
  1309. int length = ((curr_pos + 1) - command);
  1310. if (length > 0)
  1311. {
  1312. WCHAR* buffer = param.Get_Buffer(length + 1);
  1313. wcsncpy(buffer, command, length);
  1314. buffer[length - 1] = 0;
  1315. }
  1316. // Strip off whitespace
  1317. LOCAL_STRIP_WHITESPACE(curr_pos);
  1318. return curr_pos;
  1319. }