Compare commits

..

No commits in common. "bd26c5d2db2f1fe6a7376992af78f743df853a15" and "75413f5045cb5d0154c08fd751d8ec93b1867d6c" have entirely different histories.

View File

@ -6,24 +6,11 @@
// @downloadURL https://raw.githubusercontent.com/FlamedDogo99/EaglerMobile/main/eaglermobile.user.js // @downloadURL https://raw.githubusercontent.com/FlamedDogo99/EaglerMobile/main/eaglermobile.user.js
// @license Apache License 2.0 - http://www.apache.org/licenses/ // @license Apache License 2.0 - http://www.apache.org/licenses/
// @match https://eaglercraft.com/mc/* // @match https://eaglercraft.com/mc/*
// @version 3.0.4-pre-1 // @version 3.0.6-chat-fix
// @updateURL https://raw.githubusercontent.com/FlamedDogo99/EaglerMobile/main/eaglermobile.user.js // @updateURL https://raw.githubusercontent.com/FlamedDogo99/EaglerMobile/main/eaglermobile.user.js
// @run-at document-start // @run-at document-start
// @grant unsafeWindow
// ==/UserScript== // ==/UserScript==
// This is generally a bad practice, but we need to run scripts in the main context before the DOM loads. Because we are only matching eaglercraft.com, the use of unsafeWindow should be safe to use.
// If someone knows a better way of doing this, please create an issue
try {
unsafeWindow.console.warn("DANGER: This userscript is using unsafeWindow. Unsafe websites could potentially use this to gain access to data and other content that the browser normally wouldn't allow!")
Object.defineProperty(window, "clientWindow", {
value: unsafeWindow
});
} catch {
Object.defineProperty(window, "clientWindow", {
value: window
});
}
function isMobile() { function isMobile() {
try { try {
@ -36,22 +23,17 @@ function isMobile() {
if(!isMobile()) { if(!isMobile()) {
alert("WARNING: This script was created for mobile, and may break functionality in non-mobile browsers!"); alert("WARNING: This script was created for mobile, and may break functionality in non-mobile browsers!");
} }
window.keyboardEnabled = false;
clientWindow.keyboardEnabled = false; window.crouchLock = false;
clientWindow.crouchLock = false; window.sprintLock = false;
clientWindow.sprintLock = false; window.keyboardFix = false; // temporarily set to true until I can figure out whats going wrong with the event listener in charge of switching it
clientWindow.keyboardFix = false;
clientWindow.inputFix = false;
clientWindow.blockNextInput = false;
// Used for changing touchmove events to mousemove events // Used for changing touchmove events to mousemove events
var previousTouchX = null; var previousTouchX = null;
var previousTouchY = null; var previousTouchY = null;
var startTouchX = null; var startTouchX = null;
// better charCodeAt function // better charCodeAt function
String.prototype.toKeyCode = function() { String.prototype.toKeyCode = function() {
const keyCodeList = {"0": 48, "1": 49, "2": 50, "3": 51, "4": 52, "5": 53, "6": 54, "7": 55, "8": 56, "9": 57, "backspace": 8, "tab": 9, "enter": 13, "shift": 16, "ctrl": 17, "alt": 18, "pause_break": 19, "caps_lock": 20, "escape": 27, " ": 32, "page_up": 33, "page_down": 34, "end": 35, "home": 36, "left_arrow": 37, "up_arrow": 38, "right_arrow": 39, "down_arrow": 40, "insert": 45, "delete": 46, "a": 65, "b": 66, "c": 67, "d": 68, "e": 69, "f": 70, "g": 71, "h": 72, "i": 73, "j": 74, "k": 75, "l": 76, "m": 77, "n": 78, "o": 79, "p": 80, "q": 81, "r": 82, "s": 83, "t": 84, "u": 85, "v": 86, "w": 87, "x": 88, "y": 89, "z": 90, "left_window_key": 91, "right_window_key": 92, "select_key": 93, "numpad_0": 96, "numpad_1": 97, "numpad_2": 98, "numpad_3": 99, "numpad_4": 100, "numpad_5": 101, "numpad_6": 102, "numpad_7": 103, "numpad_8": 104, "numpad_9": 105, "*": 106, "+": 107, "-": 109, ".": 110, "/": 111, "f1": 112, "f2": 113, "f3": 114, "f4": 115, "f5": 116, "f6": 117, "f7": 118, "f8": 119, "f9": 120, "f10": 121, "f11": 122, "f12": 123, "num_lock": 144, "scroll_lock": 145, ";": 186, "=": 187, ",": 188, "-": 189, ".": 190, "/": 191, "\u0060": 192, "[": 219, "\u005C": 220, "]": 221, "\u0022": 222}; const keyCodeList = {"0": 48, "1": 49, "2": 50, "3": 51, "4": 52, "5": 53, "6": 54, "7": 55, "8": 56, "9": 57, "backspace": 8, "tab": 9, "enter": 13, "shift": 16, "ctrl": 17, "alt": 18, "pause_break": 19, "caps_lock": 20, "escape": 27, " ": 32, "page_up": 33, "page_down": 34, "end": 35, "home": 36, "left_arrow": 37, "up_arrow": 38, "right_arrow": 39, "down_arrow": 40, "insert": 45, "delete": 46, "a": 65, "b": 66, "c": 67, "d": 68, "e": 69, "f": 70, "g": 71, "h": 72, "i": 73, "j": 74, "k": 75, "l": 76, "m": 77, "n": 78, "o": 79, "p": 80, "q": 81, "r": 82, "s": 83, "t": 84, "u": 85, "v": 86, "w": 87, "x": 88, "y": 89, "z": 90, "left_window_key": 91, "right_window_key": 92, "select_key": 93, "numpad_0": 96, "numpad_1": 97, "numpad_2": 98, "numpad_3": 99, "numpad_4": 100, "numpad_5": 101, "numpad_6": 102, "numpad_7": 103, "numpad_8": 104, "numpad_9": 105, "*": 106, "+": 107, "-": 109, ".": 110, "/": 111, "f1": 112, "f2": 113, "f3": 114, "f4": 115, "f5": 116, "f6": 117, "f7": 118, "f8": 119, "f9": 120, "f10": 121, "f11": 122, "f12": 123, "num_lock": 144, "scroll_lock": 145, ";": 186, "=": 187, ",": 188, "-": 189, ".": 190, "/": 191, "`": 192, "[": 219, "\\": 220, "]": 221, "\"": 222};
return keyCodeList[this]; return keyCodeList[this];
} }
// Ignores keydown events that don't have the isValid parameter set to true // Ignores keydown events that don't have the isValid parameter set to true
@ -60,20 +42,28 @@ Object.defineProperty(EventTarget.prototype, "addEventListener", {
value: function (type, fn, ...rest) { value: function (type, fn, ...rest) {
if(type == 'keydown') { if(type == 'keydown') {
_addEventListener.call(this, type, function(...args) { _addEventListener.call(this, type, function(...args) {
if(!args[0].isValid && clientWindow.keyboardFix) { if(!args[0].isValid && window.keyboardFix) {
return; return;
} }
return fn.apply(this, args); return fn.apply(this, args);
}, ...rest); }, ...rest);
} else if (type == 'blur' || type == 'mouseleave') {
_addEventListener.call(this, type, function(...args) {
return;
}, ...rest);
} else { } else {
_addEventListener.call(this, type, fn, ...rest); // _addEventListener.call(this, type, fn, ...rest);
_addEventListener.call(this, type, function(...args) {
// console.log(`%c CALLED ${type}`, 'background: #222; color: #bada55', args);
return fn.apply(this, args);
}, ...rest);
} }
} }
}); });
// Allows typing in #hiddenInput // Allows typing in #hiddenInput
const _preventDefault = Event.prototype.preventDefault; const _preventDefault = Event.prototype.preventDefault;
Event.prototype.preventDefault = function(shouldBypass) { Event.prototype.preventDefault = function() {
if(document.activeElement.id != "hiddenInput" || shouldBypass) { if(document.activeElement.id != "hiddenInput") {
this._preventDefault = _preventDefault; this._preventDefault = _preventDefault;
this._preventDefault(); this._preventDefault();
} }
@ -91,7 +81,7 @@ function keyEvent(name, state) {
which: charCode which: charCode
}); });
evt.isValid = true; // Disables fix for bad keyboard input evt.isValid = true; // Disables fix for bad keyboard input
clientWindow.dispatchEvent(evt); window.dispatchEvent(evt);
} }
function mouseEvent(number, state, canvas) { function mouseEvent(number, state, canvas) {
canvas.dispatchEvent(new PointerEvent(state, {"button": number})) canvas.dispatchEvent(new PointerEvent(state, {"button": number}))
@ -108,56 +98,56 @@ function setButtonVisibility(pointerLocked) {
inMenuStyle.disabled = !pointerLocked; inMenuStyle.disabled = !pointerLocked;
} }
// POINTERLOCK // POINTERLOCK
// When requestpointerlock is called, this dispatches an event, saves the requested element to clientWindow.fakelock, and unhides the touch controls // When requestpointerlock is called, this dispatches an event, saves the requested element to window.fakelock, and unhides the touch controls
clientWindow.fakelock = null; window.fakelock = null;
Object.defineProperty(Element.prototype, "requestPointerLock", { Object.defineProperty(Element.prototype, "requestPointerLock", {
value: function() { value: function() {
clientWindow.fakelock = this window.fakelock = this
document.dispatchEvent(new Event('pointerlockchange')); document.dispatchEvent(new Event('pointerlockchange'));
setButtonVisibility(true); setButtonVisibility(true);
return true return true
} }
}); });
// Makes pointerLockElement return clientWindow.fakelock // Makes pointerLockElement return window.fakelock
Object.defineProperty(Document.prototype, "pointerLockElement", { Object.defineProperty(Document.prototype, "pointerLockElement", {
get: function() { get: function() {
return clientWindow.fakelock; return window.fakelock;
} }
}); });
// When exitPointerLock is called, this dispatches an event, clears the // When exitPointerLock is called, this dispatches an event, clears the
Object.defineProperty(Document.prototype, "exitPointerLock", { Object.defineProperty(Document.prototype, "exitPointerLock", {
value: function() { value: function() {
clientWindow.fakelock = null window.fakelock = null
document.dispatchEvent(new Event('pointerlockchange')); document.dispatchEvent(new Event('pointerlockchange'));
setButtonVisibility(false); setButtonVisibility(false);
return true return true
} }
}); });
// FULLSCREEN // FULLSCREEN
clientWindow.fakefull = null; window.fakefull = null;
// Stops the client from crashing when fullscreen is requested // Stops the client from crashing when fullscreen is requested
Object.defineProperty(Element.prototype, "requestFullscreen", { Object.defineProperty(Element.prototype, "requestFullscreen", {
value: function() { value: function() {
clientWindow.fakefull = this window.fakefull = this
document.dispatchEvent(new Event('fullscreenchange')); document.dispatchEvent(new Event('fullscreenchange'));
return true return true
} }
}); });
Object.defineProperty(document, "fullscreenElement", { Object.defineProperty(document, "fullscreenElement", {
get: function() { get: function() {
return clientWindow.fakefull; return window.fakefull;
} }
}); });
Object.defineProperty(Document.prototype, "exitFullscreen", { Object.defineProperty(Document.prototype, "exitFullscreen", {
value: function() { value: function() {
clientWindow.fakefull = null window.fakefull = null
document.dispatchEvent(new Event('fullscreenchange')); document.dispatchEvent(new Event('fullscreenchange'));
return true return true
} }
}); });
// FILE UPLOADING // FILE UPLOADING
@ -168,16 +158,16 @@ document.createElement = function(type, ignore) {
this._createElement = _createElement; this._createElement = _createElement;
var element = this._createElement(type); var element = this._createElement(type);
if(type == "input" && !ignore) { if(type == "input" && !ignore) {
document.querySelectorAll('#fileUpload').forEach(e => e.parentNode.removeChild(e)); document.querySelectorAll('#fileUpload').forEach(e => e.parentNode.removeChild(e));
element.id = "fileUpload"; element.id = "fileUpload";
element.addEventListener('change', function(e) { element.addEventListener('change', function(e) {
element.hidden = true; element.hidden = true;
element.style.display = "none"; element.style.display = "none";
}, {passive: false, once: true}); }, {passive: false, once: true});
clientWindow.addEventListener('focus', function(e) { window.addEventListener('focus', function(e) {
setTimeout(() => { setTimeout(() => {
element.hidden = true; element.hidden = true;
element.style.display = "none"; element.style.display = "none";
}, 300) }, 300)
}, { once: true }) }, { once: true })
document.body.appendChild(element); document.body.appendChild(element);
@ -227,17 +217,16 @@ function createTouchButton(buttonClass, buttonDisplay, elementName) {
touchButton.classList.add(buttonDisplay); touchButton.classList.add(buttonDisplay);
touchButton.classList.add("mobileControl"); touchButton.classList.add("mobileControl");
touchButton.addEventListener("touchmove", function(e){e.preventDefault()}, false); touchButton.addEventListener("touchmove", function(e){e.preventDefault()}, false);
touchButton.addEventListener("contextmenu", function(e){e.preventDefault()});
return touchButton; return touchButton;
} }
function toggleKeyboard() { function toggleKeyboard() {
const keyboardInput = document.getElementById('hiddenInput'); const keyboardInput = document.getElementById('hiddenInput');
if (clientWindow.keyboardEnabled) { if (window.keyboardEnabled) {
clientWindow.keyboardEnabled = false; window.keyboardEnabled = false;
keyboardInput.blur(); keyboardInput.blur();
} else { } else {
clientWindow.keyboardEnabled = true; window.keyboardEnabled = true;
keyboardInput.select(); keyboardInput.select();
} }
} }
@ -256,7 +245,7 @@ function insertCanvasElements() {
} }
e.movementX = touch.pageX - previousTouchX; e.movementX = touch.pageX - previousTouchX;
e.movementY = touch.pageY - previousTouchY; e.movementY = touch.pageY - previousTouchY;
var evt = clientWindow.fakelock ? new MouseEvent("mousemove", {movementX: e.movementX, movementY: e.movementY}) : new WheelEvent("wheel", {"wheelDeltaY": e.movementY}); var evt = window.fakelock ? new MouseEvent("mousemove", {movementX: e.movementX, movementY: e.movementY}) : new WheelEvent("wheel", {"wheelDeltaY": e.movementY});
canvas.dispatchEvent(evt); canvas.dispatchEvent(evt);
previousTouchX = touch.pageX; previousTouchX = touch.pageX;
previousTouchY = touch.pageY; previousTouchY = touch.pageY;
@ -267,7 +256,7 @@ function insertCanvasElements() {
previousTouchY = null; previousTouchY = null;
}, false) }, false)
//Updates button visibility on load //Updates button visibility on load
setButtonVisibility(clientWindow.fakelock != null); setButtonVisibility(window.fakelock != null);
// Adds all of the touch screen controls // Adds all of the touch screen controls
// Theres probably a better way to do this but this works for now // Theres probably a better way to do this but this works for now
let strafeRightButton = createTouchButton("strafeRightButton", "inGame", "div"); let strafeRightButton = createTouchButton("strafeRightButton", "inGame", "div");
@ -293,13 +282,13 @@ function insertCanvasElements() {
startTouchX = touch.pageX; startTouchX = touch.pageX;
} }
let movementX = touch.pageX - startTouchX; let movementX = touch.pageX - startTouchX;
if((movementX * 10) > clientWindow.innerHeight) { if((movementX * 10) > window.innerHeight) {
strafeRightButton.classList.add("active"); strafeRightButton.classList.add("active");
strafeLeftButton.classList.remove("active"); strafeLeftButton.classList.remove("active");
keyEvent("d", "keydown"); keyEvent("d", "keydown");
keyEvent("a", "keyup"); keyEvent("a", "keyup");
} else if ((movementX * 10) < (0 - clientWindow.innerHeight)) { } else if ((movementX * 10) < (0 - window.innerHeight)) {
strafeLeftButton.classList.add("active"); strafeLeftButton.classList.add("active");
strafeRightButton.classList.remove("active"); strafeRightButton.classList.remove("active");
keyEvent("a", "keydown"); keyEvent("a", "keydown");
@ -352,20 +341,20 @@ function insertCanvasElements() {
crouchButton.style.cssText = "left:10vh;bottom:10vh;" crouchButton.style.cssText = "left:10vh;bottom:10vh;"
crouchButton.addEventListener("touchstart", function(e){ crouchButton.addEventListener("touchstart", function(e){
keyEvent("shift", "keydown") keyEvent("shift", "keydown")
clientWindow.crouchLock = clientWindow.crouchLock ? null : false window.crouchLock = window.crouchLock ? null : false
clientWindow.crouchTimer = setTimeout(function(e) { crouchTimer = setTimeout(function(e) {
clientWindow.crouchLock = (clientWindow.crouchLock != null); window.crouchLock = (window.crouchLock != null);
crouchButton.classList.toggle('active'); crouchButton.classList.toggle('active');
}, 1000); }, 1000);
}, false); }, false);
crouchButton.addEventListener("touchend", function(e) { crouchButton.addEventListener("touchend", function(e) {
if(!clientWindow.crouchLock) { if(!window.crouchLock) {
keyEvent("shift", "keyup") keyEvent("shift", "keyup")
crouchButton.classList.remove('active'); crouchButton.classList.remove('active');
clientWindow.crouchLock = false window.crouchLock = false
} }
clearTimeout(clientWindow.crouchTimer); clearTimeout(crouchTimer);
}, false); }, false);
document.body.appendChild(crouchButton); document.body.appendChild(crouchButton);
let inventoryButton = createTouchButton("inventoryButton", "inGame"); let inventoryButton = createTouchButton("inventoryButton", "inGame");
@ -386,51 +375,34 @@ function insertCanvasElements() {
hiddenInput.style.cssText = "position:absolute;top: 0vh; margin: auto; left: 8vh; right:0vh; width: 8vh; height: 8vh;font-size:20px;z-index:-10;color: transparent;text-shadow: 0 0 0 black;"; hiddenInput.style.cssText = "position:absolute;top: 0vh; margin: auto; left: 8vh; right:0vh; width: 8vh; height: 8vh;font-size:20px;z-index:-10;color: transparent;text-shadow: 0 0 0 black;";
hiddenInput.value = " " //Allows delete to be detected before input is changed hiddenInput.value = " " //Allows delete to be detected before input is changed
hiddenInput.addEventListener("input", function(e) { hiddenInput.addEventListener("input", function(e) {
e.stopImmediatePropagation(); let inputData = (e.data == null) ? "delete" : e.data.slice(-1); // backspace makes null
e.preventDefault(true); window.lastKey = inputData
let inputData = e.data == null ? "delete" : e.data.slice(-1); hiddenInput.value = " "; // We need a character to detect deleting
if(!clientWindow.lastKey) { // If we get an event before any keys have been pressed, we know that setting the hiddenInput creates duplicate input events, so we can apply the fix if(window.keyboardFix) {
clientWindow.console.warn("Enabling blocking duplicate key events. Some functionality may be lost.") if(e.inputType == 'insertText' || e.inputType == 'insertCompositionText') {
clientWindow.inputFix = true; let isShift = (inputData.toLowerCase() != inputData);
} if(isShift) {
clientWindow.console.log(`Received input by ${e.inputType}: ${e.data} -> ${inputData}`); keyEvent("shift", "keydown")
keyEvent(inputData, "keydown");
hiddenInput.value = " "; keyEvent(inputData, "keyup");
if(clientWindow.keyboardFix) { keyEvent("shift", "keyup")
const sliceInputType = e.inputType.slice(0,1); // This is a really dumb way to do this because it's not future-proof, but its the easiest way to deal with Android
if(sliceInputType== 'i') {
const isDuplicate = (clientWindow.lastKey == inputData) && clientWindow.blockNextInput && clientWindow.inputFix;
if(isDuplicate) {
clientWindow.blockNextInput = false;
} else { } else {
let isShift = (inputData.toLowerCase() != inputData); keyEvent(inputData, "keydown");
if(isShift) { keyEvent(inputData, "keyup");
keyEvent("shift", "keydown")
keyEvent(inputData, "keydown");
keyEvent(inputData, "keyup");
keyEvent("shift", "keyup")
} else {
keyEvent(inputData, "keydown");
keyEvent(inputData, "keyup");
}
clientWindow.blockNextInput = true;
} }
} else if (sliceInputType == 'd') { } else if (e.inputType == 'deleteContentForward' || e.inputType == 'deleteContentBackward') {
keyEvent("backspace", "keydown"); keyEvent("backspace", "keydown")
keyEvent("backspace", "keyup"); keyEvent("backspace", "keyup")
clientWindow.blockNextInput = false;
} }
} }
clientWindow.lastKey = inputData
}, false); }, false);
hiddenInput.addEventListener("keydown", function(e) { hiddenInput.addEventListener("keydown", function(e) {
if((e.keyCode == 229 || e.which == 229) && !clientWindow.keyboardFix) { if(!(e.key && e.keyCode && e.which) && !window.keyboardFix) {
clientWindow.console.warn("Switching from keydown to input events due to invalid KeyboardEvent. Some functionality will be lost.") console.warn("Switching from keydown to input events due to invalid KeyboardEvent. Some functionality will be lost.")
clientWindow.keyboardFix = true; window.keyboardFix = true;
if(clientWindow.lastKey) { if(window.lastKey) {
keyEvent(clientWindow.lastKey, "keydown"); keyEvent(window.lastKey, "keydown")
keyEvent(clientWindow.lastKey, "keyup"); keyEvent(window.lastKey, "keyup")
} }
} }
}, false); }, false);
@ -472,20 +444,20 @@ function insertCanvasElements() {
sprintButton.style.cssText = "right:0vh;bottom:10vh;" sprintButton.style.cssText = "right:0vh;bottom:10vh;"
sprintButton.addEventListener("touchstart", function(e) { sprintButton.addEventListener("touchstart", function(e) {
keyEvent("r", "keydown"); keyEvent("r", "keydown");
clientWindow.sprintLock = clientWindow.sprintLock ? null : false window.sprintLock = window.sprintLock ? null : false
clientWindow.sprintTimer = setTimeout(function(e) { sprintTimer = setTimeout(function(e) {
clientWindow.sprintLock = (clientWindow.sprintLock != null); window.sprintLock = (window.sprintLock != null);
sprintButton.classList.toggle('active'); sprintButton.classList.toggle('active');
}, 1000); }, 1000);
}, false); }, false);
sprintButton.addEventListener("touchend", function(e) { sprintButton.addEventListener("touchend", function(e) {
if(!clientWindow.sprintLock) { if(!window.sprintLock) {
keyEvent("r", "keyup"); keyEvent("r", "keyup");
sprintButton.classList.remove('active'); sprintButton.classList.remove('active');
clientWindow.sprintLock = false window.sprintLock = false
} }
clearTimeout(clientWindow.sprintTimer); clearTimeout(sprintTimer);
}, false); }, false);
document.body.appendChild(sprintButton); document.body.appendChild(sprintButton);
let pauseButton = createTouchButton("pauseButton", "inGame"); let pauseButton = createTouchButton("pauseButton", "inGame");
@ -495,11 +467,11 @@ function insertCanvasElements() {
document.body.appendChild(pauseButton); document.body.appendChild(pauseButton);
let chatButton = createTouchButton("chatButton", "inGame"); let chatButton = createTouchButton("chatButton", "inGame");
chatButton.style.cssText = "top: 0vh; margin: auto; left: 0vh; right: 16vh; width: 8vh; height: 8vh;" chatButton.style.cssText = "top: 0vh; margin: auto; left: 0vh; right: 16vh; width: 8vh; height: 8vh;"
chatButton.addEventListener("touchstart", function(e){ // Trying to figure out why the input isn't focusing chatButton.addEventListener("touchstart", function(e){
canvas.dispatchEvent(new Event("focus", { window.dispatchEvent(new Event("focus", {
returnValue: true, returnValue: true,
srcElement: canvas, srcElement: window,
target: canvas, target: window,
timeStamp: 1 timeStamp: 1
})); }));
canvas.dispatchEvent(new MouseEvent("mouseenter", { canvas.dispatchEvent(new MouseEvent("mouseenter", {
@ -513,10 +485,10 @@ function insertCanvasElements() {
y: 1, y: 1,
target: canvas, target: canvas,
toElement: canvas, toElement: canvas,
view: window
})); }));
keyEvent("t", "keydown") keyEvent("t", "keydown");
}, false); }, false); document.body.appendChild(chatButton);
document.body.appendChild(chatButton);
let perspectiveButton = createTouchButton("perspectiveButton", "inGame"); let perspectiveButton = createTouchButton("perspectiveButton", "inGame");
perspectiveButton.style.cssText = "top: 0vh; margin: auto; left: 0vh; right: 0vh; width: 8vh; height: 8vh;" perspectiveButton.style.cssText = "top: 0vh; margin: auto; left: 0vh; right: 0vh; width: 8vh; height: 8vh;"
perspectiveButton.addEventListener("touchstart", function(e) { perspectiveButton.addEventListener("touchstart", function(e) {
@ -540,7 +512,7 @@ function insertCanvasElements() {
}, false); }, false);
document.body.appendChild(screenshotButton); document.body.appendChild(screenshotButton);
let coordinatesButton = createTouchButton("coordinatesButton", "inGame"); let coordinatesButton = createTouchButton("coordinatesButton", "inGame");
coordinatesButton.style.cssText = "" coordinatesButton.style.cssText = "top: 0vh; margin: auto; left: 32vh; right: 0vh; width: 8vh; height: 8vh;"
coordinatesButton.addEventListener("touchstart", function(e) { coordinatesButton.addEventListener("touchstart", function(e) {
keyEvent("f", "keydown"); keyEvent("f", "keydown");
keyEvent("3", "keydown"); keyEvent("3", "keydown");
@ -571,7 +543,6 @@ customStyle.textContent = `
outline:none; outline:none;
box-shadow: none; box-shadow: none;
border: none; border: none;
pointer-events: none !important;
} }
.mobileControl:active, .mobileControl.active { .mobileControl:active, .mobileControl.active {
position: absolute; position: absolute;
@ -592,32 +563,24 @@ customStyle.textContent = `
outline:none; outline:none;
box-shadow: none; box-shadow: none;
border: none; border: none;
pointer-events: none !important;
} }
html, body, canvas { html, body {
height: -webkit-fill-available !important; height: -webkit-fill-available !important;
touch-action: pan-x pan-y; touch-action: pan-x pan-y;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
outline: none;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
} }
.hide { .hide {
display: none; display: none;
} }
#fileUpload { #fileUpload {
position: absolute; position: absolute;
left: 0; left: 0;
right: 100vw; right: 100vw;
top: 0; top: 0;
bottom: 100vh; bottom: 100vh;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background-color:rgba(255,255,255,0.5); background-color:rgba(255,255,255,0.5);
} }
.strafeRightButton { .strafeRightButton {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAUGVYSWZNTQAqAAAACAACARIAAwAAAAEAAQAAh2kABAAAAAEAAAAmAAAAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAAWoAMABAAAAAEAAAAWAAAAAA78HUQAAAIwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yMjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yMjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhDb0tQAAANRJREFUOBHVlMENwyAMRWnVHcqIjMEYzJAemlUidQh6aFZIApIt20FgUC/JxTb8/2wRgTFX+25i4E3UvSXyMDkIGeqc64VlfQgBfJnJwAC11oJIFWOMFJ6Zd+nshSZ/yXMCy0aj9aPH6L1HOc1xkSQqcAtCeJhWwSNAIA+dsaZhFawBwIQyVsFJLOGylkCom+ASHMy1WP151KidFDynieF6gkATSx42cYzf43o+TUnYajBNLyZh4LSzLB8mGC3YUczze5Rj1vXHvPTZTBt/e+hZl0sUO9qPMTJ6UlWFAAAAAElFTkSuQmCC"); background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAUGVYSWZNTQAqAAAACAACARIAAwAAAAEAAQAAh2kABAAAAAEAAAAmAAAAAAADoAEAAwAAAAEAAQAAoAIABAAAAAEAAAAWoAMABAAAAAEAAAAWAAAAAA78HUQAAAIwaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yMjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yMjwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KhDb0tQAAANRJREFUOBHVlMENwyAMRWnVHcqIjMEYzJAemlUidQh6aFZIApIt20FgUC/JxTb8/2wRgTFX+25i4E3UvSXyMDkIGeqc64VlfQgBfJnJwAC11oJIFWOMFJ6Zd+nshSZ/yXMCy0aj9aPH6L1HOc1xkSQqcAtCeJhWwSNAIA+dsaZhFawBwIQyVsFJLOGylkCom+ASHMy1WP151KidFDynieF6gkATSx42cYzf43o+TUnYajBNLyZh4LSzLB8mGC3YUczze5Rj1vXHvPTZTBt/e+hZl0sUO9qPMTJ6UlWFAAAAAElFTkSuQmCC");