Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/gui/lobby/lobby.js
Show All 35 Lines | |||||
* Initial sorting order of the gamelist. | * Initial sorting order of the gamelist. | ||||
*/ | */ | ||||
var g_GameStatusOrder = ["init", "waiting", "running"]; | var g_GameStatusOrder = ["init", "waiting", "running"]; | ||||
/** | /** | ||||
* The playerlist will be assembled using these values. | * The playerlist will be assembled using these values. | ||||
*/ | */ | ||||
var g_PlayerStatuses = { | var g_PlayerStatuses = { | ||||
"available": { "color": "0 219 0", "status": translate("Online") }, | "available": { "color": "0 219 0", "messageBrightness": 1.0, "status": translate("Online") }, | ||||
"away": { "color": "229 76 13", "status": translate("Away") }, | "away": { "color": "229 76 13", "messageBrightness": 0.6, "status": translate("Away") }, | ||||
"playing": { "color": "200 0 0", "status": translate("Busy") }, | "playing": { "color": "200 0 0", "messageBrightness": 0.6, "status": translate("Busy") }, | ||||
"offline": { "color": "0 0 0", "status": translate("Offline") }, | "offline": { "color": "0 0 0", "messageBrightness": 0.6, "status": translate("Offline") }, | ||||
"unknown": { "color": "178 178 178", "status": translateWithContext("lobby presence", "Unknown") } | "unknown": { "color": "178 178 178", "messageBrightness": 0.6, "status": translateWithContext("lobby presence", "Unknown") } | ||||
}; | }; | ||||
var g_RoleNames = { | var g_RoleNames = { | ||||
"moderator": translate("Moderator"), | "moderator": translate("Moderator"), | ||||
"participant": translate("Player"), | "participant": translate("Player"), | ||||
"visitor": translate("Muted Player") | "visitor": translate("Muted Player") | ||||
}; | }; | ||||
Show All 29 Lines | |||||
var g_UserRating = ""; | var g_UserRating = ""; | ||||
/** | /** | ||||
* All games currently running. | * All games currently running. | ||||
*/ | */ | ||||
var g_GameList = {}; | var g_GameList = {}; | ||||
/** | /** | ||||
* All players currently in the lobby. | |||||
*/ | |||||
var g_PlayerList = []; | |||||
/** | |||||
* Used to restore the selection after updating the playerlist. | * Used to restore the selection after updating the playerlist. | ||||
*/ | */ | ||||
var g_SelectedPlayer = ""; | var g_SelectedPlayer = ""; | ||||
/** | /** | ||||
* Used to restore the selection after updating the gamelist. | * Used to restore the selection after updating the gamelist. | ||||
*/ | */ | ||||
var g_SelectedGameIP = ""; | var g_SelectedGameIP = ""; | ||||
/** | /** | ||||
* Used to restore the selection after updating the gamelist. | * Used to restore the selection after updating the gamelist. | ||||
*/ | */ | ||||
var g_SelectedGamePort = ""; | var g_SelectedGamePort = ""; | ||||
/** | /** | ||||
* Whether the current user has been kicked or banned. | * Whether the current user has been kicked or banned. | ||||
*/ | */ | ||||
var g_Kicked = false; | var g_Kicked = false; | ||||
/** | /** | ||||
* Processing of notifications sent by XmppClient.cpp. | * Processing of notifications sent by XmppClient.cpp. | ||||
* | * | ||||
* @returns true if the playerlist GUI must be updated. | * @returns true if the playerlist GUI must be updated. | ||||
elexisUnsubmitted Not Done Inline Actions
elexis: 1. `var g_PlayerList;`
2. List of online players, their ratings and presence state. | |||||
*/ | */ | ||||
var g_NetMessageTypes = { | var g_NetMessageTypes = { | ||||
"system": { | "system": { | ||||
// Three cases are handled in prelobby.js | // Three cases are handled in prelobby.js | ||||
"registered": msg => false, | "registered": msg => false, | ||||
"connected": msg => false, | "connected": msg => false, | ||||
"disconnected": msg => { | "disconnected": msg => { | ||||
▲ Show 20 Lines • Show All 480 Lines • ▼ Show 20 Lines | function updatePlayerList() | ||||
let sortBy = playersBox.selected_column || "name"; | let sortBy = playersBox.selected_column || "name"; | ||||
let sortOrder = playersBox.selected_column_order || 1; | let sortOrder = playersBox.selected_column_order || 1; | ||||
let buddyStatusList = []; | let buddyStatusList = []; | ||||
let playerList = []; | let playerList = []; | ||||
let presenceList = []; | let presenceList = []; | ||||
let nickList = []; | let nickList = []; | ||||
let ratingList = []; | let ratingList = []; | ||||
let index = 0; | |||||
let updateChat = false; | |||||
let playerListPrev = g_PlayerList; | |||||
let updatePlayerSentMsgs = player => { | |||||
player.msgs.sent.brightness = g_PlayerStatuses[player.presence].messageBrightness; | |||||
player.msgs.sent.coloredName = (player.presence != "offline" && | |||||
Engine.ConfigDB_GetValue("user", "lobby.chat.presencedot") == "true" ? | |||||
coloredText(" " + g_BuddySymbol + " ", setColorBrightness( | |||||
g_PlayerStatuses[player.presence].color, | |||||
player.presence == "offline" && Engine.ConfigDB_GetValue("user", "lobby.chat.presencebrightness") == "true" ? | |||||
player.msgs.sent.brightness : 1.0 | |||||
)) : "") + | |||||
colorPlayerName( | |||||
(player.role == "moderator" ? g_ModeratorPrefix : "") + player.name, | |||||
Engine.ConfigDB_GetValue("user", "lobby.chat.rating") == "true" ? | |||||
player.rating : 0, | |||||
player.presence == "offline" && Engine.ConfigDB_GetValue("user", "lobby.chat.presencebrightness") == "true" ? | |||||
player.msgs.sent.brightness : 1.0 | |||||
); | |||||
player.msgs.sent.list.forEach(msg => { | |||||
player.msgs.sent.updateMsg(msg); | |||||
msg.formatted = ircFormat(msg); | |||||
}); | |||||
updateChat = true; | |||||
}; | |||||
let cleanPlayerList = Engine.GetPlayerList().map(player => { | g_PlayerList = Engine.GetPlayerList().map(player => { | ||||
player.isBuddy = g_Buddies.indexOf(player.name) != -1; | player.isBuddy = g_Buddies.indexOf(player.name) != -1; | ||||
let findPlayerPrev = playerPrev => playerPrev.name == player.name && playerPrev; | |||||
ffffffffAuthorUnsubmitted Not Done Inline Actionsrename to isPlayerPrev ffffffff: rename to isPlayerPrev
rid off && playerPrev | |||||
let playerPrev = g_PlayerList[index] && findPlayerPrev(g_PlayerList[index]) || g_PlayerList.find(playerPrev => findPlayerPrev(playerPrev)); | |||||
if (playerPrev) | |||||
{ | |||||
player.msgs = playerPrev.msgs; | |||||
playerPrev.isPresent = true; | |||||
++index; | |||||
} | |||||
else | |||||
player.msgs = { "sent": { | |||||
"coloredName": "", | |||||
"brightness": 255, | |||||
"list": g_ChatMessages.filter(m => m.from && m.from == player.name), | |||||
"updateMsg": msg => { | |||||
msg.coloredFrom = player.msgs.sent.coloredName; | |||||
msg.brightness = player.msgs.sent.brightness; | |||||
msg.moderatorPrefix = (player.role == "moderator" ? g_ModeratorPrefix : ""); | |||||
} } }; | |||||
if (!playerPrev || playerPrev.name != player.name || playerPrev.rating != player.rating || playerPrev.presence != player.presence || | |||||
playerPrev.role != player.role) | |||||
updatePlayerSentMsgs(player); | |||||
return player; | return player; | ||||
}).sort((a, b) => { | }).sort((a, b) => { | ||||
let sortA, sortB; | let sortA, sortB; | ||||
let statusOrder = Object.keys(g_PlayerStatuses); | let statusOrder = Object.keys(g_PlayerStatuses); | ||||
let statusA = statusOrder.indexOf(a.presence) + a.name.toLowerCase(); | let statusA = statusOrder.indexOf(a.presence) + a.name.toLowerCase(); | ||||
let statusB = statusOrder.indexOf(b.presence) + b.name.toLowerCase(); | let statusB = statusOrder.indexOf(b.presence) + b.name.toLowerCase(); | ||||
switch (sortBy) | switch (sortBy) | ||||
Show All 16 Lines | default: | ||||
sortB = b.name.toLowerCase(); | sortB = b.name.toLowerCase(); | ||||
break; | break; | ||||
} | } | ||||
if (sortA < sortB) return -sortOrder; | if (sortA < sortB) return -sortOrder; | ||||
if (sortA > sortB) return +sortOrder; | if (sortA > sortB) return +sortOrder; | ||||
return 0; | return 0; | ||||
}); | }); | ||||
playerListPrev.forEach(playerPrev => !playerPrev.isPresent && (playerPrev.presence = "offline") && updatePlayerSentMsgs(playerPrev)); | |||||
// Colorize list entries | // Colorize list entries | ||||
for (let player of cleanPlayerList) | for (let player of g_PlayerList) | ||||
{ | { | ||||
if (player.rating && player.name == g_Username) | if (player.rating && player.name == g_Username) | ||||
g_UserRating = player.rating; | g_UserRating = player.rating; | ||||
let rating = player.rating ? (" " + player.rating).substr(-5) : " -"; | let rating = player.rating ? (" " + player.rating).substr(-5) : " -"; | ||||
let presence = g_PlayerStatuses[player.presence] ? player.presence : "unknown"; | let presence = g_PlayerStatuses[player.presence] ? player.presence : "unknown"; | ||||
if (presence == "unknown") | if (presence == "unknown") | ||||
warn("Unknown presence:" + player.presence); | warn("Unknown presence:" + player.presence); | ||||
let statusColor = g_PlayerStatuses[presence].color; | let statusColor = g_PlayerStatuses[presence].color; | ||||
buddyStatusList.push(player.isBuddy ? coloredText(g_BuddySymbol, statusColor) : ""); | buddyStatusList.push(player.isBuddy ? coloredText(g_BuddySymbol, statusColor) : ""); | ||||
playerList.push(colorPlayerName((player.role == "moderator" ? g_ModeratorPrefix : "") + player.name)); | playerList.push(colorPlayerName((player.role == "moderator" ? g_ModeratorPrefix : "") + player.name)); | ||||
presenceList.push(coloredText(g_PlayerStatuses[presence].status, statusColor)); | presenceList.push(coloredText(g_PlayerStatuses[presence].status, statusColor)); | ||||
ratingList.push(coloredText(rating, statusColor)); | ratingList.push(coloredText(rating, statusColor)); | ||||
nickList.push(player.name); | nickList.push(player.name); | ||||
} | } | ||||
playersBox.list_buddy = buddyStatusList; | playersBox.list_buddy = buddyStatusList; | ||||
playersBox.list_name = playerList; | playersBox.list_name = playerList; | ||||
playersBox.list_status = presenceList; | playersBox.list_status = presenceList; | ||||
playersBox.list_rating = ratingList; | playersBox.list_rating = ratingList; | ||||
playersBox.list = nickList; | playersBox.list = nickList; | ||||
playersBox.selected = playersBox.list.indexOf(g_SelectedPlayer); | playersBox.selected = playersBox.list.indexOf(g_SelectedPlayer); | ||||
if (updateChat) | |||||
updateChatGUI(); | |||||
} | } | ||||
/** | /** | ||||
* Toggle buddy state for a player in playerlist within the user config | * Toggle buddy state for a player in playerlist within the user config | ||||
*/ | */ | ||||
function toggleBuddy() | function toggleBuddy() | ||||
{ | { | ||||
let playerList = Engine.GetGUIObjectByName("playersBox"); | let playerList = Engine.GetGUIObjectByName("playersBox"); | ||||
▲ Show 20 Lines • Show All 578 Lines • ▼ Show 20 Lines | |||||
* Process and if appropriate, display a formatted message. | * Process and if appropriate, display a formatted message. | ||||
* | * | ||||
* @param {Object} msg - The message to be processed. | * @param {Object} msg - The message to be processed. | ||||
*/ | */ | ||||
function addChatMessage(msg) | function addChatMessage(msg) | ||||
{ | { | ||||
if (msg.from) | if (msg.from) | ||||
{ | { | ||||
if (Engine.LobbyGetPlayerRole(msg.from) == "moderator") | msg.moderatorPrefix = Engine.LobbyGetPlayerRole(msg.from) == "moderator" ? g_ModeratorPrefix : ""; | ||||
msg.from = g_ModeratorPrefix + msg.from; | |||||
if (!g_PlayerList.find(player => { | |||||
Not Done Inline Actionsreturn false for consistency elexis: return false for consistency | |||||
if (player.name == msg.from) | |||||
{ | |||||
// Max. 20 messages can be dynamically changed per a player seems enough. | |||||
if (player.msgs.sent.list.length > 20) | |||||
player.msgs.sent.list.shift(); | |||||
player.msgs.sent.list.push(msg); | |||||
player.msgs.sent.updateMsg(msg); | |||||
return true; | |||||
} | |||||
return false; | |||||
})) | |||||
msg.brightness = g_PlayerStatuses.offline.messageBrightness; | |||||
// Highlight local user's nick | // Highlight local user's nick | ||||
if (g_Username != msg.from) | if (g_Username != msg.from) | ||||
{ | { | ||||
msg.text = msg.text.replace(g_Username, colorPlayerName(g_Username)); | msg.text = msg.text.replace(g_Username, colorPlayerName(g_Username)); | ||||
if (!msg.historic && msg.text.toLowerCase().indexOf(g_Username.toLowerCase()) != -1) | if (!msg.historic && msg.text.toLowerCase().indexOf(g_Username.toLowerCase()) != -1) | ||||
soundNotification("nick"); | soundNotification("nick"); | ||||
} | } | ||||
} | } | ||||
let formatted = ircFormat(msg); | msg.formatted = ircFormat(msg); | ||||
if (!formatted) | if (!msg.formatted) | ||||
return; | return; | ||||
g_ChatMessages.push(formatted); | g_ChatMessages.push(msg); | ||||
Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n"); | updateChatGUI(); | ||||
} | |||||
function updateChatGUI() | |||||
{ | |||||
Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.map(msg => msg.formatted).join("\n"); | |||||
} | } | ||||
/** | /** | ||||
* Splits given input into command and argument. | * Splits given input into command and argument. | ||||
*/ | */ | ||||
function ircSplit(string) | function ircSplit(string) | ||||
{ | { | ||||
let idx = string.indexOf(' '); | let idx = string.indexOf(' '); | ||||
if (idx != -1) | if (idx != -1) | ||||
return [string.substr(1, idx - 1), string.substr(idx + 1)]; | return [string.substr(1, idx - 1), string.substr(idx + 1)]; | ||||
return [string.substr(1), ""]; | return [string.substr(1), ""]; | ||||
} | } | ||||
/** | /** | ||||
* @param {string} color - RGB color string "r g b" | |||||
* @param {float} brightness - Float number 0.0 - 1.0 (more brighten 1.0+) | |||||
*/ | |||||
function setColorBrightness(color, brightness) | |||||
{ | |||||
return color.split(" ").map(colorPart => { let part = Math.round(colorPart * brightness); return part > 255 ? 255 : part; }).join(" "); | |||||
} | |||||
/** | |||||
* Format text in an IRC-like way. | * Format text in an IRC-like way. | ||||
* | * | ||||
* @param {Object} msg - Received chat message. | * @param {Object} msg - Received chat message. | ||||
* @returns {string} - Formatted text. | * @returns {string} - Formatted text. | ||||
*/ | */ | ||||
function ircFormat(msg) | function ircFormat(msg) | ||||
{ | { | ||||
let formattedMessage = ""; | let formattedMessage = ""; | ||||
let coloredFrom = msg.from && colorPlayerName(msg.from); | let brightness = msg.brightness === undefined || | ||||
Engine.ConfigDB_GetValue("user", "lobby.chat.presencebrightness") == "false" ? 1.0 : msg.brightness; | |||||
let coloredFrom = msg.coloredFrom || msg.from && colorPlayerName(msg.moderatorPrefix + msg.from, 0, brightness); | |||||
// Handle commands allowed past handleChatCommand. | // Handle commands allowed past handleChatCommand. | ||||
if (msg.text[0] == '/') | if (msg.text[0] == '/') | ||||
{ | { | ||||
let [command, message] = ircSplit(msg.text); | let [command, message] = ircSplit(msg.text); | ||||
switch (command) | switch (command) | ||||
{ | { | ||||
case "me": | case "me": | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | else | ||||
formattedMessage = sprintf(translate("%(sender)s %(message)s"), { | formattedMessage = sprintf(translate("%(sender)s %(message)s"), { | ||||
"sender": senderFont(senderString), | "sender": senderFont(senderString), | ||||
"message": msg.text | "message": msg.text | ||||
}); | }); | ||||
} | } | ||||
// Add chat message timestamp | // Add chat message timestamp | ||||
if (Engine.ConfigDB_GetValue("user", "chat.timestamp") != "true") | if (Engine.ConfigDB_GetValue("user", "chat.timestamp") != "true") | ||||
return formattedMessage; | return coloredText(formattedMessage, setColorBrightness("255 255 255", brightness)); | ||||
// Translation: Time as shown in the multiplayer lobby (when you enable it in the options page). | // Translation: Time as shown in the multiplayer lobby (when you enable it in the options page). | ||||
// For a list of symbols that you can use, see: | // For a list of symbols that you can use, see: | ||||
// https://sites.google.com/site/icuprojectuserguide/formatparse/datetime?pli=1#TOC-Date-Field-Symbol-Table | // https://sites.google.com/site/icuprojectuserguide/formatparse/datetime?pli=1#TOC-Date-Field-Symbol-Table | ||||
let timeString = Engine.FormatMillisecondsIntoDateStringLocal(msg.time ? msg.time * 1000 : Date.now(), translate("HH:mm")); | let timeString = Engine.FormatMillisecondsIntoDateStringLocal(msg.time ? msg.time * 1000 : Date.now(), translate("HH:mm")); | ||||
// Translation: Time prefix as shown in the multiplayer lobby (when you enable it in the options page). | // Translation: Time prefix as shown in the multiplayer lobby (when you enable it in the options page). | ||||
let timePrefixString = sprintf(translate("\\[%(time)s]"), { | let timePrefixString = sprintf(translate("\\[%(time)s]"), { | ||||
"time": timeString | "time": timeString | ||||
}); | }); | ||||
// Translation: IRC message format when there is a time prefix. | // Translation: IRC message format when there is a time prefix. | ||||
return sprintf(translate("%(time)s %(message)s"), { | return coloredText(sprintf(translate("%(time)s %(message)s"), { | ||||
"time": senderFont(timePrefixString), | "time": senderFont(timePrefixString), | ||||
"message": formattedMessage | "message": formattedMessage | ||||
}); | }), setColorBrightness("255 255 255", brightness)); | ||||
} | } | ||||
/** | /** | ||||
* Generate a (mostly) unique color for this player based on their name. | * Generate a (mostly) unique color for this player based on their name. | ||||
* @see http://stackoverflow.com/questions/3426404/create-a-hexadecimal-colour-based-on-a-string-with-jquery-javascript | * @see http://stackoverflow.com/questions/3426404/create-a-hexadecimal-colour-based-on-a-string-with-jquery-javascript | ||||
* @param {string} playername | * @param {string} playername | ||||
*/ | */ | ||||
function getPlayerColor(playername) | function getPlayerColor(playername) | ||||
Show All 15 Lines | |||||
} | } | ||||
/** | /** | ||||
* Returns the given playername wrapped in an appropriate color-tag. | * Returns the given playername wrapped in an appropriate color-tag. | ||||
* | * | ||||
* @param {string} playername | * @param {string} playername | ||||
* @param {string} rating | * @param {string} rating | ||||
*/ | */ | ||||
function colorPlayerName(playername, rating) | function colorPlayerName(playername, rating, brightness) | ||||
{ | { | ||||
return coloredText( | return coloredText( | ||||
(rating ? sprintf( | (rating ? sprintf( | ||||
translate("%(nick)s (%(rating)s)"), { | translate("%(nick)s (%(rating)s)"), { | ||||
"nick": playername, | "nick": playername, | ||||
"rating": rating | "rating": rating | ||||
}) : playername | }) : playername | ||||
), | ), | ||||
getPlayerColor(playername.replace(g_ModeratorPrefix, ""))); | setColorBrightness(getPlayerColor(playername.replace(g_ModeratorPrefix, "")), brightness === undefined ? 1.0 : brightness)); | ||||
} | } | ||||
function senderFont(text) | function senderFont(text) | ||||
{ | { | ||||
return '[font="' + g_SenderFont + '"]' + text + "[/font]"; | return '[font="' + g_SenderFont + '"]' + text + "[/font]"; | ||||
} | } | ||||
function formatWinRate(attr) | function formatWinRate(attr) | ||||
{ | { | ||||
if (!attr.totalGamesPlayed) | if (!attr.totalGamesPlayed) | ||||
return translateWithContext("Used for an undefined winning rate", "-"); | return translateWithContext("Used for an undefined winning rate", "-"); | ||||
return sprintf(translate("%(percentage)s%%"), { | return sprintf(translate("%(percentage)s%%"), { | ||||
"percentage": (attr.wins / attr.totalGamesPlayed * 100).toFixed(2) | "percentage": (attr.wins / attr.totalGamesPlayed * 100).toFixed(2) | ||||
}); | }); | ||||
} | } |
Wildfire Games · Phabricator