From 09ba027f9b8285eeea65a7e113b95cdaa45ee7ba Mon Sep 17 00:00:00 2001 From: KalmeMarq <55203647+KalmeMarq@users.noreply.github.com> Date: Thu, 20 Jan 2022 19:38:11 +0000 Subject: [PATCH] Fix chat messages (#272) * added readme pt-pt * added url/querystring deps and fix chat pos/scale url and querystring were missing in node_modules. chat scale option wasn't implemented and chat input was on top instead of bottom. * added bot version text field and guiScale for small screens text field to choose bot version. gui scale changes on small screens (slider takes no effect then). Removed unused images. * Update index.js * fix chat messages and chat on top on mobile * npm fix * fixed mcData var * removed debug stuff and fixed color shadow Co-authored-by: Romain Beaumont --- lib/chat.js | 196 ++++++++++++++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 91 deletions(-) diff --git a/lib/chat.js b/lib/chat.js index 605f0498..fb4bc562 100644 --- a/lib/chat.js +++ b/lib/chat.js @@ -1,4 +1,5 @@ const { LitElement, html, css } = require('lit') +const { isMobile } = require('./menus/components/common') const styles = { black: 'color:#000000', @@ -22,17 +23,16 @@ const styles = { underlined: 'text-decoration:underline', italic: 'font-style:italic' } -const dictionary = { - 'chat.stream.emote': '(%s) * %s %s', - 'chat.stream.text': '(%s) <%s> %s', - // 'chat.type.achievement': '%s has just earned the achievement %s', // 1.8? Not tested - // 'chat.type.advancement.task': '%s has just earned the advancement %s', - // 'chat.type.advancement.goal': '%s has just reached the goal %s', - // 'chat.type.advancement.challenge': '%s did a challenge lolol %s', - 'chat.type.admin': '[%s: %s]', - 'chat.type.announcement': '[%s] %s', - 'chat.type.emote': '* %s %s', - 'chat.type.text': '<%s> %s' + +function colorShadow (hex, dim = 0.25) { + const color = parseInt(hex.replace('#', ''), 16) + + const r = (color >> 16 & 0xFF) * dim | 0 + const g = (color >> 8 & 0xFF) * dim | 0 + const b = (color & 0xFF) * dim | 0 + + const f = (c) => ('00' + c.toString(16)).substr(-2) + return `#${f(r)}${f(g)}${f(b)}` } class ChatBox extends LitElement { @@ -63,6 +63,14 @@ class ChatBox extends LitElement { background-color: rgba(0, 0, 0, 0); } + .input-mobile { + top: 1px; + } + + .display-mobile { + top: 40px; + } + .chat { overflow: hidden; color: white; @@ -137,6 +145,9 @@ class ChatBox extends LitElement { const chat = this.shadowRoot.querySelector('#chat') const chatInput = this.shadowRoot.querySelector('#chatinput') + this.shadowRoot.querySelector('#chat-wrapper2').classList.toggle('input-mobile', isMobile()) + this.shadowRoot.querySelector('#chat-wrapper').classList.toggle('display-mobile', isMobile()) + // Set inChat value this.inChat = true // Exit the pointer lock @@ -155,6 +166,10 @@ class ChatBox extends LitElement { document.querySelector('#hud').shadowRoot.querySelector('#chat').shadowRoot.querySelectorAll('.chat-message').forEach(e => e.classList.add('chat-message-chat-opened')) } + /** + * @param {globalThis.THREE.Renderer} client + * @param {import('minecraft-protocol').Client} renderer + */ init (client, renderer) { this.inChat = false const chat = this.shadowRoot.querySelector('#chat') @@ -168,21 +183,21 @@ class ChatBox extends LitElement { // Show chat chat.style.display = 'block' - const self = this - // Esc event - Doesnt work with onkeypress?! - keypressed is deprecated uk document.addEventListener('keydown', e => { if (gameMenu.inMenu) return - if (!self.inChat) return + if (!this.inChat) return e = e || window.event if (e.code === 'Escape') { disableChat() - } else if (e.keyCode === 38) { + } else if (e.code === 'ArrowUp') { if (this.chatHistoryPos === 0) return chatInput.value = this.chatHistory[--this.chatHistoryPos] !== undefined ? this.chatHistory[this.chatHistoryPos] : '' - } else if (e.keyCode === 40) { + setTimeout(() => { chatInput.setSelectionRange(-1, -1) }, 0) + } else if (e.code === 'ArrowDown') { if (this.chatHistoryPos === this.chatHistory.length) return chatInput.value = this.chatHistory[++this.chatHistoryPos] !== undefined ? this.chatHistory[this.chatHistoryPos] : '' + setTimeout(() => { chatInput.setSelectionRange(-1, -1) }, 0) } }) @@ -192,7 +207,7 @@ class ChatBox extends LitElement { document.addEventListener('keypress', e => { if (gameMenu.inMenu) return e = e || window.event - if (self.inChat === false) { + if (this.inChat === false) { keyBindScrn.keymaps.forEach(km => { if (e.code === km.key) { switch (km.defaultKey) { @@ -209,34 +224,24 @@ class ChatBox extends LitElement { return false } - if (!self.inChat) return + if (!this.inChat) return + e.stopPropagation() + if (e.code === 'Enter') { this.chatHistory.push(chatInput.value) client.write('chat', { message: chatInput.value }) disableChat() } }) - // Enable inputs back when focused - /* document.addEventListener("pointerlockchange", function(event) { - const canvas = document.getElementById("noa-canvas"); - if ( - document.pointerLockElement === canvas || - document.mozPointerLockElement === canvas - ) { - // Someone focused the game back so we hide chat. - chatState.inChat = false; - hideChat(); - } - }); */ - function disableChat () { - self.inChat = false + const disableChat = () => { + this.inChat = false hideChat() renderer.domElement.requestPointerLock() } - function hideChat () { + const hideChat = () => { // Clear chat input chatInput.value = '' // Unfocus it @@ -249,74 +254,83 @@ class ChatBox extends LitElement { document.querySelector('#hud').shadowRoot.querySelector('#chat').shadowRoot.querySelectorAll('.chat-message').forEach(e => e.classList.remove('chat-message-chat-opened')) } - function readExtra (extra) { - const shouldReturn = [] - for (const i in extra) { - if (extra[i].text) { - shouldReturn.push({ - text: extra[i].text, - color: extra[i].color, - bold: !!extra[i].bold, - italic: !!extra[i].italic, - underlined: !!extra[i].underlined, - strikethrough: !!extra[i].strikethrough, - obfuscated: !!extra[i].obfuscated - }) - } else { - readExtra(extra).forEach(function (el) { - shouldReturn.push(el) - }) - } - } - return shouldReturn - } - client.on('chat', (packet) => { // Reading of chat message const fullmessage = JSON.parse(packet.message.toString()) - let msglist = [] - if ( - fullmessage.extra && - fullmessage.extra.length > 0 && - !fullmessage.translate - ) { - msglist = readExtra(fullmessage.extra) - } else if (fullmessage.text && fullmessage.text.length > 0) { - msglist.push({ text: fullmessage.text, color: undefined }) - } else if (dictionary[fullmessage.translate]) { - let msg = dictionary[fullmessage.translate] - fullmessage.with.forEach(obj => { - if (obj.insertion && obj.text) { - msg = msg.replace('%s', obj.text) - } - if (obj.extra) { - if (obj.text && obj.text.length > 0) { - msglist.push({ text: obj.text, color: undefined }) - } else { - const text = readExtra(obj.extra) - if (text.length > 1) { - console.log('Unsupported chat alert :(') - } - msg = msg.replace('%s', text[0].text) - msglist.push({ text: msg, color: undefined }) - } - } - }) - } else { - // msglist.push({ - // text: - // "Unsupported message (Please report this):\n" + - // JSON.stringify(fullmessage), - // color: undefined - // }); + const msglist = [] + + const colorF = (color) => { + return color.trim().startsWith('#') ? `color:${color}` : styles[color] ?? undefined } + + const readMsg = (msglist, msg) => { + const styles = { + color: msg.color, + bold: !!msg.bold, + italic: !!msg.italic, + underlined: !!msg.underlined, + strikethrough: !!msg.strikethrough, + obfuscated: !!msg.obfuscated + } + + if (msg.text) { + msglist.push({ + text: msg.text, + ...styles + }) + } + + if (msg.translate) { + const tText = window.mcData.language[msg.translate] ?? msg.translate + + if (msg.with) { + const splited = tText.split(/%s|%\d+\$s/g) + + let i = 0 + splited.forEach((spl, j, arr) => { + msglist.push({ text: spl, ...styles }) + + if (j + 1 < arr.length) { + if (msg.with[i]) { + if (typeof msg.with[i] === 'string') { + readMsg(msglist, { + ...styles, + text: msg.with[i] + }) + } else { + readMsg(msglist, { + ...styles, + ...msg.with[i] + }) + } + } + i++ + } + }) + } else { + msglist.push({ + text: tText, + ...styles + }) + } + } + + if (msg.extra) { + msg.extra.forEach(ex => { + readMsg(msglist, { ...styles, ...ex }) + }) + } + } + + readMsg(msglist, fullmessage) + const li = document.createElement('li') msglist.forEach(msg => { const span = document.createElement('span') span.appendChild(document.createTextNode(msg.text)) span.setAttribute( 'style', - `${msg.color ? styles[msg.color.toLowerCase()] : styles.white}; ${ + `${msg.color ? colorF(msg.color.toLowerCase()) + `; text-shadow: 1px 1px 0px ${colorShadow(colorF(msg.color.toLowerCase()).replace('color:', ''))}` : styles.white}; ${ msg.bold ? styles.bold + ';' : '' }${msg.italic ? styles.italic + ';' : ''}${ msg.strikethrough ? styles.strikethrough + ';' : ''