Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -399,6 +399,14 @@ xpartamupp = "wfgbot23" ; 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.players] +sortBy = "buddy,status,name" ; Comma separated list of columns sort ordering of players +sortOrder = "ascending" + +[lobby.games] +sortBy = "buddy,name" ; Comma separated list of columns sort ordering of games +sortOrder = "ascending" + [lobby.columns] gamerating = false ; Show the average rating of the participating players in a column of the gamelist 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 @@ -8,6 +8,14 @@ }; /** + * Use this human readable delimiter to separate array values, that are concatenated to a string + * into a user config setting in the user config file. + * This works also for nicknames in the lobby to our lobby policy. + */ +var g_ConfigListDelimiter = ","; + + +/** * Returns translated history and gameplay data of all civs, optionally including a mock gaia civ. */ function loadCivData(selectableOnly, gaia) 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 @@ -8,12 +8,6 @@ */ 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. @@ -27,7 +21,7 @@ /** * Array of playernames that the current user has marked as buddies. */ -var g_Buddies = Engine.ConfigDB_GetValue("user", "lobby.buddies").split(g_BuddyListDelimiter); +var g_Buddies = Engine.ConfigDB_GetValue("user", "lobby.buddies").split(g_ConfigListDelimiter); /** * Denotes which players are a lobby buddy of the current user. 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 @@ -106,11 +106,26 @@ var g_SelectedGamePort = ""; /** + * Gives the order for the sort of the columns in the playerlist. + */ +let g_PlayerListColumnsSort = []; + +/** + * Gives the order for the sort of the columns in the gamelist. + */ +let g_GameListColumnsSort = []; + +/** * Whether the current user has been kicked or banned. */ var g_Kicked = false; /** + * Locale language used for string comparisons. + */ +var g_Locale = ""; + +/** * Processing of notifications sent by XmppClient.cpp. * * @returns true if the playerlist GUI must be updated. @@ -385,6 +400,9 @@ initMusic(); global.music.setState(global.music.states.MENU); + g_Locale = Engine.ConfigDB_GetValue("user", "locale").replace("_", "-") || "en-GB"; + + initListsSort(); initGameFilters(); Engine.LobbySetPlayerPresence("available"); @@ -403,6 +421,38 @@ g_NetMessageTypes[msg.type][msg.level](msg); } +function initListsSort() +{ + g_PlayerListColumnsSort = Engine.ConfigDB_GetValue("user", "lobby.players.sortBy").split(g_ConfigListDelimiter); + g_GameListColumnsSort = Engine.ConfigDB_GetValue("user", "lobby.games.sortBy").split(g_ConfigListDelimiter); + + let lists = [ { + "name": "players", + "columnSort": g_PlayerListColumnsSort, + "onSelectionColumnChange": guiObj => { + updateListSortConfig("players", g_PlayerListColumnsSort, guiObj.selected_column, guiObj.selected_column_order); + updatePlayerList(); + } + }, { + "name": "games", + "columnSort": g_GameListColumnsSort, + "onSelectionColumnChange": guiObj => { + updateListSortConfig("games", g_GameListColumnsSort, guiObj.selected_column, guiObj.selected_column_order); + applyFilters(); + } + } ]; + + for (let i in lists) + { + let list = lists[i]; + let guiObj = Engine.GetGUIObjectByName(list.name + "Box"); + guiObj.selected_column = list.columnSort[0] || "buddy"; + guiObj.selected_column_order = Engine.ConfigDB_GetValue("user", "lobby." + list.name + ".sortOrder") == "ascending" ? 1 : -1; + guiObj.sortable = "true"; + guiObj.onSelectionColumnChange = (guiObj => function() { list.onSelectionColumnChange(guiObj); })(guiObj); + }; +} + function updateLobbyColumns() { let gameRating = Engine.ConfigDB_GetValue("user", "lobby.columns.gamerating") == "true"; @@ -597,13 +647,25 @@ } /** + * Create sortString based on attributesOrder for string comparison sort. + * + * @param {*} object - Object to add sortString + * @param {list} attributesOrder - List with the order of attributes + * @param {object} compareStringFunctions - Contains the string builder function for the attributes + */ +function createSortString(object, attributesOrder, compareStringFunctions) +{ + object.sortString = ""; + attributesOrder.forEach(attribute => object.sortString += compareStringFunctions[attribute](object)); +} + +/** * Do a full update of the player listing, including ratings from cached C++ information. */ function updatePlayerList() { let playersBox = Engine.GetGUIObjectByName("playersBox"); - let sortBy = playersBox.selected_column || "name"; - let sortOrder = playersBox.selected_column_order || 1; + let sortOrder = playersBox.selected_column_order; let buddyStatusList = []; let playerList = []; @@ -611,39 +673,28 @@ let nickList = []; let ratingList = []; - let cleanPlayerList = Engine.GetPlayerList().map(player => { + let attributesCompareStringFuncs = { + "buddy": + player => player.name.toLowerCase() == g_Username.toLowerCase() ? 1 : player.isBuddy ? 2 : 3, + "rating": + // Turn around sort order for ratings, as higher numbers are more important to us than lower. + // Do this by deviding 1 / number, so higher numbers become smaller. + // As in this devision integer numbers < 10000 always changes at the 7th digit, take this as least comparing digit. + player => (player.rating ? 1 / player.rating : 1.0).toFixed(7), + "status": + player => Object.keys(g_PlayerStatuses).indexOf(player.presence), + "name": + player => player.name.toLowerCase(), + }; + + let cleanPlayerList = [{name:"fpre", presence:"available", rating:"1700", role:"participant", isBuddy:false}, {name:"nigel87", presence:"available", rating:"1560", role:"participant", isBuddy:true}, {name:"phoenixdesk", presence:"available", rating:"1229", role:"participant", isBuddy:true}, {name:"Achelao", presence:"playing", rating:"1547", role:"participant", isBuddy:true}, {name:"borg-", presence:"playing", rating:"2159", role:"participant", isBuddy:true}, {name:"chrstgtr", presence:"playing", rating:"1641", role:"participant", isBuddy:true}, {name:"elexis", presence:"playing", rating:"", role:"moderator", isBuddy:true}, {name:"iApprove", presence:"playing", rating:"1464", role:"participant", isBuddy:true}, {name:"LeGenDz", presence:"playing", rating:"1471", role:"participant", isBuddy:true}, {name:"Pretension", presence:"playing", rating:"", role:"participant", isBuddy:true}, {name:"user1", presence:"playing", rating:"", role:"moderator", isBuddy:true}, {name:"fsvn", presence:"available", rating:"1175", role:"participant", isBuddy:false}, {name:"GoodBay", presence:"available", rating:"1135", role:"participant", isBuddy:false}, {name:"MadMeatBallMan", presence:"available", rating:"", role:"participant", isBuddy:false}, {name:"Ratings", presence:"available", rating:"", role:"moderator", isBuddy:false}, {name:"roxanne", presence:"available", rating:"909", role:"participant", isBuddy:false}, {name:"WFGbot", presence:"available", rating:"", role:"moderator", isBuddy:false}, {name:"ahmedteling", presence:"playing", rating:"1030", role:"participant", isBuddy:false}, {name:"Andresfcb2003", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"Bolvar", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"CaptIsler", presence:"playing", rating:"1100", role:"participant", isBuddy:false}, {name:"cleuberjs", presence:"playing", rating:"1064", role:"participant", isBuddy:false}, {name:"Crowley", presence:"playing", rating:"1135", role:"participant", isBuddy:false}, {name:"Emilio2006", presence:"playing", rating:"1089", role:"participant", isBuddy:false}, {name:"Ferhat_C", presence:"playing", rating:"961", role:"participant", isBuddy:false}, {name:"gaetheboss", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"good", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"HirnWolf", presence:"playing", rating:"1311", role:"participant", isBuddy:false}, {name:"iceblendedmocha", presence:"playing", rating:"1253", role:"participant", isBuddy:false}, {name:"imperator3", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"josavatar", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"K4OS", presence:"playing", rating:"1353", role:"participant", isBuddy:false}, {name:"kazutoo", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"Kuchen", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"Lombave", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"lucasbr788", presence:"playing", rating:"1202", role:"participant", isBuddy:false}, {name:"marciofly1", presence:"playing", rating:"1185", role:"participant", isBuddy:false}, {name:"markeloff_1.6", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"MTT123", presence:"playing", rating:"1283", role:"participant", isBuddy:false}, {name:"OutLander1", presence:"playing", rating:"1265", role:"participant", isBuddy:false}, {name:"outlander384", presence:"playing", rating:"1226", role:"participant", isBuddy:false}, {name:"Outlaw_7", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"Pale.May", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"playsofty", presence:"playing", rating:"1109", role:"participant", isBuddy:false}, {name:"protolich", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"Quicksilver", presence:"playing", rating:"1277", role:"participant", isBuddy:false}, {name:"Ragnark-", presence:"playing", rating:"1222", role:"participant", isBuddy:false}, {name:"Resul-55", presence:"playing", rating:"1335", role:"participant", isBuddy:false}, {name:"silius117", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"softcase", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"thatazoreanguy", presence:"playing", rating:"", role:"participant", isBuddy:false}, {name:"thered", presence:"playing", rating:"", role:"participant", isBuddy:false}].map(player => { player.isBuddy = g_Buddies.indexOf(player.name) != -1; + + createSortString(player, g_PlayerListColumnsSort, attributesCompareStringFuncs); + return player; - }).sort((a, b) => { - let sortA, sortB; - let statusOrder = Object.keys(g_PlayerStatuses); - let statusA = statusOrder.indexOf(a.presence) + a.name.toLowerCase(); - let statusB = statusOrder.indexOf(b.presence) + b.name.toLowerCase(); + }).sort((a, b) => sortOrder * a.sortString.localeCompare(b.sortString, g_Locale)); - switch (sortBy) - { - case 'buddy': - sortA = (a.isBuddy ? 1 : 2) + statusA; - sortB = (b.isBuddy ? 1 : 2) + statusB; - break; - case 'rating': - sortA = +a.rating; - sortB = +b.rating; - break; - case 'status': - sortA = statusA; - sortB = statusB; - break; - case 'name': - default: - sortA = a.name.toLowerCase(); - sortB = b.name.toLowerCase(); - break; - } - if (sortA < sortB) return -sortOrder; - if (sortA > sortB) return +sortOrder; - return 0; - }); // Colorize list entries for (let player of cleanPlayerList) @@ -680,8 +731,7 @@ { let playerList = Engine.GetGUIObjectByName("playersBox"); let name = playerList.list[playerList.selected]; - - if (!name || name == g_Username || name.indexOf(g_BuddyListDelimiter) != -1) + if (!name || name == g_Username || name.indexOf(g_ConfigListDelimiter) != -1) return; let index = g_Buddies.indexOf(name); @@ -693,7 +743,7 @@ updateToggleBuddy(); // Don't save empty strings to the config file - let buddies = g_Buddies.filter(nick => nick).join(g_BuddyListDelimiter) || g_BuddyListDelimiter; + let buddies = g_Buddies.filter(nick => nick).join(g_ConfigListDelimiter) || g_ConfigListDelimiter; Engine.ConfigDB_CreateValue("user", "lobby.buddies", buddies); Engine.ConfigDB_WriteValueToFile("user", "lobby.buddies", buddies, "config/user.cfg"); @@ -894,7 +944,6 @@ function updateGameList() { let gamesBox = Engine.GetGUIObjectByName("gamesBox"); - let sortBy = gamesBox.selected_column; let sortOrder = gamesBox.selected_column_order; if (gamesBox.selected > -1) @@ -903,8 +952,30 @@ g_SelectedGamePort = g_GameList[gamesBox.selected].port; } - g_GameList = Engine.GetGameList().map(game => { + let attributesCompareStringFuncs = { + "buddy": + game => game.hasBuddies ? game.hasBuddies : 99, + "gameRating": + // Turn around sort order for ratings, as higher numbers are more important than lower. + // Do this by deviding 1 / number, so higher numbers become smaller. + // As in this devision integer numbers < 10000 always changes at the 7th digit, take this as least comparing digit. + game => (game.gameRating ? 1 / game.gameRating : 1.0).toFixed(7), + "mapSize": + game => game.mapSize, + "mapType": + game => game.mapType, + "mapName": + game => translate(game.niceMapName), + "nPlayers": + // Sort 1st: number of players, 2nd: max number of players. Turn around order by devision 1 / number, + // as higher numbers of players and max number of players are seem to be more interesting games. + // As in this devision integer numbers < 100 always changes at the 4th digit, take this as least comparing digit. + game => (1 / game.nbp).toFixed(4) + (1 / game.maxnbp).toFixed(4), + "name": + game => g_GameStatusOrder.indexOf(game.state) + game.name.toLowerCase() + }; + g_GameList = [{name:"CaptIsler's game", ip:"69.79.227.33", port:"20595", stunIP:"69.79.227.33", stunPort:"20595", hostUsername:"CaptIsler", state:"waiting", nbp:"3", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"borg- (2159)\",\"Team\":0},{\"Name\":\"marciofly1 (1185)\",\"Team\":0}],\"1\":\\[{\"Name\":\"Andresfcb2003\",\"Team\":1},{\"Name\":\"delfinouno\",\"Team\":1,\"Offline\":true,\"State\":\"defeated\"}]}", mapName:"maps/random/mainland", niceMapName:"Mainland", mapSize:"384", mapType:"random", victoryCondition:"conquest", startTime:"1502491208", hasBuddies:0, gameRating:1171}, {name:"jjoin", ip:"88.232.31.170", port:"20595", stunIP:"", stunPort:"", hostUsername:"Resul-55", state:"waiting", nbp:"1", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"Resul-55 (1335)\",\"Team\":0,\"State\":\"defeated\"},{\"Name\":\"JordiStc2 (1157)\",\"Team\":0,\"Offline\":true,\"State\":\"defeated\"}],\"1\":\\[{\"Name\":\"Adrianoo (1132)\",\"Team\":1,\"Offline\":true,\"State\":\"won\"},{\"Name\":\"ElJaUnCa\",\"Team\":1,\"Offline\":true,\"State\":\"defeated\"}]}", mapName:"maps/skirmishes/Corinthian Isthmus (4)", niceMapName:"Corinthian Isthmus (4)", mapSize:"Default", mapType:"skirmish", victoryCondition:"conquest", startTime:"1502484628", hasBuddies:0, gameRating:1206}, {name:"1c1", ip:"73.191.6.77", port:"20595", stunIP:"73.191.6.77", stunPort:"20595", hostUsername:"protolich", state:"running", nbp:"2", maxnbp:"2", players:"{\"-1\":\\[{\"Name\":\"protolich\",\"Team\":-1},{\"Name\":\"outlander384 (1226)\",\"Team\":-1}]}", mapName:"maps/random/unknown_land", niceMapName:"Unknown Land", mapSize:"256", mapType:"random", victoryCondition:"conquest", startTime:"1502492620", hasBuddies:0, gameRating:1213}, {name:"2v2 3v3", ip:"80.142.22.43", port:"20595", stunIP:"80.142.22.43", stunPort:"20595", hostUsername:"Quicksilver", state:"running", nbp:"4", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"Quicksilver (1258)\",\"Team\":0},{\"Name\":\"K4OS (1353)\",\"Team\":0}],\"1\":\\[{\"Name\":\"MTT123 (1283)\",\"Team\":1},{\"Name\":\"markeloff_1.6\",\"Team\":1}],\"observer\":\\[{\"Name\":\"user1\",\"Team\":\"observer\"},{\"Name\":\"Achelao (1547)\",\"Team\":\"observer\"}]}", mapName:"maps/random/african_plains", niceMapName:"African Plains", mapSize:"256", mapType:"random", victoryCondition:"conquest", startTime:"1502493352", hasBuddies:1, gameRating:1274}, {name:"2vs2 for noobs", ip:"24.133.23.153", port:"20595", stunIP:"24.133.23.153", stunPort:"48043", hostUsername:"Ferhat_C", state:"running", nbp:"4", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"Ferhat_C (961)\",\"Team\":0},{\"Name\":\"softcase\",\"Team\":0}],\"1\":\\[{\"Name\":\"silius117\",\"Team\":1},{\"Name\":\"Ragnark- (1222)\",\"Team\":1}]}", mapName:"maps/random/mainland", niceMapName:"Mainland", mapSize:"256", mapType:"random", victoryCondition:"conquest", startTime:"1502493326", hasBuddies:0, gameRating:1146}, {name:"ahmedteling's game", ip:"197.2.63.204", port:"20595", stunIP:"197.2.63.204", stunPort:"20595", hostUsername:"ahmedteling", state:"running", nbp:"2", maxnbp:"2", players:"{\"0\":\\[{\"Name\":\"ahmedteling (1062)\",\"Team\":0}],\"1\":\\[{\"Name\":\"playsofty (1055)\",\"Team\":1}]}", mapName:"maps/random/empire", niceMapName:"Empire", mapSize:"320", mapType:"random", victoryCondition:"conquest", startTime:"1502493395", hasBuddies:0, gameRating:1059}, {name:"Crowley's game", ip:"5.146.195.89", port:"20595", stunIP:"5.146.195.89", stunPort:"23806", hostUsername:"Crowley", state:"running", nbp:"3", maxnbp:"5", players:"{\"0\":\\[{\"Name\":\"Crowley (1135)\",\"Team\":0},{\"Name\":\"OutLander1 (1265)\",\"Team\":0},{\"Name\":\"Kuchen\",\"Team\":0}],\"1\":\\[{\"Name\":\"Viriato\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":3},{\"Name\":\"Demosthenes\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":3}]}", mapName:"maps/random/island_stronghold", niceMapName:"Island Stronghold", mapSize:"384", mapType:"random", victoryCondition:"conquest_structures", startTime:"1502485786", hasBuddies:0, gameRating:1200}, {name:"Emilio2006's game", ip:"189.216.75.3", port:"20595", stunIP:"189.216.75.3", stunPort:"18583", hostUsername:"Emilio2006", state:"init", nbp:"2", maxnbp:"2", players:"{\"-1\":\\[{\"Name\":\"Emilio2006 (1089)\",\"Team\":-1},{\"Name\":\"iceblendedmocha (1253)\",\"Team\":-1}],\"observer\":\\[{\"Name\":\"imperator3\",\"Team\":\"observer\"}]}", mapName:"maps/random/cycladic_archipelago", niceMapName:"Cycladic Archipelago", mapSize:"256", mapType:"random", victoryCondition:"conquest", startTime:"1502494400", hasBuddies:0, gameRating:1171}, {name:"gaetheboss's game", ip:"85.69.131.38", port:"20595", stunIP:"85.69.131.38", stunPort:"20595", hostUsername:"gaetheboss", state:"running", nbp:"2", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"gaetheboss\",\"Team\":0},{\"Name\":\"Lombave\",\"Team\":0}],\"1\":\\[{\"Name\":\"Alcibiades\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":3},{\"Name\":\"Antiochus V Eupator\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":3}]}", mapName:"maps/skirmishes/Corinthian Isthmus (4)", niceMapName:"Corinthian Isthmus (4)", mapSize:"Default", mapType:"skirmish", victoryCondition:"conquest", startTime:"1502488118", hasBuddies:0, gameRating:1200}, {name:"HirnWolf's game", ip:"151.62.141.194", port:"20595", stunIP:"151.62.141.194", stunPort:"20595", hostUsername:"HirnWolf", state:"running", nbp:"4", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"HirnWolf (1311)\",\"Team\":0},{\"Name\":\"kazutoo\",\"Team\":0}],\"1\":\\[{\"Name\":\"lucasbr788 (1202)\",\"Team\":1},{\"Name\":\"cleuberjs (1064)\",\"Team\":1}]}", mapName:"maps/random/rivers", niceMapName:"Rivers", mapSize:"320", mapType:"random", victoryCondition:"conquest", startTime:"1502491882", hasBuddies:0, gameRating:1194}, {name:"Pale.May's game", ip:"85.242.180.216", port:"20595", stunIP:"85.242.180.216", stunPort:"20595", hostUsername:"Pale.May", state:"running", nbp:"2", maxnbp:"6", players:"{\"0\":\\[{\"Name\":\"Pale.May\",\"Team\":0},{\"Name\":\"thatazoreanguy\",\"Team\":0},{\"Name\":\"Darayavahush I\",\"Team\":0,\"AI\":\"petra\",\"AIDiff\":1}],\"1\":\\[{\"Name\":\"Viriato\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":1}],\"2\":\\[{\"Name\":\"Demosthenes\",\"Team\":2,\"AI\":\"petra\",\"AIDiff\":1}],\"3\":\\[{\"Name\":\"Hasdrubal Barca\",\"Team\":3,\"AI\":\"petra\",\"AIDiff\":1}]}", mapName:"maps/skirmishes/Two Seas (6)", niceMapName:"Two Seas (6)", mapSize:"Default", mapType:"skirmish", victoryCondition:"conquest", startTime:"1502492263", hasBuddies:0, gameRating:1200}, {name:"please dont join", ip:"24.66.44.35", port:"20595", stunIP:"24.66.44.35", stunPort:"20595", hostUsername:"Bolvar", state:"running", nbp:"2", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"Bolvar\",\"Team\":0},{\"Name\":\"Outlaw_7\",\"Team\":0}],\"1\":\\[{\"Name\":\"Ashokavardhan Maurya\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":2},{\"Name\":\"Gaius Servilius Structus Ahala\",\"Team\":1,\"AI\":\"petra\",\"AIDiff\":2}]}", mapName:"maps/skirmishes/Caspian Sea (2v2)", niceMapName:"Caspian Sea (2v2)", mapSize:"Default", mapType:"skirmish", victoryCondition:"conquest", startTime:"1502490832", hasBuddies:0, gameRating:1200}, {name:"Pretension's game", ip:"81.240.97.23", port:"20595", stunIP:"81.240.97.23", stunPort:"58098", hostUsername:"Pretension", state:"init", nbp:"4", maxnbp:"4", players:"{\"0\":\\[{\"Name\":\"Pretension\",\"Team\":0},{\"Name\":\"iApprove (1464)\",\"Team\":0}],\"1\":\\[{\"Name\":\"chrstgtr (1641)\",\"Team\":1},{\"Name\":\"LeGenDz (1471)\",\"Team\":1}]}", mapName:"maps/random/african_plains", niceMapName:"African Plains", mapSize:"320", mapType:"random", victoryCondition:"conquest", startTime:"1502492173", hasBuddies:2, gameRating:1444}].map(game => { game.hasBuddies = 0; // Compute average rating of participating players @@ -917,9 +988,12 @@ if (player.Team != "observer") playerRatings.push(playerNickRating.rating || g_DefaultLobbyRating); + if (playerNickRating.nick == g_Username) + game.hasBuddies = 1; + // Sort games with playing buddies above games with spectating buddies - if (game.hasBuddies < 2 && g_Buddies.indexOf(playerNickRating.nick) != -1) - game.hasBuddies = player.Team == "observer" ? 1 : 2; + if ((!game.hasBuddies || game.hasBuddies > 2) && g_Buddies.indexOf(playerNickRating.nick) != -1) + game.hasBuddies = player.Team == "observer" ? 3 : 2; } game.gameRating = @@ -927,38 +1001,11 @@ Math.round(playerRatings.reduce((sum, current) => sum + current) / playerRatings.length) : g_DefaultLobbyRating; + // Concatenate the list entry values to one string together for comparison (in the selected columns sort order). + createSortString(game, g_GameListColumnsSort, attributesCompareStringFuncs); + return game; - }).filter(game => !filterGame(game)).sort((a, b) => { - let sortA, sortB; - switch (sortBy) - { - case 'name': - sortA = g_GameStatusOrder.indexOf(a.state) + a.name.toLowerCase(); - sortB = g_GameStatusOrder.indexOf(b.state) + b.name.toLowerCase(); - break; - case 'gameRating': - case 'mapSize': - case 'mapType': - sortA = a[sortBy]; - sortB = b[sortBy]; - break; - case 'buddy': - sortA = String(b.hasBuddies) + g_GameStatusOrder.indexOf(a.state) + a.name.toLowerCase(); - sortB = String(a.hasBuddies) + g_GameStatusOrder.indexOf(b.state) + b.name.toLowerCase(); - break; - case 'mapName': - sortA = translate(a.niceMapName); - sortB = translate(b.niceMapName); - break; - case 'nPlayers': - sortA = a.maxnbp; - sortB = b.maxnbp; - break; - } - if (sortA < sortB) return -sortOrder; - if (sortA > sortB) return +sortOrder; - return 0; - }); + }).filter(game => !filterGame(game)).sort((a, b) => sortOrder * a.sortString.localeCompare(b.sortString, g_Locale)); let list_buddy = []; let list_name = []; @@ -1008,6 +1055,38 @@ } /** + * Update sort order and columns sort in user config. + * + * @param {string} listName - List is either "players" or "games" + * @param {array} sortColumns - Array with names of columns in list to sort by (in the order they are setted in that array). + * @param {string} sortByColumn - Sort-by column to be changend in the sortColumns array + * @param {integer} sortOrder - Direction of the sort (1 or -1) + */ +function updateListSortConfig(listName, sortByColumns, sortByColumn, sortOrder) +{ + // Columns sort order changed. + if (sortByColumn != sortByColumns[0]) + { + // Move changed sort-by column to the front in the array. + while (sortByColumns.lastIndexOf(sortByColumn) != -1) + sortByColumns.splice(sortByColumns.lastIndexOf(sortByColumn), 1); + + sortByColumns.unshift(sortByColumn); + + let setting = "lobby." + listName + ".sortBy"; + let value = sortByColumns.filter(value => value).join(g_ConfigListDelimiter) || g_ConfigListDelimiter; + + Engine.ConfigDB_CreateValue("user", setting, value); + Engine.ConfigDB_WriteValueToFile("user", setting, value, "config/user.cfg"); + } + + let [ setting, value ] = [ "lobby." + listName + ".sortOrder", sortOrder == 1 ? "ascending" : "descending" ]; + + Engine.ConfigDB_CreateValue("user", setting, value); + Engine.ConfigDB_WriteValueToFile("user", setting, value, "config/user.cfg"); +} + +/** * Populate the game info area with information on the current game selection. */ function updateGameSelection() Index: binaries/data/mods/public/gui/lobby/lobby_panels.xml =================================================================== --- binaries/data/mods/public/gui/lobby/lobby_panels.xml +++ binaries/data/mods/public/gui/lobby/lobby_panels.xml @@ -10,10 +10,7 @@ @@ -30,9 +27,6 @@ onPlayerListSelection(); - - updatePlayerList(); - // In case of clicking on the same player again selectGameFromPlayername(); @@ -174,15 +168,11 @@ updateGameSelection(); - applyFilters(); joinButton();