prismarine-web-client
Version:
A minecraft client running in a browser
1,087 lines (993 loc) • 30.6 MB
JavaScript
/*! For license information please see index.js.LICENSE.txt */
(()=>{var __webpack_modules__={54747:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677),{isMobile:s}=a(27472),o={black:"color:#000000",dark_blue:"color:#0000AA",dark_green:"color:#00AA00",dark_aqua:"color:#00AAAA",dark_red:"color:#AA0000",dark_purple:"color:#AA00AA",gold:"color:#FFAA00",gray:"color:#AAAAAA",dark_gray:"color:#555555",blue:"color:#5555FF",green:"color:#55FF55",aqua:"color:#55FFFF",red:"color:#FF5555",light_purple:"color:#FF55FF",yellow:"color:#FFFF55",white:"color:#FFFFFF",bold:"font-weight:900",strikethrough:"text-decoration:line-through",underlined:"text-decoration:underline",italic:"font-style:italic"};window.customElements.define("chat-box",class extends i{static get styles(){return r`
.chat-wrapper {
position: fixed;
z-index: 10;
}
.chat-display-wrapper {
bottom: 40px;
padding: 4px;
padding-left: 0;
max-height: var(--chatHeight);
width: var(--chatWidth);
transform-origin: bottom left;
transform: scale(var(--chatScale));
}
.chat-input-wrapper {
bottom: 1px;
width: calc(100% - 3px);
position: absolute;
left: 1px;
box-sizing: border-box;
overflow: hidden;
background-color: rgba(0, 0, 0, 0);
}
.input-mobile {
top: 1px;
}
.display-mobile {
top: 40px;
}
.chat {
overflow: hidden;
color: white;
font-size: 10px;
margin: 0px;
line-height: 100%;
text-shadow: 1px 1px 0px #3f3f3f;
font-family: mojangles, minecraft, monospace;
width: 100%;
max-height: var(--chatHeight);
}
input[type=text], #chatinput {
background-color: rgba(0, 0, 0, 0.5);
border: 1px solid rgba(0, 0, 0, 0);
display: none;
outline: none;
}
#chatinput:focus {
border-color: white;
}
.chat-message {
display: block;
padding-left: 4px;
background-color: rgba(0, 0, 0, 0.5);
}
.chat-message-fadeout {
opacity: 1;
transition: all 3s;
}
.chat-message-fade {
opacity: 0;
}
.chat-message-faded {
transition: none !important;
}
.chat-message-chat-opened {
opacity: 1 !important;
transition: none !important;
}
`}render(){return n`
<div id="chat-wrapper" class="chat-wrapper chat-display-wrapper">
<div class="chat" id="chat">
<li class="chat-message chat-message-fade chat-message-faded">Welcome to prismarine-web-client! Chat appears here.</li>
</div>
</div>
<div id="chat-wrapper2" class="chat-wrapper chat-input-wrapper">
<div class="chat" id="chat-input">
<input type="text" class="chat" id="chatinput" spellcheck="false" autocomplete="off"></input>
</div>
</div>
`}constructor(){super(),this.chatHistoryPos=0,this.chatHistory=[]}enableChat(e){const t=this.shadowRoot.querySelector("#chat"),a=this.shadowRoot.querySelector("#chatinput");this.shadowRoot.querySelector("#chat-wrapper2").classList.toggle("input-mobile",s()),this.shadowRoot.querySelector("#chat-wrapper").classList.toggle("display-mobile",s()),this.inChat=!0,document.exitPointerLock(),a.style.display="block",t.style.maxHeight="var(--chatHeight)",t.scrollTop=t.scrollHeight,e&&(a.value="/"),a.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(e,t){this.inChat=!1;const a=this.shadowRoot.querySelector("#chat"),i=document.getElementById("pause-screen"),n=this.shadowRoot.querySelector("#chatinput");t.domElement.requestPointerLock=t.domElement.requestPointerLock||t.domElement.mozRequestPointerLock||t.domElement.webkitRequestPointerLock,a.style.display="block",document.addEventListener("keydown",(e=>{if(!i.inMenu&&this.inChat)if("Escape"===(e=e||window.event).code)s();else if("ArrowUp"===e.code){if(0===this.chatHistoryPos)return;n.value=void 0!==this.chatHistory[--this.chatHistoryPos]?this.chatHistory[this.chatHistoryPos]:"",setTimeout((()=>{n.setSelectionRange(-1,-1)}),0)}else if("ArrowDown"===e.code){if(this.chatHistoryPos===this.chatHistory.length)return;n.value=void 0!==this.chatHistory[++this.chatHistoryPos]?this.chatHistory[this.chatHistoryPos]:"",setTimeout((()=>{n.setSelectionRange(-1,-1)}),0)}}));const r=document.getElementById("keybinds-screen");document.addEventListener("keypress",(t=>{if(!i.inMenu){if(t=t||window.event,!1===this.inChat)return r.keymaps.forEach((e=>{if(t.code===e.key)switch(e.defaultKey){case"KeyT":setTimeout((()=>this.enableChat(!1)),0);break;case"Slash":setTimeout((()=>this.enableChat(!0)),0)}})),!1;this.inChat&&(t.stopPropagation(),"Enter"===t.code&&(this.chatHistory.push(n.value),e.write("chat",{message:n.value}),s()))}}));const s=()=>{this.inChat=!1,l(),t.domElement.requestPointerLock()},l=()=>{n.value="",n.blur(),n.style.display="none",a.style.maxHeight="var(--chatHeight)",a.scrollTop=a.scrollHeight,document.querySelector("#hud").shadowRoot.querySelector("#chat").shadowRoot.querySelectorAll(".chat-message").forEach((e=>e.classList.remove("chat-message-chat-opened")))};e.on("chat",(e=>{const t=JSON.parse(e.message.toString()),i=[],n=e=>e.trim().startsWith("#")?`color:${e}`:o[e]??void 0,r=(e,t)=>{const a={color:t.color,bold:!!t.bold,italic:!!t.italic,underlined:!!t.underlined,strikethrough:!!t.strikethrough,obfuscated:!!t.obfuscated};if(t.text&&e.push({text:t.text,...a}),t.translate){const i=window.mcData.language[t.translate]??t.translate;if(t.with){const n=i.split(/%s|%\d+\$s/g);let s=0;n.forEach(((i,n,o)=>{e.push({text:i,...a}),n+1<o.length&&(t.with[s]&&("string"==typeof t.with[s]?r(e,{...a,text:t.with[s]}):r(e,{...a,...t.with[s]})),s++)}))}else e.push({text:i,...a})}t.extra&&t.extra.forEach((t=>{r(e,{...a,...t})}))};r(i,t);const s=document.createElement("li");i.forEach((e=>{const t=document.createElement("span");t.appendChild(document.createTextNode(e.text)),t.setAttribute("style",`${e.color?n(e.color.toLowerCase())+`; text-shadow: 1px 1px 0px ${function(e,t=.25){const a=parseInt(e.replace("#",""),16),i=(a>>8&255)*t|0,n=(255&a)*t|0,r=e=>("00"+e.toString(16)).substr(-2);return`#${r((a>>16&255)*t|0)}${r(i)}${r(n)}`}(n(e.color.toLowerCase()).replace("color:",""))}`:o.white}; ${e.bold?o.bold+";":""}${e.italic?o.italic+";":""}${e.strikethrough?o.strikethrough+";":""}${e.underlined?o.underlined+";":""}`),s.appendChild(t)})),a.appendChild(s),a.scrollTop=a.scrollHeight,s.classList.add("chat-message"),this.inChat&&s.classList.add("chat-message-chat-opened"),setTimeout((()=>{s.classList.add("chat-message-fadeout"),s.classList.add("chat-message-fade"),setTimeout((()=>{s.classList.add("chat-message-faded")}),3e3)}),5e3)})),l()}})},61578:(e,t,a)=>{const{Vec3:i}=a(14298);e.exports=class{constructor(e,t,a){this.buttons=[!1,!1,!1],this.lastButtons=[!1,!1,!1],this.breakStartTime=0,this.cursorBlock=null;const n=new THREE.BoxGeometry(1.001,1.001,1.001);this.cursorMesh=new THREE.LineSegments(new THREE.EdgesGeometry(n),new THREE.LineBasicMaterial({color:0})),this.cursorMesh.visible=!1,e.scene.add(this.cursorMesh);const r=new THREE.TextureLoader;this.breakTextures=[];for(let t=0;t<10;t++){const a=r.load("textures/"+e.version+"/blocks/destroy_stage_"+t+".png");a.magFilter=THREE.NearestFilter,a.minFilter=THREE.NearestFilter,this.breakTextures.push(a)}const s=new THREE.MeshBasicMaterial({transparent:!0,blending:THREE.MultiplyBlending});this.blockBreakMesh=new THREE.Mesh(n,s),this.blockBreakMesh.visible=!1,this.blockBreakMesh.renderOrder=999,e.scene.add(this.blockBreakMesh),document.addEventListener("mouseup",(e=>{this.buttons[e.button]=!1})),document.addEventListener("mousedown",(e=>{if(document.pointerLockElement!==t.domElement)return;this.buttons[e.button]=!0;const n=a.nearestEntity((e=>{if(e.position.distanceTo(a.entity.position)<=(1===a.player.gamemode?5:3)){const t=function(e,t){const a=Math.cos(e),n=Math.sin(e),r=Math.cos(t),s=Math.sin(t);return new i(-s*a,n,-r*a)}(a.entity.pitch,a.entity.yaw),{width:n,height:r}=e,{x:s,y:o,z:l}=e.position,{x:d,y:c,z:m}=a.entity.position,u=new THREE.Box3(new THREE.Vector3(s-n/2,o,l-n/2),new THREE.Vector3(s+n/2,o+r,l+n/2));return null!==new THREE.Raycaster(new THREE.Vector3(d,c+1.52,m),new THREE.Vector3(t.x,t.y,t.z)).ray.intersectBox(u,new THREE.Vector3(s,o,l))}return!1}));n&&a.attack(n)})),this.lastPlaced=4,a.on("physicsTick",(()=>{this.lastPlaced<4&&this.lastPlaced++}))}update(e){let t=e.blockAtCursor(6);e.canDigBlock(t)||(t=null);let a=!t!=!this.cursorBlock;if(t&&this.cursorBlock&&(a=!t.position.equals(this.cursorBlock.position)),t&&this.buttons[2]&&(!this.lastButtons[2]||a)&&this.lastPlaced>=4){const a=[new i(0,-1,0),new i(0,1,0),new i(0,0,-1),new i(0,0,1),new i(-1,0,0),new i(1,0,0)],n=t.intersect.minus(t.position);e._placeBlockWithOptions(t,a[t.face],{delta:n,forceLook:"ignore"}),e.lastPlaced=0}if(t&&this.buttons[0]&&(!this.lastButtons[0]||a)){this.breakStartTime=performance.now();try{e.dig(t,"ignore")}catch(e){}}if(!this.buttons[0]&&this.lastButtons[0])try{e.stopDigging()}catch(e){}if(t&&this.buttons[0]){const a=performance.now()-this.breakStartTime,i=e.digTime(t),n=Math.floor(a/i*10);this.blockBreakMesh.position.set(t.position.x+.5,t.position.y+.5,t.position.z+.5),this.blockBreakMesh.material.map=this.breakTextures[n],this.blockBreakMesh.visible=!0}else this.blockBreakMesh.visible=!1;t?(this.cursorMesh.visible=!0,this.cursorMesh.position.set(t.position.x+.5,t.position.y+.5,t.position.z+.5)):this.cursorMesh.visible=!1,this.cursorBlock=t,this.lastButtons[0]=this.buttons[0],this.lastButtons[1]=this.buttons[1],this.lastButtons[2]=this.buttons[2]}}},25701:e=>{e.exports.resolveSrv=function(e,t){const a=new XMLHttpRequest,i=`https://dns.google.com/resolve?name=${e}&type=SRV`;a.open("GET",i),a.responseType="json",a.send(),a.onload=function(){const e=a.response;if(3===e.Status){const e=new Error("querySrv ENOTFOUND");return e.code="ENOTFOUND",void t(e)}if(!e.Answer||e.Answer.length<1){const e=new Error("querySrv ENODATA");return e.code="ENODATA",void t(e)}const i=[];e.Answer.forEach((function(e){const t=e.data.split(" ");i.push({priority:t[0],weight:t[1],port:t[2],name:t[3]})})),console.log(i),t(null,i)}}},54902:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677),{styleMap:s}=a(48921),o=["pink","blue","red","green","yellow","purple","white"],l=[0,6,10,12,20],d={"entity.minecraft.ender_dragon":"Ender Dragon","entity.minecraft.wither":"Wither"};class c extends i{constructor(e){super(),this.bar=e,this.title="",this.progress=0,this.bossBarStyles={},this.fillStyles={},this.div1Styles={},this.div2Styles={}}static get styles(){return r`
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.title {
font-size: 7px;
color: #fff;
}
.bossbar {
background-image: url("textures/1.18.1/gui/bars.png");
width: 182px;
height: 5px;
position: relative;
}
.bossbar .fill {
content: "";
position: absolute;
top: 0;
left: 0;
height: 5px;
width: 0;
background-image: url("textures/1.18.1/gui/bars.png");
}`}static get properties(){return{bar:{type:Object}}}render(){return this.updateBar(this.bar),n`
<div class="container">
<div class="title">${this.title}</div>
<div class="bossbar" style=${s(this.bossBarStyles)}>
<div class="fill" style=${s(this.fillStyles)}></div>
<div class="fill" style=${s(this.div1Styles)}></div>
<div class="fill" style=${s(this.div2Styles)}></div>
</div>
</div>`}setTitle(e){e._title.text?this.title=e._title.text:this.title=d[this._title.translate]||"Unkown Entity"}setColor(e){this.bossBarStyles.backgroundPositionY=`-${10*o.indexOf(e._color)}px`,this.fillStyles.backgroundPositionY=`-${10*o.indexOf(e._color)+5}px`}setProgress(e){this.fillStyles.width=100*e._health+"%",this.div2Styles.width=100*e._health+"%"}setDiv(e){this.div1Styles.backgroundPositionY=`-${10*l.indexOf(e._dividers)+70}px`,this.div2Styles.backgroundPositionY=`-${10*l.indexOf(e._dividers)+75}px`}updateBar(e){this.setTitle(e),this.setColor(e),this.setDiv(e),this.setProgress(e)}}window.customElements.define("pmui-bossbars-overlay",class extends i{constructor(){super(),this.bossBars=new Map}static get styles(){return r`
.bossBars {
display: flex;
flex-direction: column;
gap: 5px;
position: absolute;
top: 9px;
left: 50%;
transform: translate(-50%);
}`}static get properties(){return{bossBars:{type:Map}}}render(){return n`<div class="bossBars" id="bossBars">
${[...this.bossBars.values()]}
</div>`}init(){this.bot.on("bossBarCreated",(async e=>{this.bossBars.set(e.entityUUID,new c(e)),this.requestUpdate()})),this.bot.on("bossBarUpdated",(e=>{const t=this.bossBars.get(e.entityUUID);t.bar=e,t.requestUpdate()})),this.bot.on("bossBarDeleted",(e=>{this.bossBars.delete(e.entityUUID),this.requestUpdate()}))}}),window.customElements.define("pmui-bossbar",c)},97234:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);window.customElements.define("pmui-breathbar",class extends i{static get styles(){return r`
.breathbar {
position: absolute;
display: flex;
flex-direction: row-reverse;
left: calc(50% + 91px);
transform: translate(-100%);
bottom: 40px;
--offset: calc(-1 * 16px);
--bg-x: calc(-1 * 16px);
--bg-y: calc(-1 * 18px);
}
.breath {
width: 9px;
height: 9px;
margin-left: -1px;
}
.breath.full {
background-image: url('textures/1.17.1/gui/icons.png');
background-size: 256px;
background-position: var(--offset) var(--bg-y);
}
.breath.half {
background-image: url('textures/1.17.1/gui/icons.png');
background-size: 256px;
background-position: calc(var(--offset) - 9) var(--bg-y);
}
`}gameModeChanged(e){this.shadowRoot.querySelector("#breathbar").classList.toggle("creative",1===e)}updateOxygen(e){const t=this.shadowRoot.querySelector("#breathbar");t.style.display="block";const a=t.children;for(let e=0;e<a.length;e++)a[e].classList.remove("full"),a[e].classList.remove("half");for(let t=0;t<Math.ceil(e/2)&&!(t>=a.length);t++)e%2!=0&&Math.ceil(e/2)===t+1?a[t].classList.add("half"):a[t].classList.add("full")}render(){return n`
<div id="breathbar" class="breathbar">
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
<div class="breath"></div>
</div>
`}})},9195:(e,t,a)=>{"use strict";a.r(t),a.d(t,{playSound:()=>d});const{LitElement:i,html:n,css:r}=a(37677),s=new window.AudioContext,o={};async function l(e){let t=1;const a=document.getElementById("options-screen");a&&(t=a.sound/100);let i=o[e];if(!i){const t=await window.fetch(e),a=await t.arrayBuffer();i=await s.decodeAudioData(a),o[e]=i}const n=s.createGain(),r=s.createBufferSource();r.buffer=i,r.connect(n),n.connect(s.destination),n.gain.value=t,r.start(0)}window.customElements.define("pmui-button",class extends i{static get styles(){return r`
.button {
--txrV: 66px;
position: relative;
width: 200px;
height: 20px;
font-family: minecraft, mojangles, monospace;
font-size: 10px;
color: white;
text-shadow: 1px 1px #222;
border: none;
z-index: 1;
outline: none;
}
.button:hover,
.button:focus-visible {
--txrV: 86px;
}
.button:disabled {
--txrV: 46px;
color: #A0A0A0;
text-shadow: 1px 1px #111;
}
.button::after {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 20px;
background: url('textures/1.17.1/gui/widgets.png');
background-size: 256px;
background-position-y: calc(var(--txrV) * -1);
z-index: -1;
}
.button::before {
content: '';
display: block;
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 20px;
background: url('textures/1.17.1/gui/widgets.png');
background-size: 256px;
background-position-x: calc(-200px + 100%);
background-position-y: calc(var(--txrV) * -1);
z-index: -1;
}
`}static get properties(){return{label:{type:String,attribute:"pmui-label"},width:{type:String,attribute:"pmui-width"},disabled:{type:Boolean,attribute:"pmui-disabled"},onPress:{type:Function,attribute:"pmui-click"}}}constructor(){super(),this.label="",this.disabled=!1,this.width="200px",this.onPress=()=>{}}render(){return n`
<button
class="button"
?disabled=${this.disabled}
@click=${this.onBtnClick}
style="width: ${this.width};"
>
${this.label}
</button>`}onBtnClick(){l("click_stereo.ogg"),this.dispatchEvent(new window.CustomEvent("pmui-click"))}});const d=l},27472:(e,t,a)=>{"use strict";a.r(t),a.d(t,{commonCss:()=>i,displayScreen:()=>s,isMobile:()=>n,openURL:()=>r});const i=a(37677).css`
.dirt-bg {
position: absolute;
top: 0;
left: 0;
background: url('textures/1.17.1/gui/options_background.png'), rgba(0, 0, 0, 0.75);
background-size: 16px;
background-repeat: repeat;
width: 100%;
height: 100%;
transform-origin: top left;
transform: scale(2);
background-blend-mode: overlay;
}
.bg {
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.75);
width: 100%;
height: 100%;
}
.title {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%);
font-size: 10px;
color: white;
text-align: center;
text-shadow: 1px 1px #222;
}
.text {
color: white;
font-size: 10px;
text-shadow: 1px 1px #222;
}
`;function n(){return a(90891).Z().any}function r(e){window.open(e,"_blank","noopener,noreferrer")}function s(e,t){e.style.display="none",t.style.display="block"}},56041:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);window.customElements.define("pmui-debug-overlay",class extends i{static get styles(){return r`
.debug-left-side,
.debug-right-side {
position: absolute;
display: flex;
flex-direction: column;
z-index: 40;
}
.debug-left-side {
top: 1px;
left: 1px;
}
.debug-right-side {
top: 1px;
right: 1px;
}
p {
display: block;
color: white;
font-size: 10px;
width: fit-content;
height: 9px;
margin: 0;
padding: 0;
padding-bottom: 1px;
background: rgba(110, 110, 110, 0.5);
}
.debug-right-side p {
margin-left: auto;
}
.empty {
display: block;
height: 9px;
}
`}static get properties(){return{showOverlay:{type:Boolean},cursorBlock:{type:Object},bot:{type:Object},customEntries:{type:Object}}}constructor(){super(),this.showOverlay=!1,this.customEntries={}}firstUpdated(){document.addEventListener("keydown",(e=>{e??=window.event,"F3"===e.key&&(this.showOverlay=!this.showOverlay,e.preventDefault())}))}updated(e){e.has("bot")&&(this.bot.on("move",(()=>{this.requestUpdate()})),this.bot.on("time",(()=>{this.requestUpdate()})),this.bot.on("entitySpawn",(()=>{this.requestUpdate()})),this.bot.on("entityGone",(()=>{this.requestUpdate()})))}render(){if(!this.showOverlay)return n``;const e=this.cursorBlock,t=e&&this.bot.canDigBlock(e),i=this.bot.entity.position,r=[this.bot.entity.yaw,this.bot.entity.pitch],s=(o=-180*r[0]/Math.PI)%360-180*(o<0?-1:1);var o;const l=Math.floor(((s+180)/90+.5)%4),d=this.bot.world.getSkyLight(this.bot.entity.position),c=this.bot.world.getBiome(this.bot.entity.position);return n`
<div class="debug-left-side">
<p>Prismarine Web Client (${this.bot.version})</p>
<p>E: ${Object.values(this.bot.entities).length}</p>
<p>${this.bot.game.dimension}</p>
<div class="empty"></div>
<p>XYZ: ${i.x.toFixed(3)} / ${i.y.toFixed(3)} / ${i.z.toFixed(3)}</p>
<p>Chunk: ${Math.floor(i.x%16)} ~ ${Math.floor(i.z%16)} in ${Math.floor(i.x/16)} ~ ${Math.floor(i.z/16)}</p>
<p>Facing (viewer): ${r[0].toFixed(3)} ${r[1].toFixed(3)}</p>
<p>Facing (minecraft): ${["north (towards negative Z)","east (towards positive X)","south (towards positive Z)","west (towards negative X)"][l]} (${s.toFixed(1)} ${(-180*r[1]/Math.PI).toFixed(1)})</p>
<p>Light: ${d} (${d} sky)</p>
<p>Biome: minecraft:${window.mcData.biomesArray[c].name}</p>
<p>Day: ${this.bot.time.day}</p>
<div class="empty"></div>
${Object.entries(this.customEntries).map((([e,t])=>n`<p>${e}: ${t}</p>`))}
</div>
<div class="debug-right-side">
<p>Renderer: three.js r${a.g.THREE.REVISION}</p>
<div class="empty"></div>
${t?n`<p>${e.name}</p>${Object.entries(e.getProperties()).map((([e,t],a,i)=>{return r=e,s=t,i[a+1],n`<p>${r}: ${"boolean"==typeof s?n`<span style="color: ${s?"lightgreen":"red"}">${s}</span>`:s}</p>`;var r,s}))}`:""}
${t?n`<p>Looking at: ${e.position.x} ${e.position.y} ${e.position.z}</p>`:""}
</div>
`}})},64383:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);window.customElements.define("pmui-editbox",class extends i{static get styles(){return r`
.edit-container {
position: relative;
width: 200px;
height: 20px;
background: black;
border: 1px solid grey;
}
.edit-container:hover,
.edit-container:focus-within {
border-color: white;
}
.edit-container label {
position: absolute;
z-index: 2;
pointer-events: none;
bottom: 21px;
left: 0;
font-size: 10px;
color: rgb(206, 206, 206);
text-shadow: 1px 1px black;
}
.edit-box {
position: relative;
outline: none;
border: none;
background: none;
left: 1px;
width: calc(100% - 2px);
height: 100%;
font-family: minecraft, mojangles, monospace;
font-size: 10px;
color: white;
text-shadow: 1px 1px #222;
}
`}constructor(){super(),this.width="200px",this.id="",this.value="",this.label=""}static get properties(){return{width:{type:String,attribute:"pmui-width"},id:{type:String,attribute:"pmui-id"},label:{type:String,attribute:"pmui-label"},value:{type:String,attribute:"pmui-value"}}}render(){return n`
<div
class="edit-container"
style="width: ${this.width};"
>
<label for="${this.id}">${this.label}</label>
<input
id="${this.id}"
type="text"
name=""
spellcheck="false"
required=""
autocomplete="off"
value="${this.value}"
@input=${e=>{this.value=e.target.value}}
class="edit-box">
</div>
`}})},10791:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);window.customElements.define("pmui-foodbar",class extends i{static get styles(){return r`
.foodbar {
position: absolute;
display: flex;
flex-direction: row-reverse;
left: calc(50% + 91px);
transform: translate(-100%);
bottom: 30px;
--lightened: 0;
--offset: calc(-1 * (52px));
--bg-x: calc(-1 * (16px + 9px * var(--lightened)));
--bg-y: calc(-1 * 27px);
}
.food {
width: 9px;
height: 9px;
background-image: url('textures/1.17.1/gui/icons.png'), url('textures/1.17.1/gui/icons.png');
background-size: 256px, 256px;
background-position: var(--bg-x) var(--bg-y), var(--bg-x) var(--bg-y);
margin-left: -1px;
}
.food.full {
background-position: var(--offset) var(--bg-y), var(--bg-x) var(--bg-y);
}
.food.half {
background-position: calc(var(--offset) - 9px) var(--bg-y), var(--bg-x) var(--bg-y);
}
.foodbar.low .food {
animation: lowHungerAnim 0.2s steps(2, end) infinite;
}
.foodbar.low .food:nth-of-type(2n) {
animation-direction: reverse;
}
.foodbar.low .food:nth-of-type(3n) {
animation-duration: 0.1s;
}
.foodbar.updated {
animation: updatedAnim 0.3s steps(2, end) 2;
}
@keyframes lowHungerAnim {
to { transform: translateY(1px); }
}
@keyframes updatedAnim {
to { --lightened: 1; }
}
`}gameModeChanged(e){this.shadowRoot.querySelector("#foodbar").classList.toggle("creative",1===e)}onHungerUpdate(){this.shadowRoot.querySelector("#foodbar").classList.toggle("updated",!0),this.hungerTimeout&&clearTimeout(this.hungerTimeout),this.hungerTimeout=setTimeout((()=>{this.shadowRoot.querySelector("#foodbar").classList.toggle("updated",!1),this.hungerTimeout=null}),1e3)}updateHunger(e,t){const a=this.shadowRoot.querySelector("#foodbar");a.classList.toggle("low",e<=5);const i=a.children;for(let e=0;e<i.length;e++)i[e].classList.remove("full"),i[e].classList.remove("half");for(let t=0;t<Math.ceil(e/2)&&!(t>=i.length);t++)e%2!=0&&Math.ceil(e/2)===t+1?i[t].classList.add("half"):i[t].classList.add("full")}render(){return n`
<div id="foodbar" class="foodbar" data-value="4">
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
<div class="food"></div>
</div>
`}})},3671:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);function s(e){switch(e.id){case 19:return"poisoned";case 20:return"withered";case 22:return"absorption";default:return""}}window.customElements.define("pmui-healthbar",class extends i{static get styles(){return r`
.health {
position: absolute;
display: flex;
flex-direction: row;
left: calc(50% - 91px);
bottom: 30px;
--hardcore: 0;
--kind: 0;
--lightened: 0;
--offset: calc(-1 * (52px + (9px * (4 * var(--kind) + var(--lightened) * 2)) ));
--bg-x: calc(-1 * (16px + 9px * var(--lightened)));
--bg-y: calc(-1 * var(--hardcore) * 45px);
}
.health.creative {
display: none;
}
.health.hardcore {
--hardcore: 1;
}
.health.poisoned {
--kind: 1;
}
.health.withered {
--kind: 2;
}
.health.absorption {
--kind: 3;
}
.heart {
width: 9px;
height: 9px;
background-image: url('textures/1.17.1/gui/icons.png'), url('textures/1.17.1/gui/icons.png');
background-size: 256px, 256px;
background-position: var(--bg-x) var(--bg-y), var(--bg-x) var(--bg-y);
margin-left: -1px;
}
.heart.full {
background-position: var(--offset) var(--bg-y), var(--bg-x) var(--bg-y);
}
.heart.half {
background-position: calc(var(--offset) - 9px) var(--bg-y), var(--bg-x) var(--bg-y);
}
.health.low .heart {
animation: lowHealthAnim 0.2s steps(2, end) infinite;
}
.health.low .heart:nth-of-type(2n) {
animation-direction: reverse;
}
.health.low .heart:nth-of-type(3n) {
animation-duration: 0.1s;
}
.health.damaged {
animation: damagedAnim 0.3s steps(2, end) 2;
}
@keyframes lowHealthAnim {
to {
transform: translateY(1px);
}
}
@keyframes damagedAnim {
to { --lightened: 1; }
}
`}effectAdded(e){this.shadowRoot.querySelector("#health").classList.add(s(e))}effectEnded(e){this.shadowRoot.querySelector("#health").classList.remove(s(e))}onDamage(){this.shadowRoot.querySelector("#health").classList.toggle("damaged",!0),this.hurtTimeout&&clearTimeout(this.hurtTimeout),this.hurtTimeout=setTimeout((()=>{this.shadowRoot.querySelector("#health").classList.toggle("damaged",!1),this.hurtTimeout=null}),1e3)}gameModeChanged(e,t){this.shadowRoot.querySelector("#health").classList.toggle("creative",1===e),this.shadowRoot.querySelector("#health").classList.toggle("hardcore",t)}updateHealth(e,t){const a=this.shadowRoot.querySelector("#health");a.classList.toggle("low",e<=4);const i=a.children;for(let e=0;e<i.length;e++)i[e].classList.remove("full"),i[e].classList.remove("half");t&&this.onDamage();for(let t=0;t<Math.ceil(e/2)&&!(t>=i.length);t++)e%2!=0&&Math.ceil(e/2)===t+1?i[t].classList.add("half"):i[t].classList.add("full")}render(){return n`
<div id="health" class="health">
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
</div>
`}})},46071:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677),s=a(85982);window.customElements.define("pmui-hotbar",class extends i{static get styles(){return r`
.hotbar {
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%);
width: 182px;
height: 22px;
background: url("textures/1.16.4/gui/widgets.png");
background-size: 256px;
}
#hotbar-selected {
position: absolute;
left: -1px;
top: -1px;
width: 24px;
height: 24px;
background: url("textures/1.16.4/gui/widgets.png");
background-size: 256px;
background-position-y: -22px;
}
#hotbar-items-wrapper {
position: absolute;
top: 0;
left: 1px;
display: flex;
flex-direction: row;
height: 22px;
margin: 0;
padding: 0;
}
.hotbar-item {
position: relative;
width: 20px;
height: 22px;
}
.item-icon {
top: 3px;
left: 2px;
position: absolute;
width: 32px;
height: 32px;
transform-origin: top left;
transform: scale(0.5);
background-image: url('invsprite.png');
background-size: 1024px auto;
}
.item-stack {
position: absolute;
color: white;
font-size: 10px;
text-shadow: 1px 1px 0 rgb(63, 63, 63);
right: 1px;
bottom: 1px;
}
#hotbar-item-name {
color: white;
position: absolute;
bottom: 51px;
left: 50%;
transform: translate(-50%);
text-shadow: rgb(63, 63, 63) 1px 1px 0px;
font-family: mojangles, minecraft, monospace;
font-size: 10px;
text-align: center;
}
.hotbar-item-name-fader {
opacity: 0;
transition: visibility 0s, opacity 1s linear;
transition-delay: 2s;
}
`}static get properties(){return{activeItemName:{type:String},bot:{type:Object},viewerVersion:{type:String}}}constructor(){super(),this.activeItemName=""}updated(e){e.has("bot")&&this.bot.once("spawn",(()=>{this.init()}))}init(){this.reloadHotbar(),this.reloadHotbarSelected(0),document.addEventListener("wheel",(e=>{const t=((this.bot.quickBarSlot+Math.sign(e.deltaY))%9+9)%9;this.reloadHotbarSelected(t)})),document.addEventListener("keydown",(e=>{const t=e.code.substr(5);t<1||t>9||this.reloadHotbarSelected(t-1)})),this.bot.inventory.on("updateSlot",((e,t,a)=>{if(e>=this.bot.inventory.hotbarStart+9)return;if(e<this.bot.inventory.hotbarStart)return;const i=a?s[a.name]:s.air,n=this.shadowRoot.getElementById("hotbar-"+(e-this.bot.inventory.hotbarStart)),r=n.children[0],o=n.children[1];r.style["background-position-x"]=`-${i.x}px`,r.style["background-position-y"]=`-${i.y}px`,o.innerHTML=a?.count>1?a.count:""}))}async reloadHotbar(){for(let e=0;e<9;e++){const t=this.bot.inventory.slots[this.bot.inventory.hotbarStart+e],a=t?s[t.name]:s.air,i=this.shadowRoot.getElementById("hotbar-"+e),n=i.children[0],r=i.children[1];n.style["background-position-x"]=`-${a.x}px`,n.style["background-position-y"]=`-${a.y}px`,r.innerHTML=t?.count>1?t.count:""}}async reloadHotbarSelected(e){const t=this.bot.inventory.slots[this.bot.inventory.hotbarStart+e],a=20*e-1+"px";this.shadowRoot.getElementById("hotbar-selected").style.left=a,this.bot.setQuickBarSlot(e),this.activeItemName=t?.displayName??"";const i=this.shadowRoot.getElementById("hotbar-item-name");i.classList.remove("hotbar-item-name-fader"),setTimeout((()=>i.classList.add("hotbar-item-name-fader")),10)}render(){return n`
<div class="hotbar">
<p id="hotbar-item-name">${this.activeItemName}</p>
<div id="hotbar-selected"></div>
<div id="hotbar-items-wrapper">
<div class="hotbar-item" id="hotbar-0">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-1">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-2">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-3">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-4">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-5">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-6">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-7">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
<div class="hotbar-item" id="hotbar-8">
<div class="item-icon"></div>
<span class="item-stack"></span>
</div>
</div>
</div>
`}})},68066:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);window.customElements.define("pmui-playerlist-overlay",class extends i{static get styles(){return r`
.playerlist-container {
position: absolute;
background-color: rgba(0, 0, 0, 0.3);
top: 9px;
left: 50%;
transform: translate(-50%);
width: fit-content;
padding: 1px;
display: flex;
flex-direction: column;
gap: 1px 0;
place-items: center;
z-index: 30;
}
.title {
color: white;
text-shadow: 1px 1px 0px #3f3f3f;
font-size: 10px;
margin: 0;
padding: 0;
}
.playerlist-entry {
overflow: hidden;
color: white;
font-size: 10px;
margin: 0px;
line-height: calc(100% - 1px);
text-shadow: 1px 1px 0px #3f3f3f;
font-family: mojangles, minecraft, monospace;
background: rgba(255, 255, 255, 0.1);
width: 100%;
}
.active-player {
color: rgb(42, 204, 237);
text-shadow: 1px 1px 0px rgb(4, 44, 67);
}
.playerlist-ping {
text-align: right;
float: right;
padding-left: 10px;
}
.playerlist-ping-value {
color: rgb(114, 255, 114);
text-shadow: 1px 1px 0px rgb(28, 105, 28);
float: left;
margin: 0;
margin-right: 1px;
}
.playerlist-ping-label {
text-shadow: 1px 1px 0px #3f3f3f;
color: white;
float: right;
margin: 0px;
}
.player-lists {
display: flex;
flex-direction: row;
place-items: center;
place-content: center;
gap: 0 4px;
}
.player-list {
display: flex;
flex-direction: column;
gap: 1px 0;
min-width: 80px;
}
`}static get properties(){return{serverIP:{type:String},clientId:{type:String},players:{type:Object}}}constructor(){super(),this.serverIP="",this.clientId="",this.players={}}init(e,t){const a=this.shadowRoot.querySelector("#playerlist-container");this.isOpen=!1,this.players=e.players,this.clientId=e.player.uuid,this.serverIP=t,this.requestUpdate();const i=(e=!0)=>{a.style.display=e?"block":"none",this.isOpen=e};document.addEventListener("keydown",(e=>{e??=window.event,"Tab"===e.key&&(i(!0),e.preventDefault())})),document.addEventListener("keyup",(e=>{this.isOpen&&(e??=window.event,"Tab"===e.key&&(i(!1),e.preventDefault()))})),e.on("playerUpdated",(()=>this.requestUpdate())),e.on("playerJoined",(()=>this.requestUpdate())),e.on("playerLeft",(()=>this.requestUpdate()))}render(){const e=[],t=Object.values(this.players).sort(((e,t)=>e.username>t.username?1:e.username<t.username?-1:0));let a=[];for(let i=0;i<t.length;i++)a.push(t[i]),(i+1)/10!=1&&i+1!==t.length||(e.push([...a]),a=[]);return n`
<div class="playerlist-container" id="playerlist-container" style="display: none;">
<span class="title">Server IP: ${this.serverIP}</span>
<div class="player-lists">
${e.map((e=>n`
<div class="player-list">
${e.map((e=>n`
<div class="playerlist-entry${this.clientId===e.uuid?" active-player":""}" id="plist-player-${e.uuid}">
${e.username}
<div class="playerlist-ping">
<p class="playerlist-ping-value">${e.ping}</p>
<p class="playerlist-ping-label">ms</p>
</div>
</div>
`))}
</div>
`))}
</div>
</div>
`}})},76702:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677);window.customElements.define("pmui-slider",class extends i{static get styles(){return r`
.slider-container {
--txrV: -46px;
position: relative;
width: 150px;
height: 20px;
font-family: minecraft, mojangles, monospace;
font-size: 10px;
color: white;
text-shadow: 1px 1px #220;
z-index: 1;
}
.slider-thumb {
--txrV: -66px;
pointer-events: none;
width: 8px;
height: 20px;
position: absolute;
top: 0;
left: 0;
z-index: 3;
}
.slider-container:hover .slider-thumb {
--txrV: -86px;
}
.slider-container::after,
.slider-thumb::after {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 20px;
background: url('textures/1.17.1/gui/widgets.png');
background-size: 256px;
background-position-y: var(--txrV);
z-index: -1;
}
.slider-container::before,
.slider-thumb::before {
content: '';
display: block;
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 20px;
background: url('textures/1.17.1/gui/widgets.png');
background-size: 256px;
background-position-x: calc(-200px + 100%);
background-position-y: var(--txrV);
z-index: -1;
}
.slider {
display: block;
position: absolute;
top: 0;
left: 0;
-webkit-appearance: none;
appearance: none;
background: none;
width: 100%;
height: 20px;
margin: 0;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
position: relative;
appearance: none;
width: 8px;
height: 20px;
background: transparent;
}
.slider::-moz-range-thumb {
width: 8px;
height: 20px;
background: transparent;
}
label {
pointer-events: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 6;
width: max-content;
}
`}constructor(){super(),this.label="",this.type="%",this.width="150px",this.value="50",this.min="0",this.max="100",this.ratio=(Number(this.value)-Number(this.min))/(Number(this.max)-Number(this.min))}updated(){this.ratio=(Number(this.value)-Number(this.min))/(Number(this.max)-Number(this.min))}static get properties(){return{label:{type:String,attribute:"pmui-label"},type:{type:String,attribute:"pmui-type"},width:{type:String,attribute:"pmui-width"},value:{type:String,attribute:"pmui-value"},min:{type:String,attribute:"pmui-min"},max:{type:String,attribute:"pmui-max"},ratio:{type:Number}}}render(){return n`
<div
class="slider-container"
style="width: ${this.width};"
>
<input
type="range"
class="slider"
min="${this.min}"
max="${this.max}"
value="${this.value}"
@input=${e=>{const t=e.target;this.ratio=(t.value-t.min)/(t.max-t.min),this.value=t.value}}>
<div
class="slider-thumb"
style="left: calc((100% * ${this.ratio}) - (8px * ${this.ratio}));"
></div>
<label>${this.label}: ${this.value}${this.type}</label>
</div>
`}})},11587:(e,t,a)=>{const{LitElement:i,html:n,css:r}=a(37677),{isMobile:s}=a(27472);window.customElements.define("pmui-hud",class extends i{static get styles(){return r`
:host {
position: absolute;
top: 0;
left: 0;
z-index: -2;
width: 100%;
height: 100%;
}
.crosshair {
width: 16px;
height: 16px;
background: url('textures/1.17.1/gui/icons.png');
background-size: 256px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
}
#xp-label {
position: absolute;
top: -8px;
left: 50%;
transform: translate(-50%);
font-size: 10px;
font-family: minecraft, mojangles, monospace;
color: rgb(30, 250, 30);
text-shadow: 0px -1px #000, 0px 1px #000, 1px 0px #000, -1px 0px #000;
z-index: 10;
}
#xp-bar-bg {
position: absolute;
left: 50%;
bottom: 24px;
transform: translate(-50%);
width: 182px;
height: 5px;
background-image: url('textures/1.16.4/gui/icons.png');
background-size: 256px;
background-position-y: -64px;
}
.xp-bar {
width: 182px;
height: 5px;
background-image: url('textures/1.17.1/gui/icons.png');
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}}}preload(e){const t=this.shadowRoot.querySelector("#bossbars-overlay");t.bot=e,t.init()}init(e,t,a){const i=this.shadowRoot.querySelector("#debug-overlay"),n=this.shadowRoot.querySelector("#playerlist-overlay"),r=this.shadowRoot.querySelector("#health-bar"),o=this.shadowRoot.querySelector("#food-bar"),l=this.shadowRoot.querySelector("#chat"),d=this.shadowRoot.querySelector("#hotbar"),c=this.shadowRoot.querySelector("#xp-label");this.bot=t,d.bot=t,i.bot=t,d.init(),l.init(t._client,e),t.on("spawn",(()=>n.init(t,a))),t.on("entityHurt",(e=>{e===t.entity&&r.onDamage()})),t.on("entityEffect",((e,a)=>{e===t.entity&&r.effectAdded(a)})),t.on("entityEffectEnd",((e,a)=>{e===t.entity&&r.effectEnded(a)})),t.on("game",(()=>{r.gameModeChanged(t.player.gamemode,t.game.hardcore),o.gameModeChanged(t.player.gamemode),this.shadowRoot.querySelector("#xp-bar-bg").style.display=1===t.player.gamemode?"none":"block"})),t.on("health",(()=>{r.updateHealth(t.health,!0),o.updateHunger(t.food,!0)})),t.on("experience",(()=>{this.shadowRoot.querySelector("#xp-bar-bg").firstElementChild.style.width=182*t.experience.progress+"px",c.innerHTML=t.experience.level,c.style.display=t.experience.level>0?"block":"none"})),t.on("spawn",(()=>{this.shadowRoot.querySelector("#xp-bar-bg").style.display=1===t.player.gamemode?"none":"block",this.shadowRoot.querySelector("#xp-bar-bg").firstElementChild.style.width=182*t.experience.progress+"px",c.innerHTML=t.experience.level,c.style.display=t.experience.level>0?"block":"none",r.gameModeChanged(t.player.gamemode,t.game.hardcore),r.updateHealth(t.health),o.updateHunger(t.food)})),document.getElementById("options-screen").forceMobileControls||s()?this.showMobileControls(!0):this.showMobileControls(!1)}showMobileControls(e){this.shadowRoot.querySelector("#mobile-top").style.display=e?"flex":"none",this.shadowRoot.querySelector("#mobile-left").style.display=e?"block":"none",this.shadowRoot.querySelector("#mobile-right").style.display=e?"flex":"none"}mobileControl(e,t,a){e.stopPropagation(),this.bot.setControlState(t,a)}render(){return n`
<div class="mobile-top-btns" id="mobile-top">
<button class="chat-btn" @click=${e=>{e.stopPropagation(),this.shadowRoot.querySelector("#chat").enableChat(!1)}}></button>
<button class="pause-btn" @click=${e=>{e.stopPropagation(),document.getElementById("pause-screen").enableGameMenu()}}></button>
</div>
<div class="mobile-controls-left" id="mobile-left">
<button
class="mobile-control-forward"
@touchstart=${e=>this.mobileControl(e,"forward",!0)}
@touchend=${e=>this.mobileControl(e,"forward",!1)}
@mousedown=${e=>this.mobileControl(e,"forward",!0)}
@mouseup=${e=>this.mobileControl(e,"forward",!1)}
></button>
<button
class="mobile-control-back"
@touchstart=${e=>this.mobileControl(e,"back",!0)}
@touchend=${e=>this.mobileControl(e,"back",!1)}
@mousedown=${e=>this.mobileControl(e,"back",!0)}
@mouseup=${e=>this.mobileControl(e,"back",!1)}
></button>
<button class="mobile-control-left"
@touchstart=${e=>this.mobileControl(e,"right",!0)}
@touchen