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 = ""; var g_SelectedGamePort = "";
/**
* Whether the current user has been kicked or banned.
*/
var g_Kicked = false;
/** /**
* Notifications sent by XmppClient.cpp * Notifications sent by XmppClient.cpp
*/ */
@ -117,22 +122,24 @@ var g_NetMessageTypes = {
"connected": msg => { "connected": msg => {
}, },
"disconnected": msg => { "disconnected": msg => {
updateGameList(); updateGameList();
updateLeaderboard(); updateLeaderboard();
updatePlayerList(); updatePlayerList();
Engine.GetGUIObjectByName("hostButton").enabled = false;
addChatMessage({ for (let button of ["host", "leaderboard", "userprofile"])
"from": "system", Engine.GetGUIObjectByName(button + "Button").enabled = false;
"text": translate("Disconnected.") + msg.text,
"color": g_SystemColor if (!g_Kicked)
}); addChatMessage({
"from": "system",
"text": translate("Disconnected.") + " " + msg.text
});
}, },
"error": msg => { "error": msg => {
addChatMessage({ addChatMessage({
"from": "system", "from": "system",
"text": msg.text, "text": msg.text
"color": g_SystemColor
}); });
} }
}, },
@ -156,6 +163,9 @@ var g_NetMessageTypes = {
}), }),
"isSpecial": true "isSpecial": true
}); });
if (msg.text == g_Username)
Engine.DisconnectXmppClient();
}, },
"presence": msg => { "presence": msg => {
}, },
@ -168,6 +178,12 @@ var g_NetMessageTypes = {
"isSpecial": true "isSpecial": true
}); });
}, },
"kicked": msg => {
handleKick(false, msg.text, msg.data || "");
},
"banned": msg => {
handleKick(true, msg.text, msg.data || "");
},
"room-message": msg => { "room-message": msg => {
addChatMessage({ addChatMessage({
"from": escapeText(msg.from), "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. * Called after the XmppConnection succeeded and when returning from a game.
* *
@ -785,7 +841,8 @@ function handleSpecialCommand(text)
if (text[0] != '/') if (text[0] != '/')
return false; return false;
let [cmd, nick] = ircSplit(text); let [cmd, args] = ircSplit(text);
let [nick, reason] = ircSplit("/" + args);
switch (cmd) switch (cmd)
{ {
@ -796,11 +853,10 @@ function handleSpecialCommand(text)
Engine.LobbySetPlayerPresence("available"); Engine.LobbySetPlayerPresence("available");
break; break;
case "kick": case "kick":
// TODO: Split reason from nick and pass it too Engine.LobbyKick(nick, reason);
Engine.LobbyKick(nick, "");
break; break;
case "ban": case "ban":
Engine.LobbyBan(nick, ""); Engine.LobbyBan(nick, reason);
break; break;
case "quit": case "quit":
returnToMainMenu(); returnToMainMenu();
@ -859,7 +915,6 @@ function addChatMessage(msg)
Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n"); Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n");
} }
/** /**
* Splits given input into command and argument. * Splits given input into command and argument.
*/ */
@ -882,11 +937,7 @@ function ircSplit(string)
function ircFormat(msg) function ircFormat(msg)
{ {
let formattedMessage = ""; let formattedMessage = "";
let coloredFrom = msg.from && colorPlayerName(msg.from);
let coloredFrom = !msg.from ? "" :
msg.color ?
'[color="' + msg.color + '"]' + msg.from + "[/color]" :
colorPlayerName(msg.from);
// Handle commands allowed past handleSpecialCommand. // Handle commands allowed past handleSpecialCommand.
if (msg.text[0] == '/') if (msg.text[0] == '/')
@ -1094,6 +1145,9 @@ function checkSpamMonitor()
*/ */
function getPlayerColor(playername) 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. // Generate a probably-unique hash for the player name and use that to create a color.
let hash = 0; let hash = 0;
for (let i in playername) for (let i in playername)

View File

@ -88,7 +88,7 @@
</object> </object>
<object name="leftButtonPanel" size="20 100%-75 20% 100%-20"> <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> <translatableAttribute id="caption">Leaderboard</translatableAttribute>
<action on="Press"> <action on="Press">
Engine.SendGetBoardList(); Engine.SendGetBoardList();
@ -97,7 +97,7 @@
displayProfile("leaderboard"); displayProfile("leaderboard");
</action> </action>
</object> </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> <translatableAttribute id="caption">User Profile Lookup</translatableAttribute>
<action on="Press"> <action on="Press">
Engine.GetGUIObjectByName("profileFetch").hidden = false; 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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][0] = presenceString;
m_PlayerMap[newNick][2] = roleString; m_PlayerMap[newNick][2] = roleString;
CreateGUIMessage("chat", "nick", nick, participant.newNick.to_string()); 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 else
{
DbgXMPP(nick << " left the room (flags " << flags << participant.flags << ")");
CreateGUIMessage("chat", "leave", nick); CreateGUIMessage("chat", "leave", nick);
}
DbgXMPP(nick << " left the room");
m_PlayerMap.erase(nick); m_PlayerMap.erase(nick);
} }
else 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. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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)) bool JSI_Lobby::HasXmppClient(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))
{ {
return (g_XmppClient ? true : false); return g_XmppClient;
} }
bool JSI_Lobby::IsRankedGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) bool JSI_Lobby::IsRankedGame(ScriptInterface::CxPrivate* UNUSED(pCxPrivate))