Ticket #3143: 3143_lobby_data_v2.6.03.patch
File 3143_lobby_data_v2.6.03.patch, 17.4 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/gui/common/functions_utility.js
67 67 return text.substr(0, 255).replace(/\\/g, "\\\\").replace(/\[/g, "\\["); 68 68 } 69 69 70 function unescapeText(text) 71 { 72 if (!text) 73 return text; 74 return text.replace(/\\\\/g, "\\").replace(/\\\[/g, "\["); 75 } 76 70 77 function translateMapTitle(mapTitle) 71 78 { 72 79 return mapTitle == "random" ? translateWithContext("map selection", "Random") : translate(mapTitle); … … 226 233 227 234 for (let playerData of playerDataArray) 228 235 { 229 if (playerData == null || playerData.Civ == "gaia")236 if (playerData == null || playerData.Civ && playerData.Civ == "gaia") 230 237 continue; 231 238 232 239 ++playerIdx; 233 240 let teamIdx = playerData.Team; 234 241 let isAI = playerData.AI && playerData.AI != ""; 235 let playerState = playerStates && playerStates[playerIdx] ;242 let playerState = playerStates && playerStates[playerIdx] || playerData.State; 236 243 let isActive = !playerState || playerState == "active"; 244 let isOffline = playerData.Offline; 237 245 238 246 let playerDescription; 239 247 if (isAI) … … 247 255 } 248 256 else 249 257 { 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 } 253 275 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 } 256 292 } 257 293 258 294 // Sort player descriptions by team … … 283 319 } 284 320 285 321 let teams = Object.keys(playerDescriptions); 322 if (teams.indexOf("observer") > -1) 323 teams.splice(teams.indexOf("observer"), 1); 286 324 325 let teamDescription = []; 326 287 327 // If there are no teams, merge all playersDescriptions 288 328 if (teams.length == 1) 289 return playerDescriptions[teams[0]].join("\n") + "\n";329 teamDescription.push(playerDescriptions[teams[0]].join("\n")); 290 330 291 331 // If there are teams, merge "Team N:" + playerDescriptions 292 return teams.map(team => { 332 else 333 teamDescription = teamDescription.concat(teams.map(team => { 293 334 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 }); 297 338 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"); 304 355 } -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
676 676 { 677 677 if (g_IsController && Engine.HasXmppClient()) 678 678 { 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); 681 681 } 682 682 683 683 Engine.SwitchGuiPage("page_loading.xml", { … … 1926 1926 setReady(false, false); 1927 1927 } 1928 1928 1929 function 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 1929 1954 /** 1930 1955 * Send the relevant gamesettings to the lobbybot. 1931 1956 */ … … 1939 1964 1940 1965 let mapSize = g_GameAttributes.mapType == "random" ? Engine.GetGUIObjectByName("mapSize").list_data[selectedMapSize] : "Default"; 1941 1966 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(); 1943 1968 1944 1969 let stanza = { 1945 1970 "name": g_ServerName, … … 1949 1974 "mapSize": mapSize, 1950 1975 "mapType": g_GameAttributes.mapType, 1951 1976 "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, 1955 1980 }; 1956 1981 1957 1982 // Only send the stanza if the relevant settings actually changed -
binaries/data/mods/public/gui/lobby/lobby.js
285 285 return true; 286 286 287 287 if (playersNumberFilter.selected != 0 && 288 game. tnbp != playersNumberFilter.list_data[playersNumberFilter.selected])288 game.maxnbp != playersNumberFilter.list_data[playersNumberFilter.selected]) 289 289 return true; 290 290 291 291 if (mapTypeFilter.selected != 0 && … … 292 292 game.mapType != mapTypeFilter.list_data[mapTypeFilter.selected]) 293 293 return true; 294 294 295 if (!showFullFilter.checked && game. tnbp <= game.nbp)295 if (!showFullFilter.checked && game.maxnbp <= game.nbp) 296 296 return true; 297 297 298 298 return false; … … 555 555 break; 556 556 case 'nPlayers': 557 557 // 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; 560 560 break; 561 561 case 'status': 562 562 default: … … 591 591 list_mapName.push(translateMapTitle(game.niceMapName)); 592 592 list_mapSize.push(translateMapSize(game.mapSize)); 593 593 list_mapType.push(g_MapTypes.Title[mapTypeIdx] || ""); 594 list_nPlayers.push(game.nbp + "/" + game. tnbp);594 list_nPlayers.push(game.nbp + "/" + game.maxnbp); 595 595 list.push(gameName); 596 596 list_data.push(i); 597 597 } … … 625 625 626 626 Engine.GetGUIObjectByName("sgMapName").caption = translateMapTitle(game.niceMapName); 627 627 Engine.GetGUIObjectByName("sgNbPlayers").caption = sprintf( 628 translate("Players: %(current)s/%( total)s"), {628 translate("Players: %(current)s/%(max)s"), { 629 629 "current": game.nbp, 630 " total": game.tnbp630 "max": game.maxnbp 631 631 }); 632 632 633 Engine.GetGUIObjectByName("sgPlayersNames").caption = game.players;633 Engine.GetGUIObjectByName("sgPlayersNames").caption = formatPlayerInfo(JSON.parse(unescapeText(game.clients))); 634 634 Engine.GetGUIObjectByName("sgMapSize").caption = translateMapSize(game.mapSize); 635 635 636 636 let mapTypeIdx = g_MapTypes.Name.indexOf(game.mapType); … … 662 662 663 663 let username = g_UserRating ? g_Username + " (" + g_UserRating + ")" : g_Username; 664 664 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)) 666 666 joinSelectedGame(); 667 667 else 668 668 messageBox( -
binaries/data/mods/public/gui/session/messages.js
544 544 545 545 // Update lobby gamestatus 546 546 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(); 551 548 } 552 549 553 550 function onClientJoin(guid) -
binaries/data/mods/public/gui/session/session.js
288 288 if (hotloadData) 289 289 g_Selection.selected = hotloadData.selection; 290 290 291 if (g_IsController && Engine.HasXmppClient()) 292 sendLobbyReportUpdate(); 293 291 294 onSimulationUpdate(); 292 295 293 296 setTimeout(displayGamestateNotifications, 1000); -
binaries/data/mods/public/gui/session/utility_functions.js
131 131 alpha = alpha > 125 ? 125 : alpha; 132 132 return "color:255 0 0 " + alpha; 133 133 } 134 135 function 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) 201 5Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 38 38 virtual void SendIqGameReport(ScriptInterface& scriptInterface, JS::HandleValue data) = 0; 39 39 virtual void SendIqRegisterGame(ScriptInterface& scriptInterface, JS::HandleValue data) = 0; 40 40 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; 42 42 virtual void SetNick(const std::string& nick) = 0; 43 43 virtual void GetNick(std::string& nick) = 0; 44 44 virtual void kick(const std::string& nick, const std::string& reason) = 0; -
source/lobby/scripting/JSInterface_Lobby.cpp
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 171 171 g_XmppClient->SendIqUnregisterGame(); 172 172 } 173 173 174 void JSI_Lobby::SendChangeStateGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& nbp, const std::wstring& players)174 void JSI_Lobby::SendChangeStateGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& nbp, const std::wstring& clients) 175 175 { 176 176 if (!g_XmppClient) 177 177 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)); 179 179 } 180 180 181 181 JS::Value JSI_Lobby::GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate) -
source/lobby/scripting/JSInterface_Lobby.h
1 /* Copyright (C) 201 4Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 43 43 void SendGameReport(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data); 44 44 void SendRegisterGame(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue data); 45 45 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); 47 47 JS::Value GetPlayerList(ScriptInterface::CxPrivate* pCxPrivate); 48 48 void LobbyClearPresenceUpdates(ScriptInterface::CxPrivate* pCxPrivate); 49 49 int LobbyGetMucMessageCount(ScriptInterface::CxPrivate* pCxPrivate); -
source/lobby/XmppClient.cpp
408 408 * decides which - but we need to update the current players that are 409 409 * in-game so the server can make the calculation. 410 410 */ 411 void XmppClient::SendIqChangeStateGame(const std::string& nbp, const std::string& players)411 void XmppClient::SendIqChangeStateGame(const std::string& nbp, const std::string& clients) 412 412 { 413 413 glooxwrapper::JID xpartamuppJid(m_xpartamuppId); 414 414 … … 417 417 g->m_Command = "changestate"; 418 418 glooxwrapper::Tag* game = glooxwrapper::Tag::allocate("game"); 419 419 game->addAttribute("nbp", nbp); 420 game->addAttribute(" players", players);420 game->addAttribute("clients", clients); 421 421 g->m_GameList.emplace_back(game); 422 422 423 423 glooxwrapper::IQ iq(gloox::IQ::Set, xpartamuppJid); … … 502 502 JSAutoRequest rq(cx); 503 503 504 504 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" }; 506 506 for(const glooxwrapper::Tag* const& t : m_GameList) 507 507 { 508 508 JS::RootedValue game(cx); -
source/lobby/XmppClient.h
68 68 void SendIqGameReport(ScriptInterface& scriptInterface, JS::HandleValue data); 69 69 void SendIqRegisterGame(ScriptInterface& scriptInterface, JS::HandleValue data); 70 70 void SendIqUnregisterGame(); 71 void SendIqChangeStateGame(const std::string& nbp, const std::string& players);71 void SendIqChangeStateGame(const std::string& nbp, const std::string& clients); 72 72 void SetNick(const std::string& nick); 73 73 void GetNick(std::string& nick); 74 74 void kick(const std::string& nick, const std::string& reason);