Ticket #3143: 3143_lobby_data_v2.6.4.patch

File 3143_lobby_data_v2.6.4.patch, 16.5 KB (added by Imarok, 8 years ago)

Made the changes proposed by elexis

  • binaries/data/mods/public/gui/common/functions_utility.js

     
    5959 * Escape tag start and escape characters, so users cannot use special formatting.
    6060 * Also limit string length to 256 characters (not counting escape characters).
    6161 */
    62 function escapeText(text)
     62function escapeText(text, limitLength = true)
    6363{
    6464    if (!text)
    6565        return text;
    6666
    67     return text.substr(0, 255).replace(/\\/g, "\\\\").replace(/\[/g, "\\[");
     67    if (limitLength)
     68        text = text.substr(0, 255);
     69
     70    return text.replace(/\\/g, "\\\\").replace(/\[/g, "\\[");
    6871}
    6972
     73function unescapeText(text)
     74{
     75    if (!text)
     76        return text;
     77    return text.replace(/\\\\/g, "\\").replace(/\\\[/g, "\[");
     78}
     79
     80function playerDataToTeamList(originalplayerDataArray)
     81{
     82    let playerDataArray = clone(originalplayerDataArray);
     83    let teamList = {};
     84    for (let playerData of playerDataArray)
     85    {
     86        if (playerData.Team === undefined)
     87            playerData.Team = -1;
     88        if (!teamList[playerData.Team])
     89            teamList[playerData.Team] = [];
     90        teamList[playerData.Team].push(playerData);
     91        delete teamList[playerData.Team].Team;
     92    }
     93    return teamList;
     94}
     95
     96function teamListToPlayerData(teamList)
     97{
     98    let playerData = [];
     99    for (let team in teamList)
     100    {
     101        for (let player of teamList[team])
     102        {
     103            player.Team = team;
     104            playerData.push(player);
     105        }
     106    }
     107    return playerData;
     108}
     109
    70110function translateMapTitle(mapTitle)
    71111{
    72112    return mapTitle == "random" ? translateWithContext("map selection", "Random") : translate(mapTitle);
     
    226266
    227267    for (let playerData of playerDataArray)
    228268    {
    229         if (playerData == null || playerData.Civ == "gaia")
     269        if (playerData == null || playerData.Civ && playerData.Civ == "gaia")
    230270            continue;
    231271
    232272        ++playerIdx;
    233273        let teamIdx = playerData.Team;
    234274        let isAI = playerData.AI && playerData.AI != "";
    235         let playerState = playerStates && playerStates[playerIdx];
     275        let playerState = playerStates && playerStates[playerIdx] || playerData.State;
    236276        let isActive = !playerState || playerState == "active";
     277        let isOffline = playerData.Offline;
    237278
    238279        let playerDescription;
    239280        if (isAI)
    240281        {
    241             if (isActive)
    242                 // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
    243                 playerDescription = translate("%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s)");
     282            if (playerData.Civ)
     283            {
     284                if (isActive)
     285                    // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     286                    playerDescription = translate("%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s)");
     287                else
     288                    // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     289                    playerDescription = translate("%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s, %(state)s)");
     290            }
    244291            else
    245                 // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
    246                 playerDescription = translate("%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s, %(state)s)");
     292            {
     293                if (isActive)
     294                    // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     295                    playerDescription = translate("%(playerName)s (%(AIdifficulty)s %(AIname)s)");
     296                else
     297                    // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     298                    playerDescription = translate("%(playerName)s (%(AIdifficulty)s %(AIname)s, %(state)s)");
     299            }
    247300        }
    248301        else
    249302        {
    250             if (isActive)
    251                 // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
    252                 playerDescription = translate("%(playerName)s (%(civ)s)");
     303            // Can only occur in the lobby for now, so no strings with civ needed
     304            if (isOffline)
     305            {
     306                if (isActive)
     307                    // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     308                    playerDescription = translate("%(playerName)s (OFFLINE)");
     309                else
     310                    // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     311                    playerDescription = translate("%(playerName)s (OFFLINE, %(state)s)");
     312            }
    253313            else
    254                 // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
    255                 playerDescription = translate("%(playerName)s (%(civ)s, %(state)s)");
     314            {
     315                if (playerData.Civ)
     316                    if (isActive)
     317                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     318                        playerDescription = translate("%(playerName)s (%(civ)s)");
     319                    else
     320                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     321                        playerDescription = translate("%(playerName)s (%(civ)s, %(state)s)");
     322                else
     323                    if (isActive)
     324                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     325                        playerDescription = translate("%(playerName)s");
     326                    else
     327                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     328                        playerDescription = translate("%(playerName)s (%(state)s)");
     329            }
    256330        }
    257331
    258332        // Sort player descriptions by team
     
    262336        playerDescriptions[teamIdx].push(sprintf(playerDescription, {
    263337            "playerName":
    264338                '[color="' +
    265                 rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color) +
     339                (typeof getPlayerColor == 'function' ?
     340                    (isAI ?
     341                        "255 255 255" :
     342                        getPlayerColor(playerData.Name)) :
     343                    rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color)) +
    266344                '"]' + escapeText(playerData.Name) + "[/color]",
    267345
    268346            "civ":
     
    283361    }
    284362
    285363    let teams = Object.keys(playerDescriptions);
     364    if (teams.indexOf("observer") > -1)
     365        teams.splice(teams.indexOf("observer"), 1);
    286366
     367    let teamDescription = [];
     368
    287369    // If there are no teams, merge all playersDescriptions
    288370    if (teams.length == 1)
    289         return playerDescriptions[teams[0]].join("\n") + "\n";
     371        teamDescription.push(playerDescriptions[teams[0]].join("\n"));
    290372
    291373    // If there are teams, merge "Team N:" + playerDescriptions
    292     return teams.map(team => {
     374    else
     375        teamDescription = teamDescription.concat(teams.map(team => {
    293376
    294         let teamCaption = team == -1 ?
    295             translate("No Team") :
    296             sprintf(translate("Team %(team)s"), { "team": +team + 1 });
     377            let teamCaption = team == -1 ?
     378                translate("No Team") :
     379                sprintf(translate("Team %(team)s"), { "team": +team + 1 });
    297380
    298         // Translation: Describe players of one team in a selected game, f.e. in the replay- or savegame menu or lobby
    299         return sprintf(translate("%(team)s:\n%(playerDescriptions)s"), {
    300             "team": '[font="sans-bold-14"]' + teamCaption + "[/font]",
    301             "playerDescriptions": playerDescriptions[team].join("\n")
    302         });
    303     }).join("\n\n");
     381            // Translation: Describe players of one team in a selected game, f.e. in the replay- or savegame menu or lobby
     382            return sprintf(translate("%(team)s:\n%(playerDescriptions)s"), {
     383                "team": '[font="sans-bold-14"]' + teamCaption + "[/font]",
     384                "playerDescriptions": playerDescriptions[team].join("\n")
     385            });
     386        }));
     387
     388    if (playerDescriptions.observer)
     389        teamDescription.push(sprintf(translate("%(team)s:\n%(playerDescriptions)s"), {
     390            "team": '[font="sans-bold-14"]' + translatePlural("Observer", "Observers", playerDescriptions.observer.length) + "[/font]",
     391            "playerDescriptions": playerDescriptions.observer.join("\n")
     392        }));
     393
     394    return teamDescription.join("\n\n");
    304395}
  • binaries/data/mods/public/gui/gamesetup/gamesetup.js

     
    676676{
    677677    if (g_IsController && Engine.HasXmppClient())
    678678    {
    679         let playerNames = Object.keys(g_PlayerAssignments).map(guid => g_PlayerAssignments[guid].name);
    680         Engine.SendChangeStateGame(playerNames.length, playerNames.join(", "));
     679        let clients = formatClientsForStanza();
     680        Engine.SendChangeStateGame(clients.nbp, clients.list);
    681681    }
    682682
    683683    Engine.SwitchGuiPage("page_loading.xml", {
     
    19361936        setReady(false, false);
    19371937}
    19381938
     1939function formatClientsForStanza()
     1940{
     1941    let numberOfPlayers = 0;
     1942    let list = [];
     1943    for (let guid in g_PlayerAssignments)
     1944    {
     1945        if (g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1])
     1946        {
     1947            ++numberOfPlayers;
     1948            list.push({
     1949                "Name": g_PlayerAssignments[guid].name
     1950            });
     1951        }
     1952        else
     1953            list.push({
     1954                "Name": g_PlayerAssignments[guid].name,
     1955                "Team": "observer"
     1956            });
     1957    }
     1958    return {
     1959        "list": escapeText(JSON.stringify(playerDataToTeamList(list))),
     1960        "nbp": numberOfPlayers
     1961    };
     1962}
     1963
    19391964/**
    19401965 * Send the relevant gamesettings to the lobbybot.
    19411966 */
     
    19491974
    19501975    let mapSize = g_GameAttributes.mapType == "random" ? Engine.GetGUIObjectByName("mapSize").list_data[selectedMapSize] : "Default";
    19511976    let victoryCondition = Engine.GetGUIObjectByName("victoryCondition").list[selectedVictoryCondition];
    1952     let playerNames = Object.keys(g_PlayerAssignments).map(guid => g_PlayerAssignments[guid].name).sort();
     1977    let clients = formatClientsForStanza();
    19531978
    19541979    let stanza = {
    19551980        "name": g_ServerName,
     
    19591984        "mapSize": mapSize,
    19601985        "mapType": g_GameAttributes.mapType,
    19611986        "victoryCondition": victoryCondition,
    1962         "nbp": Object.keys(g_PlayerAssignments).length || 1,
    1963         "tnbp": g_GameAttributes.settings.PlayerData.length,
    1964         "players": playerNames.join(", ")
     1987        "nbp": clients.nbp,
     1988        "maxnbp": g_GameAttributes.settings.PlayerData.length,
     1989        "players": clients.list,
    19651990    };
    19661991
    19671992    // Only send the stanza if the relevant settings actually changed
  • binaries/data/mods/public/gui/lobby/lobby.js

     
    285285        return true;
    286286
    287287    if (playersNumberFilter.selected != 0 &&
    288         game.tnbp != playersNumberFilter.list_data[playersNumberFilter.selected])
     288        game.maxnbp != playersNumberFilter.list_data[playersNumberFilter.selected])
    289289        return true;
    290290
    291291    if (mapTypeFilter.selected != 0 &&
     
    292292        game.mapType != mapTypeFilter.list_data[mapTypeFilter.selected])
    293293        return true;
    294294
    295     if (!showFullFilter.checked && game.tnbp <= game.nbp)
     295    if (!showFullFilter.checked && game.maxnbp <= game.nbp)
    296296        return true;
    297297
    298298    return false;
     
    546546            break;
    547547        case 'nPlayers':
    548548            // Compare playercount ratio
    549             sortA = a.nbp * b.tnbp;
    550             sortB = b.nbp * a.tnbp;
     549            sortA = a.nbp * b.maxnbp;
     550            sortB = b.nbp * a.maxnbp;
    551551            break;
    552552        case 'status':
    553553        default:
     
    582582        list_mapName.push(translateMapTitle(game.niceMapName));
    583583        list_mapSize.push(translateMapSize(game.mapSize));
    584584        list_mapType.push(g_MapTypes.Title[mapTypeIdx] || "");
    585         list_nPlayers.push(game.nbp + "/" + game.tnbp);
     585        list_nPlayers.push(game.nbp + "/" + game.maxnbp);
    586586        list.push(gameName);
    587587        list_data.push(i);
    588588    }
     
    616616
    617617    Engine.GetGUIObjectByName("sgMapName").caption = translateMapTitle(game.niceMapName);
    618618    Engine.GetGUIObjectByName("sgNbPlayers").caption = sprintf(
    619         translate("Players: %(current)s/%(total)s"), {
     619        translate("Players: %(current)s/%(max)s"), {
    620620            "current": game.nbp,
    621             "total": game.tnbp
     621            "max": game.maxnbp
    622622        });
    623623
    624     Engine.GetGUIObjectByName("sgPlayersNames").caption = game.players;
     624    Engine.GetGUIObjectByName("sgPlayersNames").caption = formatPlayerInfo(teamListToPlayerData(JSON.parse(unescapeText(game.players))));
    625625    Engine.GetGUIObjectByName("sgMapSize").caption = translateMapSize(game.mapSize);
    626626
    627627    let mapTypeIdx = g_MapTypes.Name.indexOf(game.mapType);
     
    653653
    654654    let username = g_UserRating ? g_Username + " (" + g_UserRating + ")" : g_Username;
    655655
    656     if (game.state == "init" || game.players.split(", ").indexOf(username) > -1)
     656    if (game.state == "init" || teamListToPlayerData(JSON.parse(unescapeText(game.players))).some(player => player.Name == username))
    657657        joinSelectedGame();
    658658    else
    659659        messageBox(
  • binaries/data/mods/public/gui/session/messages.js

     
    544544
    545545    // Update lobby gamestatus
    546546    if (g_IsController && Engine.HasXmppClient())
    547     {
    548         let players = Object.keys(g_PlayerAssignments).map(guid => g_PlayerAssignments[guid].name);
    549         Engine.SendChangeStateGame(Object.keys(g_PlayerAssignments).length, players.join(", "));
    550     }
     547        sendLobbyStanzaUpdate();
    551548}
    552549
    553550function onClientJoin(guid)
     
    746743
    747744function formatDefeatMessage(msg)
    748745{
     746    if (g_IsController && Engine.HasXmppClient())
     747        sendLobbyStanzaUpdate();
     748
    749749    return sprintf(
    750750        msg.resign ?
    751751            translate("%(player)s has resigned.") :
  • binaries/data/mods/public/gui/session/session.js

     
    288288    if (hotloadData)
    289289        g_Selection.selected = hotloadData.selection;
    290290
     291    if (g_IsController && Engine.HasXmppClient())
     292        sendLobbyStanzaUpdate();
     293
    291294    onSimulationUpdate();
    292295
    293296    setTimeout(displayGamestateNotifications, 1000);
  • binaries/data/mods/public/gui/session/utility_functions.js

     
    131131    alpha = alpha > 125 ? 125 : alpha;
    132132    return "color:255 0 0 " + alpha;
    133133}
     134 
     135function sendLobbyStanzaUpdate()
     136{
     137    let playerDataArray = clone(g_GameAttributes.settings.PlayerData);
     138    let numberOfPlayers = 0;
     139    let playerStates = {};
     140
     141    for (let player of g_Players)
     142    {
     143        playerStates[player.name] = {};
     144        playerStates[player.name].State = player.state;
     145        playerStates[player.name].Offline = player.offline;
     146    }
     147
     148    for (let guid in g_PlayerAssignments)
     149    {
     150        let pData = g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1];
     151
     152        if (pData)
     153            ++numberOfPlayers;
     154        else
     155            playerDataArray.push({
     156                "Name": g_PlayerAssignments[guid].name,
     157                "Team": "observer"
     158            });
     159    }
     160
     161    for (let playerData of playerDataArray)
     162    {
     163        delete playerData.Civ;
     164        delete playerData.Color;
     165
     166        if (!g_GameAttributes.settings.LockTeams && playerData.Team != "observer")
     167            delete playerData.Team;
     168
     169        let pState = playerStates[playerData.Name];
     170        if (pState)
     171        {
     172            playerData.State = pState.State;
     173            playerData.Offline = pState.Offline;
     174        }
     175    }
     176    Engine.SendChangeStateGame(numberOfPlayers, escapeText(JSON.stringify(playerDataToTeamList(playerDataArray)), false));
     177}
  • source/lobby/XmppClient.cpp

     
    502502    JSAutoRequest rq(cx);
    503503
    504504    scriptInterface.Eval("([])", ret);
    505     const char* stats[] = { "name", "ip", "port", "state", "nbp", "tnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" };
     505    const char* stats[] = { "name", "ip", "port", "state", "nbp", "maxnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" };
    506506    for(const glooxwrapper::Tag* const& t : m_GameList)
    507507    {
    508508        JS::RootedValue game(cx);
  • source/tools/XpartaMuPP/XpartaMuPP.py

     
    301301    if JID in self.gameList:
    302302      if self.gameList[JID]['nbp-init'] > data['nbp']:
    303303        logging.debug("change game (%s) state from %s to %s", JID, self.gameList[JID]['state'], 'waiting')
    304         self.gameList[JID]['nbp'] = data['nbp']
    305304        self.gameList[JID]['state'] = 'waiting'
    306305      else:
    307306        logging.debug("change game (%s) state from %s to %s", JID, self.gameList[JID]['state'], 'running')
    308         self.gameList[JID]['nbp'] = data['nbp']
    309307        self.gameList[JID]['state'] = 'running'
     308      self.gameList[JID]['nbp'] = data['nbp']
     309      self.gameList[JID]['players'] = data['players']
    310310
    311311## Class which manages different game reports from clients ##
    312312##   and calls leaderboard functions as appropriate.       ##