Implement clientside kick/ban support for the lobby.

Displays a chat notification for all lobby clients if a client is kicked
or banned, pop up a message box for the affected one, including the kick
reason.
Clean the player- and gamelist upon disconnect and disable the control
elements.

Reviewed By: Imarok
Differential Revision: https://code.wildfiregames.com/D116
This was SVN commit r19250.
This commit is contained in:
elexis 2017-02-28 11:16:46 +00:00
parent e14ad3c771
commit 39fcd1d031
4 changed files with 91 additions and 24 deletions

View File

@ -106,6 +106,11 @@ var g_SelectedGameIP = "";
*/
var g_SelectedGamePort = "";
/**
* Whether the current user has been kicked or banned.
*/
var g_Kicked = false;
/**
* Notifications sent by XmppClient.cpp
*/
@ -117,22 +122,24 @@ var g_NetMessageTypes = {
"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 @@ var g_NetMessageTypes = {
}),
"isSpecial": true
});
if (msg.text == g_Username)
Engine.DisconnectXmppClient();
},
"presence": msg => {
},
@ -168,6 +178,12 @@ var g_NetMessageTypes = {
"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 @@ var g_NetMessageTypes = {
}
};
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 @@ function handleSpecialCommand(text)
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 @@ function handleSpecialCommand(text)
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 @@ function addChatMessage(msg)
Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n");
}
/**
* Splits given input into command and argument.
*/
@ -882,11 +937,7 @@ function ircSplit(string)
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 checkSpamMonitor()
*/
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)

View File

@ -88,7 +88,7 @@
</object>
<object name="leftButtonPanel" size="20 100%-75 20% 100%-20">
<object type="button" style="ModernButtonRed" size="0 0 100% 25">
<object name="leaderboardButton" type="button" style="ModernButtonRed" size="0 0 100% 25">
<translatableAttribute id="caption">Leaderboard</translatableAttribute>
<action on="Press">
Engine.SendGetBoardList();
@ -97,7 +97,7 @@
displayProfile("leaderboard");
</action>
</object>
<object type="button" style="ModernButtonRed" size="0 30 100% 100%">
<object name="userprofileButton" type="button" style="ModernButtonRed" size="0 30 100% 100%">
<translatableAttribute id="caption">User Profile Lookup</translatableAttribute>
<action on="Press">
Engine.GetGUIObjectByName("profileFetch").hidden = false;

View File

@ -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 @@ void XmppClient::handleMUCParticipantPresence(glooxwrapper::MUCRoom*, const gloo
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

View File

@ -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 @@ void JSI_Lobby::RegisterScriptFunctions(ScriptInterface& scriptInterface)
bool JSI_Lobby::HasXmppClient(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
{
return (g_XmppClient ? true : false);
return g_XmppClient;
}
bool JSI_Lobby::IsRankedGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))