Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -399,6 +399,11 @@ xpartamupp = "wfgbot23" ; Name of the server-side xmpp client that manage games buddies = "," ; Comma separated list of playernames that the current user has marked as buddies +[lobby.chat] +presencedot = false ; Show presence on sender of a chat message +rating = false ; Show player rating on sender of a chat message +presencebrightness = true ; Light message according to sender presence + [lobby.columns] gamerating = false ; Show the average rating of the participating players in a column of the gamelist Index: binaries/data/mods/public/gui/lobby/lobby.js =================================================================== --- binaries/data/mods/public/gui/lobby/lobby.js +++ binaries/data/mods/public/gui/lobby/lobby.js @@ -41,11 +41,11 @@ * The playerlist will be assembled using these values. */ var g_PlayerStatuses = { - "available": { "color": "0 219 0", "status": translate("Online") }, - "away": { "color": "229 76 13", "status": translate("Away") }, - "playing": { "color": "200 0 0", "status": translate("Busy") }, - "offline": { "color": "0 0 0", "status": translate("Offline") }, - "unknown": { "color": "178 178 178", "status": translateWithContext("lobby presence", "Unknown") } + "available": { "color": "0 219 0", "messageBrightness": 1.0, "status": translate("Online") }, + "away": { "color": "229 76 13", "messageBrightness": 0.6, "status": translate("Away") }, + "playing": { "color": "200 0 0", "messageBrightness": 0.6, "status": translate("Busy") }, + "offline": { "color": "0 0 0", "messageBrightness": 0.6, "status": translate("Offline") }, + "unknown": { "color": "178 178 178", "messageBrightness": 0.6, "status": translateWithContext("lobby presence", "Unknown") } }; var g_RoleNames = { @@ -91,6 +91,11 @@ var g_GameList = {}; /** + * All players currently in the lobby. + */ +var g_PlayerList = []; + +/** * Used to restore the selection after updating the playerlist. */ var g_SelectedPlayer = ""; @@ -610,9 +615,60 @@ let presenceList = []; let nickList = []; 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; + + let findPlayerPrev = playerPrev => playerPrev.name == player.name && 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; }).sort((a, b) => { let sortA, sortB; @@ -645,8 +701,10 @@ return 0; }); + playerListPrev.forEach(playerPrev => !playerPrev.isPresent && (playerPrev.presence = "offline") && updatePlayerSentMsgs(playerPrev)); + // Colorize list entries - for (let player of cleanPlayerList) + for (let player of g_PlayerList) { if (player.rating && player.name == g_Username) g_UserRating = player.rating; @@ -671,6 +729,9 @@ playersBox.list = nickList; playersBox.selected = playersBox.list.indexOf(g_SelectedPlayer); + + if (updateChat) + updateChatGUI(); } /** @@ -1265,8 +1326,21 @@ { if (msg.from) { - if (Engine.LobbyGetPlayerRole(msg.from) == "moderator") - msg.from = g_ModeratorPrefix + msg.from; + msg.moderatorPrefix = Engine.LobbyGetPlayerRole(msg.from) == "moderator" ? g_ModeratorPrefix : ""; + + if (!g_PlayerList.find(player => { + 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 if (g_Username != msg.from) @@ -1277,13 +1351,18 @@ soundNotification("nick"); } } - - let formatted = ircFormat(msg); - if (!formatted) + + msg.formatted = ircFormat(msg); + if (!msg.formatted) return; - g_ChatMessages.push(formatted); - Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.join("\n"); + g_ChatMessages.push(msg); + updateChatGUI(); +} + +function updateChatGUI() +{ + Engine.GetGUIObjectByName("chatText").caption = g_ChatMessages.map(msg => msg.formatted).join("\n"); } /** @@ -1300,6 +1379,15 @@ } /** + * @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. * * @param {Object} msg - Received chat message. @@ -1308,7 +1396,9 @@ function ircFormat(msg) { 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. if (msg.text[0] == '/') @@ -1394,7 +1484,7 @@ // Add chat message timestamp 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). // For a list of symbols that you can use, see: @@ -1407,10 +1497,10 @@ }); // 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), "message": formattedMessage - }); + }), setColorBrightness("255 255 255", brightness)); } /** @@ -1442,7 +1532,7 @@ * @param {string} playername * @param {string} rating */ -function colorPlayerName(playername, rating) +function colorPlayerName(playername, rating, brightness) { return coloredText( (rating ? sprintf( @@ -1451,7 +1541,7 @@ "rating": rating }) : playername ), - getPlayerColor(playername.replace(g_ModeratorPrefix, ""))); + setColorBrightness(getPlayerColor(playername.replace(g_ModeratorPrefix, "")), brightness === undefined ? 1.0 : brightness)); } function senderFont(text)