WOLBuddyOverlay.cpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. /*
  2. ** Command & Conquer Generals(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. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. ///////////////////////////////////////////////////////////////////////////////////////
  24. // FILE: WOLBuddyOverlay.cpp
  25. // Author: Chris Huybregts, November 2001
  26. // Description: Lan Lobby Menu
  27. ///////////////////////////////////////////////////////////////////////////////////////
  28. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  29. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  30. #include "Common/AudioEventRTS.h"
  31. #include "Common/PlayerList.h"
  32. #include "Common/Player.h"
  33. #include "GameClient/GameText.h"
  34. #include "GameClient/WindowLayout.h"
  35. #include "GameClient/Gadget.h"
  36. #include "GameClient/Shell.h"
  37. #include "GameClient/KeyDefs.h"
  38. #include "GameClient/GameWindowManager.h"
  39. #include "GameClient/GadgetListBox.h"
  40. #include "GameClient/GadgetPushButton.h"
  41. #include "GameClient/GadgetStaticText.h"
  42. #include "GameClient/GadgetTextEntry.h"
  43. #include "GameClient/GadgetRadioButton.h"
  44. #include "GameClient/Display.h"
  45. #include "GameNetwork/GameSpyOverlay.h"
  46. #include "GameNetwork/GameSpy/PeerDefs.h"
  47. #include "GameNetwork/GameSpy/BuddyDefs.h"
  48. #include "GameNetwork/GameSpy/BuddyThread.h"
  49. #include "GameNetwork/GameSpy/LobbyUtils.h"
  50. #include "GameNetwork/GameSpy/PersistentStorageDefs.h"
  51. #include "GameNetwork/GameSpy/PersistentStorageThread.h"
  52. #include "GameNetwork/GameSpy/ThreadUtils.h"
  53. // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
  54. #ifdef _INTERNAL
  55. // for occasional debugging...
  56. //#pragma optimize("", off)
  57. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  58. #endif
  59. // window ids ------------------------------------------------------------------------------
  60. static NameKeyType parentID = NAMEKEY_INVALID;
  61. static NameKeyType buttonHideID = NAMEKEY_INVALID;
  62. static NameKeyType buttonAddBuddyID = NAMEKEY_INVALID;
  63. static NameKeyType buttonDeleteBuddyID = NAMEKEY_INVALID;
  64. static NameKeyType textEntryID = NAMEKEY_INVALID;
  65. static NameKeyType listboxBuddyID = NAMEKEY_INVALID;
  66. static NameKeyType listboxChatID = NAMEKEY_INVALID;
  67. static NameKeyType buttonAcceptBuddyID = NAMEKEY_INVALID;
  68. static NameKeyType buttonDenyBuddyID = NAMEKEY_INVALID;
  69. static NameKeyType radioButtonBuddiesID = NAMEKEY_INVALID;
  70. static NameKeyType radioButtonIgnoreID = NAMEKEY_INVALID;
  71. static NameKeyType parentBuddiesID = NAMEKEY_INVALID;
  72. static NameKeyType parentIgnoreID = NAMEKEY_INVALID;
  73. static NameKeyType listboxIgnoreID = NAMEKEY_INVALID;
  74. static NameKeyType buttonNotificationID = NAMEKEY_INVALID;
  75. // Window Pointers ------------------------------------------------------------------------
  76. static GameWindow *parent = NULL;
  77. static GameWindow *buttonHide = NULL;
  78. static GameWindow *buttonAddBuddy = NULL;
  79. static GameWindow *buttonDeleteBuddy = NULL;
  80. static GameWindow *textEntry = NULL;
  81. static GameWindow *listboxBuddy = NULL;
  82. static GameWindow *listboxChat = NULL;
  83. static GameWindow *buttonAcceptBuddy = NULL;
  84. static GameWindow *buttonDenyBuddy = NULL;
  85. static GameWindow *radioButtonBuddies = NULL;
  86. static GameWindow *radioButtonIgnore = NULL;
  87. static GameWindow *parentBuddies = NULL;
  88. static GameWindow *parentIgnore = NULL;
  89. static GameWindow *listboxIgnore = NULL;
  90. static Bool isOverlayActive = false;
  91. void insertChat( BuddyMessage msg );
  92. // RightClick pointers ---------------------------------------------------------------------
  93. static GameWindow *rcMenu = NULL;
  94. static WindowLayout *noticeLayout = NULL;
  95. static UnsignedInt noticeExpires = 0;
  96. enum { NOTIFICATION_EXPIRES = 3000 };
  97. void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id);
  98. void refreshIgnoreList( void );
  99. void showNotificationBox( AsciiString nick, UnicodeString message);
  100. void deleteNotificationBox( void );
  101. static Bool lastNotificationWasStatus = FALSE;
  102. static Int numOnlineInNotification = 0;
  103. class BuddyControls
  104. {
  105. public:
  106. BuddyControls(void );
  107. GameWindow *listboxChat;
  108. NameKeyType listboxChatID;
  109. GameWindow *listboxBuddies;
  110. NameKeyType listboxBuddiesID;
  111. GameWindow *textEntryEdit;
  112. NameKeyType textEntryEditID;
  113. Bool isInit;
  114. };
  115. static BuddyControls buddyControls;
  116. BuddyControls::BuddyControls( void )
  117. {
  118. listboxChat = NULL;
  119. listboxChatID = NAMEKEY_INVALID;
  120. listboxBuddies = NULL;
  121. listboxBuddiesID = NAMEKEY_INVALID;
  122. textEntryEdit = NULL;
  123. textEntryEditID = NAMEKEY_INVALID;
  124. isInit = FALSE;
  125. }
  126. // At this point I don't give a damn about how good this way is. I'm doing it anyway.
  127. enum
  128. {
  129. BUDDY_RESETALL_CRAP = -1,
  130. BUDDY_WINDOW_BUDDIES = 0,
  131. BUDDY_WINDOW_DIPLOMACY,
  132. BUDDY_WINDOW_WELCOME_SCREEN,
  133. };
  134. void InitBuddyControls(Int type)
  135. {
  136. if(!TheGameSpyInfo)
  137. {
  138. buddyControls.textEntryEditID = NAMEKEY_INVALID;
  139. buddyControls.textEntryEdit = NULL;
  140. buddyControls.listboxBuddiesID = NAMEKEY_INVALID;
  141. buddyControls.listboxChatID = NAMEKEY_INVALID;
  142. buddyControls.listboxBuddies = NULL;
  143. buddyControls.listboxChat = NULL;
  144. buddyControls.isInit = FALSE;
  145. return;
  146. }
  147. switch (type) {
  148. case BUDDY_RESETALL_CRAP:
  149. buddyControls.textEntryEditID = NAMEKEY_INVALID;
  150. buddyControls.textEntryEdit = NULL;
  151. buddyControls.listboxBuddiesID = NAMEKEY_INVALID;
  152. buddyControls.listboxChatID = NAMEKEY_INVALID;
  153. buddyControls.listboxBuddies = NULL;
  154. buddyControls.listboxChat = NULL;
  155. buddyControls.isInit = FALSE;
  156. break;
  157. case BUDDY_WINDOW_BUDDIES:
  158. buddyControls.textEntryEditID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:TextEntryChat" ) );
  159. buddyControls.textEntryEdit = TheWindowManager->winGetWindowFromId(NULL, buddyControls.textEntryEditID);
  160. buddyControls.listboxBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddies" ) );
  161. buddyControls.listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddyChat" ) );
  162. buddyControls.listboxBuddies = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxBuddiesID );
  163. buddyControls.listboxChat = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxChatID);
  164. GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString.TheEmptyString);
  165. buddyControls.isInit = TRUE;
  166. break;
  167. case BUDDY_WINDOW_DIPLOMACY:
  168. buddyControls.textEntryEditID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:TextEntryChat" ) );
  169. buddyControls.textEntryEdit = TheWindowManager->winGetWindowFromId(NULL, buddyControls.textEntryEditID);
  170. buddyControls.listboxBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:ListboxBuddies" ) );
  171. buddyControls.listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "Diplomacy.wnd:ListboxBuddyChat" ) );
  172. buddyControls.listboxBuddies = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxBuddiesID );
  173. buddyControls.listboxChat = TheWindowManager->winGetWindowFromId( NULL, buddyControls.listboxChatID);
  174. GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString.TheEmptyString);
  175. buddyControls.isInit = TRUE;
  176. break;
  177. case BUDDY_WINDOW_WELCOME_SCREEN:
  178. break;
  179. default:
  180. DEBUG_ASSERTCRASH(FALSE, ("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either"));
  181. }
  182. }
  183. WindowMsgHandledType BuddyControlSystem( GameWindow *window, UnsignedInt msg,
  184. WindowMsgData mData1, WindowMsgData mData2)
  185. {
  186. if(!TheGameSpyInfo || TheGameSpyInfo->getLocalProfileID() == 0 || !buddyControls.isInit)
  187. {
  188. return MSG_IGNORED;
  189. }
  190. switch( msg )
  191. {
  192. case GLM_RIGHT_CLICKED:
  193. {
  194. GameWindow *control = (GameWindow *)mData1;
  195. Int controlID = control->winGetWindowId();
  196. if( controlID == buddyControls.listboxBuddiesID )
  197. {
  198. RightClickStruct *rc = (RightClickStruct *)mData2;
  199. WindowLayout *rcLayout;
  200. if(rc->pos < 0)
  201. break;
  202. GPProfile profileID = (GPProfile)GadgetListBoxGetItemData(control, rc->pos, 0);
  203. RCItemType itemType = (RCItemType)(Int)GadgetListBoxGetItemData(control, rc->pos, 1);
  204. UnicodeString nick = GadgetListBoxGetText(control, rc->pos);
  205. GadgetListBoxSetSelected(control, rc->pos);
  206. if (itemType == ITEM_BUDDY)
  207. rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd"));
  208. else if (itemType == ITEM_REQUEST)
  209. rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddyRequestMenu.wnd"));
  210. else
  211. rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd"));
  212. rcMenu = rcLayout->getFirstWindow();
  213. rcMenu->winGetLayout()->runInit();
  214. rcMenu->winBringToTop();
  215. rcMenu->winHide(FALSE);
  216. ICoord2D rcSize, rcPos;
  217. rcMenu->winGetSize(&rcSize.x, &rcSize.y);
  218. rcPos.x = rc->mouseX;
  219. rcPos.y = rc->mouseY;
  220. if(rc->mouseX + rcSize.x > TheDisplay->getWidth())
  221. rcPos.x = TheDisplay->getWidth() - rcSize.x;
  222. if(rc->mouseY + rcSize.y > TheDisplay->getHeight())
  223. rcPos.y = TheDisplay->getHeight() - rcSize.y;
  224. rcMenu->winSetPosition(rcPos.x, rcPos.y);
  225. GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData;
  226. rcData->m_id = profileID;
  227. rcData->m_nick.translate(nick);
  228. rcData->m_itemType = itemType;
  229. setUnignoreText(rcLayout, rcData->m_nick, rcData->m_id);
  230. rcMenu->winSetUserData((void *)rcData);
  231. TheWindowManager->winSetLoneWindow(rcMenu);
  232. }
  233. else
  234. return MSG_IGNORED;
  235. break;
  236. }
  237. case GEM_EDIT_DONE:
  238. {
  239. GameWindow *control = (GameWindow *)mData1;
  240. Int controlID = control->winGetWindowId();
  241. if(controlID != buddyControls.textEntryEditID)
  242. return MSG_IGNORED;
  243. // see if someone's selected
  244. Int selected = -1;
  245. GadgetListBoxGetSelected(buddyControls.listboxBuddies, &selected);
  246. if (selected >= 0)
  247. {
  248. GPProfile selectedProfile = (GPProfile)GadgetListBoxGetItemData(buddyControls.listboxBuddies, selected);
  249. BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap();
  250. BuddyInfoMap::iterator recipIt = m->find(selectedProfile);
  251. if (recipIt == m->end())
  252. break;
  253. DEBUG_LOG(("Trying to send a buddy message to %d.\n", selectedProfile));
  254. if (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->isGameInProgress() &&
  255. !ThePlayerList->getLocalPlayer()->isPlayerActive())
  256. {
  257. DEBUG_LOG(("I'm dead - gotta look for cheats.\n"));
  258. for (Int i=0; i<MAX_SLOTS; ++i)
  259. {
  260. DEBUG_LOG(("Slot[%d] profile is %d\n", i, TheGameSpyGame->getGameSpySlot(i)->getProfileID()));
  261. if (TheGameSpyGame->getGameSpySlot(i)->getProfileID() == selectedProfile)
  262. {
  263. // can't send to someone in our game if we're dead/observing. security breach and all that. no seances for you.
  264. if (buddyControls.listboxChat)
  265. {
  266. GadgetListBoxAddEntryText( buddyControls.listboxChat, TheGameText->fetch("Buddy:CantTalkToIngameBuddy"),
  267. GameSpyColor[GSCOLOR_DEFAULT], -1, -1 );
  268. }
  269. return MSG_HANDLED;
  270. }
  271. }
  272. }
  273. // read the user's input and clear the entry box
  274. UnicodeString txtInput;
  275. txtInput.set(GadgetTextEntryGetText( buddyControls.textEntryEdit ));
  276. GadgetTextEntrySetText(buddyControls.textEntryEdit, UnicodeString::TheEmptyString);
  277. txtInput.trim();
  278. if (!txtInput.isEmpty())
  279. {
  280. // Send the message
  281. BuddyRequest req;
  282. req.buddyRequestType = BuddyRequest::BUDDYREQUEST_MESSAGE;
  283. wcsncpy(req.arg.message.text, txtInput.str(), MAX_BUDDY_CHAT_LEN);
  284. req.arg.message.text[MAX_BUDDY_CHAT_LEN-1] = 0;
  285. req.arg.message.recipient = selectedProfile;
  286. TheGameSpyBuddyMessageQueue->addRequest(req);
  287. // save message for future incarnations of the buddy window
  288. BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages();
  289. BuddyMessage message;
  290. message.m_timestamp = time(NULL);
  291. message.m_senderID = TheGameSpyInfo->getLocalProfileID();
  292. message.m_senderNick = TheGameSpyInfo->getLocalBaseName();
  293. message.m_recipientID = selectedProfile;
  294. message.m_recipientNick = recipIt->second.m_name;
  295. message.m_message = UnicodeString(req.arg.message.text);
  296. messages->push_back(message);
  297. // put message on screen
  298. insertChat(message);
  299. }
  300. }
  301. else
  302. {
  303. // nobody selected. Prompt the user.
  304. if (buddyControls.listboxChat)
  305. {
  306. GadgetListBoxAddEntryText( buddyControls.listboxChat, TheGameText->fetch("Buddy:SelectBuddyToChat"),
  307. GameSpyColor[GSCOLOR_DEFAULT], -1, -1 );
  308. }
  309. }
  310. break;
  311. }
  312. default:
  313. return MSG_IGNORED;
  314. }
  315. return MSG_HANDLED;
  316. }
  317. static void insertChat( BuddyMessage msg )
  318. {
  319. if (buddyControls.listboxChat)
  320. {
  321. BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap();
  322. BuddyInfoMap::iterator senderIt = m->find(msg.m_senderID);
  323. BuddyInfoMap::iterator recipientIt = m->find(msg.m_recipientID);
  324. Bool localSender = (msg.m_senderID == TheGameSpyInfo->getLocalProfileID());
  325. UnicodeString s;
  326. //UnicodeString timeStr = UnicodeString(_wctime( (const time_t *)&msg.m_timestamp ));
  327. UnicodeString timeStr;
  328. if (localSender /*&& recipientIt != m->end()*/)
  329. {
  330. s.format(L"[%hs -> %hs] %s", TheGameSpyInfo->getLocalBaseName().str(), msg.m_recipientNick.str(), msg.m_message.str());
  331. Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_PLAYER_SELF], -1, -1 );
  332. GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_PLAYER_SELF], index, 1);
  333. }
  334. else if (!localSender /*&& senderIt != m->end()*/)
  335. {
  336. if (!msg.m_senderID)
  337. {
  338. s = msg.m_message;
  339. Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_DEFAULT], -1, -1 );
  340. GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1);
  341. }
  342. else
  343. {
  344. s.format(L"[%hs] %s", msg.m_senderNick.str(), msg.m_message.str());
  345. Int index = GadgetListBoxAddEntryText( buddyControls.listboxChat, s, GameSpyColor[GSCOLOR_PLAYER_BUDDY], -1, -1 );
  346. GadgetListBoxAddEntryText( buddyControls.listboxChat, timeStr, GameSpyColor[GSCOLOR_PLAYER_BUDDY], index, 1);
  347. }
  348. }
  349. }
  350. }
  351. void updateBuddyInfo( void )
  352. {
  353. if (!TheGameSpyBuddyMessageQueue->isConnected())
  354. {
  355. GadgetListBoxReset(buddyControls.listboxBuddies);
  356. return;
  357. }
  358. if (!buddyControls.isInit)
  359. return;
  360. int selected;
  361. GPProfile selectedProfile = 0;
  362. int visiblePos = GadgetListBoxGetTopVisibleEntry(buddyControls.listboxBuddies);
  363. GadgetListBoxGetSelected(buddyControls.listboxBuddies, &selected);
  364. if (selected >= 0)
  365. selectedProfile = (GPProfile)GadgetListBoxGetItemData(buddyControls.listboxBuddies, selected);
  366. selected = -1;
  367. GadgetListBoxReset(buddyControls.listboxBuddies);
  368. // Add buddies
  369. BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap();
  370. BuddyInfoMap::iterator bIt;
  371. for (bIt = buddies->begin(); bIt != buddies->end(); ++bIt)
  372. {
  373. BuddyInfo info = bIt->second;
  374. GPProfile profileID = bIt->first;
  375. // insert name into box
  376. UnicodeString formatStr;
  377. formatStr.translate(info.m_name.str());//, info.m_status, info.m_statusString.str(), info.m_locationString.str());
  378. Color nameColor = (TheGameSpyInfo->isSavedIgnored(profileID)) ?
  379. GameSpyColor[GSCOLOR_PLAYER_IGNORED] : GameSpyColor[GSCOLOR_PLAYER_BUDDY];
  380. int index = GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, nameColor, -1, -1);
  381. // insert status into box
  382. AsciiString marker;
  383. marker.format("Buddy:%ls", info.m_statusString.str());
  384. if (!info.m_statusString.compareNoCase(L"Offline") ||
  385. !info.m_statusString.compareNoCase(L"Online") ||
  386. !info.m_statusString.compareNoCase(L"Matching"))
  387. {
  388. formatStr = TheGameText->fetch(marker);
  389. }
  390. else if (!info.m_statusString.compareNoCase(L"Staging") ||
  391. !info.m_statusString.compareNoCase(L"Loading") ||
  392. !info.m_statusString.compareNoCase(L"Playing"))
  393. {
  394. formatStr.format(TheGameText->fetch(marker), info.m_locationString.str());
  395. }
  396. else if (!info.m_statusString.compareNoCase(L"Chatting"))
  397. {
  398. UnicodeString roomName;
  399. GroupRoomMap::iterator gIt = TheGameSpyInfo->getGroupRoomList()->find( _wtoi(info.m_locationString.str()) );
  400. if (gIt != TheGameSpyInfo->getGroupRoomList()->end())
  401. {
  402. AsciiString s;
  403. s.format("GUI:%s", gIt->second.m_name.str());
  404. roomName = TheGameText->fetch(s);
  405. }
  406. formatStr.format(TheGameText->fetch(marker), roomName.str());
  407. }
  408. else
  409. {
  410. formatStr = info.m_statusString;
  411. }
  412. GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1);
  413. GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(profileID), index, 0 );
  414. GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(ITEM_BUDDY), index, 1 );
  415. if (profileID == selectedProfile)
  416. selected = index;
  417. }
  418. // add requests
  419. buddies = TheGameSpyInfo->getBuddyRequestMap();
  420. for (bIt = buddies->begin(); bIt != buddies->end(); ++bIt)
  421. {
  422. BuddyInfo info = bIt->second;
  423. GPProfile profileID = bIt->first;
  424. // insert name into box
  425. UnicodeString formatStr;
  426. formatStr.translate(info.m_name.str());
  427. int index = GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], -1, -1);
  428. GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(profileID), index, 0 );
  429. // insert status into box
  430. formatStr = TheGameText->fetch("GUI:BuddyAddReq");
  431. GadgetListBoxAddEntryText(buddyControls.listboxBuddies, formatStr, GameSpyColor[GSCOLOR_DEFAULT], index, 1);
  432. GadgetListBoxSetItemData(buddyControls.listboxBuddies, (void *)(ITEM_REQUEST), index, 1 );
  433. if (profileID == selectedProfile)
  434. selected = index;
  435. }
  436. // select the same guy
  437. if (selected >= 0)
  438. {
  439. GadgetListBoxSetSelected(buddyControls.listboxBuddies, selected);
  440. }
  441. // view the same spot
  442. GadgetListBoxSetTopVisibleEntry(buddyControls.listboxBuddies, visiblePos);
  443. }
  444. void HandleBuddyResponses( void )
  445. {
  446. if (TheGameSpyBuddyMessageQueue)
  447. {
  448. BuddyResponse resp;
  449. if (TheGameSpyBuddyMessageQueue->getResponse( resp ))
  450. {
  451. switch (resp.buddyResponseType)
  452. {
  453. case BuddyResponse::BUDDYRESPONSE_LOGIN:
  454. {
  455. deleteNotificationBox();
  456. }
  457. break;
  458. case BuddyResponse::BUDDYRESPONSE_DISCONNECT:
  459. {
  460. lastNotificationWasStatus = FALSE;
  461. numOnlineInNotification = 0;
  462. showNotificationBox(AsciiString::TheEmptyString, TheGameText->fetch("Buddy:MessageDisconnected"));
  463. }
  464. break;
  465. case BuddyResponse::BUDDYRESPONSE_MESSAGE:
  466. {
  467. if ( !wcscmp(resp.arg.message.text, L"I have authorized your request to add me to your list") )
  468. break;
  469. if (TheGameSpyInfo->isSavedIgnored(resp.profile))
  470. {
  471. //DEBUG_CRASH(("Player is ignored!\n"));
  472. break; // no buddy messages from ignored people
  473. }
  474. // save message for future incarnations of the buddy window
  475. BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages();
  476. BuddyMessage message;
  477. message.m_timestamp = resp.arg.message.date;
  478. message.m_senderID = resp.profile;
  479. message.m_recipientID = TheGameSpyInfo->getLocalProfileID();
  480. message.m_recipientNick = TheGameSpyInfo->getLocalBaseName();
  481. message.m_message = resp.arg.message.text;
  482. // insert status into box
  483. BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap();
  484. BuddyInfoMap::iterator senderIt = m->find(message.m_senderID);
  485. AsciiString nick;
  486. if (senderIt != m->end())
  487. nick = senderIt->second.m_name.str();
  488. else
  489. nick = resp.arg.message.nick;
  490. message.m_senderNick = nick;
  491. messages->push_back(message);
  492. DEBUG_LOG(("Inserting buddy chat from '%s'/'%s'\n", nick.str(), resp.arg.message.nick));
  493. // put message on screen
  494. insertChat(message);
  495. // play audio notification
  496. AudioEventRTS buddyMsgAudio("GUIMessageReceived");
  497. if( TheAudio )
  498. {
  499. TheAudio->addAudioEvent( &buddyMsgAudio );
  500. } // end if
  501. UnicodeString snippet = message.m_message;
  502. while (snippet.getLength() > 11)
  503. {
  504. snippet.removeLastChar();
  505. }
  506. UnicodeString s;
  507. s.format(TheGameText->fetch("Buddy:MessageNotification"), nick.str(), snippet.str());
  508. lastNotificationWasStatus = FALSE;
  509. numOnlineInNotification = 0;
  510. showNotificationBox(AsciiString::TheEmptyString, s);
  511. }
  512. break;
  513. case BuddyResponse::BUDDYRESPONSE_REQUEST:
  514. {
  515. // save request for future incarnations of the buddy window
  516. BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap();
  517. BuddyInfo info;
  518. info.m_countryCode = resp.arg.request.countrycode;
  519. info.m_email = resp.arg.request.email;
  520. info.m_name = resp.arg.request.nick;
  521. info.m_id = resp.profile;
  522. info.m_status = (GPEnum)0;
  523. info.m_statusString = resp.arg.request.text;
  524. (*m)[resp.profile] = info;
  525. // TODO: put request on screen
  526. updateBuddyInfo();
  527. // insert status into box
  528. lastNotificationWasStatus = FALSE;
  529. numOnlineInNotification = 0;
  530. showNotificationBox(info.m_name, TheGameText->fetch("Buddy:AddNotification"));
  531. }
  532. break;
  533. case BuddyResponse::BUDDYRESPONSE_STATUS:
  534. {
  535. BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap();
  536. BuddyInfoMap::const_iterator bit = m->find(resp.profile);
  537. Bool seenPreviously = FALSE;
  538. GPEnum oldStatus = GP_OFFLINE;
  539. GPEnum newStatus = resp.arg.status.status;
  540. if (bit != m->end())
  541. {
  542. seenPreviously = TRUE;
  543. oldStatus = (*m)[resp.profile].m_status;
  544. }
  545. BuddyInfo info;
  546. info.m_countryCode = resp.arg.status.countrycode;
  547. info.m_email = resp.arg.status.email;
  548. info.m_name = resp.arg.status.nick;
  549. info.m_id = resp.profile;
  550. info.m_status = newStatus;
  551. info.m_statusString = UnicodeString(MultiByteToWideCharSingleLine(resp.arg.status.statusString).c_str());
  552. info.m_locationString = UnicodeString(MultiByteToWideCharSingleLine(resp.arg.status.location).c_str());
  553. (*m)[resp.profile] = info;
  554. updateBuddyInfo();
  555. PopulateLobbyPlayerListbox();
  556. RefreshGameListBoxes();
  557. if ( (newStatus == GP_OFFLINE && seenPreviously) ||
  558. (newStatus == GP_ONLINE && (oldStatus == GP_OFFLINE || !seenPreviously)) )
  559. //if (!info.m_statusString.compareNoCase(L"Offline") ||
  560. //!info.m_statusString.compareNoCase(L"Online"))
  561. {
  562. // insert status into box
  563. AsciiString marker;
  564. marker.format("Buddy:%lsNotification", info.m_statusString.str());
  565. lastNotificationWasStatus = TRUE;
  566. if (newStatus != GP_OFFLINE)
  567. ++numOnlineInNotification;
  568. showNotificationBox(info.m_name, TheGameText->fetch(marker));
  569. }
  570. else if( newStatus == GP_RECV_GAME_INVITE && !seenPreviously)
  571. {
  572. lastNotificationWasStatus = TRUE;
  573. if (newStatus != GP_OFFLINE)
  574. ++numOnlineInNotification;
  575. showNotificationBox(info.m_name, TheGameText->fetch("Buddy:OnlineNotification"));
  576. }
  577. }
  578. break;
  579. }
  580. }
  581. }
  582. else
  583. {
  584. DEBUG_CRASH(("No buddy message queue!\n"));
  585. }
  586. if(noticeLayout && timeGetTime() > noticeExpires)
  587. {
  588. deleteNotificationBox();
  589. }
  590. }
  591. void showNotificationBox( AsciiString nick, UnicodeString message)
  592. {
  593. // if(!GameSpyIsOverlayOpen(GSOVERLAY_BUDDY))
  594. // return;
  595. if( !noticeLayout )
  596. noticeLayout = TheWindowManager->winCreateLayout( "Menus/PopupBuddyListNotification.wnd" );
  597. noticeLayout->hide( FALSE );
  598. if (buttonNotificationID == NAMEKEY_INVALID)
  599. {
  600. buttonNotificationID = TheNameKeyGenerator->nameToKey("PopupBuddyListNotification.wnd:ButtonNotification");
  601. }
  602. GameWindow *win = TheWindowManager->winGetWindowFromId(NULL,buttonNotificationID);
  603. if(!win)
  604. {
  605. deleteNotificationBox();
  606. return;
  607. }
  608. if (lastNotificationWasStatus && numOnlineInNotification > 1)
  609. {
  610. message = TheGameText->fetch("Buddy:MultipleOnlineNotification");
  611. }
  612. if (nick.isNotEmpty())
  613. message.format(message, nick.str());
  614. GadgetButtonSetText(win, message);
  615. //GadgetStaticTextSetText(win, message);
  616. noticeExpires = timeGetTime() + NOTIFICATION_EXPIRES;
  617. noticeLayout->bringForward();
  618. AudioEventRTS buttonClick("GUICommunicatorIncoming");
  619. if( TheAudio )
  620. {
  621. TheAudio->addAudioEvent( &buttonClick );
  622. } // end if
  623. }
  624. void deleteNotificationBox( void )
  625. {
  626. lastNotificationWasStatus = FALSE;
  627. numOnlineInNotification = 0;
  628. if(noticeLayout)
  629. {
  630. noticeLayout->destroyWindows();
  631. noticeLayout->deleteInstance();
  632. noticeLayout = NULL;
  633. }
  634. }
  635. void PopulateOldBuddyMessages(void)
  636. {
  637. // show previous messages
  638. BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages();
  639. for (BuddyMessageList::iterator mIt = messages->begin(); mIt != messages->end(); ++mIt)
  640. {
  641. BuddyMessage message = *mIt;
  642. insertChat(message);
  643. }
  644. }
  645. //-------------------------------------------------------------------------------------------------
  646. /** Initialize the WOL Buddy Overlay */
  647. //-------------------------------------------------------------------------------------------------
  648. void WOLBuddyOverlayInit( WindowLayout *layout, void *userData )
  649. {
  650. parentID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:BuddyMenuParent" ) );
  651. buttonHideID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonHide" ) );
  652. buttonAddBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonAdd" ) );
  653. buttonDeleteBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonDelete" ) );
  654. //textEntryID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:TextEntryChat" ) );
  655. //listboxBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddies" ) );
  656. //listboxChatID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxBuddyChat" ) );
  657. buttonAcceptBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonYes" ) );
  658. buttonDenyBuddyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ButtonNo" ) );
  659. radioButtonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:RadioButtonBuddies" ) );
  660. radioButtonIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:RadioButtonIgnore" ) );
  661. parentBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:BuddiesParent" ) );
  662. parentIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:IgnoreParent" ) );
  663. listboxIgnoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLBuddyOverlay.wnd:ListboxIgnore" ) );
  664. parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
  665. buttonHide = TheWindowManager->winGetWindowFromId( parent, buttonHideID);
  666. buttonAddBuddy = TheWindowManager->winGetWindowFromId( parent, buttonAddBuddyID);
  667. buttonDeleteBuddy = TheWindowManager->winGetWindowFromId( parent, buttonDeleteBuddyID);
  668. // textEntry = TheWindowManager->winGetWindowFromId( parent, textEntryID);
  669. //listboxBuddy = TheWindowManager->winGetWindowFromId( parent, listboxBuddyID);
  670. //listboxChat = TheWindowManager->winGetWindowFromId( parent, listboxChatID);
  671. buttonAcceptBuddy = TheWindowManager->winGetWindowFromId( parent, buttonAcceptBuddyID);
  672. buttonDenyBuddy = TheWindowManager->winGetWindowFromId( parent, buttonDenyBuddyID);
  673. radioButtonBuddies = TheWindowManager->winGetWindowFromId( parent, radioButtonBuddiesID);
  674. radioButtonIgnore = TheWindowManager->winGetWindowFromId( parent, radioButtonIgnoreID);
  675. parentBuddies = TheWindowManager->winGetWindowFromId( parent, parentBuddiesID);
  676. parentIgnore = TheWindowManager->winGetWindowFromId( parent, parentIgnoreID);
  677. listboxIgnore = TheWindowManager->winGetWindowFromId( parent, listboxIgnoreID);
  678. InitBuddyControls(BUDDY_WINDOW_BUDDIES);
  679. GadgetRadioSetSelection(radioButtonBuddies,FALSE);
  680. parentBuddies->winHide(FALSE);
  681. parentIgnore->winHide(TRUE);
  682. //GadgetTextEntrySetText(textEntry, UnicodeString.TheEmptyString);
  683. PopulateOldBuddyMessages();
  684. // Show Menu
  685. layout->hide( FALSE );
  686. // Set Keyboard to Main Parent
  687. TheWindowManager->winSetFocus( parent );
  688. isOverlayActive = true;
  689. updateBuddyInfo();
  690. } // WOLBuddyOverlayInit
  691. //-------------------------------------------------------------------------------------------------
  692. /** WOL Buddy Overlay shutdown method */
  693. //-------------------------------------------------------------------------------------------------
  694. void WOLBuddyOverlayShutdown( WindowLayout *layout, void *userData )
  695. {
  696. listboxIgnore = NULL;
  697. // hide menu
  698. layout->hide( TRUE );
  699. // our shutdown is complete
  700. //TheShell->shutdownComplete( layout );
  701. isOverlayActive = false;
  702. InitBuddyControls(BUDDY_RESETALL_CRAP);
  703. } // WOLBuddyOverlayShutdown
  704. //-------------------------------------------------------------------------------------------------
  705. /** WOL Buddy Overlay update method */
  706. //-------------------------------------------------------------------------------------------------
  707. void WOLBuddyOverlayUpdate( WindowLayout * layout, void *userData)
  708. {
  709. if (!TheGameSpyBuddyMessageQueue || !TheGameSpyBuddyMessageQueue->isConnected())
  710. GameSpyCloseOverlay(GSOVERLAY_BUDDY);
  711. }// WOLBuddyOverlayUpdate
  712. //-------------------------------------------------------------------------------------------------
  713. /** WOL Buddy Overlay input callback */
  714. //-------------------------------------------------------------------------------------------------
  715. WindowMsgHandledType WOLBuddyOverlayInput( GameWindow *window, UnsignedInt msg,
  716. WindowMsgData mData1, WindowMsgData mData2 )
  717. {
  718. switch( msg )
  719. {
  720. // --------------------------------------------------------------------------------------------
  721. case GWM_CHAR:
  722. {
  723. UnsignedByte key = mData1;
  724. UnsignedByte state = mData2;
  725. switch( key )
  726. {
  727. // ----------------------------------------------------------------------------------------
  728. case KEY_ESC:
  729. {
  730. //
  731. // send a simulated selected event to the parent window of the
  732. // back/exit button
  733. //
  734. if( BitTest( state, KEY_STATE_UP ) )
  735. {
  736. TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
  737. (WindowMsgData)buttonHide, buttonHideID );
  738. } // end if
  739. // don't let key fall through anywhere else
  740. return MSG_HANDLED;
  741. } // end escape
  742. } // end switch( key )
  743. } // end char
  744. } // end switch( msg )
  745. return MSG_IGNORED;
  746. }// WOLBuddyOverlayInput
  747. //-------------------------------------------------------------------------------------------------
  748. /** WOL Buddy Overlay window system callback */
  749. //-------------------------------------------------------------------------------------------------
  750. WindowMsgHandledType WOLBuddyOverlaySystem( GameWindow *window, UnsignedInt msg,
  751. WindowMsgData mData1, WindowMsgData mData2 )
  752. {
  753. UnicodeString txtInput;
  754. if(BuddyControlSystem(window, msg, mData1, mData2) == MSG_HANDLED)
  755. {
  756. return MSG_HANDLED;
  757. }
  758. switch( msg )
  759. {
  760. case GWM_CREATE:
  761. {
  762. break;
  763. } // case GWM_DESTROY:
  764. case GWM_DESTROY:
  765. {
  766. break;
  767. } // case GWM_DESTROY:
  768. case GWM_INPUT_FOCUS:
  769. {
  770. // if we're givin the opportunity to take the keyboard focus we must say we want it
  771. if( mData1 == TRUE )
  772. *(Bool *)mData2 = TRUE;
  773. return MSG_HANDLED;
  774. }//case GWM_INPUT_FOCUS:
  775. case GLM_RIGHT_CLICKED:
  776. {
  777. GameWindow *control = (GameWindow *)mData1;
  778. Int controlID = control->winGetWindowId();
  779. if( controlID == listboxIgnoreID )
  780. {
  781. RightClickStruct *rc = (RightClickStruct *)mData2;
  782. WindowLayout *rcLayout;
  783. if(rc->pos < 0)
  784. break;
  785. Bool isBuddy = false, isRequest = false;
  786. GPProfile profileID = (GPProfile)GadgetListBoxGetItemData(control, rc->pos);
  787. UnicodeString nick = GadgetListBoxGetText(control, rc->pos);
  788. BuddyInfoMap *buddies = TheGameSpyInfo->getBuddyMap();
  789. BuddyInfoMap::iterator bIt;
  790. bIt = buddies->find(profileID);
  791. if (bIt != buddies->end())
  792. {
  793. isBuddy = true;
  794. }
  795. else
  796. {
  797. buddies = TheGameSpyInfo->getBuddyRequestMap();
  798. bIt = buddies->find(profileID);
  799. if (bIt != buddies->end())
  800. {
  801. isRequest = true;
  802. }
  803. else
  804. {
  805. // neither buddy nor request
  806. //break;
  807. }
  808. }
  809. GadgetListBoxSetSelected(control, rc->pos);
  810. if (isBuddy)
  811. rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddiesMenu.wnd"));
  812. else if (isRequest)
  813. rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCBuddyRequestMenu.wnd"));
  814. else
  815. rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/RCNonBuddiesMenu.wnd"));
  816. rcMenu = rcLayout->getFirstWindow();
  817. rcMenu->winGetLayout()->runInit();
  818. rcMenu->winBringToTop();
  819. rcMenu->winHide(FALSE);
  820. rcMenu->winSetPosition(rc->mouseX, rc->mouseY);
  821. GameSpyRCMenuData *rcData = NEW GameSpyRCMenuData;
  822. rcData->m_id = profileID;
  823. rcData->m_nick.translate(nick);
  824. rcData->m_itemType = (isBuddy)?ITEM_BUDDY:((isRequest)?ITEM_REQUEST:ITEM_NONBUDDY);
  825. setUnignoreText(rcLayout, rcData->m_nick, rcData->m_id);
  826. rcMenu->winSetUserData((void *)rcData);
  827. TheWindowManager->winSetLoneWindow(rcMenu);
  828. }
  829. break;
  830. }
  831. case GBM_SELECTED:
  832. {
  833. GameWindow *control = (GameWindow *)mData1;
  834. Int controlID = control->winGetWindowId();
  835. if (controlID == buttonHideID)
  836. {
  837. GameSpyCloseOverlay( GSOVERLAY_BUDDY );
  838. }
  839. else if (controlID == radioButtonBuddiesID)
  840. {
  841. parentBuddies->winHide(FALSE);
  842. parentIgnore->winHide(TRUE);
  843. }
  844. else if (controlID == radioButtonIgnoreID)
  845. {
  846. parentBuddies->winHide(TRUE);
  847. parentIgnore->winHide(FALSE);
  848. refreshIgnoreList();
  849. }
  850. else if (controlID == buttonAddBuddyID)
  851. {
  852. /*
  853. UnicodeString uName = GadgetTextEntryGetText(textEntry);
  854. AsciiString aName;
  855. aName.translate(uName);
  856. if (!aName.isEmpty())
  857. {
  858. TheWOLBuddyList->requestBuddyAdd(aName);
  859. }
  860. GadgetTextEntrySetText(textEntry, UnicodeString::TheEmptyString);
  861. */
  862. }
  863. else if (controlID == buttonDeleteBuddyID)
  864. {
  865. /*
  866. int selected;
  867. AsciiString selectedName = AsciiString::TheEmptyString;
  868. GadgetListBoxGetSelected(listbox, &selected);
  869. if (selected >= 0)
  870. selectedName = TheNameKeyGenerator->keyToName((NameKeyType)(int)GadgetListBoxGetItemData(listbox, selected));
  871. if (!selectedName.isEmpty())
  872. {
  873. TheWOLBuddyList->requestBuddyDelete(selectedName);
  874. }
  875. */
  876. }
  877. break;
  878. }// case GBM_SELECTED:
  879. case GLM_DOUBLE_CLICKED:
  880. {
  881. /*
  882. GameWindow *control = (GameWindow *)mData1;
  883. Int controlID = control->winGetWindowId();
  884. if( controlID == listboxBuddyID )
  885. {
  886. int rowSelected = mData2;
  887. if (rowSelected >= 0)
  888. {
  889. UnicodeString buddyName;
  890. GameWindow *listboxWindow = TheWindowManager->winGetWindowFromId( parent, listboxBuddyID );
  891. // get text of buddy name
  892. buddyName = GadgetListBoxGetText( listboxWindow, rowSelected,0 );
  893. GPProfile buddyID = (GPProfile)GadgetListBoxGetItemData( listboxWindow, rowSelected, 0 );
  894. Int index = -1;
  895. gpGetBuddyIndex(TheGPConnection, buddyID, &index);
  896. if (index >= 0)
  897. {
  898. GPBuddyStatus status;
  899. gpGetBuddyStatus(TheGPConnection, rowSelected, &status);
  900. UnicodeString string;
  901. string.format(L"To join %s in %hs:", buddyName.str(), status.locationString);
  902. GameSpyAddText(string, GSCOLOR_DEFAULT);
  903. if (status.status == GP_CHATTING)
  904. {
  905. AsciiString location = status.locationString;
  906. AsciiString val;
  907. location.nextToken(&val, "/");
  908. location.nextToken(&val, "/");
  909. location.nextToken(&val, "/");
  910. string.format(L" ???");
  911. if (!val.isEmpty())
  912. {
  913. Int groupRoom = atoi(val.str());
  914. if (TheGameSpyChat->getCurrentGroupRoomID() == groupRoom)
  915. {
  916. // already there
  917. string.format(L" nothing");
  918. GameSpyAddText(string, GSCOLOR_DEFAULT);
  919. }
  920. else
  921. {
  922. GroupRoomMap *rooms = TheGameSpyChat->getGroupRooms();
  923. if (rooms)
  924. {
  925. Bool needToJoin = true;
  926. GroupRoomMap::iterator it = rooms->find(groupRoom);
  927. if (it != rooms->end())
  928. {
  929. // he's in a different room
  930. if (TheGameSpyChat->getCurrentGroupRoomID())
  931. {
  932. string.format(L" leave group room");
  933. GameSpyAddText(string, GSCOLOR_DEFAULT);
  934. TheGameSpyChat->leaveRoom(GroupRoom);
  935. }
  936. else if (TheGameSpyGame->isInGame())
  937. {
  938. if (TheGameSpyGame->isGameInProgress())
  939. {
  940. string.format(L" can't leave game in progress");
  941. GameSpyAddText(string, GSCOLOR_DEFAULT);
  942. needToJoin = false;
  943. }
  944. else
  945. {
  946. string.format(L" leave game setup");
  947. GameSpyAddText(string, GSCOLOR_DEFAULT);
  948. TheGameSpyChat->leaveRoom(StagingRoom);
  949. TheGameSpyGame->leaveGame();
  950. }
  951. }
  952. if (needToJoin)
  953. {
  954. string.format(L" join lobby %d", groupRoom);
  955. TheGameSpyChat->joinGroupRoom(groupRoom);
  956. GameSpyAddText(string, GSCOLOR_DEFAULT);
  957. }
  958. }
  959. }
  960. }
  961. }
  962. }
  963. }
  964. else
  965. {
  966. DEBUG_CRASH(("No buddy associated with that ProfileID"));
  967. GameSpyUpdateBuddyOverlay();
  968. }
  969. }
  970. }
  971. */
  972. break;
  973. }
  974. default:
  975. return MSG_IGNORED;
  976. }//Switch
  977. return MSG_HANDLED;
  978. }// WOLBuddyOverlaySystem
  979. WindowMsgHandledType PopupBuddyNotificationSystem( GameWindow *window, UnsignedInt msg,
  980. WindowMsgData mData1, WindowMsgData mData2 )
  981. {
  982. switch( msg )
  983. {
  984. case GWM_CREATE:
  985. {
  986. break;
  987. } // case GWM_DESTROY:
  988. case GWM_DESTROY:
  989. {
  990. break;
  991. } // case GWM_DESTROY:
  992. case GBM_SELECTED:
  993. {
  994. GameWindow *control = (GameWindow *)mData1;
  995. Int controlID = control->winGetWindowId();
  996. if (controlID == buttonNotificationID)
  997. {
  998. GameSpyOpenOverlay( GSOVERLAY_BUDDY );
  999. }
  1000. break;
  1001. }
  1002. default:
  1003. return MSG_IGNORED;
  1004. }//Switch
  1005. return MSG_HANDLED;
  1006. }// PopupBuddyNotificationSystem
  1007. /*
  1008. static NameKeyType buttonAcceptBuddyID = NAMEKEY_INVALID;
  1009. static NameKeyType buttonDenyBuddyID = NAMEKEY_INVALID;
  1010. */
  1011. static NameKeyType buttonAddID = NAMEKEY_INVALID;
  1012. static NameKeyType buttonDeleteID = NAMEKEY_INVALID;
  1013. static NameKeyType buttonPlayID = NAMEKEY_INVALID;
  1014. static NameKeyType buttonIgnoreID = NAMEKEY_INVALID;
  1015. static NameKeyType buttonStatsID = NAMEKEY_INVALID;
  1016. // Window Pointers ------------------------------------------------------------------------
  1017. //static GameWindow *rCparent = NULL;
  1018. //-------------------------------------------------------------------------------------------------
  1019. /** WOL Buddy Overlay Right Click menu callbacks */
  1020. //-------------------------------------------------------------------------------------------------
  1021. void WOLBuddyOverlayRCMenuInit( WindowLayout *layout, void *userData )
  1022. {
  1023. AsciiString controlName;
  1024. controlName.format("%s:ButtonAdd",layout->getFilename().str()+6);
  1025. buttonAddID = TheNameKeyGenerator->nameToKey( controlName );
  1026. controlName.format("%s:ButtonDelete",layout->getFilename().str()+6);
  1027. buttonDeleteID = TheNameKeyGenerator->nameToKey( controlName );
  1028. controlName.format("%s:ButtonPlay",layout->getFilename().str()+6);
  1029. buttonPlayID = TheNameKeyGenerator->nameToKey( controlName );
  1030. controlName.format("%s:ButtonIgnore",layout->getFilename().str()+6);
  1031. buttonIgnoreID = TheNameKeyGenerator->nameToKey( controlName );
  1032. controlName.format("%s:ButtonStats",layout->getFilename().str()+6);
  1033. buttonStatsID = TheNameKeyGenerator->nameToKey( controlName );
  1034. }
  1035. static void closeRightClickMenu(GameWindow *win)
  1036. {
  1037. if(win)
  1038. {
  1039. WindowLayout *winLay = win->winGetLayout();
  1040. if(!winLay)
  1041. return;
  1042. winLay->destroyWindows();
  1043. winLay->deleteInstance();
  1044. winLay = NULL;
  1045. }
  1046. }
  1047. void RequestBuddyAdd(Int profileID, AsciiString nick)
  1048. {
  1049. // request to add a buddy
  1050. BuddyRequest req;
  1051. req.buddyRequestType = BuddyRequest::BUDDYREQUEST_ADDBUDDY;
  1052. req.arg.addbuddy.id = profileID;
  1053. UnicodeString buddyAddstr;
  1054. buddyAddstr = TheGameText->fetch("GUI:BuddyAddReq");
  1055. wcsncpy(req.arg.addbuddy.text, buddyAddstr.str(), MAX_BUDDY_CHAT_LEN);
  1056. req.arg.addbuddy.text[MAX_BUDDY_CHAT_LEN-1] = 0;
  1057. TheGameSpyBuddyMessageQueue->addRequest(req);
  1058. UnicodeString s;
  1059. Bool exists = TRUE;
  1060. s.format(TheGameText->fetch("Buddy:InviteSent", &exists));
  1061. if (!exists)
  1062. {
  1063. // no string yet. don't display.
  1064. return;
  1065. }
  1066. // save message for future incarnations of the buddy window
  1067. BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages();
  1068. BuddyMessage message;
  1069. message.m_timestamp = time(NULL);
  1070. message.m_senderID = 0;
  1071. message.m_senderNick = "";
  1072. message.m_recipientID = TheGameSpyInfo->getLocalProfileID();
  1073. message.m_recipientNick = TheGameSpyInfo->getLocalBaseName();
  1074. message.m_message.format(TheGameText->fetch("Buddy:InviteSentToPlayer"), nick.str());
  1075. // insert status into box
  1076. messages->push_back(message);
  1077. DEBUG_LOG(("Inserting buddy add request\n"));
  1078. // put message on screen
  1079. insertChat(message);
  1080. // play audio notification
  1081. AudioEventRTS buddyMsgAudio("GUIMessageReceived");
  1082. if( TheAudio )
  1083. {
  1084. TheAudio->addAudioEvent( &buddyMsgAudio );
  1085. } // end if
  1086. lastNotificationWasStatus = FALSE;
  1087. numOnlineInNotification = 0;
  1088. showNotificationBox(AsciiString::TheEmptyString, s);
  1089. }
  1090. WindowMsgHandledType WOLBuddyOverlayRCMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
  1091. {
  1092. switch( msg )
  1093. {
  1094. case GWM_CREATE:
  1095. {
  1096. break;
  1097. } // case GWM_DESTROY:
  1098. case GWM_DESTROY:
  1099. {
  1100. rcMenu = NULL;
  1101. break;
  1102. } // case GWM_DESTROY:
  1103. case GGM_CLOSE:
  1104. {
  1105. closeRightClickMenu(window);
  1106. //rcMenu = NULL;
  1107. break;
  1108. }
  1109. case GBM_SELECTED:
  1110. {
  1111. GameWindow *control = (GameWindow *)mData1;
  1112. Int controlID = control->winGetWindowId();
  1113. GameSpyRCMenuData *rcData = (GameSpyRCMenuData*)window->winGetUserData();
  1114. if(!rcData)
  1115. break;
  1116. DEBUG_ASSERTCRASH(rcData, ("WOLBuddyOverlayRCMenuSystem GBM_SELECTED:: we're attempting to read the GameSpyRCMenuData from the window, but the data's not there"));
  1117. GPProfile profileID = rcData->m_id;
  1118. AsciiString nick = rcData->m_nick;
  1119. Bool isBuddy = false, isRequest = false;
  1120. Bool isGameSpyUser = profileID > 0;
  1121. if (rcData->m_itemType == ITEM_BUDDY)
  1122. isBuddy = TRUE;
  1123. else if (rcData->m_itemType == ITEM_REQUEST)
  1124. isRequest = TRUE;
  1125. if(rcData)
  1126. {
  1127. delete rcData;
  1128. rcData = NULL;
  1129. }
  1130. window->winSetUserData(NULL);
  1131. //DEBUG_ASSERTCRASH(profileID > 0, ("Bad profile ID in user data!"));
  1132. if( controlID == buttonAddID )
  1133. {
  1134. if(!isGameSpyUser)
  1135. break;
  1136. DEBUG_LOG(("ButtonAdd was pushed\n"));
  1137. if (isRequest)
  1138. {
  1139. // ok the request
  1140. BuddyRequest req;
  1141. req.buddyRequestType = BuddyRequest::BUDDYREQUEST_OKADD;
  1142. req.arg.profile.id = profileID;
  1143. TheGameSpyBuddyMessageQueue->addRequest(req);
  1144. BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap();
  1145. m->erase( profileID );
  1146. // DONT CHECK IN UNTIL MATT HAS REVIEWED
  1147. // if the profile ID is not from a buddy and we're okaying his request, then
  1148. // request to add him to our list automatically CLH 2-18-03
  1149. if(!TheGameSpyInfo->isBuddy(profileID))
  1150. {
  1151. RequestBuddyAdd(profileID, nick);
  1152. }
  1153. updateBuddyInfo();
  1154. }
  1155. else if (!isBuddy)
  1156. {
  1157. RequestBuddyAdd(profileID, nick);
  1158. }
  1159. }
  1160. else if( controlID == buttonDeleteID )
  1161. {
  1162. if(!isGameSpyUser)
  1163. break;
  1164. if (isBuddy)
  1165. {
  1166. // delete the buddy
  1167. BuddyRequest req;
  1168. req.buddyRequestType = BuddyRequest::BUDDYREQUEST_DELBUDDY;
  1169. req.arg.profile.id = profileID;
  1170. TheGameSpyBuddyMessageQueue->addRequest(req);
  1171. }
  1172. else
  1173. {
  1174. // delete the request
  1175. BuddyRequest req;
  1176. req.buddyRequestType = BuddyRequest::BUDDYREQUEST_DENYADD;
  1177. req.arg.profile.id = profileID;
  1178. TheGameSpyBuddyMessageQueue->addRequest(req);
  1179. BuddyInfoMap *m = TheGameSpyInfo->getBuddyRequestMap();
  1180. m->erase( profileID );
  1181. }
  1182. BuddyInfoMap *buddies = (isBuddy)?TheGameSpyInfo->getBuddyMap():TheGameSpyInfo->getBuddyRequestMap();
  1183. buddies->erase(profileID);
  1184. updateBuddyInfo();
  1185. DEBUG_LOG(("ButtonDelete was pushed\n"));
  1186. PopulateLobbyPlayerListbox();
  1187. }
  1188. else if( controlID == buttonPlayID )
  1189. {
  1190. DEBUG_LOG(("buttonPlayID was pushed\n"));
  1191. }
  1192. else if( controlID == buttonIgnoreID )
  1193. {
  1194. DEBUG_LOG(("%s is isGameSpyUser %d", nick.str(), isGameSpyUser));
  1195. if( isGameSpyUser )
  1196. {
  1197. if(TheGameSpyInfo->isSavedIgnored(profileID))
  1198. {
  1199. TheGameSpyInfo->removeFromSavedIgnoreList(profileID);
  1200. }
  1201. else
  1202. {
  1203. TheGameSpyInfo->addToSavedIgnoreList(profileID, nick);
  1204. }
  1205. }
  1206. else
  1207. {
  1208. if(TheGameSpyInfo->isIgnored(nick))
  1209. {
  1210. TheGameSpyInfo->removeFromIgnoreList(nick);
  1211. }
  1212. else
  1213. {
  1214. TheGameSpyInfo->addToIgnoreList(nick);
  1215. }
  1216. }
  1217. updateBuddyInfo();
  1218. refreshIgnoreList();
  1219. // repopulate our player listboxes now
  1220. PopulateLobbyPlayerListbox();
  1221. }
  1222. else if( controlID == buttonStatsID )
  1223. {
  1224. DEBUG_LOG(("buttonStatsID was pushed\n"));
  1225. GameSpyCloseOverlay(GSOVERLAY_PLAYERINFO);
  1226. SetLookAtPlayer(profileID,nick );
  1227. GameSpyOpenOverlay(GSOVERLAY_PLAYERINFO);
  1228. PSRequest req;
  1229. req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
  1230. req.player.id = profileID;
  1231. TheGameSpyPSMessageQueue->addRequest(req);
  1232. }
  1233. closeRightClickMenu(window);
  1234. break;
  1235. }
  1236. default:
  1237. return MSG_IGNORED;
  1238. }//Switch
  1239. return MSG_HANDLED;
  1240. }
  1241. void setUnignoreText( WindowLayout *layout, AsciiString nick, GPProfile id)
  1242. {
  1243. AsciiString controlName;
  1244. controlName.format("%s:ButtonIgnore",layout->getFilename().str()+6);
  1245. NameKeyType ID = TheNameKeyGenerator->nameToKey( controlName );
  1246. GameWindow *win = TheWindowManager->winGetWindowFromId(layout->getFirstWindow(), ID);
  1247. if(win)
  1248. {
  1249. if(TheGameSpyInfo->isSavedIgnored(id) || TheGameSpyInfo->isIgnored(nick))
  1250. GadgetButtonSetText(win, TheGameText->fetch("GUI:Unignore"));
  1251. }
  1252. }
  1253. void refreshIgnoreList( void )
  1254. {
  1255. SavedIgnoreMap tempMap;
  1256. tempMap = TheGameSpyInfo->returnSavedIgnoreList();
  1257. SavedIgnoreMap::iterator it = tempMap.begin();
  1258. GadgetListBoxReset(listboxIgnore);
  1259. while(it != tempMap.end())
  1260. {
  1261. UnicodeString name;
  1262. name.translate(it->second);
  1263. Int pos = GadgetListBoxAddEntryText(listboxIgnore, name, GameMakeColor(255,100,100,255),-1);
  1264. GadgetListBoxSetItemData(listboxIgnore, (void *)it->first,pos );
  1265. ++it;
  1266. }
  1267. IgnoreList tempList;
  1268. tempList = TheGameSpyInfo->returnIgnoreList();
  1269. IgnoreList::iterator iListIt = tempList.begin();
  1270. while( iListIt != tempList.end())
  1271. {
  1272. AsciiString aName = *iListIt;
  1273. UnicodeString name;
  1274. name.translate(aName);
  1275. Int pos = GadgetListBoxAddEntryText(listboxIgnore, name, GameMakeColor(255,100,100,255),-1);
  1276. GadgetListBoxSetItemData(listboxIgnore, 0,pos );
  1277. ++iListIt;
  1278. }
  1279. //
  1280. // GPProfile profileID = 0;
  1281. // PlayerInfoMap::iterator it = TheGameSpyInfo->getPlayerInfoMap()->find(aName);
  1282. // if (it != TheGameSpyInfo->getPlayerInfoMap()->end())
  1283. // profileID = it->second.m_profileID;
  1284. }