Index: ps/trunk/binaries/data/mods/public/gui/lobby/lobby.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/lobby/lobby.js +++ ps/trunk/binaries/data/mods/public/gui/lobby/lobby.js @@ -107,6 +107,11 @@ var g_SelectedGamePort = ""; /** + * Whether the current user has been kicked or banned. + */ +var g_Kicked = false; + +/** * Notifications sent by XmppClient.cpp */ var g_NetMessageTypes = { @@ -117,22 +122,24 @@ "connected": msg => { }, "disconnected": msg => { + updateGameList(); updateLeaderboard(); updatePlayerList(); - Engine.GetGUIObjectByName("hostButton").enabled = false; - addChatMessage({ - "from": "system", - "text": translate("Disconnected.") + msg.text, - "color": g_SystemColor - }); + for (let button of ["host", "leaderboard", "userprofile"]) + Engine.GetGUIObjectByName(button + "Button").enabled = false; + + if (!g_Kicked) + addChatMessage({ + "from": "system", + "text": translate("Disconnected.") + " " + msg.text + }); }, "error": msg => { addChatMessage({ "from": "system", - "text": msg.text, - "color": g_SystemColor + "text": msg.text }); } }, @@ -156,6 +163,9 @@ }), "isSpecial": true }); + + if (msg.text == g_Username) + Engine.DisconnectXmppClient(); }, "presence": msg => { }, @@ -168,6 +178,12 @@ "isSpecial": true }); }, + "kicked": msg => { + handleKick(false, msg.text, msg.data || ""); + }, + "banned": msg => { + handleKick(true, msg.text, msg.data || ""); + }, "room-message": msg => { addChatMessage({ "from": escapeText(msg.from), @@ -194,6 +210,46 @@ } }; +function handleKick(banned, nick, reason) +{ + let kickString = nick == g_Username ? + banned ? + translate("You have been banned from the lobby!") : + translate("You have been kicked from the lobby!") : + banned ? + translate("%(nick)s has been banned from the lobby.") : + translate("%(nick)s has been kicked from the lobby."); + + if (reason) + reason = sprintf(translateWithContext("lobby kick", "Reason: %(reason)s"), { + "reason": reason + }); + + if (nick != g_Username) + { + addChatMessage({ + "text": "/special " + sprintf(kickString, { "nick": nick }) + " " + reason, + "isSpecial": true + }); + return; + } + + addChatMessage({ + "from": "system", + "text": kickString + " " + reason, + }); + + g_Kicked = true; + + Engine.DisconnectXmppClient(); + + messageBox( + 400, 250, + kickString + "\n" + reason, + banned ? translate("BANNED") : translate("KICKED") + ); +} + /** * Called after the XmppConnection succeeded and when returning from a game. * @@ -785,7 +841,8 @@ if (text[0] != '/') return false; - let [cmd, nick] = ircSplit(text); + let [cmd, args] = ircSplit(text); + let [nick, reason] = ircSplit("/" + args); switch (cmd) { @@ -796,11 +853,10 @@ Engine.LobbySetPlayerPresence("available"); break; case "kick": - // TODO: Split reason from nick and pass it too - Engine.LobbyKick(nick, ""); + Engine.LobbyKick(nick, reason); break; case "ban": - Engine.LobbyBan(nick, ""); + Engine.LobbyBan(nick, reason); break; case "quit": returnToMainMenu(); @@ -859,7 +915,6 @@ Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n"); } - /** * Splits given input into command and argument. */ @@ -882,11 +937,7 @@ function ircFormat(msg) { let formattedMessage = ""; - - let coloredFrom = !msg.from ? "" : - msg.color ? - '[color="' + msg.color + '"]' + msg.from + "[/color]" : - colorPlayerName(msg.from); + let coloredFrom = msg.from && colorPlayerName(msg.from); // Handle commands allowed past handleSpecialCommand. if (msg.text[0] == '/') @@ -1094,6 +1145,9 @@ */ function getPlayerColor(playername) { + if (playername == "system") + return g_SystemColor; + // Generate a probably-unique hash for the player name and use that to create a color. let hash = 0; for (let i in playername) Index: ps/trunk/binaries/data/mods/public/gui/lobby/lobby.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/lobby/lobby.xml +++ ps/trunk/binaries/data/mods/public/gui/lobby/lobby.xml @@ -88,7 +88,7 @@ - + Leaderboard Engine.SendGetBoardList(); @@ -97,7 +97,7 @@ displayProfile("leaderboard"); - + User Profile Lookup Engine.GetGUIObjectByName("profileFetch").hidden = false; Index: ps/trunk/source/lobby/XmppClient.cpp =================================================================== --- ps/trunk/source/lobby/XmppClient.cpp +++ ps/trunk/source/lobby/XmppClient.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -797,11 +797,24 @@ m_PlayerMap[newNick][0] = presenceString; m_PlayerMap[newNick][2] = roleString; CreateGUIMessage("chat", "nick", nick, participant.newNick.to_string()); + DbgXMPP(nick << " is now known as " << participant.newNick.to_string()); + } + else if (participant.flags & gloox::UserKicked) + { + DbgXMPP(nick << " was kicked. Reason: " << participant.reason.to_string()); + CreateGUIMessage("chat", "kicked", nick, participant.reason.to_string()); + } + else if (participant.flags & gloox::UserBanned) + { + DbgXMPP(nick << " was banned. Reason: " << participant.reason.to_string()); + CreateGUIMessage("chat", "banned", nick, participant.reason.to_string()); } else + { + DbgXMPP(nick << " left the room (flags " << flags << participant.flags << ")"); CreateGUIMessage("chat", "leave", nick); + } - DbgXMPP(nick << " left the room"); m_PlayerMap.erase(nick); } else Index: ps/trunk/source/lobby/scripting/JSInterface_Lobby.cpp =================================================================== --- ps/trunk/source/lobby/scripting/JSInterface_Lobby.cpp +++ ps/trunk/source/lobby/scripting/JSInterface_Lobby.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -69,7 +69,7 @@ bool JSI_Lobby::HasXmppClient(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) { - return (g_XmppClient ? true : false); + return g_XmppClient; } bool JSI_Lobby::IsRankedGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))