move chat to web component ()

This commit is contained in:
Romain Beaumont 2021-03-14 20:34:35 +01:00 committed by GitHub
parent 332d28e1c5
commit cc1a14ea4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 250 additions and 249 deletions

View file

@ -7,16 +7,7 @@
</head> </head>
<body> <body>
<img id="crosshair" src="extra-textures/icons.png" style="display: none;"> <img id="crosshair" src="extra-textures/icons.png" style="display: none;">
<div id="chat-wrapper" class="chat-wrapper chat-display-wrapper" style="display: none;"> <chat-box id="chatbox" style="display: none;"></chat-box>
<div class="chat" id="chat">
<p>Welcome to prismarine-web-client! Chat appears here.</p>
</div>
</div>
<div id="chat-wrapper2" class="chat-wrapper chat-input-wrapper" style="display: none;">
<div class="chat" id="chat-input">
<input type="text" class="chat" id="chatinput"></input>
</div>
</div>
<hot-bar id="hotbar" style="display: none;"></hot-bar> <hot-bar id="hotbar" style="display: none;"></hot-bar>
<loading-screen id="loading-background" style="display: none;"></loading-screen> <loading-screen id="loading-background" style="display: none;"></loading-screen>
<prismarine-menu id="prismarine-menu"></prismarine-menu> <prismarine-menu id="prismarine-menu"></prismarine-menu>

View file

@ -2,6 +2,7 @@
require('./lib/menu') require('./lib/menu')
require('./lib/loading_screen') require('./lib/loading_screen')
require('./lib/hotbar') require('./lib/hotbar')
require('./lib/chat')
const net = require('net') const net = require('net')
@ -13,7 +14,6 @@ const { WorldView, Viewer } = require('prismarine-viewer/viewer')
const pathfinder = require('mineflayer-pathfinder') const pathfinder = require('mineflayer-pathfinder')
const { Vec3 } = require('vec3') const { Vec3 } = require('vec3')
global.THREE = require('three') global.THREE = require('three')
const Chat = require('./lib/chat')
const maxPitch = 0.5 * Math.PI const maxPitch = 0.5 * Math.PI
const minPitch = -0.5 * Math.PI const minPitch = -0.5 * Math.PI
@ -25,8 +25,7 @@ async function main () {
menu.style = 'display: none;' menu.style = 'display: none;'
document.getElementById('hotbar').style = 'display:block' document.getElementById('hotbar').style = 'display:block'
document.getElementById('crosshair').style = 'display:block' document.getElementById('crosshair').style = 'display:block'
document.getElementById('chat-wrapper').style = 'display:block' document.getElementById('chatbox').style = 'display:block'
document.getElementById('chat-wrapper2').style = 'display:block'
document.getElementById('loading-background').style = 'display:block' document.getElementById('loading-background').style = 'display:block'
connect(options) connect(options)
@ -36,6 +35,7 @@ async function main () {
async function connect (options) { async function connect (options) {
const loadingScreen = document.getElementById('loading-background') const loadingScreen = document.getElementById('loading-background')
const hotbar = document.getElementById('hotbar') const hotbar = document.getElementById('hotbar')
const chat = document.getElementById('chatbox')
const viewDistance = 6 const viewDistance = 6
const hostprompt = options.server const hostprompt = options.server
@ -119,7 +119,7 @@ async function connect (options) {
renderer.setSize(window.innerWidth, window.innerHeight) renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement) document.body.appendChild(renderer.domElement)
const chat = Chat.init(bot._client, renderer) chat.init(bot._client, renderer)
// Create viewer // Create viewer
const viewer = new Viewer(renderer) const viewer = new Viewer(renderer)

View file

@ -1,3 +1,5 @@
const { LitElement, html, css } = require('lit-element')
const styles = { const styles = {
black: 'color:#000000', black: 'color:#000000',
dark_blue: 'color:#0000AA', dark_blue: 'color:#0000AA',
@ -33,193 +35,254 @@ const dictionary = {
'chat.type.text': '<%s> %s' 'chat.type.text': '<%s> %s'
} }
export function init (client, renderer) { class ChatBox extends LitElement {
const chat = document.querySelector('#chat') static get styles () {
const chatInput = document.querySelector('#chatinput') return css`
.chat-wrapper {
position: fixed;
background-color: rgba(0, 0, 0, 0.5);
z-index:10;
}
const chatHistory = [] .chat-display-wrapper {
let chatHistoryPos = 0 bottom: calc(8px * 16);
padding: 4px;
max-height: calc(90px * 8);
width: calc(320px * 4);
}
renderer.domElement.requestPointerLock = renderer.domElement.requestPointerLock || .chat-input-wrapper {
renderer.domElement.mozRequestPointerLock || bottom: calc(2px * 16);
renderer.domElement.webkitRequestPointerLock width: 100%;
overflow: hidden;
background-color: rgba(0, 0, 0, 0);
}
// Show chat .chat {
chat.style.display = 'block' overflow: hidden;
color: white;
font-size: 16px;
margin: 0px;
line-height: 100%;
text-shadow: 2px 2px 0px #3f3f3f;
font-family: mojangles, minecraft, monospace;
width: 100%;
max-height: calc(90px * 8)
}
const chatState = { input[type=text], #chatinput {
inChat: false background-color: rgba(0, 0, 0, 0.5);
display: none;
}
li {
display: block;
}
`
} }
// Esc event - Doesnt work with onkeypress?! render () {
document.onkeydown = function (e) { return html`
if (!chatState.inChat) return <div id="chat-wrapper" class="chat-wrapper chat-display-wrapper">
e = e || window.event <div class="chat" id="chat">
if (e.keyCode === 27 || e.key === 'Escape' || e.key === 'Esc') { <p>Welcome to prismarine-web-client! Chat appears here.</p>
disableChat() </div>
} else if (e.keyCode === 38) { </div>
if (chatHistoryPos === 0) return <div id="chat-wrapper2" class="chat-wrapper chat-input-wrapper">
chatInput.value = chatHistory[--chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : '' <div class="chat" id="chat-input">
} else if (e.keyCode === 40) { <input type="text" class="chat" id="chatinput"></input>
if (chatHistoryPos === chatHistory.length) return </div>
chatInput.value = chatHistory[++chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : '' </div>
`
}
init (client, renderer) {
this.inChat = false
const chat = this.shadowRoot.querySelector('#chat')
const chatInput = this.shadowRoot.querySelector('#chatinput')
const chatHistory = []
let chatHistoryPos = 0
renderer.domElement.requestPointerLock = renderer.domElement.requestPointerLock ||
renderer.domElement.mozRequestPointerLock ||
renderer.domElement.webkitRequestPointerLock
// Show chat
chat.style.display = 'block'
const self = this
// Esc event - Doesnt work with onkeypress?!
document.onkeydown = function (e) {
if (!self.inChat) return
e = e || window.event
if (e.keyCode === 27 || e.key === 'Escape' || e.key === 'Esc') {
disableChat()
} else if (e.keyCode === 38) {
if (chatHistoryPos === 0) return
chatInput.value = chatHistory[--chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : ''
} else if (e.keyCode === 40) {
if (chatHistoryPos === chatHistory.length) return
chatInput.value = chatHistory[++chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : ''
}
} }
}
// Chat events // Chat events
document.onkeypress = function (e) { document.onkeypress = function (e) {
e = e || window.event e = e || window.event
if (chatState.inChat === false) { if (self.inChat === false) {
if (e.code === 'KeyT') { if (e.code === 'KeyT') {
enableChat(false) enableChat(false)
}
if (e.code === 'Slash') {
enableChat(true)
}
return false
} }
if (e.code === 'Slash') { if (!self.inChat) return
enableChat(true) e.stopPropagation()
if (e.code === 'Enter') {
chatHistory.push(chatInput.value)
client.write('chat', { message: chatInput.value })
disableChat()
} }
return false }
// 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 enableChat (isCommand) {
// Set inChat value
self.inChat = true
// Exit the pointer lock
document.exitPointerLock()
// Show chat input
chatInput.style.display = 'block'
// Show extended chat history
chat.style.maxHeight = 'calc(90px * 8)'
chat.scrollTop = chat.scrollHeight // Stay bottom of the list
if (isCommand) { // handle commands
chatInput.value = '/'
}
// Focus element
chatInput.focus()
chatHistoryPos = chatHistory.length
} }
if (!chatState.inChat) return function disableChat () {
e.stopPropagation() // Set inChat value
if (e.code === 'Enter') { self.inChat = false
chatHistory.push(chatInput.value)
client.write('chat', { message: chatInput.value }) // Hide chat
disableChat() hideChat()
renderer.domElement.requestPointerLock()
} }
}
// Enable inputs back when focused function hideChat () {
/* document.addEventListener("pointerlockchange", function(event) { // Clear chat input
const canvas = document.getElementById("noa-canvas"); chatInput.value = ''
if ( // Unfocus it
document.pointerLockElement === canvas || chatInput.blur()
document.mozPointerLockElement === canvas // Hide it
) { chatInput.style.display = 'none'
// Someone focused the game back so we hide chat. // Hide extended chat history
chatState.inChat = false; chat.style.maxHeight = 'calc(90px * 4)'
hideChat(); chat.scrollTop = chat.scrollHeight // Stay bottom of the list
} }
}); */
function enableChat (isCommand) { function readExtra (extra) {
// Set inChat value const shouldReturn = []
chatState.inChat = true for (const i in extra) {
// Exit the pointer lock if (extra[i].text) {
document.exitPointerLock() shouldReturn.push({
// Show chat input text: extra[i].text,
chatInput.style.display = 'block' color: extra[i].color,
// Show extended chat history bold: !!extra[i].bold,
chat.style.maxHeight = 'calc(90px * 8)' italic: !!extra[i].italic,
chat.scrollTop = chat.scrollHeight // Stay bottom of the list underlined: !!extra[i].underlined,
if (isCommand) { // handle commands strikethrough: !!extra[i].strikethrough,
chatInput.value = '/' obfuscated: !!extra[i].obfuscated
})
} else {
readExtra(extra).forEach(function (el) {
shouldReturn.push(el)
})
}
}
return shouldReturn
} }
// Focus element
chatInput.focus()
chatHistoryPos = chatHistory.length
}
function disableChat () { client.on('chat', (packet) => {
// Set inChat value // Reading of chat message
chatState.inChat = false const fullmessage = JSON.parse(packet.message.toString())
let msglist = []
// Hide chat if (
hideChat() fullmessage.extra &&
fullmessage.extra.length > 0 &&
renderer.domElement.requestPointerLock() !fullmessage.translate
} ) {
msglist = readExtra(fullmessage.extra)
function hideChat () { } else if (fullmessage.text && fullmessage.text.length > 0) {
// Clear chat input msglist.push({ text: fullmessage.text, color: undefined })
chatInput.value = '' } else if (dictionary[fullmessage.translate]) {
// Unfocus it let msg = dictionary[fullmessage.translate]
chatInput.blur() fullmessage.with.forEach(obj => {
// Hide it if (obj.insertion && obj.text) {
chatInput.style.display = 'none' msg = msg.replace('%s', obj.text)
// Hide extended chat history }
chat.style.maxHeight = 'calc(90px * 4)' if (obj.extra) {
chat.scrollTop = chat.scrollHeight // Stay bottom of the list if (obj.text && obj.text.length > 0) {
} msglist.push({ text: obj.text, color: undefined })
} else {
function readExtra (extra) { const text = readExtra(obj.extra)
const shouldReturn = [] if (text.length > 1) {
for (const i in extra) { console.log('Unsupported chat alert :(')
if (extra[i].text) { }
shouldReturn.push({ msg = msg.replace('%s', text[0].text)
text: extra[i].text, msglist.push({ text: msg, color: undefined })
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 { } else {
readExtra(extra).forEach(function (el) { // msglist.push({
shouldReturn.push(el) // text:
}) // "Unsupported message (Please report this):\n" +
// JSON.stringify(fullmessage),
// color: undefined
// });
} }
} const li = document.createElement('li')
return shouldReturn msglist.forEach(msg => {
} const span = document.createElement('span')
span.appendChild(document.createTextNode(msg.text))
client.on('chat', (packet) => { span.setAttribute(
// Reading of chat message 'style',
const fullmessage = JSON.parse(packet.message.toString()) `${msg.color ? styles[msg.color.toLowerCase()] : styles.white}; ${
let msglist = [] msg.bold ? styles.bold + ';' : ''
if ( }${msg.italic ? styles.italic + ';' : ''}${
fullmessage.extra && msg.strikethrough ? styles.strikethrough + ';' : ''
fullmessage.extra.length > 0 && }${msg.underlined ? styles.underlined + ';' : ''}`
!fullmessage.translate )
) { li.appendChild(span)
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 { chat.appendChild(li)
// msglist.push({ chat.scrollTop = chat.scrollHeight // Stay bottom of the list
// text:
// "Unsupported message (Please report this):\n" +
// JSON.stringify(fullmessage),
// color: undefined
// });
}
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.bold ? styles.bold + ';' : ''
}${msg.italic ? styles.italic + ';' : ''}${
msg.strikethrough ? styles.strikethrough + ';' : ''
}${msg.underlined ? styles.underlined + ';' : ''}`
)
li.appendChild(span)
}) })
chat.appendChild(li)
chat.scrollTop = chat.scrollHeight // Stay bottom of the list
})
hideChat() hideChat()
}
return chatState
} }
window.customElements.define('chat-box', ChatBox)

View file

@ -34,16 +34,6 @@ class LoadingScreen extends LitElement {
static get styles () { static get styles () {
return css` return css`
@font-face {
font-family: minecraft;
src: url(minecraftia.woff);
}
@font-face {
font-family: mojangles;
src: url(mojangles.ttf);
}
h1 { h1 {
font-family: mojangles, minecraft, monospace; font-family: mojangles, minecraft, monospace;
} }

View file

@ -1,22 +1,28 @@
@font-face {
font-family: minecraft;
src: url(minecraftia.woff);
}
@font-face {
font-family: mojangles;
src: url(mojangles.ttf);
}
html { html {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
} }
@font-face {
font-family: minecraft;
src: url(minecraftia.woff);
}
@font-face {
font-family: mojangles;
src: url(mojangles.ttf);
}
body { body {
margin:0; margin:0;
padding:0; padding:0;
font-family: sans-serif; font-family: sans-serif;
background: linear-gradient(#141e30, #243b55); background: linear-gradient(#141e30, #243b55);
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
} }
canvas { canvas {
@ -27,46 +33,6 @@ canvas {
padding: 0; padding: 0;
} }
.chat-wrapper {
position: fixed;
background-color: rgba(0, 0, 0, 0.5);
}
.chat-display-wrapper {
bottom: calc(8px * 16);
padding: 4px;
max-height: calc(90px * 8);
width: calc(320px * 4);
}
.chat-input-wrapper {
bottom: calc(2px * 16);
width: 100%;
overflow: hidden;
background-color: rgba(0, 0, 0, 0);
}
.chat {
overflow: hidden;
color: white;
font-size: 16px;
margin: 0px;
line-height: 100%;
text-shadow: 2px 2px 0px #3f3f3f;
font-family: mojangles, minecraft, monospace;
width: 100%;
max-height: calc(90px * 8)
}
input[type=text], #chatinput {
background-color: rgba(0, 0, 0, 0.5);
display: none;
}
li {
display: block;
}
#crosshair { #crosshair {
image-rendering: optimizeSpeed; image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges; image-rendering: -moz-crisp-edges;
@ -82,12 +48,3 @@ li {
transform: translate(calc(-50% + 120px * 4), calc(-50% + 120px * 4)); transform: translate(calc(-50% + 120px * 4), calc(-50% + 120px * 4));
clip-path: inset(0px calc(240px * 4) calc(240px * 4) 0px); clip-path: inset(0px calc(240px * 4) calc(240px * 4) 0px);
} }
body {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}