Ticket #3171: t3171_clear_muc_messages_v7_16836.patch
File t3171_clear_muc_messages_v7_16836.patch, 12.2 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/lobby/lobby.js
12 12 var g_mapSizes = {}; 13 13 const g_mapTypesText = [translateWithContext("map", "Skirmish"), translateWithContext("map", "Random"), translate("Scenario")]; 14 14 const g_mapTypes = ["skirmish", "random", "scenario"]; 15 15 var g_userRating = ""; // Rating of user, defaults to Unrated 16 16 var g_modPrefix = "@"; 17 var g_joined = false;18 17 // Block spammers for 30 seconds. 19 18 var SPAM_BLOCK_LENGTH = 30; 20 19 21 20 //////////////////////////////////////////////////////////////////////////////////////////////// 22 21 … … 163 162 logo.size = "50%-110 40 50%+110 140"; 164 163 } 165 164 } 166 165 167 166 /** 168 * Do a full update of the player listing, including ratings from cached C++ information.167 * Replace the playerlist with the current list cached in C++. 169 168 * 170 169 * @return Array containing the player, presence, nickname, and rating listings. 171 170 */ 172 171 function updatePlayerList() 173 172 { 174 173 var playersBox = Engine.GetGUIObjectByName("playersBox"); 175 174 var playerList = []; 176 175 var presenceList = []; 177 176 var nickList = []; 178 177 var ratingList = []; 179 var cleanPlayerList = Engine.GetPlayerList( );178 var cleanPlayerList = Engine.GetPlayerList(true); 180 179 // Sort the player list, ignoring case. 181 180 cleanPlayerList.sort(function(a,b) 182 181 { 183 182 switch (g_PlayerListSortBy) 184 183 { … … 701 700 case "join": 702 701 if (nick == g_Name) 703 702 { 704 703 // We just joined, we need to get the full player list 705 704 [playerList, presenceList, nickList, ratingList] = updatePlayerList(); 706 // Don't display any joins until our join request bounces back707 // Our join message should be the last one as we just got added to the stack708 g_joined = true;709 break;710 705 } 711 else if (g_joined)706 else 712 707 { 713 708 var [name, status, rating] = formatPlayerListEntry(nick, presence, "-"); 714 709 playerList.push(name); 715 710 presenceList.push(status); 716 711 nickList.push(nick); … … 727 722 nickList.splice(nickIndex, 1); 728 723 ratingList.splice(nickIndex, 1); 729 724 addChatMessage({ "text": "/special " + sprintf(translate("%(nick)s has left."), { nick: nick }), "key": g_specialKey }); 730 725 break; 731 726 case "nick": 732 if (nickIndex == -1) // This shouldn't ever happen727 if (nickIndex == -1) // Changed nick, but not present 733 728 break; 734 729 if (!isValidNick(message.data)) 735 730 { 736 731 addChatMessage({ "from": "system", "text": sprintf(translate("Invalid nickname: %(nick)s"), { nick: message.data })}); 737 732 break; … … 742 737 nickList[nickIndex] = message.data; 743 738 addChatMessage({ "text": "/special " + sprintf(translate("%(oldnick)s is now known as %(newnick)s."), { oldnick: nick, newnick: message.data }), "key": g_specialKey }); 744 739 Engine.SendGetRatingList(); 745 740 break; 746 741 case "presence": 747 if (nickIndex == -1) // This shouldn't ever happen742 if (nickIndex == -1) // Changed presence, but not online 748 743 break; 749 744 var [name, status, rating] = formatPlayerListEntry(nick, presence, stripColorCodes(ratingList[nickIndex])); 750 745 presenceList[nickIndex] = status; 751 746 playerList[nickIndex] = name; 752 747 ratingList[nickIndex] = rating; -
binaries/data/mods/public/gui/lobby/lobby.xml
233 233 234 234 <object name="chatPanel" size="0 49% 100% 100%" type="image" sprite="ModernDarkBoxGold"> 235 235 <object name="chatText" size="0 0 100% 94%" type="text" style="ChatPanel" font="sans-13"/> 236 236 <object name="chatInput" size="0 94% 100% 100%" type="input" style="ModernInput" font="sans-13"> 237 237 <action on="Press">submitChatInput();</action> 238 <action on="Tab">autoCompleteNick("chatInput", Engine.GetPlayerList( ));</action>238 <action on="Tab">autoCompleteNick("chatInput", Engine.GetPlayerList(false));</action> 239 239 </object> 240 240 </object> 241 241 </object> 242 242 243 243 <!-- START Window for leaderboard stats --> -
source/lobby/IXmppClient.h
52 52 virtual void GUIGetGameList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 53 53 virtual void GUIGetBoardList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 54 54 virtual void GUIGetProfile(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 55 55 56 56 virtual void GuiPollMessage(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 57 virtual void ClearPresenceUpdates() = 0; 57 58 virtual void SendMUCMessage(const std::string& message) = 0; 58 59 }; 59 60 60 61 extern IXmppClient *g_XmppClient; 61 62 extern bool g_rankedGame; -
source/lobby/XmppClient.cpp
77 77 78 78 m_xpartamuppId = sXpartamupp + "@" + sServer + "/CC"; 79 79 glooxwrapper::JID clientJid(sUsername + "@" + sServer + "/0ad"); 80 80 glooxwrapper::JID roomJid(sRoom + "@conference." + sServer + "/" + sNick); 81 81 82 m_Joined = false; 83 82 84 // If we are connecting, use the full jid and a password 83 85 // If we are registering, only use the server name 84 86 if (!regOpt) 85 87 m_client = new glooxwrapper::Client(clientJid, sPassword); 86 88 else … … 486 488 /***************************************************** 487 489 * Requests from GUI * 488 490 *****************************************************/ 489 491 490 492 /** 493 * If someone plays a game while being connected to the lobby, those presence updats 494 * will pile up for the duration of the game (up to some thousands of updates in 1-2 hours) - 495 * thus freezing the game for some seconds and spamming the lobby with joins and disconnects. 496 * 497 * The messages are also invalidated since lobby.js applies them to the refreshed playerlist 498 * instead of the one from the time when the update arrived. This creates dupes that remain 499 * online after the player left. More information on #3171. 500 * 501 * Therefore we remove all presence updates when replacing the playerlist with a current one. 502 */ 503 void XmppClient::ClearPresenceUpdates() 504 { 505 std::remove_if(m_GuiMessageQueue.begin(), m_GuiMessageQueue.end(), 506 [](XmppClient::GUIMessage& message) 507 { 508 return message.type == L"muc" && message.level != L"subject"; 509 } 510 ); 511 } 512 513 /** 491 514 * Handle requests from the GUI for the list of players. 492 515 * 493 516 * @return A JS array containing all known players and their presences 494 517 */ 495 518 void XmppClient::GUIGetPlayerList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) … … 789 812 // we have a nick change 790 813 std::string newNick = participant.newNick.to_string(); 791 814 m_PlayerMap[newNick].resize(3); 792 815 m_PlayerMap[newNick][0] = presenceString; 793 816 m_PlayerMap[newNick][2] = roleString; 794 CreateSimpleMessage("muc", nick, "nick", participant.newNick.to_string()); 817 if (m_Joined) 818 CreateSimpleMessage("muc", nick, "nick", participant.newNick.to_string()); 795 819 } 796 else 820 else if (m_Joined) 797 821 CreateSimpleMessage("muc", nick, "leave"); 798 822 799 823 DbgXMPP(nick << " left the room"); 800 824 m_PlayerMap.erase(nick); 801 825 } 802 826 else 803 827 { 804 if (m_PlayerMap.find(nick) == m_PlayerMap.end()) 805 CreateSimpleMessage("muc", nick, "join"); 806 else 807 CreateSimpleMessage("muc", nick, "presence"); 828 if (nick == m_mucRoom->nick().to_string()) 829 m_Joined = true; 830 831 // Only send updates after we joined the room 832 if (m_Joined) 833 { 834 if (m_PlayerMap.find(nick) == m_PlayerMap.end()) 835 CreateSimpleMessage("muc", nick, "join"); 836 else 837 CreateSimpleMessage("muc", nick, "presence"); 838 } 808 839 809 840 DbgXMPP(nick << " is in the room, presence : " << (int)presenceType); 810 841 m_PlayerMap[nick].resize(3); 811 842 m_PlayerMap[nick][0] = presenceString; 812 843 m_PlayerMap[nick][2] = roleString; -
source/lobby/XmppClient.h
132 132 std::wstring from; 133 133 std::wstring message; 134 134 std::string datetime; 135 135 }; 136 136 void GuiPollMessage(ScriptInterface& scriptInterface, JS::MutableHandleValue ret); 137 void ClearPresenceUpdates(); 137 138 void SendMUCMessage(const std::string& message); 138 139 protected: 139 140 void PushGuiMessage(XmppClient::GUIMessage message); 140 141 void CreateSimpleMessage(const std::string& type, const std::string& text, const std::string& level = "standard", const std::string& data = ""); 141 142 142 143 private: 144 // Whether or not we have successfully joined the lobby 145 bool m_Joined; 143 146 /// Map of players 144 147 std::map<std::string, std::vector<std::string> > m_PlayerMap; 145 148 /// List of games 146 149 std::vector<const glooxwrapper::Tag*> m_GameList; 147 150 /// List of rankings -
source/lobby/scripting/JSInterface_Lobby.cpp
44 44 scriptInterface.RegisterFunction<void, std::wstring, &JSI_Lobby::SendGetProfile>("SendGetProfile"); 45 45 scriptInterface.RegisterFunction<void, JS::HandleValue, &JSI_Lobby::SendRegisterGame>("SendRegisterGame"); 46 46 scriptInterface.RegisterFunction<void, JS::HandleValue, &JSI_Lobby::SendGameReport>("SendGameReport"); 47 47 scriptInterface.RegisterFunction<void, &JSI_Lobby::SendUnregisterGame>("SendUnregisterGame"); 48 48 scriptInterface.RegisterFunction<void, std::wstring, std::wstring, &JSI_Lobby::SendChangeStateGame>("SendChangeStateGame"); 49 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetPlayerList>("GetPlayerList");49 scriptInterface.RegisterFunction<JS::Value, bool, &JSI_Lobby::GetPlayerList>("GetPlayerList"); 50 50 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetGameList>("GetGameList"); 51 51 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetBoardList>("GetBoardList"); 52 52 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetProfile>("GetProfile"); 53 53 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::LobbyGuiPollMessage>("LobbyGuiPollMessage"); 54 54 scriptInterface.RegisterFunction<void, std::wstring, &JSI_Lobby::LobbySendMessage>("LobbySendMessage"); … … 173 173 if (!g_XmppClient) 174 174 return; 175 175 g_XmppClient->SendIqChangeStateGame(utf8_from_wstring(nbp), utf8_from_wstring(players)); 176 176 } 177 177 178 JS::Value JSI_Lobby::GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate )178 JS::Value JSI_Lobby::GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate, bool clearPresenceUpdates = false) 179 179 { 180 180 if (!g_XmppClient) 181 181 return JS::UndefinedValue(); 182 182 183 183 JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); 184 184 JSAutoRequest rq(cx); 185 185 186 if (clearPresenceUpdates) 187 g_XmppClient->ClearPresenceUpdates(); 188 186 189 JS::RootedValue playerList(cx); 187 190 g_XmppClient->GUIGetPlayerList(*(pCxPrivate->pScriptInterface), &playerList); 188 191 189 192 return playerList; 190 193 } -
source/lobby/scripting/JSInterface_Lobby.h
42 42 void SendGetProfile(ScriptInterface::CxPrivate* pCxPrivate, std::wstring player); 43 43 void SendGameReport(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data); 44 44 void SendRegisterGame(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data); 45 45 void SendUnregisterGame(ScriptInterface::CxPrivate* pCxPrivate); 46 46 void SendChangeStateGame(ScriptInterface::CxPrivate* pCxPrivate, std::wstring nbp, std::wstring players); 47 JS::Value GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate );47 JS::Value GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate, bool clearPresenceUpdates); 48 48 JS::Value GetGameList(ScriptInterface::CxPrivate* pCxPrivate); 49 49 JS::Value GetBoardList(ScriptInterface::CxPrivate* pCxPrivate); 50 50 JS::Value GetProfile(ScriptInterface::CxPrivate* pCxPrivate); 51 51 JS::Value LobbyGuiPollMessage(ScriptInterface::CxPrivate* pCxPrivate); 52 52 void LobbySendMessage(ScriptInterface::CxPrivate* pCxPrivate, std::wstring message);