Displays ratings in the userlist. Fixes #2371.
This was SVN commit r14650.
This commit is contained in:
parent
d82282e358
commit
e5e634f768
@ -36,6 +36,7 @@ function init(attribs)
|
||||
Engine.LobbySetPlayerPresence("available");
|
||||
Engine.SendGetGameList();
|
||||
Engine.SendGetBoardList();
|
||||
Engine.SendGetRatingList();
|
||||
updatePlayerList();
|
||||
|
||||
resetFilters();
|
||||
@ -105,24 +106,37 @@ function displayGame(g, mapSizeFilter, playersNumberFilter, mapTypeFilter, showF
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do a full update of the player listing **Only call on init**
|
||||
// Do a full update of the player listing, including ratings.
|
||||
function updatePlayerList()
|
||||
{
|
||||
var playersBox = Engine.GetGUIObjectByName("playersBox");
|
||||
[playerList, presenceList, nickList] = [[],[],[]];
|
||||
[playerList, presenceList, nickList, ratingList] = [[],[],[],[]];
|
||||
var ratingsmap = Engine.GetRatingList();
|
||||
var defaultrating;
|
||||
for each (var p in Engine.GetPlayerList())
|
||||
{
|
||||
var [name, status] = formatPlayerListEntry(p.name, p.presence);
|
||||
defaultrating = ' -'; //Start with unrated. If no rating is found, keep it unrated.
|
||||
for each (var user in ratingsmap)
|
||||
{
|
||||
if (user.name.toLowerCase() == p.name.toLowerCase())
|
||||
{
|
||||
defaultrating = user.rating;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var [name, status, rating] = formatPlayerListEntry(p.name, p.presence, defaultrating);
|
||||
playerList.push(name);
|
||||
presenceList.push(status);
|
||||
nickList.push(p.name);
|
||||
ratingList.push(String(" " + rating));
|
||||
}
|
||||
playersBox.list_name = playerList;
|
||||
playersBox.list_status = presenceList;
|
||||
playersBox.list = nickList;
|
||||
playersBox.list_rating = ratingList;
|
||||
playersBox.list = nickList;
|
||||
if (playersBox.selected >= playersBox.list.length)
|
||||
playersBox.selected = -1;
|
||||
return [playerList, presenceList, nickList];
|
||||
return [playerList, presenceList, nickList, ratingList];
|
||||
}
|
||||
|
||||
// Update leaderboard listing
|
||||
@ -229,40 +243,41 @@ function updateGameList()
|
||||
}
|
||||
|
||||
// The following function colorizes and formats the entries in the player list.
|
||||
function formatPlayerListEntry(nickname, presence)
|
||||
function formatPlayerListEntry(nickname, presence, rating)
|
||||
{
|
||||
// Set colors based on player status
|
||||
var color;
|
||||
var color_close = '[/color]';
|
||||
switch (presence)
|
||||
{
|
||||
case "playing":
|
||||
var color = '[color="125 0 0"]';
|
||||
color = '[color="125 0 0"]';
|
||||
var status = color + "Busy" + color_close;
|
||||
break;
|
||||
case "gone":
|
||||
case "away":
|
||||
var color = '[color="229 76 13"]';
|
||||
color = '[color="229 76 13"]';
|
||||
var status = color + "Away" + color_close;
|
||||
break;
|
||||
case "available":
|
||||
var color = '[color="0 125 0"]';
|
||||
color = '[color="0 125 0"]';
|
||||
var status = color + "Online" + color_close;
|
||||
break;
|
||||
case "offline":
|
||||
var color = '[color="0 0 0"]';
|
||||
color = '[color="0 0 0"]';
|
||||
var status = color + "Offline" + color_close;
|
||||
break;
|
||||
default:
|
||||
warn("Unknown presence '"+presence+"'");
|
||||
var color = '[color="178 178 178"]';
|
||||
color = '[color="178 178 178"]';
|
||||
var status = color + "Unknown" + color_close;
|
||||
break;
|
||||
}
|
||||
|
||||
var elo = color + rating + color_close;
|
||||
var name = colorPlayerName(nickname);
|
||||
|
||||
// Push this player's name and status onto the list
|
||||
return [name, status];
|
||||
return [name, status, elo];
|
||||
}
|
||||
|
||||
function selectGame(selected)
|
||||
@ -349,6 +364,11 @@ function twoDigits(n)
|
||||
return n < 10 ? "0" + n : n;
|
||||
}
|
||||
|
||||
function stripColorCodes(input)
|
||||
{
|
||||
return input.replace(/\[(\w+)[^w]*?](.*?)\[\/\1]/g, '$2');
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GUI event handlers
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -384,6 +404,7 @@ function onTick()
|
||||
var playerList = playersBox.list_name;
|
||||
var presenceList = playersBox.list_status;
|
||||
var nickList = playersBox.list;
|
||||
var ratingList = playersBox.list_rating;
|
||||
var nickIndex = nickList.indexOf(nick);
|
||||
switch(message.level)
|
||||
{
|
||||
@ -391,13 +412,15 @@ function onTick()
|
||||
if (nick == g_Name)
|
||||
{
|
||||
// We just joined, we need to get the full player list
|
||||
[playerList, presenceList, nickList] = updatePlayerList();
|
||||
[playerList, presenceList, nickList, ratingList] = updatePlayerList();
|
||||
break;
|
||||
}
|
||||
var [name, status] = formatPlayerListEntry(nick, presence);
|
||||
var [name, status, rating] = formatPlayerListEntry(nick, presence, " -");
|
||||
playerList.push(name);
|
||||
presenceList.push(status);
|
||||
nickList.push(nick);
|
||||
ratingList.push(String(rating));
|
||||
Engine.SendGetRatingList();
|
||||
addChatMessage({ "text": "/special " + nick + " has joined.", "key": g_specialKey });
|
||||
break;
|
||||
case "leave":
|
||||
@ -406,6 +429,7 @@ function onTick()
|
||||
playerList.splice(nickIndex, 1);
|
||||
presenceList.splice(nickIndex, 1);
|
||||
nickList.splice(nickIndex, 1);
|
||||
ratingList.splice(nickIndex, 1);
|
||||
addChatMessage({ "text": "/special " + nick + " has left.", "key": g_specialKey });
|
||||
break;
|
||||
case "nick":
|
||||
@ -416,18 +440,20 @@ function onTick()
|
||||
addChatMessage({ "from": "system", "text": "Invalid nickname: " + message.data });
|
||||
break;
|
||||
}
|
||||
var [name, status] = formatPlayerListEntry(message.data, presence); // TODO: actually we don't want to change the presence here, so use what was used before
|
||||
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 before
|
||||
playerList[nickIndex] = name;
|
||||
// presence stays the same
|
||||
nickList[nickIndex] = message.data;
|
||||
addChatMessage({ "text": "/special " + nick + " is now known as " + message.data + ".", "key": g_specialKey });
|
||||
Engine.SendGetRatingList();
|
||||
break;
|
||||
case "presence":
|
||||
if (nickIndex == -1) // This shouldn't ever happen
|
||||
break;
|
||||
var [name, status] = formatPlayerListEntry(nick, presence);
|
||||
var [name, status, rating] = formatPlayerListEntry(nick, presence, stripColorCodes(ratingList[nickIndex]));
|
||||
presenceList[nickIndex] = status;
|
||||
playerList[nickIndex] = name;
|
||||
ratingList[nickIndex] = rating;
|
||||
break;
|
||||
default:
|
||||
warn("Unknown message.level '" + message.level + "'");
|
||||
@ -436,7 +462,8 @@ function onTick()
|
||||
// Push new data to GUI
|
||||
playersBox.list_name = playerList;
|
||||
playersBox.list_status = presenceList;
|
||||
playersBox.list = nickList;
|
||||
playersBox.list_rating = ratingList;
|
||||
playersBox.list = nickList;
|
||||
if (playersBox.selected >= playersBox.list.length)
|
||||
playersBox.selected = -1;
|
||||
break;
|
||||
@ -471,6 +498,9 @@ function onTick()
|
||||
case "boardlist updated":
|
||||
updateBoardList();
|
||||
break;
|
||||
case "ratinglist updated":
|
||||
updatePlayerList();
|
||||
break;
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -542,14 +572,6 @@ function handleSpecialCommand(text)
|
||||
case "back":
|
||||
Engine.LobbySetPlayerPresence("available");
|
||||
break;
|
||||
case "nick":
|
||||
if (g_spammers[g_Name] != undefined)
|
||||
break;
|
||||
// Strip invalid characters.
|
||||
nick = sanitizePlayerName(nick, true, true);
|
||||
Engine.LobbySetNick(nick);
|
||||
g_Name = nick;
|
||||
break;
|
||||
case "kick": // TODO: Split reason from nick and pass it too, for now just support "/kick nick"
|
||||
// also allow quoting nicks (and/or prevent users from changing it here, but that doesn't help if the spammer uses a different client)
|
||||
Engine.LobbyKick(nick, "");
|
||||
|
@ -19,14 +19,15 @@
|
||||
</action>
|
||||
|
||||
<!-- Left panel: Player list. -->
|
||||
<object name="leftPanel" size="20 30 15% 100%-50">
|
||||
<object name="playersBox" style="ModernList" type="olist" size="0 0 100% 100%">
|
||||
<def id="status" heading="Status" width="40%"/>
|
||||
<def id="name" heading="Name" width="60%"/>
|
||||
<object name="leftPanel" size="20 30 20% 100%-50">
|
||||
<object name="playersBox" style="ModernList" type="olist" size="0 0 100% 100%" font="serif-bold-13">
|
||||
<def id="status" heading="Status" width="28%"/>
|
||||
<def id="name" heading="Name" width="47%"/>
|
||||
<def id="rating" heading="Rating" width="25%" />
|
||||
</object>
|
||||
</object>
|
||||
|
||||
<object name="leftButtonPanel" size="20 100%-45 15% 100%-20">
|
||||
<object name="leftButtonPanel" size="20 100%-45 20% 100%-20">
|
||||
<object type="button" style="StoneButton" size="0 0 100% 100%">
|
||||
Leaderboard
|
||||
<action on="Press">Engine.GetGUIObjectByName("leaderboard").hidden = false;Engine.GetGUIObjectByName("leaderboardFade").hidden = false;</action>
|
||||
@ -34,7 +35,7 @@
|
||||
</object>
|
||||
|
||||
<!-- Right panel: Game details. -->
|
||||
<object name="rightPanel" size="100%-300 30 100%-20 100%-20">
|
||||
<object name="rightPanel" size="100%-250 30 100%-20 100%-20" >
|
||||
<object name="gameInfoEmpty" size="0 0 100% 100%-60" type="image" sprite="ModernDarkBoxGold" hidden="false">
|
||||
<object size="50%-110 50%-50 50%+110 50%+50" type="image" sprite="productLogo"/>
|
||||
</object>
|
||||
@ -106,7 +107,7 @@
|
||||
</object>
|
||||
|
||||
<!-- Middle panel: Filters, game list, chat box. -->
|
||||
<object name="middlePanel" size="15%+5 5% 100%-305 97.2%">
|
||||
<object name="middlePanel" size="20%+5 5% 100%-255 97.2%">
|
||||
<object name="gamesBox" style="ModernList" type="olist" size="0 25 100% 48%">
|
||||
<action on="SelectionChange">selectGame(this.selected);</action>
|
||||
<def id="name" heading="Name" color="0 60 0" width="25%"/>
|
||||
@ -121,21 +122,24 @@
|
||||
<object name="mapSizeFilter"
|
||||
type="dropdown"
|
||||
style="ModernDropDown"
|
||||
size="49.7% 0 62% 100%">
|
||||
size="49.7% 0 62% 100%"
|
||||
font="serif-bold-13">
|
||||
<action on="SelectionChange">applyFilters();</action>
|
||||
</object>
|
||||
|
||||
<object name="mapTypeFilter"
|
||||
type="dropdown"
|
||||
style="ModernDropDown"
|
||||
size="69.3% 0 82% 100%">
|
||||
size="69.3% 0 82% 100%"
|
||||
font="serif-bold-13">
|
||||
<action on="SelectionChange">applyFilters();</action>
|
||||
</object>
|
||||
|
||||
<object name="playersNumberFilter"
|
||||
type="dropdown"
|
||||
style="ModernDropDown"
|
||||
size="89% 0 100% 100%">
|
||||
size="89% 0 100% 100%"
|
||||
font="serif-bold-13">
|
||||
<action on="SelectionChange">applyFilters();</action>
|
||||
</object>
|
||||
|
||||
@ -144,14 +148,15 @@
|
||||
type="checkbox"
|
||||
checked="true"
|
||||
style="ModernTickBox"
|
||||
size="0% 0 20 100%">
|
||||
size="0% 0 20 100%"
|
||||
font="serif-bold-13">
|
||||
<action on="Press">applyFilters();</action>
|
||||
</object>
|
||||
</object>
|
||||
|
||||
<object name="chatPanel" size="0 49% 100% 100%" type="image" sprite="ModernDarkBoxGold">
|
||||
<object name="chatText" size="0 0 100% 94%" type="text" style="ChatPanel"/>
|
||||
<object name="chatInput" size="0 94% 100% 100%" type="input" style="ModernInput">
|
||||
<object name="chatText" size="0 0 100% 94%" type="text" style="ChatPanel" font="serif-13"/>
|
||||
<object name="chatInput" size="0 94% 100% 100%" type="input" style="ModernInput" font="serif-13">
|
||||
<action on="Press">submitChatInput();</action>
|
||||
<action on="Tab">completeNick();</action>
|
||||
</object>
|
||||
|
@ -897,6 +897,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
|
||||
scriptInterface.RegisterFunction<void, &JSI_Lobby::RecvXmppClient>("RecvXmppClient");
|
||||
scriptInterface.RegisterFunction<void, &JSI_Lobby::SendGetGameList>("SendGetGameList");
|
||||
scriptInterface.RegisterFunction<void, &JSI_Lobby::SendGetBoardList>("SendGetBoardList");
|
||||
scriptInterface.RegisterFunction<void, &JSI_Lobby::SendGetRatingList>("SendGetRatingList");
|
||||
scriptInterface.RegisterFunction<void, CScriptVal, &JSI_Lobby::SendRegisterGame>("SendRegisterGame");
|
||||
scriptInterface.RegisterFunction<void, CScriptVal, &JSI_Lobby::SendGameReport>("SendGameReport");
|
||||
scriptInterface.RegisterFunction<void, &JSI_Lobby::SendUnregisterGame>("SendUnregisterGame");
|
||||
@ -904,6 +905,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
|
||||
scriptInterface.RegisterFunction<CScriptVal, &JSI_Lobby::GetPlayerList>("GetPlayerList");
|
||||
scriptInterface.RegisterFunction<CScriptVal, &JSI_Lobby::GetGameList>("GetGameList");
|
||||
scriptInterface.RegisterFunction<CScriptVal, &JSI_Lobby::GetBoardList>("GetBoardList");
|
||||
scriptInterface.RegisterFunction<CScriptVal, &JSI_Lobby::GetBoardList>("GetRatingList");
|
||||
scriptInterface.RegisterFunction<CScriptVal, &JSI_Lobby::LobbyGuiPollMessage>("LobbyGuiPollMessage");
|
||||
scriptInterface.RegisterFunction<void, std::wstring, &JSI_Lobby::LobbySendMessage>("LobbySendMessage");
|
||||
scriptInterface.RegisterFunction<void, std::wstring, &JSI_Lobby::LobbySetPlayerPresence>("LobbySetPlayerPresence");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -33,6 +33,7 @@ public:
|
||||
virtual void recv() = 0;
|
||||
virtual void SendIqGetGameList() = 0;
|
||||
virtual void SendIqGetBoardList() = 0;
|
||||
virtual void SendIqGetRatingList() = 0;
|
||||
virtual void SendIqGameReport(ScriptInterface& scriptInterface, CScriptVal data) = 0;
|
||||
virtual void SendIqRegisterGame(ScriptInterface& scriptInterface, CScriptVal data) = 0;
|
||||
virtual void SendIqUnregisterGame() = 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -59,22 +59,30 @@ glooxwrapper::StanzaExtension* GameReport::clone() const
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* BoardListQuery, custom IQ Stanza, used solely to
|
||||
* request and receive leaderboard data from server.
|
||||
* BoardListQuery, a flexible custom IQ Stanza useful for anything with ratings, used to
|
||||
* request and receive leaderboard and rating data from server.
|
||||
* Example stanza:
|
||||
* <board player="foobar">1200</board>
|
||||
*/
|
||||
BoardListQuery::BoardListQuery( const glooxwrapper::Tag* tag ):StanzaExtension( ExtBoardListQuery )
|
||||
{
|
||||
if( !tag || tag->name() != "query" || tag->xmlns() != XMLNS_BOARDLIST )
|
||||
return;
|
||||
|
||||
|
||||
const glooxwrapper::Tag* c = tag->findTag_clone( "query/command" );
|
||||
if (c)
|
||||
m_Command = c->cdata();
|
||||
glooxwrapper::Tag::free(c);
|
||||
const glooxwrapper::ConstTagList boardTags = tag->findTagList_clone( "query/board" );
|
||||
glooxwrapper::ConstTagList::const_iterator it = boardTags.begin();
|
||||
for ( ; it != boardTags.end(); ++it )
|
||||
m_BoardList.push_back( *it );
|
||||
{
|
||||
m_StanzaBoardList.push_back( *it );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Required by gloox, used to find the BoardList element in a recived IQ.
|
||||
* Required by gloox, used to find the BoardList element in a received IQ.
|
||||
*/
|
||||
const glooxwrapper::string& BoardListQuery::filterString() const
|
||||
{
|
||||
@ -89,9 +97,13 @@ glooxwrapper::Tag* BoardListQuery::tag() const
|
||||
{
|
||||
glooxwrapper::Tag* t = glooxwrapper::Tag::allocate( "query" );
|
||||
t->setXmlns( XMLNS_BOARDLIST );
|
||||
|
||||
// Check for ratinglist or boardlist command
|
||||
if(!m_Command.empty())
|
||||
t->addChild(glooxwrapper::Tag::allocate("command", m_Command));
|
||||
|
||||
std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin();
|
||||
for( ; it != m_BoardList.end(); ++it )
|
||||
std::vector<const glooxwrapper::Tag*>::const_iterator it = m_StanzaBoardList.begin();
|
||||
for( ; it != m_StanzaBoardList.end(); ++it )
|
||||
t->addChild( (*it)->clone() );
|
||||
|
||||
return t;
|
||||
@ -105,10 +117,10 @@ glooxwrapper::StanzaExtension* BoardListQuery::clone() const
|
||||
|
||||
BoardListQuery::~BoardListQuery()
|
||||
{
|
||||
std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin();
|
||||
for( ; it != m_BoardList.end(); ++it )
|
||||
std::vector<const glooxwrapper::Tag*>::const_iterator it = m_StanzaBoardList.begin();
|
||||
for( ; it != m_StanzaBoardList.end(); ++it )
|
||||
glooxwrapper::Tag::free(*it);
|
||||
m_BoardList.clear();
|
||||
m_StanzaBoardList.clear();
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
@ -133,7 +145,7 @@ GameListQuery::GameListQuery( const glooxwrapper::Tag* tag ):StanzaExtension( Ex
|
||||
}
|
||||
|
||||
/**
|
||||
* Required by gloox, used to find the GameList element in a recived IQ.
|
||||
* Required by gloox, used to find the GameList element in a received IQ.
|
||||
*/
|
||||
const glooxwrapper::string& GameListQuery::filterString() const
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -27,7 +27,7 @@
|
||||
#define ExtBoardListQuery 1404
|
||||
#define XMLNS_BOARDLIST "jabber:iq:boardlist"
|
||||
|
||||
/// Global Boardlist Extension
|
||||
/// Global Gamereport Extension
|
||||
#define ExtGameReport 1405
|
||||
#define XMLNS_GAMEREPORT "jabber:iq:gamereport"
|
||||
|
||||
@ -84,6 +84,7 @@ public:
|
||||
|
||||
~BoardListQuery();
|
||||
|
||||
std::vector<const glooxwrapper::Tag*> m_BoardList;
|
||||
glooxwrapper::string m_Command;
|
||||
std::vector<const glooxwrapper::Tag*> m_StanzaBoardList;
|
||||
};
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -147,6 +147,8 @@ XmppClient::~XmppClient()
|
||||
glooxwrapper::Tag::free(*it);
|
||||
for (std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it)
|
||||
glooxwrapper::Tag::free(*it);
|
||||
for (std::vector<const glooxwrapper::Tag*>::const_iterator it = m_RatingList.begin(); it != m_RatingList.end(); ++it)
|
||||
glooxwrapper::Tag::free(*it);
|
||||
}
|
||||
|
||||
/// Network
|
||||
@ -208,6 +210,7 @@ void XmppClient::onDisconnect(gloox::ConnectionError error)
|
||||
for (std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it)
|
||||
glooxwrapper::Tag::free(*it);
|
||||
m_BoardList.clear();
|
||||
m_RatingList.clear();
|
||||
m_GameList.clear();
|
||||
m_PlayerMap.clear();
|
||||
|
||||
@ -270,12 +273,30 @@ void XmppClient::SendIqGetBoardList()
|
||||
glooxwrapper::JID xpartamuppJid(m_xpartamuppId);
|
||||
|
||||
// Send IQ
|
||||
BoardListQuery* b = new BoardListQuery();
|
||||
b->m_Command = "getleaderboard";
|
||||
glooxwrapper::IQ iq(gloox::IQ::Get, xpartamuppJid);
|
||||
iq.addExtension(new BoardListQuery());
|
||||
iq.addExtension(b);
|
||||
DbgXMPP("SendIqGetBoardList [" << tag_xml(iq) << "]");
|
||||
m_client->send(iq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the rating data from the server.
|
||||
*/
|
||||
void XmppClient::SendIqGetRatingList()
|
||||
{
|
||||
glooxwrapper::JID xpartamuppJid(m_xpartamuppId);
|
||||
|
||||
// Send IQ
|
||||
BoardListQuery* b = new BoardListQuery();
|
||||
b->m_Command = "getratinglist";
|
||||
glooxwrapper::IQ iq(gloox::IQ::Get, xpartamuppJid);
|
||||
iq.addExtension(b);
|
||||
DbgXMPP("SendIqGetRatingList [" << tag_xml(iq) << "]");
|
||||
m_client->send(iq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send game report containing numerous game properties to the server.
|
||||
*
|
||||
@ -523,6 +544,31 @@ CScriptValRooted XmppClient::GUIGetBoardList(ScriptInterface& scriptInterface)
|
||||
return boardList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle requests from the GUI for rating list data.
|
||||
*
|
||||
* @return A JS array containing all known leaderboard data
|
||||
*/
|
||||
CScriptValRooted XmppClient::GUIGetRatingList(ScriptInterface& scriptInterface)
|
||||
{
|
||||
CScriptValRooted ratingList;
|
||||
scriptInterface.Eval("([])", ratingList);
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_RatingList.begin(); it != m_RatingList.end(); ++it)
|
||||
{
|
||||
CScriptValRooted rating;
|
||||
scriptInterface.Eval("({})", rating);
|
||||
|
||||
const char* attributes[] = { "name", "rank", "rating" };
|
||||
short attributes_length = 3;
|
||||
for (short i = 0; i < attributes_length; i++)
|
||||
scriptInterface.SetProperty(rating.get(), attributes[i], wstring_from_utf8((*it)->findAttribute(attributes[i]).to_string()));
|
||||
|
||||
scriptInterface.CallFunctionVoid(ratingList.get(), "push", rating);
|
||||
}
|
||||
|
||||
return ratingList;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Message interfaces *
|
||||
*****************************************************/
|
||||
@ -625,14 +671,28 @@ bool XmppClient::handleIq(const glooxwrapper::IQ& iq)
|
||||
}
|
||||
if(bq)
|
||||
{
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it )
|
||||
glooxwrapper::Tag::free(*it);
|
||||
m_BoardList.clear();
|
||||
if (bq->m_Command == "boardlist")
|
||||
{
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_BoardList.begin(); it != m_BoardList.end(); ++it )
|
||||
glooxwrapper::Tag::free(*it);
|
||||
m_BoardList.clear();
|
||||
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = bq->m_BoardList.begin(); it != bq->m_BoardList.end(); ++it)
|
||||
m_BoardList.push_back( (*it)->clone() );
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = bq->m_StanzaBoardList.begin(); it != bq->m_StanzaBoardList.end(); ++it)
|
||||
m_BoardList.push_back( (*it)->clone() );
|
||||
|
||||
CreateSimpleMessage("system", "boardlist updated", "internal");
|
||||
CreateSimpleMessage("system", "boardlist updated", "internal");
|
||||
}
|
||||
else if (bq->m_Command == "ratinglist")
|
||||
{
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = m_RatingList.begin(); it != m_RatingList.end(); ++it )
|
||||
glooxwrapper::Tag::free(*it);
|
||||
m_RatingList.clear();
|
||||
|
||||
for(std::vector<const glooxwrapper::Tag*>::const_iterator it = bq->m_StanzaBoardList.begin(); it != bq->m_StanzaBoardList.end(); ++it)
|
||||
m_RatingList.push_back( (*it)->clone() );
|
||||
|
||||
CreateSimpleMessage("system", "ratinglist updated", "internal");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(iq.subtype() == gloox::IQ::Error)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -60,6 +60,7 @@ public:
|
||||
void recv();
|
||||
void SendIqGetGameList();
|
||||
void SendIqGetBoardList();
|
||||
void SendIqGetRatingList();
|
||||
void SendIqGameReport(ScriptInterface& scriptInterface, CScriptVal data);
|
||||
void SendIqRegisterGame(ScriptInterface& scriptInterface, CScriptVal data);
|
||||
void SendIqUnregisterGame();
|
||||
@ -74,7 +75,7 @@ public:
|
||||
CScriptValRooted GUIGetPlayerList(ScriptInterface& scriptInterface);
|
||||
CScriptValRooted GUIGetGameList(ScriptInterface& scriptInterface);
|
||||
CScriptValRooted GUIGetBoardList(ScriptInterface& scriptInterface);
|
||||
|
||||
CScriptValRooted GUIGetRatingList(ScriptInterface& scriptInterface);
|
||||
//Script
|
||||
ScriptInterface& GetScriptInterface();
|
||||
|
||||
@ -140,6 +141,8 @@ private:
|
||||
std::vector<const glooxwrapper::Tag*> m_GameList;
|
||||
/// List of rankings
|
||||
std::vector<const glooxwrapper::Tag*> m_BoardList;
|
||||
/// List of ratings
|
||||
std::vector<const glooxwrapper::Tag*> m_RatingList;
|
||||
/// Queue of messages
|
||||
std::deque<GUIMessage> m_GuiMessageQueue;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
@ -91,6 +91,13 @@ void JSI_Lobby::SendGetBoardList(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
|
||||
g_XmppClient->SendIqGetBoardList();
|
||||
}
|
||||
|
||||
void JSI_Lobby::SendGetRatingList(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
|
||||
{
|
||||
if (!g_XmppClient)
|
||||
return;
|
||||
g_XmppClient->SendIqGetRatingList();
|
||||
}
|
||||
|
||||
void JSI_Lobby::SendGameReport(ScriptInterface::CxPrivate* pCxPrivate, CScriptVal data)
|
||||
{
|
||||
if (!g_XmppClient)
|
||||
|
@ -35,6 +35,7 @@ namespace JSI_Lobby
|
||||
void RecvXmppClient(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
void SendGetGameList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
void SendGetBoardList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
void SendGetRatingList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
void SendGameReport(ScriptInterface::CxPrivate* pCxPrivate, CScriptVal data);
|
||||
void SendRegisterGame(ScriptInterface::CxPrivate* pCxPrivate, CScriptVal data);
|
||||
void SendUnregisterGame(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
@ -42,6 +43,7 @@ namespace JSI_Lobby
|
||||
CScriptVal GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
CScriptVal GetGameList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
CScriptVal GetBoardList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
CScriptVal GetRatingList(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
CScriptVal LobbyGuiPollMessage(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
void LobbySendMessage(ScriptInterface::CxPrivate* pCxPrivate, std::wstring message);
|
||||
void LobbySetPlayerPresence(ScriptInterface::CxPrivate* pCxPrivate, std::wstring presence);
|
||||
@ -62,4 +64,4 @@ namespace JSI_Lobby
|
||||
#endif // CONFIG2_LOBBY
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Copyright (C) 2013 Wildfire Games.
|
||||
"""Copyright (C) 2014 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -183,6 +183,24 @@ class LeaderboardList():
|
||||
continue
|
||||
board[player.jid] = {'name': '@'.join(player.jid.split('@')[:-1]), 'rating': str(player.rating)}
|
||||
return board
|
||||
def getRatingList(self, nicks):
|
||||
"""
|
||||
Returns a rating list of players
|
||||
currently in the lobby by nick
|
||||
because the client can't link
|
||||
JID to nick conveniently.
|
||||
"""
|
||||
ratinglist = {}
|
||||
for JID in nicks.keys():
|
||||
players = db.query(Player).filter_by(jid=str(JID))
|
||||
if players.first():
|
||||
if players.first().rating == -1:
|
||||
ratinglist[nicks[JID]] = {'name': nicks[JID], 'rating': ''}
|
||||
else:
|
||||
ratinglist[nicks[JID]] = {'name': nicks[JID], 'rating': str(players.first().rating)}
|
||||
else:
|
||||
ratinglist[nicks[JID]] = {'name': nicks[JID], 'rating': ''}
|
||||
return ratinglist
|
||||
|
||||
## Class to tracks all games in the lobby ##
|
||||
class GameList():
|
||||
@ -342,14 +360,16 @@ class GameListXmppPlugin(ElementBase):
|
||||
data[key] = item
|
||||
return data
|
||||
|
||||
## Class for custom boardlist stanza extension ##
|
||||
## Class for custom boardlist and ratinglist stanza extension ##
|
||||
class BoardListXmppPlugin(ElementBase):
|
||||
name = 'query'
|
||||
namespace = 'jabber:iq:boardlist'
|
||||
interfaces = ('board')
|
||||
interfaces = set(('board', 'command'))
|
||||
sub_interfaces = interfaces
|
||||
plugin_attrib = 'boardlist'
|
||||
|
||||
def addCommand(self, command):
|
||||
commandXml = ET.fromstring("<command>%s</command>" % command)
|
||||
self.xml.append(commandXml)
|
||||
def addItem(self, name, rating):
|
||||
itemXml = ET.Element("board", {"name": name, "rating": rating})
|
||||
self.xml.append(itemXml)
|
||||
@ -488,11 +508,22 @@ class XpartaMuPP(sleekxmpp.ClientXMPP):
|
||||
traceback.print_exc()
|
||||
logging.error("Failed to process gamelist request from %s" % iq['from'].bare)
|
||||
elif 'boardlist' in iq.plugins:
|
||||
try:
|
||||
self.leaderboard.getOrCreatePlayer(iq['from'])
|
||||
self.sendBoardList(iq['from'])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
command = iq['boardlist']['command']
|
||||
if command == 'getleaderboard':
|
||||
try:
|
||||
self.leaderboard.getOrCreatePlayer(iq['from'])
|
||||
self.sendBoardList(iq['from'])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error("Failed to process leaderboardlist request from %s" % iq['from'].bare)
|
||||
elif command == 'getratinglist':
|
||||
try:
|
||||
self.leaderboard.getOrCreatePlayer(iq['from'])
|
||||
self.sendRatingList(iq['from'])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error("Failed to process ratinglist request from %s" % iq['from'].bare)
|
||||
else:
|
||||
logging.error("Failed to process boardlist request from %s" % iq['from'].bare)
|
||||
else:
|
||||
logging.error("Unknown 'get' type stanza request from %s" % iq['from'].bare)
|
||||
@ -543,7 +574,8 @@ class XpartaMuPP(sleekxmpp.ClientXMPP):
|
||||
if self.leaderboard.getLastRatedMessage() != "":
|
||||
self.send_message(mto=self.room, mbody=self.leaderboard.getLastRatedMessage(), mtype="groupchat",
|
||||
mnick=self.nick)
|
||||
self.sendBoardList()
|
||||
self.sendBoardList()
|
||||
self.sendRatingList()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error("Failed to update game statistics for %s" % iq['from'].bare)
|
||||
@ -557,7 +589,7 @@ class XpartaMuPP(sleekxmpp.ClientXMPP):
|
||||
to all clients.
|
||||
"""
|
||||
games = self.gameList.getAllGames()
|
||||
if to == "":
|
||||
if to == "":
|
||||
for JID in self.nicks.keys():
|
||||
stz = GameListXmppPlugin()
|
||||
|
||||
@ -620,10 +652,11 @@ class XpartaMuPP(sleekxmpp.ClientXMPP):
|
||||
iq['type'] = 'result'
|
||||
for i in board:
|
||||
stz.addItem(board[i]['name'], board[i]['rating'])
|
||||
stz.addCommand('boardlist')
|
||||
iq.setPayload(stz)
|
||||
if to == "":
|
||||
for JID in self.nicks.keys():
|
||||
## Set aditional IQ attributes
|
||||
## Set additional IQ attributes
|
||||
iq['to'] = JID
|
||||
## Try sending the stanza
|
||||
try:
|
||||
@ -635,13 +668,50 @@ class XpartaMuPP(sleekxmpp.ClientXMPP):
|
||||
if str(to) not in self.nicks:
|
||||
logging.error("No player with the XmPP ID '%s' known to send boardlist to" % str(to))
|
||||
return
|
||||
## Set aditional IQ attributes
|
||||
## Set additional IQ attributes
|
||||
iq['to'] = to
|
||||
## Try sending the stanza
|
||||
try:
|
||||
iq.send(block=False, now=True)
|
||||
except:
|
||||
logging.error("Failed to send leaderboard list")
|
||||
|
||||
def sendRatingList(self, to = ""):
|
||||
"""
|
||||
Send the rating list.
|
||||
If no target is passed the rating list is broadcasted
|
||||
to all clients.
|
||||
"""
|
||||
## Pull rating list data and add it to the stanza
|
||||
ratinglist = self.leaderboard.getRatingList(self.nicks)
|
||||
stz = BoardListXmppPlugin()
|
||||
iq = self.Iq()
|
||||
iq['type'] = 'result'
|
||||
for i in ratinglist:
|
||||
stz.addItem(ratinglist[i]['name'], ratinglist[i]['rating'])
|
||||
stz.addCommand('ratinglist')
|
||||
iq.setPayload(stz)
|
||||
if to == "":
|
||||
for JID in self.nicks.keys():
|
||||
## Set additional IQ attributes
|
||||
iq['to'] = JID
|
||||
## Try sending the stanza
|
||||
try:
|
||||
iq.send(block=False, now=True)
|
||||
except:
|
||||
logging.error("Failed to send rating list")
|
||||
else:
|
||||
## Check recipient exists
|
||||
if str(to) not in self.nicks:
|
||||
logging.error("No player with the XmPP ID '%s' known to send ratinglist to" % str(to))
|
||||
return
|
||||
## Set additional IQ attributes
|
||||
iq['to'] = to
|
||||
## Try sending the stanza
|
||||
try:
|
||||
iq.send(block=False, now=True)
|
||||
except:
|
||||
logging.error("Failed to send rating list")
|
||||
|
||||
## Main Program ##
|
||||
if __name__ == '__main__':
|
||||
@ -680,7 +750,7 @@ if __name__ == '__main__':
|
||||
|
||||
# Setup logging.
|
||||
logging.basicConfig(level=opts.loglevel,
|
||||
format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%m-%d-%y %H:%M:%S')
|
||||
format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# XpartaMuPP
|
||||
xmpp = XpartaMuPP(opts.xlogin+'@'+opts.xdomain+'/CC', opts.xpassword, opts.xroom+'@conference.'+opts.xdomain, opts.xnickname)
|
||||
|
Loading…
Reference in New Issue
Block a user