From 77fa0ee0cd9e4dc43bdbee0db1114fd6e61de349 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Sun, 14 Mar 2021 19:33:41 +0100 Subject: [PATCH] move hotbar to web component (#89) --- index.html | 19 +----- index.js | 63 +++----------------- lib/hotbar.js | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++ styles.css | 53 ----------------- 4 files changed, 167 insertions(+), 126 deletions(-) create mode 100644 lib/hotbar.js diff --git a/index.html b/index.html index e8a363b2..90afa837 100644 --- a/index.html +++ b/index.html @@ -6,22 +6,7 @@ - + - + diff --git a/index.js b/index.js index 272411e4..e1c9fb4a 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ /* global THREE */ require('./lib/menu') require('./lib/loading_screen') +require('./lib/hotbar') const net = require('net') @@ -17,37 +18,12 @@ const Chat = require('./lib/chat') const maxPitch = 0.5 * Math.PI const minPitch = -0.5 * Math.PI -async function reloadHotbar (bot, viewer) { - for (let i = 0; i < 9; i++) { - // eslint-disable-next-line no-undef - const http = new XMLHttpRequest() - let url = bot.inventory.slots[bot.inventory.hotbarStart + i] ? window.location.href + 'textures/' + viewer.version + '/items/' + bot.inventory.slots[bot.inventory.hotbarStart + i].name + '.png' : '' - http.open('HEAD', url) - - http.onreadystatechange = function () { - if (this.readyState === this.DONE) { - if (this.status === 404) { - url = bot.inventory.slots[bot.inventory.hotbarStart + i] ? window.location.href + 'textures/' + viewer.version + '/blocks/' + bot.inventory.slots[bot.inventory.hotbarStart + i].name + '.png' : '' - } - document.getElementById('hotbar-' + i).src = url - } - } - http.send() - } -} - -async function reloadHotbarSelected (bot, slot) { - const planned = (20 * 4 * slot) + 'px' - document.getElementById('hotbar-highlight').style.marginLeft = planned - bot.setQuickBarSlot(slot) -} - async function main () { const menu = document.getElementById('prismarine-menu') menu.addEventListener('connect', e => { const options = e.detail menu.style = 'display: none;' - document.getElementById('hotbar-wrapper').style = 'display:block' + document.getElementById('hotbar').style = 'display:block' document.getElementById('crosshair').style = 'display:block' document.getElementById('chat-wrapper').style = 'display:block' document.getElementById('chat-wrapper2').style = 'display:block' @@ -59,6 +35,7 @@ async function main () { async function connect (options) { const loadingScreen = document.getElementById('loading-background') + const hotbar = document.getElementById('hotbar') const viewDistance = 6 const hostprompt = options.server @@ -102,6 +79,8 @@ async function connect (options) { closeTimeout: 240 * 1000 }) + hotbar.bot = bot + bot.on('error', (err) => { console.log('Encountered error!', err) loadingScreen.status = 'Error encountered. Please reload the page' @@ -124,7 +103,6 @@ async function connect (options) { bot.once('spawn', () => { const mcData = require('minecraft-data')(bot.version) - reloadHotbarSelected(bot, 0) loadingScreen.status = 'Placing blocks (starting viewer)...' console.log('bot spawned - starting viewer') @@ -147,6 +125,7 @@ async function connect (options) { const viewer = new Viewer(renderer) viewer.setVersion(version) + hotbar.viewerVersion = viewer.version window.worldView = worldView window.bot = bot window.mcData = mcData @@ -154,8 +133,6 @@ async function connect (options) { window.Vec3 = Vec3 window.pathfinder = pathfinder - reloadHotbar(bot, viewer) - // Link WorldView and Viewer viewer.listen(worldView) worldView.listenToBot(bot) @@ -219,7 +196,7 @@ async function connect (options) { } if (e.code.startsWith('Digit')) { const numPressed = e.code.substr(5) - reloadHotbarSelected(bot, numPressed - 1) + hotbar.reloadHotbarSelected(bot, numPressed - 1) } if (e.code === 'KeyQ') { if (bot.heldItem) bot.tossStack(bot.heldItem) @@ -255,11 +232,6 @@ async function connect (options) { bot.stopDigging() }, false) - document.addEventListener('wheel', (e) => { - const newSlot = ((bot.quickBarSlot + Math.sign(e.deltaY)) % 9 + 9) % 9 - reloadHotbarSelected(bot, newSlot) - }) - loadingScreen.status = 'Done!' console.log(loadingScreen.status) // only do that because it's read in index.html and npm run fix complains. @@ -276,27 +248,6 @@ async function connect (options) { } animate() - // inventory listener - bot.inventory.on('updateSlot', (slot, oldItem, newItem) => { - if (slot >= bot.inventory.hotbarStart + 9) return - if (slot < bot.inventory.hotbarStart) return - - // eslint-disable-next-line no-undef - const http = new XMLHttpRequest() - let url = newItem ? window.location.href + 'textures/' + viewer.version + '/items/' + newItem.name + '.png' : '' - http.open('HEAD', url) - - http.onreadystatechange = function () { - if (this.readyState === this.DONE) { - if (this.status === 404) { - url = newItem ? window.location.href + 'textures/' + viewer.version + '/blocks/' + newItem.name + '.png' : '' - } - document.getElementById('hotbar-' + (slot - bot.inventory.hotbarStart)).src = url - } - } - http.send() - }) - window.addEventListener('resize', () => { viewer.camera.aspect = window.innerWidth / window.innerHeight viewer.camera.updateProjectionMatrix() diff --git a/lib/hotbar.js b/lib/hotbar.js new file mode 100644 index 00000000..dd0beec8 --- /dev/null +++ b/lib/hotbar.js @@ -0,0 +1,158 @@ +const { LitElement, html, css } = require('lit-element') + +class HotBar extends LitElement { + updated (changedProperties) { + if (changedProperties.has('bot')) { + // inventory listener + this.bot.on('spawn', () => { + this.init() + }) + } + } + + init () { + this.reloadHotbar() + this.reloadHotbarSelected(0) + const baseUrl = window.location.href.match(/(^[^#]*)/)[0] + const self = this + document.addEventListener('wheel', (e) => { + const newSlot = ((this.bot.quickBarSlot + Math.sign(e.deltaY)) % 9 + 9) % 9 + this.reloadHotbarSelected(newSlot) + }) + + this.bot.inventory.on('updateSlot', (slot, oldItem, newItem) => { + if (slot >= this.bot.inventory.hotbarStart + 9) return + if (slot < this.bot.inventory.hotbarStart) return + + // eslint-disable-next-line no-undef + const http = new XMLHttpRequest() + let url = newItem ? baseUrl + 'textures/' + this.viewerVersion + '/items/' + newItem.name + '.png' : '' + http.open('HEAD', url) + + http.onreadystatechange = function () { + if (this.readyState === this.DONE) { + if (this.status === 404) { + url = newItem ? baseUrl + 'textures/' + self.viewerVersion + '/blocks/' + newItem.name + '.png' : '' + } + self.shadowRoot.getElementById('hotbar-' + (slot - self.bot.inventory.hotbarStart)).src = url + } + } + http.send() + }) + } + + async reloadHotbar () { + const baseUrl = window.location.href.match(/(^[^#]*)/)[0] + const self = this + for (let i = 0; i < 9; i++) { + // eslint-disable-next-line no-undef + const http = new XMLHttpRequest() + let url = this.bot.inventory.slots[this.bot.inventory.hotbarStart + i] ? baseUrl + 'textures/' + this.viewerVersion + '/items/' + this.bot.inventory.slots[this.bot.inventory.hotbarStart + i].name + '.png' : '' + http.open('HEAD', url) + + http.onreadystatechange = function () { + if (this.readyState === this.DONE) { + if (this.status === 404) { + url = self.bot.inventory.slots[self.bot.inventory.hotbarStart + i] ? baseUrl + 'textures/' + self.viewerVersion + '/blocks/' + self.bot.inventory.slots[self.bot.inventory.hotbarStart + i].name + '.png' : '' + } + self.shadowRoot.getElementById('hotbar-' + i).src = url + } + } + http.send() + } + } + + async reloadHotbarSelected (slot) { + const planned = (20 * 4 * slot) + 'px' + this.shadowRoot.getElementById('hotbar-highlight').style.marginLeft = planned + this.bot.setQuickBarSlot(slot) + } + + static get properties () { + return { + bot: { type: Object }, + viewerVersion: { type: String } + } + } + + static get styles () { + return css` + #hotbar-image { + image-rendering: optimizeSpeed; + image-rendering: -moz-crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -o-crisp-edges; + image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + position: absolute; + top: 100%; + left: 50%; + height: calc(256px * 4); + width: calc(256px * 4); + transform: translate(calc(-182px * 2), calc(-22px * 4)); + clip-path: inset(0px calc(74px * 4) calc(234px * 4) 0px); + } + #hotbar-items-wrapper { + image-rendering: optimizeSpeed; + image-rendering: -moz-crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -o-crisp-edges; + image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + position: absolute; + top: 100%; + left: 50%; + height: calc(256px * 4); + width: calc(256px * 4); + transform: translate(calc(-182px * 2), calc(-22px * 4)); + clip-path: inset(0px calc(74px * 4) calc(234px * 4) 0px); + } + + #hotbar-highlight { + image-rendering: optimizeSpeed; + image-rendering: -moz-crisp-edges; + image-rendering: -webkit-optimize-contrast; + image-rendering: -o-crisp-edges; + image-rendering: pixelated; + -ms-interpolation-mode: nearest-neighbor; + position: absolute; + top: 100%; + left: 50%; + height: calc(256px * 4); + width: calc(256px * 4); + margin-left: calc(20px * 4 * 4); /* EDIT THIS TO CHANGE WHICH SLOT IS SELECTED */ + transform: translate(calc((-24px * 2) - (20px * 4 * 4) ), calc((-22px * 4) + (-24px * 4) + 4px)); /* first need to translate up to account for clipping, then account for size of image, then 1px to center vertically over the image*/ + clip-path: inset(calc(22px * 4) calc(232px * 4) calc(210px * 4) 0px); + } + + .hotbar-item { + height: calc(16px * 4); + width: calc(16px * 4); + margin-top: calc(3px * 4); + margin-left: calc(3px * 4); + } + ` + } + + render () { + return html` +
+ + +
+ + + + + + + + + +
+
+ ` + } +} + +window.customElements.define('hot-bar', HotBar) diff --git a/styles.css b/styles.css index e49fb481..37f83456 100644 --- a/styles.css +++ b/styles.css @@ -91,57 +91,4 @@ body { -ms-user-select: none; user-select: none; } -#hotbar-image { - image-rendering: optimizeSpeed; - image-rendering: -moz-crisp-edges; - image-rendering: -webkit-optimize-contrast; - image-rendering: -o-crisp-edges; - image-rendering: pixelated; - -ms-interpolation-mode: nearest-neighbor; - position: absolute; - top: 100%; - left: 50%; - height: calc(256px * 4); - width: calc(256px * 4); - transform: translate(calc(-182px * 2), calc(-22px * 4)); - clip-path: inset(0px calc(74px * 4) calc(234px * 4) 0px); -} -#hotbar-items-wrapper { - image-rendering: optimizeSpeed; - image-rendering: -moz-crisp-edges; - image-rendering: -webkit-optimize-contrast; - image-rendering: -o-crisp-edges; - image-rendering: pixelated; - -ms-interpolation-mode: nearest-neighbor; - position: absolute; - top: 100%; - left: 50%; - height: calc(256px * 4); - width: calc(256px * 4); - transform: translate(calc(-182px * 2), calc(-22px * 4)); - clip-path: inset(0px calc(74px * 4) calc(234px * 4) 0px); -} -#hotbar-highlight { - image-rendering: optimizeSpeed; - image-rendering: -moz-crisp-edges; - image-rendering: -webkit-optimize-contrast; - image-rendering: -o-crisp-edges; - image-rendering: pixelated; - -ms-interpolation-mode: nearest-neighbor; - position: absolute; - top: 100%; - left: 50%; - height: calc(256px * 4); - width: calc(256px * 4); - margin-left: calc(20px * 4 * 4); /* EDIT THIS TO CHANGE WHICH SLOT IS SELECTED */ - transform: translate(calc((-24px * 2) - (20px * 4 * 4) ), calc((-22px * 4) + (-24px * 4) + 4px)); /* first need to translate up to account for clipping, then account for size of image, then 1px to center vertically over the image*/ - clip-path: inset(calc(22px * 4) calc(232px * 4) calc(210px * 4) 0px); -} - -.hotbar-item { - height: calc(16px * 4); - width: calc(16px * 4); - margin-top: calc(3px * 4); - margin-left: calc(3px * 4); -}