Ticket #3143: 3143_lobby_data_v2.6.03.patch

File 3143_lobby_data_v2.6.03.patch, 17.4 KB (added by Imarok, 8 years ago)

The patch should be finished. But when testing my game wasn't even displayed in the lobbys game list...

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

     
    6767    return text.substr(0, 255).replace(/\\/g, "\\\\").replace(/\[/g, "\\[");
    6868}
    6969
     70function unescapeText(text)
     71{
     72    if (!text)
     73        return text;
     74    return text.replace(/\\\\/g, "\\").replace(/\\\[/g, "\[");
     75}
     76
    7077function translateMapTitle(mapTitle)
    7178{
    7279    return mapTitle == "random" ? translateWithContext("map selection", "Random") : translate(mapTitle);
     
    226233
    227234    for (let playerData of playerDataArray)
    228235    {
    229         if (playerData == null || playerData.Civ == "gaia")
     236        if (playerData == null || playerData.Civ && playerData.Civ == "gaia")
    230237            continue;
    231238
    232239        ++playerIdx;
    233240        let teamIdx = playerData.Team;
    234241        let isAI = playerData.AI && playerData.AI != "";
    235         let playerState = playerStates && playerStates[playerIdx];
     242        let playerState = playerStates && playerStates[playerIdx] || playerData.State;
    236243        let isActive = !playerState || playerState == "active";
     244        let isOffline = playerData.Offline;
    237245
    238246        let playerDescription;
    239247        if (isAI)
     
    247255        }
    248256        else
    249257        {
    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)");
     258            if (isOffline)
     259            {
     260                if (playerData.Civ)
     261                    if (isActive)
     262                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     263                        playerDescription = translate("%(playerName)s (OFFLINE, %(civ)s)");
     264                    else
     265                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     266                        playerDescription = translate("%(playerName)s (OFFLINE, %(civ)s, %(state)s)");
     267                else
     268                    if (isActive)
     269                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     270                        playerDescription = translate("%(playerName)s (OFFLINE)");
     271                    else
     272                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     273                        playerDescription = translate("%(playerName)s (OFFLINE, %(state)s)");
     274            }
    253275            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)");
     276            {
     277                if (playerData.Civ)
     278                    if (isActive)
     279                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     280                        playerDescription = translate("%(playerName)s (%(civ)s)");
     281                    else
     282                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     283                        playerDescription = translate("%(playerName)s (%(civ)s, %(state)s)");
     284                else
     285                    if (isActive)
     286                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     287                        playerDescription = translate("%(playerName)s");
     288                    else
     289                        // Translation: Describe a player in a selected game, f.e. in the replay- or savegame menu
     290                        playerDescription = translate("%(playerName)s (%(state)s)");
     291            }
    256292        }
    257293
    258294        // Sort player descriptions by team
     
    283319    }
    284320
    285321    let teams = Object.keys(playerDescriptions);
     322    if (teams.indexOf("observer") > -1)
     323        teams.splice(teams.indexOf("observer"), 1);
    286324
     325    let teamDescription = [];
     326
    287327    // If there are no teams, merge all playersDescriptions
    288328    if (teams.length == 1)
    289         return playerDescriptions[teams[0]].join("\n") + "\n";
     329        teamDescription.push(playerDescriptions[teams[0]].join("\n"));
    290330
    291331    // If there are teams, merge "Team N:" + playerDescriptions
    292     return teams.map(team => {
     332    else
     333        teamDescription = teamDescription.concat(teams.map(team => {
    293334
    294         let teamCaption = team == -1 ?
    295             translate("No Team") :
    296             sprintf(translate("Team %(team)s"), { "team": +team + 1 });
     335            let teamCaption = team == -1 ?
     336                translate("No Team") :
     337                sprintf(translate("Team %(team)s"), { "team": +team + 1 });
    297338
    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");
     339            // Translation: Describe players of one team in a selected game, f.e. in the replay- or savegame menu or lobby
     340            return sprintf(translate("%(team)s:\n%(playerDescriptions)s"), {
     341                "team": '[font="sans-bold-14"]' + teamCaption + "[/font]",
     342                "playerDescriptions": playerDescriptions[team].join("\n")
     343            });
     344        }));
     345
     346    if (playerDescriptions.observer)
     347        teamDescription.push(sprintf(translatePlural(
     348            '[font="sans-bold-14"]Observer:[/font]\n%(observerDescription)s',
     349            '[font="sans-bold-14"]Observers:[/font]\n%(observerDescription)s',
     350            playerDescriptions.observer.length),
     351            {"observerDescription": playerDescriptions.observer.join("\n")}
     352        ));
     353
     354    return teamDescription.join("\n\n");
    304355}
  • 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 = formatClients();
     680        Engine.SendChangeStateGame(clients.nbp, clients.list);
    681681    }
    682682
    683683    Engine.SwitchGuiPage("page_loading.xml", {
     
    19261926        setReady(false, false);
    19271927}
    19281928
     1929function formatClients()
     1930{
     1931    let numberOfPlayers = 0;
     1932    let list = [];
     1933    for (let guid in g_PlayerAssignments)
     1934    {
     1935        if (g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player - 1])
     1936        {
     1937            ++numberOfPlayers;
     1938            list.push({
     1939                "Name": g_PlayerAssignments[guid].name
     1940            });
     1941        }
     1942        else
     1943            list.push({
     1944                "Name": g_PlayerAssignments[guid].name,
     1945                "Team": "observer"
     1946            });
     1947    }
     1948    return {
     1949        "list": escapeText(JSON.stringify(list)),
     1950        "nbp": numberOfPlayers
     1951    };
     1952}
     1953
    19291954/**
    19301955 * Send the relevant gamesettings to the lobbybot.
    19311956 */
     
    19391964
    19401965    let mapSize = g_GameAttributes.mapType == "random" ? Engine.GetGUIObjectByName("mapSize").list_data[selectedMapSize] : "Default";
    19411966    let victoryCondition = Engine.GetGUIObjectByName("victoryCondition").list[selectedVictoryCondition];
    1942     let playerNames = Object.keys(g_PlayerAssignments).map(guid => g_PlayerAssignments[guid].name).sort();
     1967    let clients = formatClients();
    19431968
    19441969    let stanza = {
    19451970        "name": g_ServerName,
     
    19491974        "mapSize": mapSize,
    19501975        "mapType": g_GameAttributes.mapType,
    19511976        "victoryCondition": victoryCondition,
    1952         "nbp": Object.keys(g_PlayerAssignments).length || 1,
    1953         "tnbp": g_GameAttributes.settings.PlayerData.length,
    1954         "players": playerNames.join(", ")
     1977        "nbp": clients.nbp,
     1978        "maxnbp": g_GameAttributes.settings.PlayerData.length,
     1979        "clients": clients.list,
    19551980    };
    19561981
    19571982    // 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;
     
    555555            break;
    556556        case 'nPlayers':
    557557            // Compare playercount ratio
    558             sortA = a.nbp * b.tnbp;
    559             sortB = b.nbp * a.tnbp;
     558            sortA = a.nbp * b.maxnbp;
     559            sortB = b.nbp * a.maxnbp;
    560560            break;
    561561        case 'status':
    562562        default:
     
    591591        list_mapName.push(translateMapTitle(game.niceMapName));
    592592        list_mapSize.push(translateMapSize(game.mapSize));
    593593        list_mapType.push(g_MapTypes.Title[mapTypeIdx] || "");
    594         list_nPlayers.push(game.nbp + "/" + game.tnbp);
     594        list_nPlayers.push(game.nbp + "/" + game.maxnbp);
    595595        list.push(gameName);
    596596        list_data.push(i);
    597597    }
     
    625625
    626626    Engine.GetGUIObjectByName("sgMapName").caption = translateMapTitle(game.niceMapName);
    627627    Engine.GetGUIObjectByName("sgNbPlayers").caption = sprintf(
    628         translate("Players: %(current)s/%(total)s"), {
     628        translate("Players: %(current)s/%(max)s"), {
    629629            "current": game.nbp,
    630             "total": game.tnbp
     630            "max": game.maxnbp
    631631        });
    632632
    633     Engine.GetGUIObjectByName("sgPlayersNames").caption = game.players;
     633    Engine.GetGUIObjectByName("sgPlayersNames").caption = formatPlayerInfo(JSON.parse(unescapeText(game.clients)));
    634634    Engine.GetGUIObjectByName("sgMapSize").caption = translateMapSize(game.mapSize);
    635635
    636636    let mapTypeIdx = g_MapTypes.Name.indexOf(game.mapType);
     
    662662
    663663    let username = g_UserRating ? g_Username + " (" + g_UserRating + ")" : g_Username;
    664664
    665     if (game.state == "init" || game.players.split(", ").indexOf(username) > -1)
     665    if (game.state == "init" || JSON.parse(unescapeText(game.clients)).some(player => player.Name == username))
    666666        joinSelectedGame();
    667667    else
    668668        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        sendLobbyReportUpdate();
    551548}
    552549
    553550function onClientJoin(guid)
  • 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        sendLobbyReportUpdate();
     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 sendLobbyReportUpdate()
     136{
     137    let playerDataArray = JSON.parse(JSON.stringify(g_GameAttributes.settings.PlayerData));
     138    let numberOfObservers = 0;
     139    let playerStates = {};
     140
     141    for (let player of g_Players)
     142    {
     143        playerStates[player].State = player.state;
     144        playerStates[player].Offline = player.offline;
     145    }
     146
     147    for (let pAssign of g_PlayerAssignments)
     148    {
     149        let pData = g_GameAttributes.settings.PlayerData[pAssign.player - 1];
     150
     151        //if client is observer
     152        if (!pData)
     153        {
     154            playerDataArray.push({
     155                "Name": pAssign.name,
     156                "Team": "observer"
     157            });
     158            ++numberOfObservers;
     159        }
     160    }
     161
     162    for (let playerData of playerDataArray)
     163    {
     164        delete playerData.Civ;
     165        delete playerData.Color;
     166
     167        if (!g_GameAttributes.settings.LockTeams && playerData.Team != "observer")
     168            delete playerData.Team;
     169
     170        let pState = playerStates[playerData.Name];
     171        if (pState)
     172        {
     173            playerData.State = pState.State;
     174            playerData.Offline = pState.Offline;
     175        }
     176    }
     177
     178    Engine.SendChangeStateGame(g_PlayerAssignments.length - numberOfObservers, escapeText(JSON.stringify(playerDataArray)));
     179}
  • source/lobby/IXmppClient.h

     
    1 /* Copyright (C) 2015 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3838    virtual void SendIqGameReport(ScriptInterface& scriptInterface, JS::HandleValue data) = 0;
    3939    virtual void SendIqRegisterGame(ScriptInterface& scriptInterface, JS::HandleValue data) = 0;
    4040    virtual void SendIqUnregisterGame() = 0;
    41     virtual void SendIqChangeStateGame(const std::string& nbp, const std::string& players) = 0;
     41    virtual void SendIqChangeStateGame(const std::string& nbp, const std::string& clients) = 0;
    4242    virtual void SetNick(const std::string& nick) = 0;
    4343    virtual void GetNick(std::string& nick) = 0;
    4444    virtual void kick(const std::string& nick, const std::string& reason) = 0;
  • source/lobby/scripting/JSInterface_Lobby.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    171171    g_XmppClient->SendIqUnregisterGame();
    172172}
    173173
    174 void JSI_Lobby::SendChangeStateGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& nbp, const std::wstring& players)
     174void JSI_Lobby::SendChangeStateGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& nbp, const std::wstring& clients)
    175175{
    176176    if (!g_XmppClient)
    177177        return;
    178     g_XmppClient->SendIqChangeStateGame(utf8_from_wstring(nbp), utf8_from_wstring(players));
     178    g_XmppClient->SendIqChangeStateGame(utf8_from_wstring(nbp), utf8_from_wstring(clients));
    179179}
    180180
    181181JS::Value JSI_Lobby::GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate)
  • source/lobby/scripting/JSInterface_Lobby.h

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    4343    void SendGameReport(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data);
    4444    void SendRegisterGame(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data);
    4545    void SendUnregisterGame(ScriptInterface::CxPrivate* pCxPrivate);
    46     void SendChangeStateGame(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& nbp, const std::wstring& players);
     46    void SendChangeStateGame(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& nbp, const std::wstring& clients);
    4747    JS::Value GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate);
    4848    void LobbyClearPresenceUpdates(ScriptInterface::CxPrivate* pCxPrivate);
    4949    int LobbyGetMucMessageCount(ScriptInterface::CxPrivate* pCxPrivate);
  • source/lobby/XmppClient.cpp

     
    408408 * decides which - but we need to update the current players that are
    409409 * in-game so the server can make the calculation.
    410410 */
    411 void XmppClient::SendIqChangeStateGame(const std::string& nbp, const std::string& players)
     411void XmppClient::SendIqChangeStateGame(const std::string& nbp, const std::string& clients)
    412412{
    413413    glooxwrapper::JID xpartamuppJid(m_xpartamuppId);
    414414
     
    417417    g->m_Command = "changestate";
    418418    glooxwrapper::Tag* game = glooxwrapper::Tag::allocate("game");
    419419    game->addAttribute("nbp", nbp);
    420     game->addAttribute("players", players);
     420    game->addAttribute("clients", clients);
    421421    g->m_GameList.emplace_back(game);
    422422
    423423    glooxwrapper::IQ iq(gloox::IQ::Set, xpartamuppJid);
     
    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", "clients", "mapName", "niceMapName", "mapSize", "mapType", "victoryCondition" };
    506506    for(const glooxwrapper::Tag* const& t : m_GameList)
    507507    {
    508508        JS::RootedValue game(cx);
  • source/lobby/XmppClient.h

     
    6868    void SendIqGameReport(ScriptInterface& scriptInterface, JS::HandleValue data);
    6969    void SendIqRegisterGame(ScriptInterface& scriptInterface, JS::HandleValue data);
    7070    void SendIqUnregisterGame();
    71     void SendIqChangeStateGame(const std::string& nbp, const std::string& players);
     71    void SendIqChangeStateGame(const std::string& nbp, const std::string& clients);
    7272    void SetNick(const std::string& nick);
    7373    void GetNick(std::string& nick);
    7474    void kick(const std::string& nick, const std::string& reason);