mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-07-04 05:55:47 -07:00
Shows a notification if the local client or other players connections timeout or have bad latency. This was SVN commit r17730.
200 lines
5.3 KiB
JavaScript
200 lines
5.3 KiB
JavaScript
/**
|
|
* Number of milliseconds to display network warnings.
|
|
*/
|
|
const g_NetworkWarningTimeout = 3000;
|
|
|
|
/**
|
|
* Currently displayed network warnings. At most one message per user.
|
|
*/
|
|
var g_NetworkWarnings = {};
|
|
|
|
/**
|
|
* Message-types to be displayed.
|
|
*/
|
|
var g_NetworkWarningTexts = {
|
|
|
|
"server-timeout": (msg, username) =>
|
|
sprintf(translate("Losing connection to server (%(seconds)s)"), {
|
|
"seconds": Math.ceil(msg.lastReceivedTime / 1000)
|
|
}),
|
|
|
|
"client-timeout": (msg, username) =>
|
|
sprintf(translate("%(player)s losing connection (%(seconds)s)"), {
|
|
"player": username,
|
|
"seconds": Math.ceil(msg.lastReceivedTime / 1000)
|
|
}),
|
|
|
|
"server-latency": (msg, username) =>
|
|
sprintf(translate("Bad connection to server (%(milliseconds)sms)"), {
|
|
"milliseconds": msg.meanRTT
|
|
}),
|
|
|
|
"client-latency": (msg, username) =>
|
|
sprintf(translate("Bad connection to %(player)s (%(milliseconds)sms)"), {
|
|
"player": username,
|
|
"milliseconds": msg.meanRTT
|
|
})
|
|
};
|
|
|
|
var g_NetworkCommands = {
|
|
"/kick": argument => kickPlayer(argument, false),
|
|
"/ban": argument => kickPlayer(argument, true),
|
|
"/list": argument => addChatMessage({ "type": "clientlist" }),
|
|
"/clear": argument => clearChatMessages()
|
|
};
|
|
|
|
/**
|
|
* Must be kept in sync with source/network/NetHost.h
|
|
*/
|
|
function getDisconnectReason(id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case 0: return translate("Unknown reason");
|
|
case 1: return translate("The host has ended the game");
|
|
case 2: return translate("Incorrect network protocol version");
|
|
case 3: return translate("Game is loading, please try later");
|
|
case 4: return translate("Game has already started, no observers allowed");
|
|
case 5: return translate("You have been kicked");
|
|
case 6: return translate("You have been banned");
|
|
default:
|
|
warn("Unknown disconnect-reason ID received: " + id);
|
|
return sprintf(translate("\\[Invalid value %(id)s]"), { "id": id });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show the disconnect reason in a message box.
|
|
*
|
|
* @param {number} reason
|
|
*/
|
|
function reportDisconnect(reason)
|
|
{
|
|
// Translation: States the reason why the client disconnected from the server.
|
|
let reasonText = sprintf(translate("Reason: %(reason)s."), { "reason": getDisconnectReason(reason) });
|
|
messageBox(400, 200, translate("Lost connection to the server.") + "\n\n" + reasonText, translate("Disconnected"), 2);
|
|
}
|
|
|
|
function kickPlayer(username, ban)
|
|
{
|
|
if (!Engine.KickPlayer(username, ban))
|
|
addChatMessage({
|
|
"type": "system",
|
|
"text": sprintf(ban ? translate("Could not ban %(name)s.") : translate("Could not kick %(name)s."), {
|
|
"name": username
|
|
})
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get a colorized list of usernames sorted by player slot, observers last.
|
|
* Requires g_PlayerAssignments and colorizePlayernameByGUID.
|
|
*
|
|
* @returns {string}
|
|
*/
|
|
function getUsernameList()
|
|
{
|
|
let usernames = Object.keys(g_PlayerAssignments).sort((guidA, guidB) => {
|
|
|
|
let playerIdA = g_PlayerAssignments[guidA].player;
|
|
let playerIdB = g_PlayerAssignments[guidB].player;
|
|
|
|
// Sort observers last
|
|
if (playerIdA == -1) return +1;
|
|
if (playerIdB == -1) return -1;
|
|
|
|
// Sort players
|
|
return playerIdA - playerIdB;
|
|
|
|
}).map(guid => colorizePlayernameByGUID(guid));
|
|
|
|
return sprintf(translate("Users: %(users)s"),
|
|
// Translation: This comma is used for separating first to penultimate elements in an enumeration.
|
|
{ "users": usernames.join(translate(", ")) });
|
|
}
|
|
|
|
/**
|
|
* Execute a command locally. Requires addChatMessage.
|
|
*
|
|
* @param {string} input
|
|
* @returns {Boolean} whether a command was executed
|
|
*/
|
|
function executeNetworkCommand(input)
|
|
{
|
|
if (input.indexOf("/") != 0)
|
|
return false;
|
|
|
|
let command = input.split(" ", 1)[0];
|
|
let argument = input.substr(command.length + 1);
|
|
|
|
if (g_NetworkCommands[command])
|
|
g_NetworkCommands[command](argument);
|
|
|
|
return !!g_NetworkCommands[command];
|
|
}
|
|
|
|
/**
|
|
* Remember this warning for a few seconds.
|
|
* Overwrite previous warnings for this user.
|
|
*
|
|
* @param msg - GUI message sent by NetServer or NetClient
|
|
*/
|
|
function addNetworkWarning(msg)
|
|
{
|
|
if (!g_NetworkWarningTexts[msg.warntype])
|
|
{
|
|
warn("Unknown network warning type received: " + uneval(msg));
|
|
return;
|
|
}
|
|
|
|
if (Engine.ConfigDB_GetValue("user", "overlay.netwarnings") != "true")
|
|
return;
|
|
|
|
g_NetworkWarnings[msg.guid || "server"] = {
|
|
"added": Date.now(),
|
|
"msg": msg
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Colorizes and concatenates all network warnings.
|
|
* Returns text and textWidth.
|
|
*/
|
|
function getNetworkWarnings()
|
|
{
|
|
// Remove outdated messages
|
|
for (let guid in g_NetworkWarnings)
|
|
{
|
|
if (Date.now() > g_NetworkWarnings[guid].added + g_NetworkWarningTimeout)
|
|
delete g_NetworkWarnings[guid];
|
|
|
|
if (guid != "server" && !g_PlayerAssignments[guid])
|
|
delete g_NetworkWarnings[guid];
|
|
}
|
|
|
|
// Show local messages first
|
|
let guids = Object.keys(g_NetworkWarnings).sort(guid => guid != "server");
|
|
|
|
let font = Engine.GetGUIObjectByName("gameStateNotifications").font;
|
|
|
|
let messages = [];
|
|
let maxTextWidth = 0;
|
|
|
|
for (let guid of guids)
|
|
{
|
|
let msg = g_NetworkWarnings[guid].msg;
|
|
|
|
// Add formatted text
|
|
messages.push(g_NetworkWarningTexts[msg.warntype](msg, colorizePlayernameByGUID(guid)));
|
|
|
|
// Add width of unformatted text
|
|
let username = guid != "server" && g_PlayerAssignments[guid].name;
|
|
let textWidth = Engine.GetTextWidth(font, g_NetworkWarningTexts[msg.warntype](msg, username));
|
|
maxTextWidth = Math.max(textWidth, maxTextWidth);
|
|
}
|
|
|
|
return {
|
|
"messages": messages,
|
|
"maxTextWidth": maxTextWidth
|
|
};
|
|
}
|