Ticket #3386: t3386_fix_lobby_rejoin_v3.1.patch
File t3386_fix_lobby_rejoin_v3.1.patch, 13.0 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/gui/lobby/lobby.js
46 46 mapTypeFilter.list_data = [""].concat(g_mapTypes); 47 47 48 48 Engine.LobbySetPlayerPresence("available"); 49 49 Engine.SendGetGameList(); 50 50 Engine.SendGetBoardList(); 51 52 // When rejoining the lobby after a game, we don't need to process presence changes 53 Engine.LobbyClearPresenceUpdates(); 51 54 updatePlayerList(); 55 52 56 updateSubject(Engine.LobbyGetRoomSubject()); 53 57 54 58 resetFilters(); 55 59 } 56 60 … … 231 235 playersBox.list_status = presenceList; 232 236 playersBox.list_rating = ratingList; 233 237 playersBox.list = nickList; 234 238 if (playersBox.selected >= playersBox.list.length) 235 239 playersBox.selected = -1; 236 return [playerList, presenceList, nickList, ratingList];237 240 } 238 241 239 242 /** 240 243 * Display the profile of the selected player. 241 244 * Displays N/A for all stats until updateProfile is called when the stats … … 687 690 var from = escapeText(message.from); 688 691 addChatMessage({ "from": from, "text": text, "datetime": message.datetime}); 689 692 break; 690 693 case "muc": 691 694 var nick = message.text; 692 var presence = Engine.LobbyGetPlayerPresence(nick);693 var playersBox = Engine.GetGUIObjectByName("playersBox");694 var playerList = playersBox.list_name;695 var presenceList = playersBox.list_status;696 var nickList = playersBox.list;697 var ratingList = playersBox.list_rating;698 var nickIndex = nickList.indexOf(nick);699 695 switch(message.level) 700 696 { 701 697 case "join": 702 var [name, status, rating] = formatPlayerListEntry(nick, presence, "-");703 playerList.push(name);704 presenceList.push(status);705 nickList.push(nick);706 ratingList.push(String(rating));707 698 addChatMessage({ "text": "/special " + sprintf(translate("%(nick)s has joined."), { nick: nick }), "key": g_specialKey }); 708 699 break; 709 700 case "leave": 710 if (nickIndex == -1) // Left, but not present (TODO: warn about this?)711 break;712 playerList.splice(nickIndex, 1);713 presenceList.splice(nickIndex, 1);714 nickList.splice(nickIndex, 1);715 ratingList.splice(nickIndex, 1);716 701 addChatMessage({ "text": "/special " + sprintf(translate("%(nick)s has left."), { nick: nick }), "key": g_specialKey }); 717 702 break; 718 703 case "nick": 719 if (nickIndex == -1) // Changed nick, but not present (shouldn't ever happen)720 break;721 if (!isValidNick(message.data))722 {723 addChatMessage({ "from": "system", "text": sprintf(translate("Invalid nickname: %(nick)s"), { nick: message.data })});724 break;725 }726 var [name, status, rating] = formatPlayerListEntry(message.data, presence, stripColorCodes(ratingList[nickIndex])); // TODO: actually we don't want to change the presence here, so use what was used before727 playerList[nickIndex] = name;728 // presence stays the same729 nickList[nickIndex] = message.data;730 704 addChatMessage({ "text": "/special " + sprintf(translate("%(oldnick)s is now known as %(newnick)s."), { oldnick: nick, newnick: message.data }), "key": g_specialKey }); 731 705 break; 732 706 case "presence": 733 if (nickIndex == -1) // Changed presence, but not online (shouldn't ever happen)734 break;735 var [name, status, rating] = formatPlayerListEntry(nick, presence, stripColorCodes(ratingList[nickIndex]));736 presenceList[nickIndex] = status;737 playerList[nickIndex] = name;738 ratingList[nickIndex] = rating;739 707 break; 740 708 case "subject": 741 709 updateSubject(message.text); 742 710 break; 743 711 default: 744 712 warn(sprintf("Unknown message.level '%(msglvl)s'", { msglvl: message.level })); 745 713 break; 746 714 } 747 // Push new data to GUI 748 playersBox.list_name = playerList; 749 playersBox.list_status = presenceList; 750 playersBox.list_rating = ratingList; 751 playersBox.list = nickList; 752 if (playersBox.selected >= playersBox.list.length) 753 playersBox.selected = -1; 715 // We might receive many join/leaves when returning to the lobby from a long game. 716 // To improve performance, only update the playerlist GUI when the last update in the current stack is processed 717 if (Engine.LobbyGetMucMessageCount() == 0) 718 updatePlayerList(); 754 719 break; 755 720 case "system": 756 721 switch (message.level) 757 722 { 758 723 case "standard": -
source/lobby/IXmppClient.h
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … 45 45 virtual void ban(const std::string& nick, const std::string& reason) = 0; 46 46 virtual void SetPresence(const std::string& presence) = 0; 47 47 virtual void GetPresence(const std::string& nickname, std::string& presence) = 0; 48 48 virtual void GetRole(const std::string& nickname, std::string& role) = 0; 49 49 virtual void GetSubject(std::string& subject) = 0; 50 51 50 virtual void GUIGetPlayerList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 51 virtual void ClearPresenceUpdates() = 0; 52 virtual int GetMucMessageCount() = 0; 52 53 virtual void GUIGetGameList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 53 54 virtual void GUIGetBoardList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 54 55 virtual void GUIGetProfile(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; 55 56 56 57 virtual void GuiPollMessage(ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; -
source/lobby/XmppClient.cpp
640 640 { 641 641 m_GuiMessageQueue.push_back(std::move(message)); 642 642 } 643 643 644 644 /** 645 * Clears all presence updates from the message queue. 646 * Used when rejoining the lobby, since we don't need to handle past presence changes. 647 */ 648 void XmppClient::ClearPresenceUpdates() 649 { 650 m_GuiMessageQueue.erase( 651 std::remove_if(m_GuiMessageQueue.begin(), m_GuiMessageQueue.end(), 652 [](XmppClient::GUIMessage& message) 653 { 654 return message.type == L"muc" && message.level == L"presence"; 655 } 656 ), m_GuiMessageQueue.end()); 657 } 658 659 /** 660 * Used in order to update the GUI only once when multiple updates are queued. 661 */ 662 int XmppClient::GetMucMessageCount() 663 { 664 return std::count_if(m_GuiMessageQueue.begin(), m_GuiMessageQueue.end(), 665 [](XmppClient::GUIMessage& message) 666 { 667 return message.type == L"muc"; 668 }); 669 } 670 671 /** 645 672 * Handle a standard MUC textual message. 646 673 */ 647 674 void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom*, const glooxwrapper::Message& msg, bool) 648 675 { 649 676 DbgXMPP(msg.from().resource() << " said " << msg.body()); -
source/lobby/XmppClient.h
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 5 * it under the terms of the GNU General Public License as published by 6 6 * the Free Software Foundation, either version 2 of the License, or … … 18 18 #ifndef XXXMPPCLIENT_H 19 19 #define XXXMPPCLIENT_H 20 20 21 21 #include "IXmppClient.h" 22 22 23 #include "glooxwrapper/glooxwrapper.h"24 25 //game - script26 23 #include <deque> 24 25 #include "glooxwrapper/glooxwrapper.h" 27 26 #include "scriptinterface/ScriptVal.h" 28 27 29 //Game - script30 28 class ScriptInterface; 31 29 32 30 namespace glooxwrapper 33 31 { 34 32 class Client; … … 36 34 } 37 35 38 36 class XmppClient : public IXmppClient, public glooxwrapper::ConnectionListener, public glooxwrapper::MUCRoomHandler, public glooxwrapper::IqHandler, public glooxwrapper::RegistrationHandler, public glooxwrapper::MessageHandler 39 37 { 40 38 NONCOPYABLE(XmppClient); 39 41 40 private: 42 41 //Components 43 42 glooxwrapper::Client* m_client; 44 43 glooxwrapper::MUCRoom* m_mucRoom; 45 44 glooxwrapper::Registration* m_registration; 45 46 46 //Account infos 47 47 std::string m_username; 48 48 std::string m_password; 49 49 std::string m_nick; 50 50 std::string m_xpartamuppId; 51 51 52 // State 52 53 bool m_initialLoadComplete = false; 54 53 55 public: 54 56 //Basic 55 57 XmppClient(const std::string& sUsername, const std::string& sPassword, const std::string& sRoom, const std::string& sNick, const int historyRequestSize = 0, const bool regOpt = false); 56 58 virtual ~XmppClient(); 57 59 … … 78 80 79 81 void GUIGetPlayerList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret); 80 82 void GUIGetGameList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret); 81 83 void GUIGetBoardList(ScriptInterface& scriptInterface, JS::MutableHandleValue ret); 82 84 void GUIGetProfile(ScriptInterface& scriptInterface, JS::MutableHandleValue ret); 85 83 86 //Script 84 87 ScriptInterface& GetScriptInterface(); 85 88 86 89 protected: 87 90 /* Xmpp handlers */ … … 120 123 121 124 // Helpers 122 125 void GetPresenceString(const gloox::Presence::PresenceType p, std::string& presence) const; 123 126 void GetRoleString(const gloox::MUCRoomRole r, std::string& role) const; 124 127 std::string StanzaErrorToString(gloox::StanzaError err); 128 125 129 public: 126 130 /* Messages */ 127 131 struct GUIMessage 128 132 { 129 133 std::wstring type; … … 134 138 std::wstring message; 135 139 std::string datetime; 136 140 }; 137 141 void GuiPollMessage(ScriptInterface& scriptInterface, JS::MutableHandleValue ret); 138 142 void SendMUCMessage(const std::string& message); 143 void ClearPresenceUpdates(); 144 int GetMucMessageCount(); 139 145 protected: 140 146 void PushGuiMessage(XmppClient::GUIMessage message); 141 147 void CreateSimpleMessage(const std::string& type, const std::string& text, const std::string& level = "standard", const std::string& data = ""); 142 148 143 149 private: -
source/lobby/scripting/JSInterface_Lobby.cpp
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 49 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetPlayerList>("GetPlayerList"); 50 scriptInterface.RegisterFunction<void, &JSI_Lobby::LobbyClearPresenceUpdates>("LobbyClearPresenceUpdates"); 51 scriptInterface.RegisterFunction<int, &JSI_Lobby::LobbyGetMucMessageCount>("LobbyGetMucMessageCount"); 50 52 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetGameList>("GetGameList"); 51 53 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetBoardList>("GetBoardList"); 52 54 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::GetProfile>("GetProfile"); 53 55 scriptInterface.RegisterFunction<JS::Value, &JSI_Lobby::LobbyGuiPollMessage>("LobbyGuiPollMessage"); 54 56 scriptInterface.RegisterFunction<void, std::wstring, &JSI_Lobby::LobbySendMessage>("LobbySendMessage"); … … 187 189 g_XmppClient->GUIGetPlayerList(*(pCxPrivate->pScriptInterface), &playerList); 188 190 189 191 return playerList; 190 192 } 191 193 194 void JSI_Lobby::LobbyClearPresenceUpdates(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) 195 { 196 if (!g_XmppClient) 197 return; 198 199 g_XmppClient->ClearPresenceUpdates(); 200 } 201 202 int JSI_Lobby::LobbyGetMucMessageCount(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) 203 { 204 return g_XmppClient ? g_XmppClient->GetMucMessageCount() : 0; 205 } 206 192 207 JS::Value JSI_Lobby::GetGameList(ScriptInterface::CxPrivate* pCxPrivate) 193 208 { 194 209 if (!g_XmppClient) 195 210 return JS::UndefinedValue(); 196 211 -
source/lobby/scripting/JSInterface_Lobby.h
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 47 JS::Value GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate); 48 void LobbyClearPresenceUpdates(ScriptInterface::CxPrivate* pCxPrivate); 49 int LobbyGetMucMessageCount(ScriptInterface::CxPrivate* pCxPrivate); 48 50 JS::Value GetGameList(ScriptInterface::CxPrivate* pCxPrivate); 49 51 JS::Value GetBoardList(ScriptInterface::CxPrivate* pCxPrivate); 50 52 JS::Value GetProfile(ScriptInterface::CxPrivate* pCxPrivate); 51 53 JS::Value LobbyGuiPollMessage(ScriptInterface::CxPrivate* pCxPrivate); 52 54 void LobbySendMessage(ScriptInterface::CxPrivate* pCxPrivate, std::wstring message);