From 1b08956d1071dfbcc0174471babc661c5a6f043c Mon Sep 17 00:00:00 2001 From: KalmeMarq <55203647+KalmeMarq@users.noreply.github.com> Date: Sat, 25 Dec 2021 21:50:40 +0000 Subject: [PATCH] Mobile controls (#262) * 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. * added mobile controls * fixed bot and chat * mobile controls only appear on mobile or if forced * lint fix --- lib/chat.js | 63 +++++----- lib/menus/components/common.js | 7 ++ lib/menus/hud.js | 209 +++++++++++++++++++++++++++++++++ lib/menus/options_screen.js | 18 ++- package.json | 1 + styles.css | 16 +++ 6 files changed, 284 insertions(+), 30 deletions(-) diff --git a/lib/chat.js b/lib/chat.js index a46fff40b..605f04986 100644 --- a/lib/chat.js +++ b/lib/chat.js @@ -127,15 +127,40 @@ class ChatBox extends LitElement { ` } + constructor () { + super() + this.chatHistoryPos = 0 + this.chatHistory = [] + } + + enableChat (isCommand) { + const chat = this.shadowRoot.querySelector('#chat') + const chatInput = this.shadowRoot.querySelector('#chatinput') + + // Set inChat value + this.inChat = true + // Exit the pointer lock + document.exitPointerLock() + // Show chat input + chatInput.style.display = 'block' + // Show extended chat history + chat.style.maxHeight = 'var(--chatHeight)' + chat.scrollTop = chat.scrollHeight // Stay bottom of the list + if (isCommand) { // handle commands + chatInput.value = '/' + } + // Focus element + chatInput.focus() + this.chatHistoryPos = this.chatHistory.length + document.querySelector('#hud').shadowRoot.querySelector('#chat').shadowRoot.querySelectorAll('.chat-message').forEach(e => e.classList.add('chat-message-chat-opened')) + } + init (client, renderer) { this.inChat = false const chat = this.shadowRoot.querySelector('#chat') const gameMenu = document.getElementById('pause-screen') const chatInput = this.shadowRoot.querySelector('#chatinput') - const chatHistory = [] - let chatHistoryPos = 0 - renderer.domElement.requestPointerLock = renderer.domElement.requestPointerLock || renderer.domElement.mozRequestPointerLock || renderer.domElement.webkitRequestPointerLock @@ -153,11 +178,11 @@ class ChatBox extends LitElement { if (e.code === 'Escape') { disableChat() } else if (e.keyCode === 38) { - if (chatHistoryPos === 0) return - chatInput.value = chatHistory[--chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : '' + if (this.chatHistoryPos === 0) return + chatInput.value = this.chatHistory[--this.chatHistoryPos] !== undefined ? this.chatHistory[this.chatHistoryPos] : '' } else if (e.keyCode === 40) { - if (chatHistoryPos === chatHistory.length) return - chatInput.value = chatHistory[++chatHistoryPos] !== undefined ? chatHistory[chatHistoryPos] : '' + if (this.chatHistoryPos === this.chatHistory.length) return + chatInput.value = this.chatHistory[++this.chatHistoryPos] !== undefined ? this.chatHistory[this.chatHistoryPos] : '' } }) @@ -172,10 +197,10 @@ class ChatBox extends LitElement { if (e.code === km.key) { switch (km.defaultKey) { case 'KeyT': - setTimeout(() => enableChat(false), 0) + setTimeout(() => this.enableChat(false), 0) break case 'Slash': - setTimeout(() => enableChat(true), 0) + setTimeout(() => this.enableChat(true), 0) break } } @@ -187,7 +212,7 @@ class ChatBox extends LitElement { if (!self.inChat) return e.stopPropagation() if (e.code === 'Enter') { - chatHistory.push(chatInput.value) + this.chatHistory.push(chatInput.value) client.write('chat', { message: chatInput.value }) disableChat() } @@ -204,24 +229,6 @@ class ChatBox extends LitElement { 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(var(--chatHeight) * var(--chatScale))' - chat.scrollTop = chat.scrollHeight // Stay bottom of the list - if (isCommand) { // handle commands - chatInput.value = '/' - } - // Focus element - chatInput.focus() - chatHistoryPos = chatHistory.length - document.querySelector('#hud').shadowRoot.querySelector('#chat').shadowRoot.querySelectorAll('.chat-message').forEach(e => e.classList.add('chat-message-chat-opened')) - } function disableChat () { self.inChat = false diff --git a/lib/menus/components/common.js b/lib/menus/components/common.js index bce3ccf06..5be48a78c 100644 --- a/lib/menus/components/common.js +++ b/lib/menus/components/common.js @@ -42,6 +42,12 @@ const commonCss = css` } ` +/** @returns {boolean} */ +function isMobile () { + const m = require('ismobilejs').default() + return m.any +} + /** * @param {string} url */ @@ -60,6 +66,7 @@ function displayScreen (prev, next) { export { commonCss, + isMobile, openURL, displayScreen } diff --git a/lib/menus/hud.js b/lib/menus/hud.js index fe10cfe0c..ccec66e1c 100644 --- a/lib/menus/hud.js +++ b/lib/menus/hud.js @@ -1,4 +1,5 @@ const { LitElement, html, css } = require('lit') +const { isMobile } = require('./components/common') class Hud extends LitElement { static get styles () { @@ -55,9 +56,142 @@ class Hud extends LitElement { background-size: 256px; background-position-y: -69px; } + + .mobile-top-btns { + display: none; + flex-direction: row; + position: absolute; + top: 0; + left: 50%; + transform: translate(-50%); + gap: 0 1px; + z-index: 20; + } + + .pause-btn, + .chat-btn { + border: none; + outline: none; + width: 18px; + height: 18px; + background-image: url('extra-textures/gui.png'); + background-size: 256px; + background-position-x: -200px; + background-position-y: -64px; + } + + .chat-btn { + background-position-y: -82px; + } + + .mobile-control-forward, + .mobile-control-back, + .mobile-control-left, + .mobile-control-sneak, + .mobile-control-jump, + .mobile-control-right { + position: absolute; + width: 22px; + height: 22px; + background-image: url('extra-textures/gui.png'); + background-size: 256px; + border: none; + outline: none; + } + + .mobile-control-forward:active, + .mobile-control-back:active, + .mobile-control-sneak:active, + .mobile-control-left:active, + .mobile-control-jump:active, + .mobile-control-right:active { + filter: brightness(85%); + } + + .mobile-control-forward { + top: 0; + left: 50%; + transform: translate(-50%); + background-position: -2px -109px; + } + + .mobile-control-back { + bottom: 0; + left: 50%; + transform: translate(-50%); + background-position: -54px -109px; + } + + .mobile-control-left { + top: 50%; + left: 0; + transform: translate(0, -50%); + background-position: -28px -109px; + } + + .mobile-control-right { + top: 50%; + right: 0; + transform: translate(0, -50%); + background-position: -80px -109px; + } + + .mobile-control-jump { + position: relative; + width: 18px; + height: 18px; + background-position: -108px -111px; + } + + .mobile-control-sneak { + width: 18px; + height: 18px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-position: -218px -82px; + } + .mobile-control-sneak.is-down { + background-position: -218px -64px; + } + + .mobile-controls-left { + display: none; + position: absolute; + left: 8px; + bottom: 0; + width: 70px; + height: 70px; + z-index: 30; + opacity: 0.65; + transform-origin: bottom left; + transform: scale(1.5); + } + + .mobile-controls-right { + display: none; + flex-direction: column; + place-items: center; + place-content: center; + position: absolute; + right: 20px; + bottom: 0; + width: 22px; + height: 70px; + z-index: 30; + opacity: 0.65; + transform-origin: bottom right; + transform: scale(1.5); + } ` } + static get properties () { + return { + bot: { type: Object } + } + } + /** * @param {globalThis.THREE.Renderer} renderer * @param {import('mineflayer').Bot} bot @@ -73,6 +207,7 @@ class Hud extends LitElement { const hotbar = this.shadowRoot.querySelector('#hotbar') const xpLabel = this.shadowRoot.querySelector('#xp-label') + this.bot = bot hotbar.bot = bot debugMenu.bot = bot @@ -125,10 +260,84 @@ class Hud extends LitElement { foodbar.updateHunger(bot.food) // breathbar.updateOxygen(bot.oxygenLevel ?? 20) hotbar.init() + + if (document.getElementById('options-screen').forceMobileControls || isMobile()) { + this.showMobileControls(true) + } else { + this.showMobileControls(false) + } + } + + /** @param {boolean} bl */ + showMobileControls (bl) { + this.shadowRoot.querySelector('#mobile-top').style.display = bl ? 'flex' : 'none' + this.shadowRoot.querySelector('#mobile-left').style.display = bl ? 'block' : 'none' + this.shadowRoot.querySelector('#mobile-right').style.display = bl ? 'flex' : 'none' + } + + /** + * @param {string} id + * @param {boolean} action + */ + mobileControl (e, id, action) { + e.stopPropagation() + this.bot.setControlState(id, action) } render () { return html` +