| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: GameSpyChat.cpp //////////////////////////////////////////////////////
- // GameSpy chat handlers
- // Author: Matthew D. Campbell, February 2002
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "GameClient/GameText.h"
- #include "GameClient/GadgetListBox.h"
- #include "GameClient/LanguageFilter.h"
- #include "GameNetwork/GameSpy.h"
- #include "GameNetwork/GameSpyChat.h"
- #include "Common/QuotedPrintable.h"
- typedef set<AsciiString>::const_iterator AsciiSetIter;
- /**
- * handleSlashCommands looks for slash ccommands and handles them,
- * returning true if it found one, false otherwise.
- * /i,/ignore list ignored players
- * /i,/ignore +name1 -name2 ignore name1, stop ignoring name2
- * /m,/me: shorthand for an action
- * /o,/on: find command to look up a user's location
- * /f,/find: find command to look up a user's location
- * /p,/page: page user(s)
- * /r,/reply: reply to last page
- * /raw: raw IRC command (only in debug & internal)
- * /oper: become an IRC op (only in debug & internal)
- * /quit: send the IRC quit command to exit WOL
- */
- static Bool handleSlashCommands( UnicodeString message, Bool isAction, GameWindow *playerListbox )
- {
- /*
- if (message.getCharAt(0) == L'/')
- {
- UnicodeString remainder = UnicodeString(message.str() + 1);
- UnicodeString token;
- switch (message.getCharAt(1))
- {
- case L'i':
- case L'I':
- remainder.nextToken(&token);
- if (token.compareNoCase(L"i") == 0 || token.compareNoCase(L"ignore") == 0)
- {
- if (remainder.isEmpty())
- {
- // List the people we're ignoring
- TheWOL->addText(TheGameText->fetch("WOL:BeginIgnoreList"));
- set<AsciiString> *ignoreList = getIgnoreList();
- if (ignoreList)
- {
- UnicodeString msg;
- UnicodeString uName;
- AsciiSetIter iter = ignoreList->begin();
- while (iter != ignoreList->end())
- {
- uName.translate(*iter);
- msg.format(TheGameText->fetch("WOL:IgnoredUser"), uName.str());
- TheWOL->addText(msg);
- iter++;
- }
- }
- TheWOL->addText(TheGameText->fetch("WOL:EndIgnoreList"));
- }
- while ( remainder.nextToken(&token) )
- {
- AsciiString name;
- int doIgnore = 0;
- if (token.getCharAt(0) == L'+')
- {
- // Ignore somebody
- token = UnicodeString(token.str() + 1);
- name.translate(token);
- doIgnore = 1;
- }
- else if (token.getCharAt(0) == L'-')
- {
- // Listen to someone again
- token = UnicodeString(token.str() + 1);
- name.translate(token);
- doIgnore = 0;
- }
- else
- {
- // Ignore somebody
- token = UnicodeString(token.str());
- name.translate(token);
- doIgnore = 1;
- }
- IChat *ichat = TheWOL->getIChat();
- User user;
- strncpy((char *)user.name, name.str(), 9);
- user.name[9] = 0;
- ichat->SetSquelch(&user, doIgnore);
- if (doIgnore)
- addIgnore(name);
- else
- removeIgnore(name);
- UnicodeString msg;
- UnicodeString uName;
- uName.translate(name);
- msg.format(TheGameText->fetch("WOL:IgnoredUser"), uName.str());
- TheWOL->addText(msg);
- }
- return true;
- }
- break;
- case L'r':
- case L'R':
- remainder.nextToken(&token);
- #if defined _DEBUG || defined _INTERNAL
- if (token.compareNoCase(L"raw") == 0)
- {
- // Send raw IRC commands (Ascii only)
- AsciiString str;
- str.translate(remainder);
- str.concat('\n');
- IChat *ichat = TheWOL->getIChat();
- ichat->RequestRawMessage(str.str());
- TheWOL->addText(remainder);
- return true; // show it anyway
- }
- #endif
- break;
- #if defined _DEBUG || defined _INTERNAL
- case L'k':
- case L'K':
- remainder.nextToken(&token);
- if (token.compareNoCase(L"kick") == 0)
- {
- while ( remainder.nextToken(&token) )
- {
- AsciiString name;
- name.translate(token);
- IChat *ichat = TheWOL->getIChat();
- User user;
- strncpy((char *)user.name, name.str(), 9);
- user.name[9] = 0;
- ichat->RequestUserKick(&user);
- }
- return true;
- }
- break;
- #endif
- case L'o':
- case L'O':
- remainder.nextToken(&token);
- if (token.compareNoCase(L"on") == 0 || token.compareNoCase(L"o") == 0)
- {
- remainder.nextToken(&token);
- AsciiString userName;
- userName.translate(token);
- User user;
- strncpy((char *)user.name, userName.str(), 10);
- user.name[9] = 0;
- if (user.name[0] == 0)
- {
- // didn't enter a name
- TheWOL->addText(message);
- }
- else
- {
- // Send find command
- IChat *ichat = TheWOL->getIChat();
- ichat->RequestGlobalFind(&user);
- }
- return true; // show it anyway
- }
- #if defined _DEBUG || defined _INTERNAL
- else if (token.compareNoCase(L"oper") == 0)
- {
- // Send raw IRC oper command
- AsciiString str;
- str.translate(message);
- str.concat('\n');
- IChat *ichat = TheWOL->getIChat();
- ichat->RequestRawMessage(str.str());
- TheWOL->addText(message);
- return true; // show it anyway
- }
- #endif
- break;
- case L'p':
- case L'P':
- remainder.nextToken(&token);
- if (token.compareNoCase(L"page") == 0 || token.compareNoCase(L"p") == 0)
- {
- remainder.nextToken(&token);
- AsciiString userName;
- userName.translate(token);
- User user;
- strncpy((char *)user.name, userName.str(), 10);
- user.name[9] = 0;
- remainder.trim();
- if (user.name[0] == 0 || remainder.isEmpty())
- {
- // didn't enter a name or message
- TheWOL->addText(message);
- }
- else
- {
- // Send page command
- IChat *ichat = TheWOL->getIChat();
- ichat->RequestGlobalUnicodePage(&user, remainder.str());
- }
- return true; // show it anyway
- }
- break;
- case L'q':
- case L'Q':
- remainder.nextToken(&token);
- if (token.compareNoCase(L"quit") == 0)
- {
- TheWOL->setState(WOLAPI_LOGIN);
- TheWOL->addCommand(WOLCOMMAND_LOGOUT);
- //TheWOL->setScreen(WOLAPI_MENU_WELCOME);
- return true; // show it anyway
- }
- break;
- #if defined _DEBUG || defined _INTERNAL
- case L'c':
- case L'C':
- remainder.nextToken(&token);
- if (token.compareNoCase(L"colortest") == 0)
- {
- addColorText(token, 0xDD, 0xE2, 0x0D, 0xff);
- addColorText(token, 0xFF, 0x19, 0x19, 0xff);
- addColorText(token, 0x2A, 0x74, 0xE2, 0xff);
- addColorText(token, 0x3E, 0xD1, 0x2E, 0xff);
- addColorText(token, 0xFF, 0xA0, 0x19, 0xff);
- addColorText(token, 0x32, 0xD7, 0xE6, 0xff);
- addColorText(token, 0x95, 0x28, 0xBD, 0xff);
- addColorText(token, 0xFF, 0x9A, 0xEB, 0xff);
- return true; // show it anyway
- }
- break;
- #endif // _DEBUG || defined _INTERNAL
- }
- }
- */
- return false;
- }
- static handleUnicodeMessage( const char *nick, UnicodeString msg, Bool isPublic, Bool isAction );
- Bool GameSpySendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox )
- {
- RoomType roomType = StagingRoom;
- if (TheGameSpyChat->getCurrentGroupRoomID())
- roomType = GroupRoom;
- message.trim();
- // Echo the user's input to the chat window
- if (!message.isEmpty())
- {
- // Check for slash commands
- if (handleSlashCommands(message, isAction, playerListbox))
- {
- return false; // already handled
- }
- if (!playerListbox)
- {
- // Public message
- if (isAction)
- {
- peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), ActionMessage);
- //if (roomType == StagingRoom)
- //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, true);
- }
- else
- {
- peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), NormalMessage);
- //if (roomType == StagingRoom)
- //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, false);
- }
- return false;
- }
- // Get the selections (is this a private message?)
- Int maxSel = GadgetListBoxGetListLength(playerListbox);
- Int *selections;
- GadgetListBoxGetSelected(playerListbox, (Int *)&selections);
- if (selections[0] == -1)
- {
- // Public message
- if (isAction)
- {
- peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), ActionMessage);
- //if (roomType == StagingRoom)
- //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, true);
- }
- else
- {
- peerMessageRoom(TheGameSpyChat->getPeer(), roomType, UnicodeStringToQuotedPrintable(message).str(), NormalMessage);
- //if (roomType == StagingRoom)
- //handleUnicodeMessage(TheGameSpyChat->getloginName().str(), message, true, false);
- }
- return false;
- }
- else
- {
- // Private message
- // Construct a list
- AsciiString names = AsciiString::TheEmptyString;
- AsciiString tmp = AsciiString::TheEmptyString;
- AsciiString aStr; // AsciiString buf for translating Unicode entries
- names.format("%s", TheGameSpyChat->getLoginName().str());
- for (int i=0; i<maxSel; i++)
- {
- if (selections[i] != -1)
- {
- aStr.translate(GadgetListBoxGetText(playerListbox, selections[i], 0));
- if (aStr.compareNoCase(TheGameSpyChat->getLoginName()))
- {
- tmp.format(",%s", aStr.str());
- names.concat(tmp);
- }
- }
- else
- {
- break;
- }
- }
- if (!names.isEmpty())
- {
- if (isAction)
- {
- peerMessagePlayer(TheGameSpyChat->getPeer(), names.str(), UnicodeStringToQuotedPrintable(message).str(), ActionMessage);
- }
- else
- {
- peerMessagePlayer(TheGameSpyChat->getPeer(), names.str(), UnicodeStringToQuotedPrintable(message).str(), NormalMessage);
- }
- }
- return true;
- }
- }
- return false;
- }
- void RoomMessageCallback(PEER peer, RoomType roomType,
- const char * nick, const char * message,
- MessageType messageType, void * param)
- {
- DEBUG_LOG(("RoomMessageCallback\n"));
- handleUnicodeMessage(nick, QuotedPrintableToUnicodeString(message), true, (messageType == ActionMessage));
- }
- void PlayerMessageCallback(PEER peer,
- const char * nick, const char * message,
- MessageType messageType, void * param)
- {
- DEBUG_LOG(("PlayerMessageCallback\n"));
- handleUnicodeMessage(nick, QuotedPrintableToUnicodeString(message), false, (messageType == ActionMessage));
- }
- static handleUnicodeMessage( const char *nick, UnicodeString msg, Bool isPublic, Bool isAction )
- {
- GameSpyColors style;
- Bool isOwner = false;
- Int flags = 0;
- if (TheGameSpyChat->getCurrentGroupRoomID())
- peerGetPlayerFlags(TheGameSpyChat->getPeer(), nick, GroupRoom, &flags);
- else
- peerGetPlayerFlags(TheGameSpyChat->getPeer(), nick, StagingRoom, &flags);
- isOwner = flags & PEER_FLAG_OP;
- if (isPublic && isAction)
- {
- style = (isOwner)?GSCOLOR_CHAT_OWNER_EMOTE:GSCOLOR_CHAT_EMOTE;
- }
- else if (isPublic)
- {
- style = (isOwner)?GSCOLOR_CHAT_OWNER:GSCOLOR_CHAT_NORMAL;
- }
- else if (isAction)
- {
- style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE:GSCOLOR_CHAT_PRIVATE_EMOTE;
- }
- else
- {
- style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER:GSCOLOR_CHAT_PRIVATE;
- }
- UnicodeString name;
- name.translate(nick);
- // filters language
- // if( TheGlobalData->m_languageFilterPref )
- // {
- TheLanguageFilter->filterLine(msg);
- // }
- UnicodeString fullMsg;
- if (isAction)
- {
- fullMsg.format( L"%ls %ls", name.str(), msg.str() );
- }
- else
- {
- fullMsg.format( L"[%ls] %ls", name.str(), msg.str() );
- }
- GameSpyAddText(fullMsg, style);
- }
- void GameSpyAddText( UnicodeString message, GameSpyColors color )
- {
- GameWindow *textWindow = NULL;
- if (!textWindow)
- textWindow = listboxLobbyChat;
- if (!textWindow)
- textWindow = listboxGameSetupChat;
- if (!textWindow)
- return;
- GadgetListBoxAddEntryText(textWindow, message, GameSpyColor[color], -1, -1);
- }
|