+
1.8.8
-
+
1.5.2
-
+
1.2.5
@@ -67,11 +88,15 @@
Beta 1.3
-
+
Alpha 1.2.6
-
+
Indev
@@ -82,7 +107,9 @@
- Join the MineXLauncher Discord
+ Join the MineXLauncher Discord
© 2024 MineXLauncher. All rights reserved.
diff --git a/src/resources/data/main.json b/src/resources/data/main.json
index 33d1a8c..ce4c6bb 100644
--- a/src/resources/data/main.json
+++ b/src/resources/data/main.json
@@ -78,7 +78,11 @@
},
{
"version": "1.2",
- "changelog": ["Added Eaglercraft 1.2.5", "Added more mods and resource packs", "Fix and optimize mobile site"]
+ "changelog": [
+ "Added Eaglercraft 1.2.5",
+ "Added more mods and resource packs",
+ "Fix and optimize mobile site"
+ ]
},
{
"version": "1.1",
diff --git a/src/resources/scripts/eagler-launch/1.5.2/main.ts b/src/resources/scripts/eagler-launch/1.5.2/main.ts
index 2011b8a..9071aae 100644
--- a/src/resources/scripts/eagler-launch/1.5.2/main.ts
+++ b/src/resources/scripts/eagler-launch/1.5.2/main.ts
@@ -7,11 +7,29 @@ window.addEventListener('load', function () {
localesURI: `${window.location.pathname}/lang/`,
serverWorkerURI: `${window.location.pathname}/worker_bootstrap.js`,
worldsFolder: 'MAIN',
- servers: [{ serverName: 'BrickMC', serverAddress: 'wss://play.brickmc.net', hideAddress: false }],
+ servers: [
+ {
+ serverName: 'BrickMC',
+ serverAddress: 'wss://play.brickmc.net',
+ hideAddress: false,
+ },
+ ],
relays: [
- { addr: 'wss://relay.deev.is/', name: 'lax1dude relay #1', primary: relayId === 0 },
- { addr: 'wss://relay.lax1dude.net/', name: 'lax1dude relay #2', primary: relayId === 1 },
- { addr: 'wss://relay.shhnowisnottheti.me/', name: 'ayunami relay #1', primary: relayId === 2 },
+ {
+ addr: 'wss://relay.deev.is/',
+ name: 'lax1dude relay #1',
+ primary: relayId === 0,
+ },
+ {
+ addr: 'wss://relay.lax1dude.net/',
+ name: 'lax1dude relay #2',
+ primary: relayId === 1,
+ },
+ {
+ addr: 'wss://relay.shhnowisnottheti.me/',
+ name: 'ayunami relay #1',
+ primary: relayId === 2,
+ },
],
mainMenu: {
splashes: [
diff --git a/src/resources/scripts/eagler-launch/1.8.8/eaglerforge.ts b/src/resources/scripts/eagler-launch/1.8.8/eaglerforge.ts
index 6ceeb4e..8395b01 100644
--- a/src/resources/scripts/eagler-launch/1.8.8/eaglerforge.ts
+++ b/src/resources/scripts/eagler-launch/1.8.8/eaglerforge.ts
@@ -12,9 +12,21 @@ window.addEventListener('load', () => {
{ addr: 'wss://play.brickmc.net', name: 'BrickMC' },
],
relays: [
- { addr: 'wss://relay.deev.is/', comment: 'lax1dude relay #1', primary: relayId === 0 },
- { addr: 'wss://relay.lax1dude.net/', comment: 'lax1dude relay #2', primary: relayId === 1 },
- { addr: 'wss://relay.shhnowisnottheti.me/', comment: 'ayunami relay #1', primary: relayId === 2 },
+ {
+ addr: 'wss://relay.deev.is/',
+ comment: 'lax1dude relay #1',
+ primary: relayId === 0,
+ },
+ {
+ addr: 'wss://relay.lax1dude.net/',
+ comment: 'lax1dude relay #2',
+ primary: relayId === 1,
+ },
+ {
+ addr: 'wss://relay.shhnowisnottheti.me/',
+ comment: 'ayunami relay #1',
+ primary: relayId === 2,
+ },
],
};
diff --git a/src/resources/scripts/eagler-launch/1.8.8/eaglermobile-ef.ts b/src/resources/scripts/eagler-launch/1.8.8/eaglermobile-ef.ts
index f8787f6..829755d 100644
--- a/src/resources/scripts/eagler-launch/1.8.8/eaglermobile-ef.ts
+++ b/src/resources/scripts/eagler-launch/1.8.8/eaglermobile-ef.ts
@@ -15,7 +15,10 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
} catch (A) {
return !1;
}
- })() || 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!',
+ ),
(clientWindow.crouchLock = !1),
(clientWindow.sprintLock = !1),
(clientWindow.keyboardFix = !1),
@@ -136,7 +139,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
this,
A,
function (...A) {
- if (A[0].isValid || !clientWindow.keyboardFix) return I.apply(this, A);
+ if (A[0].isValid || !clientWindow.keyboardFix)
+ return I.apply(this, A);
},
...g,
)
@@ -161,12 +165,18 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
(I.disabled = A), (g.disabled = !A);
}
(Event.prototype.preventDefault = function (A) {
- ('hiddenInput' != document.activeElement.id || A) && ((this._preventDefault = e), this._preventDefault());
+ ('hiddenInput' != document.activeElement.id || A) &&
+ ((this._preventDefault = e), this._preventDefault());
}),
(clientWindow.fakelock = null),
Object.defineProperty(Element.prototype, 'requestPointerLock', {
value: function () {
- return (clientWindow.fakelock = this), document.dispatchEvent(new Event('pointerlockchange')), d(!0), !0;
+ return (
+ (clientWindow.fakelock = this),
+ document.dispatchEvent(new Event('pointerlockchange')),
+ d(!0),
+ !0
+ );
},
}),
Object.defineProperty(Document.prototype, 'pointerLockElement', {
@@ -176,13 +186,22 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
}),
Object.defineProperty(Document.prototype, 'exitPointerLock', {
value: function () {
- return (clientWindow.fakelock = null), document.dispatchEvent(new Event('pointerlockchange')), d(!1), !0;
+ return (
+ (clientWindow.fakelock = null),
+ document.dispatchEvent(new Event('pointerlockchange')),
+ d(!1),
+ !0
+ );
},
}),
(clientWindow.fakefull = null),
Object.defineProperty(Element.prototype, 'requestFullscreen', {
value: function () {
- return (clientWindow.fakefull = this), document.dispatchEvent(new Event('fullscreenchange')), !0;
+ return (
+ (clientWindow.fakefull = this),
+ document.dispatchEvent(new Event('fullscreenchange')),
+ !0
+ );
},
}),
Object.defineProperty(document, 'fullscreenElement', {
@@ -192,7 +211,11 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
}),
Object.defineProperty(Document.prototype, 'exitFullscreen', {
value: function () {
- return (clientWindow.fakefull = null), document.dispatchEvent(new Event('fullscreenchange')), !0;
+ return (
+ (clientWindow.fakefull = null),
+ document.dispatchEvent(new Event('fullscreenchange')),
+ !0
+ );
},
});
const c = document.createElement;
@@ -202,7 +225,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
return (
'input' != A ||
I ||
- (document.querySelectorAll('#fileUpload').forEach((A) => A.parentNode.removeChild(A)),
+ (document
+ .querySelectorAll('#fileUpload')
+ .forEach((A) => A.parentNode.removeChild(A)),
(g.id = 'fileUpload'),
g.addEventListener(
'change',
@@ -225,7 +250,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
);
};
let n = document.createElement('style');
- (n.id = 'inGameStyle'), (n.textContent = '\n.inGame {\ndisplay: none;\n}'), document.documentElement.appendChild(n);
+ (n.id = 'inGameStyle'),
+ (n.textContent = '\n.inGame {\ndisplay: none;\n}'),
+ document.documentElement.appendChild(n);
let o = document.createElement('style');
function Z(A, I, g) {
var i = document.createElement(g ?? 'button', !0);
@@ -254,7 +281,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
new Promise((A) => {
if (document.querySelector(l)) return A(document.querySelector(l));
const I = new MutationObserver((g) => {
- document.querySelector(l) && (I.disconnect(), A(document.querySelector(l)));
+ document.querySelector(l) &&
+ (I.disconnect(), A(document.querySelector(l)));
});
I.observe(document.documentElement, { childList: !0, subtree: !0 });
})).then(() => {
@@ -265,9 +293,14 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
function (g) {
g.preventDefault();
const e = g.targetTouches[0];
- A || ((A = e.pageX), (I = e.pageY)), (g.movementX = e.pageX - A), (g.movementY = e.pageY - I);
+ A || ((A = e.pageX), (I = e.pageY)),
+ (g.movementX = e.pageX - A),
+ (g.movementY = e.pageY - I);
var C = clientWindow.fakelock
- ? new MouseEvent('mousemove', { movementX: g.movementX, movementY: g.movementY })
+ ? new MouseEvent('mousemove', {
+ movementX: g.movementX,
+ movementY: g.movementY,
+ })
: new WheelEvent('wheel', { wheelDeltaY: g.movementY });
i.dispatchEvent(C), (A = e.pageX), (I = e.pageY);
},
@@ -282,15 +315,20 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
),
d(null != clientWindow.fakelock);
let e = Z('strafeRightButton', 'inGame', 'div');
- (e.style.cssText = 'left:20vh;bottom:20vh;'), document.body.appendChild(e);
+ (e.style.cssText = 'left:20vh;bottom:20vh;'),
+ document.body.appendChild(e);
let c = Z('strafeLeftButton', 'inGame', 'div');
- (c.style.cssText = 'left:0vh;bottom:20vh;'), document.body.appendChild(c);
+ (c.style.cssText = 'left:0vh;bottom:20vh;'),
+ document.body.appendChild(c);
let n = Z('forwardButton', 'inGame', 'div');
(n.style.cssText = 'left:10vh;bottom:20vh;'),
n.addEventListener(
'touchstart',
function (A) {
- C('w', 'keydown'), e.classList.remove('hide'), c.classList.remove('hide'), n.classList.add('active');
+ C('w', 'keydown'),
+ e.classList.remove('hide'),
+ c.classList.remove('hide'),
+ n.classList.add('active');
},
!1,
),
@@ -302,10 +340,17 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
g || (g = I.pageX);
let i = I.pageX - g;
10 * i > clientWindow.innerHeight
- ? (e.classList.add('active'), c.classList.remove('active'), C('d', 'keydown'), C('a', 'keyup'))
+ ? (e.classList.add('active'),
+ c.classList.remove('active'),
+ C('d', 'keydown'),
+ C('a', 'keyup'))
: 10 * i < 0 - clientWindow.innerHeight
- ? (c.classList.add('active'), e.classList.remove('active'), C('a', 'keydown'), C('d', 'keyup'))
- : (e.classList.remove('active'), c.classList.remove('active'));
+ ? (c.classList.add('active'),
+ e.classList.remove('active'),
+ C('a', 'keydown'),
+ C('d', 'keyup'))
+ : (e.classList.remove('active'),
+ c.classList.remove('active'));
},
!1,
),
@@ -403,7 +448,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
C('shift', 'keydown'),
(clientWindow.crouchLock = !!clientWindow.crouchLock && null),
(clientWindow.crouchTimer = setTimeout(function (A) {
- (clientWindow.crouchLock = null != clientWindow.crouchLock), M.classList.toggle('active');
+ (clientWindow.crouchLock = null != clientWindow.crouchLock),
+ M.classList.toggle('active');
}, 1e3));
},
!1,
@@ -412,7 +458,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
'touchend',
function (A) {
clientWindow.crouchLock ||
- (C('shift', 'keyup'), M.classList.remove('active'), (clientWindow.crouchLock = !1)),
+ (C('shift', 'keyup'),
+ M.classList.remove('active'),
+ (clientWindow.crouchLock = !1)),
clearTimeout(clientWindow.crouchTimer);
},
!1,
@@ -436,7 +484,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
),
document.body.appendChild(v);
let m = Z('exitButton', 'inMenu');
- (m.style.cssText = 'top: 0vh; margin: auto; left: 0vh; right:8vh; width: 8vh; height: 8vh;'),
+ (m.style.cssText =
+ 'top: 0vh; margin: auto; left: 0vh; right:8vh; width: 8vh; height: 8vh;'),
m.addEventListener(
'touchstart',
function (A) {
@@ -461,28 +510,45 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
'beforeinput',
function (A) {
A.stopImmediatePropagation(), A.preventDefault(!0);
- let I = 'insertLineBreak' == A.inputType ? 'return' : null == A.data ? 'delete' : A.data.slice(-1);
+ let I =
+ 'insertLineBreak' == A.inputType
+ ? 'return'
+ : null == A.data
+ ? 'delete'
+ : A.data.slice(-1);
if (
(clientWindow.lastKey ||
- (clientWindow.console.warn('Enabling blocking duplicate key events. Some functionality may be lost.'),
+ (clientWindow.console.warn(
+ 'Enabling blocking duplicate key events. Some functionality may be lost.',
+ ),
(clientWindow.inputFix = !0)),
clientWindow.keyboardFix)
)
- if ('insertLineBreak' == A.inputType) C('enter', 'keydown'), C('enter', 'keyup');
+ if ('insertLineBreak' == A.inputType)
+ C('enter', 'keydown'), C('enter', 'keyup');
else {
const g = A.inputType.slice(0, 1);
if ('i' == g && A.data) {
- if (clientWindow.lastKey == I && clientWindow.blockNextInput && clientWindow.inputFix)
+ if (
+ clientWindow.lastKey == I &&
+ clientWindow.blockNextInput &&
+ clientWindow.inputFix
+ )
clientWindow.blockNextInput = !1;
else {
I.toLowerCase() != I
- ? (C('shift', 'keydown'), C(I, 'keydown'), C(I, 'keyup'), C('shift', 'keyup'))
+ ? (C('shift', 'keydown'),
+ C(I, 'keydown'),
+ C(I, 'keyup'),
+ C('shift', 'keyup'))
: (C(I, 'keydown'), C(I, 'keyup')),
(clientWindow.blockNextInput = !0);
}
} else
('d' != g && A.data) ||
- (C('backspace', 'keydown'), C('backspace', 'keyup'), (clientWindow.blockNextInput = !1));
+ (C('backspace', 'keydown'),
+ C('backspace', 'keyup'),
+ (clientWindow.blockNextInput = !1));
}
(clientWindow.lastKey = I), (h.value = ' ');
},
@@ -504,7 +570,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
'Switching from keydown to input events due to invalid KeyboardEvent. Some functionality will be lost.',
),
(clientWindow.keyboardFix = !0),
- clientWindow.lastKey && (C(clientWindow.lastKey, 'keydown'), C(clientWindow.lastKey, 'keyup')));
+ clientWindow.lastKey &&
+ (C(clientWindow.lastKey, 'keydown'),
+ C(clientWindow.lastKey, 'keyup')));
},
!1,
),
@@ -513,7 +581,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
}),
document.body.appendChild(h);
let a = Z('keyboardButton', 'inMenu');
- (a.style.cssText = 'top: 0vh; margin: auto; left: 8vh; right:0vh; width: 8vh; height: 8vh;'),
+ (a.style.cssText =
+ 'top: 0vh; margin: auto; left: 8vh; right:0vh; width: 8vh; height: 8vh;'),
a.addEventListener(
'touchstart',
function (A) {
@@ -525,7 +594,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
'touchend',
function (A) {
A.preventDefault(),
- clientWindow.hiddenInputFocused ? h.blur() : (h.select(), (clientWindow.hiddenInputFocused = !0));
+ clientWindow.hiddenInputFocused
+ ? h.blur()
+ : (h.select(), (clientWindow.hiddenInputFocused = !0));
},
!1,
),
@@ -626,7 +697,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
C('r', 'keydown'),
(clientWindow.sprintLock = !!clientWindow.sprintLock && null),
(clientWindow.sprintTimer = setTimeout(function (A) {
- (clientWindow.sprintLock = null != clientWindow.sprintLock), j.classList.toggle('active');
+ (clientWindow.sprintLock = null != clientWindow.sprintLock),
+ j.classList.toggle('active');
}, 1e3));
},
!1,
@@ -635,14 +707,17 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
'touchend',
function (A) {
clientWindow.sprintLock ||
- (C('r', 'keyup'), j.classList.remove('active'), (clientWindow.sprintLock = !1)),
+ (C('r', 'keyup'),
+ j.classList.remove('active'),
+ (clientWindow.sprintLock = !1)),
clearTimeout(clientWindow.sprintTimer);
},
!1,
),
document.body.appendChild(j);
let y = Z('pauseButton', 'inGame');
- (y.style.cssText = 'top: 0vh; margin: auto; left: 0vh; right: 32vh; width: 8vh; height: 8vh;'),
+ (y.style.cssText =
+ 'top: 0vh; margin: auto; left: 0vh; right: 32vh; width: 8vh; height: 8vh;'),
y.addEventListener(
'touchstart',
function (A) {
@@ -659,7 +734,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
),
document.body.appendChild(y);
let L = Z('chatButton', 'inGame');
- (L.style.cssText = 'top: 0vh; margin: auto; left: 0vh; right: 16vh; width: 8vh; height: 8vh;'),
+ (L.style.cssText =
+ 'top: 0vh; margin: auto; left: 0vh; right: 16vh; width: 8vh; height: 8vh;'),
L.addEventListener(
'touchstart',
function (A) {
@@ -669,7 +745,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
),
document.body.appendChild(L);
let N = Z('perspectiveButton', 'inGame');
- (N.style.cssText = 'top: 0vh; margin: auto; left: 0vh; right: 0vh; width: 8vh; height: 8vh;'),
+ (N.style.cssText =
+ 'top: 0vh; margin: auto; left: 0vh; right: 0vh; width: 8vh; height: 8vh;'),
N.addEventListener(
'touchstart',
function (A) {
@@ -686,7 +763,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
),
document.body.appendChild(N);
let U = Z('screenshotButton', 'inGame');
- (U.style.cssText = 'top: 0vh; margin: auto; left: 16vh; right: 0vh; width: 8vh; height: 8vh;'),
+ (U.style.cssText =
+ 'top: 0vh; margin: auto; left: 16vh; right: 0vh; width: 8vh; height: 8vh;'),
U.addEventListener(
'touchstart',
function (A) {
@@ -703,7 +781,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
),
document.body.appendChild(U);
let z = Z('coordinatesButton', 'inGame');
- (z.style.cssText = 'top: 0vh; margin: auto; left: 32vh; right: 0vh; width: 8vh; height: 8vh;'),
+ (z.style.cssText =
+ 'top: 0vh; margin: auto; left: 32vh; right: 0vh; width: 8vh; height: 8vh;'),
z.addEventListener(
'touchstart',
function (A) {
diff --git a/src/resources/scripts/eagler-launch/1.8.8/eaglerpocketmobile.ts b/src/resources/scripts/eagler-launch/1.8.8/eaglerpocketmobile.ts
index 190eacf..e33af43 100644
--- a/src/resources/scripts/eagler-launch/1.8.8/eaglerpocketmobile.ts
+++ b/src/resources/scripts/eagler-launch/1.8.8/eaglerpocketmobile.ts
@@ -13,7 +13,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
}
}
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!',
+ );
}
// TODO: consolidate all of these into a single object?
window.crouchLock = false; // Used for crouch mobile control
@@ -191,7 +193,12 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
});
window.dispatchEvent(evt);
}
- function mouseEvent(number, state, element, event = { clientX: 0, clientY: 0, screenX: 0, screenY: 0 }) {
+ function mouseEvent(
+ number,
+ state,
+ element,
+ event = { clientX: 0, clientY: 0, screenX: 0, screenY: 0 },
+ ) {
element.dispatchEvent(
new PointerEvent(state, {
button: number,
@@ -277,7 +284,9 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
const element = this._createElement(type);
if (type == 'input' && !ignore) {
// We set the ingore flag to true when we create the hiddenInput
- document.querySelectorAll('#fileUpload').forEach((e) => e.parentNode.removeChild(e)); // Get rid of any left over fileUpload inputs
+ document
+ .querySelectorAll('#fileUpload')
+ .forEach((e) => e.parentNode.removeChild(e)); // Get rid of any left over fileUpload inputs
element.id = 'fileUpload';
element.addEventListener(
'change',
@@ -401,9 +410,15 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
function (e) {
e.preventDefault(); // Prevents window zoom when using two fingers
let primaryTouch;
- for (let touchIndex = 0; touchIndex < e.targetTouches.length; touchIndex++) {
+ for (
+ let touchIndex = 0;
+ touchIndex < e.targetTouches.length;
+ touchIndex++
+ ) {
// Iterate through our touches to find a touch event matching the primary touch ID
- if (e.targetTouches[touchIndex].identifier == window.canvasPrimaryID) {
+ if (
+ e.targetTouches[touchIndex].identifier == window.canvasPrimaryID
+ ) {
primaryTouch = e.targetTouches[touchIndex];
break;
}
@@ -412,7 +427,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
primaryTouch.distanceX = primaryTouch.clientX - canvasTouchStartX;
primaryTouch.distanceY = primaryTouch.clientY - canvasTouchStartY;
primaryTouch.squaredNorm =
- primaryTouch.distanceX * primaryTouch.distanceX + primaryTouch.distanceY * primaryTouch.distanceY;
+ primaryTouch.distanceX * primaryTouch.distanceX +
+ primaryTouch.distanceY * primaryTouch.distanceY;
primaryTouch.movementX = primaryTouch.clientX - canvasTouchPreviousX;
primaryTouch.movementY = primaryTouch.clientY - canvasTouchPreviousY;
if (window.canvasTouchMode == 1) {
@@ -452,7 +468,11 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
);
function canvasTouchEnd(e) {
- for (let touchIndex = 0; touchIndex < e.changedTouches.length; touchIndex++) {
+ for (
+ let touchIndex = 0;
+ touchIndex < e.changedTouches.length;
+ touchIndex++
+ ) {
// Iterate through changed touches to find primary touch
if (e.changedTouches[touchIndex].identifier == window.canvasPrimaryID) {
const primaryTouch = e.changedTouches[touchIndex];
@@ -477,11 +497,19 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
canvas.addEventListener('touchcancel', canvasTouchEnd, false); // TODO: Find out why this is different than touchend
setButtonVisibility(window.fakelock != null); //Updates our mobile controls when the canvas finally loads
// All of the touch buttons
- const strafeRightButton = createTouchButton('strafeRightButton', 'inGame', 'div');
+ const strafeRightButton = createTouchButton(
+ 'strafeRightButton',
+ 'inGame',
+ 'div',
+ );
strafeRightButton.classList.add('strafeSize');
strafeRightButton.style.cssText = 'left:24vh;bottom:22vh;';
document.body.appendChild(strafeRightButton);
- const strafeLeftButton = createTouchButton('strafeLeftButton', 'inGame', 'div');
+ const strafeLeftButton = createTouchButton(
+ 'strafeLeftButton',
+ 'inGame',
+ 'div',
+ );
strafeLeftButton.classList.add('strafeSize');
strafeLeftButton.style.cssText = 'left:5.5vh;bottom:22vh;';
document.body.appendChild(strafeLeftButton);
@@ -666,7 +694,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(inventoryButton);
const exitButton = createTouchButton('exitButton', 'inMenu');
exitButton.classList.add('smallMobileControl');
- exitButton.style.cssText = 'top: 0.5vh; margin: auto; left: 1vh; right:8vh;';
+ exitButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 1vh; right:8vh;';
exitButton.addEventListener(
'touchstart',
function (e) {
@@ -712,10 +741,17 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
// For some reason beforeinput doesn't have the same deletion problems that input has on Android
e.stopImmediatePropagation(); // Android ignores this and the prevent default, so this will probably be removed in the future
e.preventDefault(true); // We pass a value because we've hijacked the prevent default function to have a "should bypass" boolean value
- const inputData = e.inputType == 'insertLineBreak' ? 'return' : e.data == null ? 'delete' : e.data.slice(-1); // Saves the last key press.
+ const inputData =
+ e.inputType == 'insertLineBreak'
+ ? 'return'
+ : e.data == null
+ ? 'delete'
+ : e.data.slice(-1); // Saves the last key press.
if (!window.lastKey) {
// When we first set hiddenInput's text contents to " " we can use this to check if Duplicate Mode is needed
- window.console.warn('Enabling blocking duplicate key events. Some functionality may be lost.');
+ window.console.warn(
+ 'Enabling blocking duplicate key events. Some functionality may be lost.',
+ );
window.inputFix = true;
}
if (window.keyboardFix) {
@@ -727,7 +763,10 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
const sliceInputType = e.inputType.slice(0, 1); // Android doesn't constiently dispatch the correct inputType, but most of them either start with i for insert or d for delete, so this dumb solution should be good enough.
if (sliceInputType == 'i' && e.data) {
// Android sometimes always dispatches insertCompositionText inputTypes, so checking that e.data isn't null is necessary
- const isDuplicate = window.lastKey == inputData && window.blockNextInput && window.inputFix;
+ const isDuplicate =
+ window.lastKey == inputData &&
+ window.blockNextInput &&
+ window.inputFix;
if (isDuplicate) {
// If our key press matches the last unblocked key press and we are in duplicaye mode, ignore the input
window.blockNextInput = false;
@@ -793,7 +832,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(hiddenInput);
const keyboardButton = createTouchButton('keyboardButton', 'inMenu');
keyboardButton.classList.add('smallMobileControl');
- keyboardButton.style.cssText = 'top: 0.5vh; margin: auto; left: 6vh; right:0vh;';
+ keyboardButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 6vh; right:0vh;';
keyboardButton.addEventListener(
'touchstart',
function (e) {
@@ -936,7 +976,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(sprintButton);
const pauseButton = createTouchButton('pauseButton', 'inGame');
pauseButton.classList.add('smallMobileControl');
- pauseButton.style.cssText = 'top: 0.5vh; margin: auto; left: 0vh; right: 0vh;';
+ pauseButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 0vh; right: 0vh;';
pauseButton.addEventListener(
'touchstart',
function (e) {
@@ -954,7 +995,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(pauseButton);
const chatButton = createTouchButton('chatButton', 'inGame');
chatButton.classList.add('smallMobileControl');
- chatButton.style.cssText = 'top: 0.5vh; margin: auto; left: 0vh; right: 14vh;';
+ chatButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 0vh; right: 14vh;';
chatButton.addEventListener(
'touchstart',
function (e) {
@@ -965,7 +1007,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(chatButton);
const perspectiveButton = createTouchButton('perspectiveButton', 'inGame');
perspectiveButton.classList.add('smallMobileControl');
- perspectiveButton.style.cssText = 'top: 0.5vh; margin: auto; left: 0vh; right: 28vh;';
+ perspectiveButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 0vh; right: 28vh;';
perspectiveButton.addEventListener(
'touchstart',
function (e) {
@@ -985,7 +1028,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(perspectiveButton);
const screenshotButton = createTouchButton('screenshotButton', 'inGame');
screenshotButton.classList.add('smallMobileControl');
- screenshotButton.style.cssText = 'top: 0.5vh; margin: auto; left: 28vh; right: 0vh;';
+ screenshotButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 28vh; right: 0vh;';
screenshotButton.addEventListener(
'touchstart',
function (e) {
@@ -1005,7 +1049,8 @@ if (new URLSearchParams(window.location.search).get('mobile') === 'true') {
document.body.appendChild(screenshotButton);
const coordinatesButton = createTouchButton('coordinatesButton', 'inGame');
coordinatesButton.classList.add('smallMobileControl');
- coordinatesButton.style.cssText = 'top: 0.5vh; margin: auto; left: 14vh; right: 0vh;';
+ coordinatesButton.style.cssText =
+ 'top: 0.5vh; margin: auto; left: 14vh; right: 0vh;';
coordinatesButton.addEventListener(
'touchstart',
function (e) {
diff --git a/src/resources/scripts/eagler-launch/1.8.8/main.ts b/src/resources/scripts/eagler-launch/1.8.8/main.ts
index 13e6d29..ca054f3 100644
--- a/src/resources/scripts/eagler-launch/1.8.8/main.ts
+++ b/src/resources/scripts/eagler-launch/1.8.8/main.ts
@@ -12,9 +12,21 @@ window.addEventListener('load', () => {
{ addr: 'wss://play.brickmc.net', name: 'BrickMC' },
],
relays: [
- { addr: 'wss://relay.deev.is/', comment: 'lax1dude relay #1', primary: relayId === 0 },
- { addr: 'wss://relay.lax1dude.net/', comment: 'lax1dude relay #2', primary: relayId === 1 },
- { addr: 'wss://relay.shhnowisnottheti.me/', comment: 'ayunami relay #1', primary: relayId === 2 },
+ {
+ addr: 'wss://relay.deev.is/',
+ comment: 'lax1dude relay #1',
+ primary: relayId === 0,
+ },
+ {
+ addr: 'wss://relay.lax1dude.net/',
+ comment: 'lax1dude relay #2',
+ primary: relayId === 1,
+ },
+ {
+ addr: 'wss://relay.shhnowisnottheti.me/',
+ comment: 'ayunami relay #1',
+ primary: relayId === 2,
+ },
],
};
diff --git a/src/resources/scripts/eagler-launch/1.9.4/main.ts b/src/resources/scripts/eagler-launch/1.9.4/main.ts
index 3ef1ed2..2ed6992 100644
--- a/src/resources/scripts/eagler-launch/1.9.4/main.ts
+++ b/src/resources/scripts/eagler-launch/1.9.4/main.ts
@@ -7,9 +7,21 @@ window.addEventListener('load', () => {
localesURI: `${window.location.pathname}/lang/`,
servers: [{ addr: 'wss://eagler.xyz', name: 'TemuzX' }],
relays: [
- { addr: 'wss://relay.deev.is/', comment: 'lax1dude relay #1', primary: relayId === 0 },
- { addr: 'wss://relay.lax1dude.net/', comment: 'lax1dude relay #2', primary: relayId === 1 },
- { addr: 'wss://relay.shhnowisnottheti.me/', comment: 'ayunami relay #1', primary: relayId === 2 },
+ {
+ addr: 'wss://relay.deev.is/',
+ comment: 'lax1dude relay #1',
+ primary: relayId === 0,
+ },
+ {
+ addr: 'wss://relay.lax1dude.net/',
+ comment: 'lax1dude relay #2',
+ primary: relayId === 1,
+ },
+ {
+ addr: 'wss://relay.shhnowisnottheti.me/',
+ comment: 'ayunami relay #1',
+ primary: relayId === 2,
+ },
],
};
diff --git a/src/resources/scripts/eagler-launch/b1.3/main.ts b/src/resources/scripts/eagler-launch/b1.3/main.ts
index 7ab2b53..2a90fbd 100644
--- a/src/resources/scripts/eagler-launch/b1.3/main.ts
+++ b/src/resources/scripts/eagler-launch/b1.3/main.ts
@@ -1,6 +1,9 @@
// @ts-nocheck
window.addEventListener('load', function () {
- window.minecraftOpts = ['game_frame', `${window.location.pathname}/assets.epk`];
+ window.minecraftOpts = [
+ 'game_frame',
+ `${window.location.pathname}/assets.epk`,
+ ];
const urlParams = new URLSearchParams(window.location.search);
window.minecraftOpts.push(urlParams.get('server') ?? undefined);
diff --git a/src/resources/scripts/main.ts b/src/resources/scripts/main.ts
index 110ed66..af704af 100644
--- a/src/resources/scripts/main.ts
+++ b/src/resources/scripts/main.ts
@@ -6,7 +6,9 @@ let articleAnimationLock = false;
const theme = {
load: function (themeToLoad?: string) {
- const themeElement = document.querySelector('#theme') as HTMLLinkElement | null;
+ const themeElement = document.querySelector(
+ '#theme',
+ ) as HTMLLinkElement | null;
if (themeElement)
themeElement.href = themeToLoad
? `/resources/styles/themes/${themeToLoad}.css`
@@ -81,7 +83,9 @@ const game = {
'b1.3': 'b13-client-version',
};
const dropdown = clients[client]
- ? (document.querySelector(`select[id='${clients[client]}']`) as HTMLSelectElement | null)
+ ? (document.querySelector(
+ `select[id='${clients[client]}']`,
+ ) as HTMLSelectElement | null)
: null;
if (dropdown?.value) {
selectedVersion = `https://archive.eaglercraft.rip/Eaglercraft${client === '1.8' ? 'X_1.8' : `_${client}`}/client/${dropdown.value}/index.html`;
@@ -160,8 +164,12 @@ const navigate = {
const article = {
open: function (articleId: string) {
- const modal = document.querySelector(`.article[data-article-id='${articleId}']`) as HTMLElement | null;
- const modalContent = document.querySelector(`.article[data-article-id='${articleId}'] > div`) as HTMLElement | null;
+ const modal = document.querySelector(
+ `.article[data-article-id='${articleId}']`,
+ ) as HTMLElement | null;
+ const modalContent = document.querySelector(
+ `.article[data-article-id='${articleId}'] > div`,
+ ) as HTMLElement | null;
if (!articleAnimationLock && modal && modalContent) {
articleAnimationLock = true;
modal.style.animation = '0.5s ease-in-out 1 normal article';
@@ -184,7 +192,9 @@ const article = {
}
},
close: function (articleId: string) {
- const modal = document.querySelector(`.article[data-article-id='${articleId}']`) as HTMLElement | null;
+ const modal = document.querySelector(
+ `.article[data-article-id='${articleId}']`,
+ ) as HTMLElement | null;
if (!articleAnimationLock && modal) {
articleAnimationLock = true;
modal.style.animation = '0.5s ease-in-out 1 reverse article-tempfix';
@@ -238,7 +248,10 @@ const storage = {
}
return undefined;
},
- set: function (key: string, value: string | number | object | boolean | null | undefined) {
+ set: function (
+ key: string,
+ value: string | number | object | boolean | null | undefined,
+ ) {
const item = localStorage.getItem('minexlauncher');
if (item === null) {
const json: Record
= {};
@@ -268,7 +281,10 @@ const storage = {
}
return undefined;
},
- set: function (key: string, value: string | number | object | boolean | null | undefined) {
+ set: function (
+ key: string,
+ value: string | number | object | boolean | null | undefined,
+ ) {
let item = sessionStorage.getItem('minexlauncher');
if (item === null) {
item = '{}';
@@ -309,7 +325,9 @@ const mods = {
mods.push(mod);
mods.sort();
storage.local.set('mods', mods);
- const modInstallElem = document.querySelector(`.mod-list > div .links .install[data-mod-id='${modId}']`);
+ const modInstallElem = document.querySelector(
+ `.mod-list > div .links .install[data-mod-id='${modId}']`,
+ );
if (modInstallElem) {
modInstallElem.textContent = 'Uninstall';
modInstallElem.classList.add('installed');
@@ -317,7 +335,9 @@ const mods = {
} else {
mods.splice(modIndex, 1);
storage.local.set('mods', mods);
- const modInstallElem = document.querySelector(`.mod-list > div .links .install[data-mod-id='${modId}']`);
+ const modInstallElem = document.querySelector(
+ `.mod-list > div .links .install[data-mod-id='${modId}']`,
+ );
if (modInstallElem) {
modInstallElem.textContent = 'Install';
modInstallElem.classList.remove('installed');
@@ -403,7 +423,9 @@ if (window.location.pathname === '/') {
? '/mobile/'
: '/home/game/';
- document.addEventListener('DOMContentLoaded', () => document.body.appendChild(iframe));
+ document.addEventListener('DOMContentLoaded', () =>
+ document.body.appendChild(iframe),
+ );
/* document.addEventListener('load', () => {
if (storage.local.get('offlineCache')) {
@@ -433,9 +455,12 @@ if (window.location.pathname === '/') {
const titleBarText = document.querySelector('.title-bar');
const lastVersion = storage.local.get('lastVersion');
- const updateData = (await (await fetch('/resources/data/main.json')).json()).updates;
+ const updateData = (await (await fetch('/resources/data/main.json')).json())
+ .updates;
const currentVersion = updateData[0].version;
- const changelog = updateData[0].changelog.map((change: string) => ` - ${change}`).join('\n');
+ const changelog = updateData[0].changelog
+ .map((change: string) => ` - ${change}`)
+ .join('\n');
if (profileName) profileName.textContent = storage.local.get('username');
if (titleBarText) titleBarText.textContent += ` ${currentVersion}`;
@@ -443,9 +468,14 @@ if (window.location.pathname === '/') {
if (
lastVersion &&
// @ts-expect-error
- gt(coerce(currentVersion, { includePrerelease: true }), coerce(lastVersion, { includePrerelease: true }))
+ gt(
+ coerce(currentVersion, { includePrerelease: true }),
+ coerce(lastVersion, { includePrerelease: true }),
+ )
) {
- alert(`MineXLauncher has been updated to v${currentVersion}!\n\nChanges in v${currentVersion}:\n${changelog}`);
+ alert(
+ `MineXLauncher has been updated to v${currentVersion}!\n\nChanges in v${currentVersion}:\n${changelog}`,
+ );
storage.local.set('lastVersion', currentVersion);
}
});
@@ -473,16 +503,28 @@ if (window.location.pathname === '/') {
if (window.location.pathname === '/settings/') {
document.addEventListener('DOMContentLoaded', async () => {
const profileName = document.querySelector('.username');
- const usernameInput = document.querySelector('#username-input') as HTMLInputElement | null;
- const themeSelect = document.querySelector('#theme-select') as HTMLSelectElement | null;
- const offlineCheckbox = document.querySelector('#offline-checkbox') as HTMLInputElement | null;
- const adsCheckbox = document.querySelector('#ads-checkbox') as HTMLInputElement | null;
- const themeData: { id: string; name: string }[] = (await (await fetch('/resources/data/main.json')).json()).themes;
+ const usernameInput = document.querySelector(
+ '#username-input',
+ ) as HTMLInputElement | null;
+ const themeSelect = document.querySelector(
+ '#theme-select',
+ ) as HTMLSelectElement | null;
+ const offlineCheckbox = document.querySelector(
+ '#offline-checkbox',
+ ) as HTMLInputElement | null;
+ const adsCheckbox = document.querySelector(
+ '#ads-checkbox',
+ ) as HTMLInputElement | null;
+ const themeData: { id: string; name: string }[] = (
+ await (await fetch('/resources/data/main.json')).json()
+ ).themes;
if (usernameInput) {
usernameInput.placeholder = storage.local.get('username') ?? '';
usernameInput.addEventListener('input', () => {
- let username = usernameInput.value.replace(/[^A-Za-z0-9]/g, '_').substring(0, 16);
+ let username = usernameInput.value
+ .replace(/[^A-Za-z0-9]/g, '_')
+ .substring(0, 16);
usernameInput.value = username;
while (username.length < 3) username += '_';
@@ -499,7 +541,9 @@ if (window.location.pathname === '/settings/') {
themeSelect?.appendChild(option);
});
themeSelect.value = storage.local.get('theme') ?? '';
- themeSelect.addEventListener('change', () => theme.set(themeSelect.value ?? 'default'));
+ themeSelect.addEventListener('change', () =>
+ theme.set(themeSelect.value ?? 'default'),
+ );
}
if (offlineCheckbox) {
@@ -523,22 +567,37 @@ if (window.location.pathname === '/settings/') {
adsCheckbox.addEventListener('change', () => {
storage.local.set('showAds', adsCheckbox.checked);
const adsContainers = document.querySelectorAll('.ads-container');
- adsContainers.forEach((adsContainer: Element) => ((adsContainer as HTMLElement).style.display = 'none'));
+ adsContainers.forEach(
+ (adsContainer: Element) =>
+ ((adsContainer as HTMLElement).style.display = 'none'),
+ );
});
}
});
} else if (window.location.pathname === '/welcome/') {
document.addEventListener('DOMContentLoaded', async () => {
- const setupForm = document.querySelector('#setup-form') as HTMLFormElement | null;
- const usernameInput = document.querySelector('#username-input') as HTMLInputElement | null;
- const themeSelect = document.querySelector('#theme-select') as HTMLSelectElement | null;
- const offlineCheckbox = document.querySelector('#offline-checkbox') as HTMLInputElement | null;
- const themeData: { id: string; name: string }[] = (await (await fetch('/resources/data/main.json')).json()).themes;
+ const setupForm = document.querySelector(
+ '#setup-form',
+ ) as HTMLFormElement | null;
+ const usernameInput = document.querySelector(
+ '#username-input',
+ ) as HTMLInputElement | null;
+ const themeSelect = document.querySelector(
+ '#theme-select',
+ ) as HTMLSelectElement | null;
+ const offlineCheckbox = document.querySelector(
+ '#offline-checkbox',
+ ) as HTMLInputElement | null;
+ const themeData: { id: string; name: string }[] = (
+ await (await fetch('/resources/data/main.json')).json()
+ ).themes;
if (setupForm) {
if (usernameInput) {
usernameInput.addEventListener('input', () => {
- const username = usernameInput.value.replace(/[^A-Za-z0-9]/g, '_').substring(0, 16);
+ const username = usernameInput.value
+ .replace(/[^A-Za-z0-9]/g, '_')
+ .substring(0, 16);
usernameInput.value = username;
});
}
@@ -550,13 +609,17 @@ if (window.location.pathname === '/settings/') {
option.textContent = theme.name;
themeSelect?.appendChild(option);
});
- themeSelect.addEventListener('change', () => theme.load(themeSelect.value ?? 'default'));
+ themeSelect.addEventListener('change', () =>
+ theme.load(themeSelect.value ?? 'default'),
+ );
}
setupForm.addEventListener('submit', async (event) => {
event.preventDefault();
- let username = usernameInput?.value.replace(/[^A-Za-z0-9]/g, '_').substring(0, 16);
+ let username = usernameInput?.value
+ .replace(/[^A-Za-z0-9]/g, '_')
+ .substring(0, 16);
if (usernameInput) usernameInput.value = username ?? '';
if (!username) {
@@ -572,7 +635,8 @@ if (window.location.pathname === '/settings/') {
storage.local.set('mods', []);
storage.local.set(
'lastVersion',
- (await (await fetch('/resources/data/main.json')).json()).updates[0].version,
+ (await (await fetch('/resources/data/main.json')).json()).updates[0]
+ .version,
);
if (offlineCheckbox?.checked) {
@@ -588,9 +652,13 @@ if (window.location.pathname === '/settings/') {
});
}
});
-} else if (window.location.pathname === '/mods/mods/' || window.location.pathname === '/mods/resourcepacks/') {
+} else if (
+ window.location.pathname === '/mods/mods/' ||
+ window.location.pathname === '/mods/resourcepacks/'
+) {
document.addEventListener('DOMContentLoaded', async () => {
- const addonType: 'mods' | 'resourcepacks' = window.location.pathname === '/mods/mods/' ? 'mods' : 'resourcepacks';
+ const addonType: 'mods' | 'resourcepacks' =
+ window.location.pathname === '/mods/mods/' ? 'mods' : 'resourcepacks';
const data: {
id: string;
name: string;
@@ -607,15 +675,17 @@ if (window.location.pathname === '/settings/') {
addon.name
}By ${addon.author}
${addon.description}
`;
modList?.appendChild(modItem);
});
if (addonType === 'mods') {
const installedMods = storage.local.get('mods') ?? [];
- const modElements = document.querySelectorAll('.mod-list > div .links .install');
+ const modElements = document.querySelectorAll(
+ '.mod-list > div .links .install',
+ );
modElements.forEach((element) => {
const modId = (element as HTMLElement).dataset['modId'];
if (installedMods.includes(`/resources/mods/downloads/${modId}.js`)) {
@@ -628,8 +698,9 @@ if (window.location.pathname === '/settings/') {
} else if (window.location.pathname === '/updates/') {
document.addEventListener('DOMContentLoaded', async () => {
const updatesContainer = document.querySelector('.updates-container');
- const data: { version: string; changelog: string[] }[] = (await (await fetch('/resources/data/main.json')).json())
- .updates;
+ const data: { version: string; changelog: string[] }[] = (
+ await (await fetch('/resources/data/main.json')).json()
+ ).updates;
data.forEach((update) => {
const version = document.createElement('div');
const name = document.createElement('strong');
@@ -651,5 +722,14 @@ if (window.location.pathname === '/settings/') {
if (window.location.hostname === null) {
// Stop the minifier from removing these functions
- console.debug([navigate, query, versionSelector, game, mods, base64Gzip, article, downloadFile]);
+ console.debug([
+ navigate,
+ query,
+ versionSelector,
+ game,
+ mods,
+ base64Gzip,
+ article,
+ downloadFile,
+ ]);
}
diff --git a/src/resources/styles/themes/campfire.css b/src/resources/styles/themes/campfire.css
index 8c0894d..33ef107 100644
--- a/src/resources/styles/themes/campfire.css
+++ b/src/resources/styles/themes/campfire.css
@@ -77,11 +77,11 @@ body {
box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.3);
}
-.downloads a {
+.downloads span {
background-color: #ff6600;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #ff8533;
}
diff --git a/src/resources/styles/themes/cherry-blossom.css b/src/resources/styles/themes/cherry-blossom.css
index c8b4cb7..b113299 100644
--- a/src/resources/styles/themes/cherry-blossom.css
+++ b/src/resources/styles/themes/cherry-blossom.css
@@ -104,11 +104,11 @@ body {
color: #e5a1b8;
}
-.downloads a {
+.downloads span {
background-color: #d0808e;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #e5a1b8;
}
diff --git a/src/resources/styles/themes/default.css b/src/resources/styles/themes/default.css
index bdcaa3c..1109655 100644
--- a/src/resources/styles/themes/default.css
+++ b/src/resources/styles/themes/default.css
@@ -354,7 +354,7 @@ body {
align-items: center;
}
-.downloads a {
+.downloads span {
display: inline-block;
background-color: #048239;
color: #fff;
@@ -365,7 +365,8 @@ body {
transition: background-color 0.3s;
}
-.downloads a:hover {
+.downloads span:hover {
+ cursor: pointer;
background-color: #00cc00;
}
diff --git a/src/resources/styles/themes/hyperdark.css b/src/resources/styles/themes/hyperdark.css
index f062d5d..9590af3 100644
--- a/src/resources/styles/themes/hyperdark.css
+++ b/src/resources/styles/themes/hyperdark.css
@@ -103,12 +103,12 @@ body {
color: #e0e0e0;
}
-.downloads a {
+.downloads span {
background-color: #333;
color: #e0e0e0;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #444;
}
diff --git a/src/resources/styles/themes/light.css b/src/resources/styles/themes/light.css
index 35c74e5..e34ea45 100644
--- a/src/resources/styles/themes/light.css
+++ b/src/resources/styles/themes/light.css
@@ -87,11 +87,11 @@ body {
color: #333;
}
-.downloads a {
+.downloads span {
background-color: #4caf50;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #66bb6a;
}
diff --git a/src/resources/styles/themes/nether.css b/src/resources/styles/themes/nether.css
index 5c10a96..7a0e67b 100644
--- a/src/resources/styles/themes/nether.css
+++ b/src/resources/styles/themes/nether.css
@@ -81,11 +81,11 @@ body {
color: #ffcc00;
}
-.downloads a {
+.downloads span {
background-color: #8b0000;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #ff4500;
}
diff --git a/src/resources/styles/themes/overworld.css b/src/resources/styles/themes/overworld.css
index 7837d8b..448e670 100644
--- a/src/resources/styles/themes/overworld.css
+++ b/src/resources/styles/themes/overworld.css
@@ -81,11 +81,11 @@ body {
color: #00ff00;
}
-.downloads a {
+.downloads span {
background-color: #00b000;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #00ff00;
}
diff --git a/src/resources/styles/themes/retro.css b/src/resources/styles/themes/retro.css
index 4e8d482..73765af 100644
--- a/src/resources/styles/themes/retro.css
+++ b/src/resources/styles/themes/retro.css
@@ -31,7 +31,7 @@ body {
.installations div .selector,
.installations div .installations div .options divs,
.installations button,
-.downloads a {
+.downloads span {
background-color: #111;
border: 2px solid #00ff00;
color: #00ff00;
@@ -41,14 +41,14 @@ body {
.nav-bar li.selected,
.installations div .options div:hover,
.installations button:hover,
-.downloads a:hover {
+.downloads span:hover {
background-color: #333;
}
.installations div .selector:hover,
.installations div .selector.open,
.installations button:hover,
-.downloads a:hover {
+.downloads span:hover {
box-shadow: none;
}
diff --git a/src/resources/styles/themes/starfall.css b/src/resources/styles/themes/starfall.css
index cb73af7..6ef8738 100644
--- a/src/resources/styles/themes/starfall.css
+++ b/src/resources/styles/themes/starfall.css
@@ -45,10 +45,10 @@ body {
border-color: #0077aa;
}
-.downloads a {
+.downloads span {
background-color: #00ccff;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #00e6ff;
}
diff --git a/src/resources/styles/themes/the-end.css b/src/resources/styles/themes/the-end.css
index a4e7d21..d49e2f9 100644
--- a/src/resources/styles/themes/the-end.css
+++ b/src/resources/styles/themes/the-end.css
@@ -77,11 +77,11 @@ body {
color: #b300b3;
}
-.downloads a {
+.downloads span {
background-color: #4d0099;
}
-.downloads a:hover {
+.downloads span:hover {
background-color: #8000ff;
}
diff --git a/src/servers/index.html b/src/servers/index.html
index ffddd14..4ebbdf6 100644
--- a/src/servers/index.html
+++ b/src/servers/index.html
@@ -4,9 +4,17 @@