Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg
+++ binaries/data/config/default.cfg
@@ -377,6 +377,9 @@
xpartamupp = "wfgbot22" ; Name of the server-side xmpp client that manage games
buddies = "," ; Comma separated list of playernames that the current user has marked as buddies
+[lobby.columns]
+gamerating = false ; Show the average rating of the participating players in a column of the gamelist
+
[mod]
enabledmods = "mod public"
Index: binaries/data/mods/public/gui/common/functions_utility.js
===================================================================
--- binaries/data/mods/public/gui/common/functions_utility.js
+++ binaries/data/mods/public/gui/common/functions_utility.js
@@ -158,15 +158,6 @@
return Engine.ConfigDB_GetValue("user", "playername.multiplayer") || Engine.GetSystemUsername();
}
-/**
- * Returns the nickname without the lobby rating.
- */
-function removeRatingFromNick(playerName)
-{
- let result = /^(\S+)\ \(\d+\)$/g.exec(playerName);
- return result ? result[1] : playerName;
-}
-
function tryAutoComplete(text, autoCompleteList)
{
if (!text.length)
Index: binaries/data/mods/public/gui/common/gamedescription.js
===================================================================
--- binaries/data/mods/public/gui/common/gamedescription.js
+++ binaries/data/mods/public/gui/common/gamedescription.js
@@ -4,11 +4,30 @@
var g_DescriptionHighlight = "orange";
/**
+ * The rating assigned to lobby players who didn't complete a ranked 1v1 yet.
+ */
+var g_DefaultLobbyRating = 1200;
+
+/**
* XEP-0172 doesn't restrict nicknames, but our lobby policy does.
* So use this human readable delimiter to separate buddy names in the config file.
*/
var g_BuddyListDelimiter = ",";
+
+/**
+ * Returns the nickname without the lobby rating.
+ */
+function splitRatingFromNick(playerName)
+{
+ let result = /^(\S+)\ \((\d+)\)$/g.exec(playerName);
+
+ if (!result)
+ return [playerName, g_DefaultLobbyRating];
+
+ return [result[1], +result[2]];
+}
+
/**
* Array of playernames that the current user has marked as buddies.
*/
@@ -140,7 +159,7 @@
(isAI ? "white" : getPlayerColor(playerData.Name)) :
rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color)) +
'"]' +
- (g_Buddies.indexOf(removeRatingFromNick(playerData.Name)) != -1 ? g_BuddySymbol + " " : "") +
+ (g_Buddies.indexOf(splitRatingFromNick(playerData.Name)[0]) != -1 ? g_BuddySymbol + " " : "") +
escapeText(playerData.Name) +
"[/color]",
Index: binaries/data/mods/public/gui/lobby/lobby.js
===================================================================
--- binaries/data/mods/public/gui/lobby/lobby.js
+++ binaries/data/mods/public/gui/lobby/lobby.js
@@ -360,10 +360,34 @@
Engine.LobbyClearPresenceUpdates();
updatePlayerList();
updateSubject(Engine.LobbyGetRoomSubject());
+ updateLobbyColumns();
Engine.GetGUIObjectByName("chatInput").tooltip = colorizeAutocompleteHotkey();
}
+function updateLobbyColumns()
+{
+ let gameRating = Engine.ConfigDB_GetValue("user", "lobby.columns.gamerating") == "true";
+
+ // Only show the selected columns
+ let gamesBox = Engine.GetGUIObjectByName("gamesBox");
+ gamesBox.hidden_mapType = gameRating;
+ gamesBox.hidden_gameRating = !gameRating;
+
+ // Only show the filters of selected columns
+ let mapTypeFilter = Engine.GetGUIObjectByName("mapTypeFilter");
+ mapTypeFilter.hidden = gameRating;
+ let gameRatingFilter = Engine.GetGUIObjectByName("gameRatingFilter");
+ gameRatingFilter.hidden = !gameRating;
+
+ // Keep filters right above the according column
+ let playersNumberFilter = Engine.GetGUIObjectByName("playersNumberFilter");
+ let size = playersNumberFilter.size;
+ size.rleft = gameRating ? 74: 90;
+ size.rright = gameRating ? 84: 100;
+ playersNumberFilter.size = size;
+}
+
function returnToMainMenu()
{
Engine.StopXmppClient();
@@ -385,6 +409,16 @@
mapTypeFilter.list = [translateWithContext("map", "Any")].concat(g_MapTypes.Title);
mapTypeFilter.list_data = [""].concat(g_MapTypes.Name);
+ let gameRatingOptions = ["<1000", "<1100","<1200",">1200",">1300",">1400",">1500"].reverse();
+ gameRatingOptions = prepareForDropdown(gameRatingOptions.map(r => ({
+ "value": r,
+ "label": sprintf(r[0] == ">" ? translate("> %(rating)s") : translate("< %(rating)s"), { "rating": r.substr(1) })
+ })))
+
+ let gameRatingFilter = Engine.GetGUIObjectByName("gameRatingFilter");
+ gameRatingFilter.list = [translateWithContext("map", "Any")].concat(gameRatingOptions.label);
+ gameRatingFilter.list_data = [""].concat(gameRatingOptions.value);
+
resetFilters();
}
@@ -393,6 +427,7 @@
Engine.GetGUIObjectByName("mapSizeFilter").selected = 0;
Engine.GetGUIObjectByName("playersNumberFilter").selected = 0;
Engine.GetGUIObjectByName("mapTypeFilter").selected = g_MapTypes.Default;
+ Engine.GetGUIObjectByName("gameRatingFilter").selected = 0;
Engine.GetGUIObjectByName("showFullFilter").checked = false;
applyFilters();
@@ -415,6 +450,7 @@
let mapSizeFilter = Engine.GetGUIObjectByName("mapSizeFilter");
let playersNumberFilter = Engine.GetGUIObjectByName("playersNumberFilter");
let mapTypeFilter = Engine.GetGUIObjectByName("mapTypeFilter");
+ let gameRatingFilter = Engine.GetGUIObjectByName("gameRatingFilter");
let showFullFilter = Engine.GetGUIObjectByName("showFullFilter");
// We assume index 0 means display all for any given filter.
@@ -433,6 +469,14 @@
if (!showFullFilter.checked && game.maxnbp <= game.nbp)
return true;
+ if (gameRatingFilter.selected > 0)
+ {
+ let selected = gameRatingFilter.list_data[gameRatingFilter.selected];
+ if (selected.startsWith(">") && +selected.substr(1) >= game.gameRating ||
+ selected.startsWith("<") && +selected.substr(1) <= game.gameRating)
+ return true;
+ }
+
return false;
}
@@ -630,7 +674,7 @@
for (let i = 0; i < g_GameList.length; ++i)
for (let player of stringifiedTeamListToPlayerData(g_GameList[i].players))
{
- let nick = removeRatingFromNick(player.Name);
+ let [nick, rating] = splitRatingFromNick(player.Name);
if (playerName != nick)
continue;
@@ -809,16 +853,30 @@
g_SelectedGamePort = g_GameList[gamesBox.selected].port;
}
- g_GameList = Engine.GetGameList().map(game => {
+ let testList = [{name:"Partida de pablek2",ip:"bla",port:"20595",state:"running",nbp:"2",maxnbp:"2",players:'{"0":\\[{"Name":"pablek2 (1269)","Team":0}],"1":\\[{"Name":"Raulyo (875)","Team":1}]}',mapName:"maps/random/marmara",niceMapName:"Marmara",mapSize:"320",mapType:"random",victoryCondition:"Conquista",startTime:"1487082783"},{name:"Reaperisonline's game",ip:"bla",port:"20595",state:"waiting",nbp:"5",maxnbp:"6",players:'{"0":\\[{"Name":"Reaperisonline (1259)","Team":0},{"Name":"Sh4d0w3rPL (1387)","Team":0}],"1":\\[{"Name":"jtggamer (1103)","Team":1},{"Name":"temik5 (1033)","Team":1},{"Name":"WGold (1180)","Team":1},{"Name":"siliboss (1143)","Team":1,"Offline":true,"State":"defeated"}]}',mapName:"maps/random/fortress",niceMapName:"Fortress",mapSize:"320",mapType:"random",victoryCondition:"Conquest",startTime:"1487081792"},{name:"siole's game",ip:"blabla",port:"20595",state:"running",nbp:"8",maxnbp:"8",players:'{"-1":\\[{"Name":"siole","Team":-1},{"Name":"Grugnas (1417)","Team":-1},{"Name":"merlin1 (1564)","Team":-1},{"Name":"snelius (1365)","Team":-1},{"Name":"imrobbyg (1622)","Team":-1},{"Name":"PrincipalityOfZeon (1652)","Team":-1},{"Name":"jaxtrx2 (1030)","Team":-1},{"Name":"nigel87 (1530)","Team":-1}],"observer":\\[{"Name":"fpre (1545)","Team":"observer"},{"Name":"Achelao (1418)","Team":"observer"},{"Name":"elexis3 (1156)","Team":"observer"}]}',mapName:"maps/random/survivalofthefittest",niceMapName:"Survival of the Fittest",mapSize:"384",mapType:"random",victoryCondition:"Regicide",startTime:"1486938980"},{name:"1v1",ip:"blabla",port:"20595",state:"running",nbp:"2",maxnbp:"2",players:'{"-1":\\[{"Name":"borg- (2114)","Team":-1},{"Name":"Feldfeld (1638)","Team":-1}]}',mapName:"maps/random/mainland",niceMapName:"Mainland",mapSize:"384",mapType:"random",victoryCondition:"Conquest",startTime:"1486532180"},{name:"Partida de JeanClaude",ip:"blabla",port:"20595",state:"running",nbp:"2",maxnbp:"2",players:'{"-1":\\[{"Name":"JeanClaude (1653)","Team":-1},{"Name":"Liberty (1569)","Team":-1}]}',mapName:"maps/random/mainland",niceMapName:"Mainland",mapSize:"384",mapType:"random",victoryCondition:"Conquest",startTime:"1486523148"},{name:"Komenoss spel",ip:"blabla",port:"20595",state:"running",nbp:"4",maxnbp:"4",players:'{"-1":\\[{"Name":"Komenos","Team":-1},{"Name":"Jordi_Iranzo93 (1278)","Team":-1},{"Name":"META-BARONS (1393)","Team":-1},{"Name":"King_Jerusalem (1265)","Team":-1}]}',mapName:"maps/random/bahrain",niceMapName:"Bahrain",mapSize:"384",mapType:"random",victoryCondition:"Erövring",startTime:"1487084910"},{name:"Partida de freedomm",ip:"blabla",port:"20595",state:"running",nbp:"2",maxnbp:"2",players:'{"0":\\[{"Name":"freedomm (1298)","Team":0}],"1":\\[{"Name":"bill13986 (1028)","Team":1}]}',mapName:"maps/skirmishes/Lorraine Plain (2)",niceMapName:"Lorraine Plain (2)",mapSize:"Default",mapType:"skirmish",victoryCondition:"Conquista",startTime:"1487085137"},{name:"Partida de comandantelobo",ip:"blabla",port:"20595",state:"running",nbp:"4",maxnbp:"4",players:'{"0":\\[{"Name":"comandantelobo (1047)","Team":0},{"Name":"perro (1153)","Team":0}],"1":\\[{"Name":"akshayhalasangi","Team":1},{"Name":"sckt (1263)","Team":1}]}',mapName:"maps/random/mainland",niceMapName:"Mainland",mapSize:"256",mapType:"random",victoryCondition:"Conquista",startTime:"1487083419"},{name:"Partie de mazert",ip:"blabla",port:"20595",state:"init",nbp:"4",maxnbp:"4",players:'{"-1":\\[{"Name":"mazert (1224)"},{"Name":"HirnWolf (1149)"},{"Name":"siliboss (1143)"},{"Name":"Ivaylo_Uzunov (1085)"}]}',mapName:"maps/random/frontier",niceMapName:"Frontier",mapSize:"256",mapType:"random",victoryCondition:"Conquête",startTime:""},{name:"mord's game",ip:"blabla",port:"20595",state:"running",nbp:"2",maxnbp:"2",players:'{"0":\\[{"Name":"mord (1165)","Team":0}],"1":\\[{"Name":"Chrisf1 (1222)","Team":1}]}',mapName:"maps/random/unknown",niceMapName:"Unknown",mapSize:"256",mapType:"random",victoryCondition:"Conquest",startTime:"1487082144"},{name:"craqqy's game",ip:"blabla",port:"20595",state:"running",nbp:"2",maxnbp:"2",players:'{"-1":\\[{"Name":"craqqy","Team":-1},{"Name":"KeaneY","Team":-1}]}',mapName:"maps/skirmishes/Acropolis Bay (2)",niceMapName:"Acropolis Bay (2)",mapSize:"Default",mapType:"skirmish",victoryCondition:"Conquest",startTime:"1487084573"},{name:"GummionkelchenIsBack's Spiel",ip:"blabla",port:"20595",state:"waiting",nbp:"5",maxnbp:"6",players:'{"0":\\[{"Name":"GummionkelchenIsBack (1396)","Team":0},{"Name":"Jordi_Iranzo93 (1278)","Team":0,"Offline":true},{"Name":"zDiegoAC","Team":0}],"1":\\[{"Name":"yashbanka123 (1141)","Team":1},{"Name":"TheRolle","Team":1},{"Name":"Rexosts (1342)","Team":1}]}',mapName:"maps/random/unknown_land",niceMapName:"Unknown Land",mapSize:"256",mapType:"random",victoryCondition:"Eroberung",startTime:"1487084209"},{name:"noobiel's game",ip:"blabla",port:"20595",state:"running",nbp:"1",maxnbp:"2",players:'{"-1":\\[{"Name":"noobiel","Team":-1},{"Name":"Ptolemy Epigone","Team":-1,"AI":"petra","AIDiff":3}]}',mapName:"maps/skirmishes/Greek Acropolis (2)",niceMapName:"Greek Acropolis (2)",mapSize:"Default",mapType:"skirmish",victoryCondition:"Conquest",startTime:"1486821890"}];
+ g_GameList = testList/*Engine.GetGameList()*/.map(game => {
+
game.hasBuddies = 0;
+
+ // Compute average rating of participating players
+ let playerRatings = [];
for (let player of stringifiedTeamListToPlayerData(game.players))
{
- let nick = removeRatingFromNick(player.Name);
+ let [nick, rating] = splitRatingFromNick(player.Name);
+
+ if (player.Team != "observer")
+ playerRatings.push(rating);
// Sort games with playing buddies above games with spectating buddies
if (game.hasBuddies < 2 && g_Buddies.indexOf(nick) != -1)
game.hasBuddies = player.Team == "observer" ? 1 : 2;
}
+
+ game.gameRating =
+ playerRatings.length ?
+ Math.round(playerRatings.reduce((sum, current) => sum + current) / playerRatings.length) :
+ g_DefaultLobbyRating;
+
return game;
}).filter(game => !filterGame(game)).sort((a, b) => {
let sortA, sortB;
@@ -827,6 +885,7 @@
case 'name':
case 'mapSize':
case 'mapType':
+ case 'gameRating':
sortA = a[sortBy];
sortB = b[sortBy];
break;
@@ -859,6 +918,7 @@
let list_mapSize = [];
let list_mapType = [];
let list_nPlayers = [];
+ let list_gameRating = [];
let list = [];
let list_data = [];
let selectedGameIndex = -1;
@@ -878,6 +938,7 @@
list_mapSize.push(translateMapSize(game.mapSize));
list_mapType.push(g_MapTypes.Title[mapTypeIdx] || "");
list_nPlayers.push(game.nbp + "/" + game.maxnbp);
+ list_gameRating.push(game.gameRating);
list.push(gameName);
list_data.push(i);
}
@@ -888,6 +949,8 @@
gamesBox.list_mapSize = list_mapSize;
gamesBox.list_mapType = list_mapType;
gamesBox.list_nPlayers = list_nPlayers;
+ gamesBox.list_gameRating = list_gameRating;
+
// Change these last, otherwise crash
gamesBox.list = list;
gamesBox.list_data = list_data;
Index: binaries/data/mods/public/gui/lobby/lobby.xml
===================================================================
--- binaries/data/mods/public/gui/lobby/lobby.xml
+++ binaries/data/mods/public/gui/lobby/lobby.xml
@@ -204,7 +204,7 @@
applyFilters();
joinButton();
-
+
Name
@@ -216,16 +216,20 @@
Type
-
+
Players
+
+ Rating
+
+
Index: binaries/data/mods/public/gui/options/options.json
===================================================================
--- binaries/data/mods/public/gui/options/options.json
+++ binaries/data/mods/public/gui/options/options.json
@@ -269,6 +269,12 @@
"label": "Chat Backlog",
"tooltip": "Number of backlogged messages to load when joining the lobby",
"parameters": { "config": "lobby.history", "min": "0" }
+ },
+ {
+ "type": "boolean",
+ "label": "Game Rating Column",
+ "tooltip": "Show the average rating of the participating players in a column of the gamelist.",
+ "parameters": { "config": "lobby.columns.gamerating" }
}
],
"notificationSetting":