mirror of
https://github.com/gradenGnostic/LegacyLauncher.git
synced 2026-08-03 02:32:27 +00:00
v2.2.0
This commit is contained in:
parent
69a0ebbfce
commit
46a484d5df
25
index.html
25
index.html
|
|
@ -35,7 +35,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-area">
|
<div class="content-area">
|
||||||
<img src="minecraftlogo.png" class="mc-logo-img" alt="Minecraft Logo">
|
<div class="relative">
|
||||||
|
<img src="minecraftlogo.png" class="mc-logo-img" alt="Minecraft Logo">
|
||||||
|
<div id="splash-text" class="splash-text">Splash!</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="btn-play-main" class="btn-mc btn-play nav-item" onclick="launchGame()" tabindex="0">PLAY</div>
|
<div id="btn-play-main" class="btn-mc btn-play nav-item" onclick="launchGame()" tabindex="0">PLAY</div>
|
||||||
|
|
||||||
|
|
@ -69,7 +72,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-overlay" id="servers-modal">
|
<div class="modal-overlay" id="servers-modal">
|
||||||
<div class="modal-box" style="width: 850px;">
|
<div class="modal-box">
|
||||||
<div class="modal-title">CUSTOM SERVERS</div>
|
<div class="modal-title">CUSTOM SERVERS</div>
|
||||||
|
|
||||||
<div id="servers-list-container" class="w-full max-h-[300px] overflow-y-auto mb-6 border-2 border-[#555] bg-black p-2">
|
<div id="servers-list-container" class="w-full max-h-[300px] overflow-y-auto mb-6 border-2 border-[#555] bg-black p-2">
|
||||||
|
|
@ -104,6 +107,15 @@
|
||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
<div class="modal-title">LAUNCHER OPTIONS</div>
|
<div class="modal-title">LAUNCHER OPTIONS</div>
|
||||||
|
|
||||||
|
<div class="mc-input-group">
|
||||||
|
<label class="mc-label">Installation Directory:</label>
|
||||||
|
<div class="flex gap-2 mb-2">
|
||||||
|
<input type="text" id="install-path-input" class="mc-input nav-item !mb-0" placeholder="Default: Documents/LegacyClient" tabindex="0">
|
||||||
|
<div class="btn-mc btn-mini nav-item !w-[60px] !h-[48px]" onclick="browseInstallDir()" tabindex="0">...</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-mc w-full !h-[40px] !text-lg !mb-0 nav-item" onclick="openGameDir()" tabindex="0">OPEN FOLDER</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mc-input-group">
|
<div class="mc-input-group">
|
||||||
<label class="mc-label">GitHub Repository Source:</label>
|
<label class="mc-label">GitHub Repository Source:</label>
|
||||||
<input type="text" id="repo-input" class="mc-input nav-item" placeholder="user/repo" tabindex="0">
|
<input type="text" id="repo-input" class="mc-input nav-item" placeholder="user/repo" tabindex="0">
|
||||||
|
|
@ -174,10 +186,7 @@
|
||||||
<div class="modal-overlay" id="update-modal">
|
<div class="modal-overlay" id="update-modal">
|
||||||
<div class="modal-box relative">
|
<div class="modal-box relative">
|
||||||
<div class="modal-close-btn" id="btn-close-update">×</div>
|
<div class="modal-close-btn" id="btn-close-update">×</div>
|
||||||
<div class="modal-title">UPDATE AVAILABLE</div>
|
<div id="update-modal-text" class="modal-body-text" style="display: none; margin-bottom: 20px;"></div>
|
||||||
<div id="update-modal-text" class="modal-body-text">
|
|
||||||
A new version is available. Would you like to update now?
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-4 w-full">
|
<div class="flex gap-4 w-full">
|
||||||
<div class="btn-mc flex-grow nav-item" id="btn-confirm-update">UPDATE NOW</div>
|
<div class="btn-mc flex-grow nav-item" id="btn-confirm-update">UPDATE NOW</div>
|
||||||
<div class="btn-mc flex-grow nav-item" id="btn-skip-update">LATER</div>
|
<div class="btn-mc flex-grow nav-item" id="btn-skip-update">LATER</div>
|
||||||
|
|
@ -187,6 +196,10 @@
|
||||||
|
|
||||||
<div id="toast">NOTIFICATION</div>
|
<div id="toast">NOTIFICATION</div>
|
||||||
|
|
||||||
|
<div id="music-toggle" class="music-btn nav-item" onclick="toggleMusic()" title="Toggle Music" tabindex="0">
|
||||||
|
<span id="music-icon">♪</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="renderer.js"></script>
|
<script src="renderer.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
9
main.js
9
main.js
|
|
@ -1,4 +1,4 @@
|
||||||
const { app, BrowserWindow, shell, ipcMain } = require('electron');
|
const { app, BrowserWindow, shell, ipcMain, dialog } = require('electron');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const Store = require('electron-store');
|
const Store = require('electron-store');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
@ -41,6 +41,13 @@ function createWindow() {
|
||||||
|
|
||||||
ipcMain.handle('store-get', (event, key) => store.get(key));
|
ipcMain.handle('store-get', (event, key) => store.get(key));
|
||||||
ipcMain.handle('store-set', (event, key, value) => store.set(key, value));
|
ipcMain.handle('store-set', (event, key, value) => store.set(key, value));
|
||||||
|
|
||||||
|
ipcMain.handle('select-directory', async () => {
|
||||||
|
const result = await dialog.showOpenDialog({
|
||||||
|
properties: ['openDirectory', 'createDirectory']
|
||||||
|
});
|
||||||
|
return result.filePaths[0];
|
||||||
|
});
|
||||||
|
|
||||||
win.on('maximize', () => win.webContents.send('window-is-maximized', true));
|
win.on('maximize', () => win.webContents.send('window-is-maximized', true));
|
||||||
win.on('unmaximize', () => win.webContents.send('window-is-maximized', false));
|
win.on('unmaximize', () => win.webContents.send('window-is-maximized', false));
|
||||||
|
|
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "legacylauncher",
|
"name": "legacylauncher",
|
||||||
"version": "1.1.1",
|
"version": "2.0.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "legacylauncher",
|
"name": "legacylauncher",
|
||||||
"version": "1.1.1",
|
"version": "2.0.2",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-store": "^6.0.1",
|
"electron-store": "^6.0.1",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "legacylauncher",
|
"name": "legacylauncher",
|
||||||
"version": "2.0.2",
|
"version": "2.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
284
renderer.js
284
renderer.js
|
|
@ -24,6 +24,9 @@ const Store = {
|
||||||
},
|
},
|
||||||
async set(key, value) {
|
async set(key, value) {
|
||||||
return await ipcRenderer.invoke('store-set', key, value);
|
return await ipcRenderer.invoke('store-set', key, value);
|
||||||
|
},
|
||||||
|
async selectDirectory() {
|
||||||
|
return await ipcRenderer.invoke('select-directory');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -293,6 +296,110 @@ const GamepadManager = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Music Player logic
|
||||||
|
const MusicManager = {
|
||||||
|
audio: new Audio(),
|
||||||
|
playlist: [],
|
||||||
|
currentIndex: -1,
|
||||||
|
enabled: false,
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
this.enabled = await Store.get('legacy_music_enabled', true);
|
||||||
|
this.updateIcon();
|
||||||
|
this.audio.volume = 1.0;
|
||||||
|
this.audio.onended = () => this.playNext();
|
||||||
|
if (this.enabled) {
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async scan() {
|
||||||
|
try {
|
||||||
|
const installDir = await getInstallDir();
|
||||||
|
// Path provided by user: root of games folder in music/music
|
||||||
|
const musicPath = path.join(installDir, 'music', 'music');
|
||||||
|
|
||||||
|
if (fs.existsSync(musicPath)) {
|
||||||
|
const files = fs.readdirSync(musicPath);
|
||||||
|
this.playlist = files
|
||||||
|
.filter(f => f.toLowerCase().endsWith('.ogg'))
|
||||||
|
.map(f => path.join(musicPath, f));
|
||||||
|
|
||||||
|
// Shuffle playlist
|
||||||
|
for (let i = this.playlist.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[this.playlist[i], this.playlist[j]] = [this.playlist[j], this.playlist[i]];
|
||||||
|
}
|
||||||
|
console.log(`MusicManager: Loaded ${this.playlist.length} tracks.`);
|
||||||
|
return this.playlist.length > 0;
|
||||||
|
} else {
|
||||||
|
console.log("MusicManager: music/music folder not found yet.");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Music scan error:", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
async start() {
|
||||||
|
if (this.playlist.length === 0) {
|
||||||
|
const success = await this.scan();
|
||||||
|
if (!success) return;
|
||||||
|
}
|
||||||
|
if (this.playlist.length > 0 && this.audio.paused) {
|
||||||
|
this.playNext();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
playNext() {
|
||||||
|
if (!this.enabled || this.playlist.length === 0) return;
|
||||||
|
|
||||||
|
let nextIndex;
|
||||||
|
if (this.playlist.length > 1) {
|
||||||
|
// Keep picking until we get a different track
|
||||||
|
do {
|
||||||
|
nextIndex = Math.floor(Math.random() * this.playlist.length);
|
||||||
|
} while (nextIndex === this.currentIndex);
|
||||||
|
} else {
|
||||||
|
nextIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentIndex = nextIndex;
|
||||||
|
this.audio.src = `file://${this.playlist[this.currentIndex]}`;
|
||||||
|
this.audio.play().catch(e => {
|
||||||
|
console.error("Audio playback error:", e);
|
||||||
|
// If failed, try next one
|
||||||
|
setTimeout(() => this.playNext(), 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.audio.pause();
|
||||||
|
this.audio.currentTime = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
async toggle() {
|
||||||
|
this.enabled = !this.enabled;
|
||||||
|
await Store.set('legacy_music_enabled', this.enabled);
|
||||||
|
this.updateIcon();
|
||||||
|
if (this.enabled) {
|
||||||
|
this.start();
|
||||||
|
} else {
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateIcon() {
|
||||||
|
const btn = document.getElementById('music-toggle');
|
||||||
|
if (!btn) return;
|
||||||
|
if (this.enabled) {
|
||||||
|
btn.classList.remove('muted');
|
||||||
|
} else {
|
||||||
|
btn.classList.add('muted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
window.onload = async () => {
|
window.onload = async () => {
|
||||||
document.getElementById('repo-input').value = await Store.get('legacy_repo', DEFAULT_REPO);
|
document.getElementById('repo-input').value = await Store.get('legacy_repo', DEFAULT_REPO);
|
||||||
document.getElementById('exec-input').value = await Store.get('legacy_exec_path', DEFAULT_EXEC);
|
document.getElementById('exec-input').value = await Store.get('legacy_exec_path', DEFAULT_EXEC);
|
||||||
|
|
@ -301,6 +408,9 @@ window.onload = async () => {
|
||||||
document.getElementById('port-input').value = await Store.get('legacy_port', "");
|
document.getElementById('port-input').value = await Store.get('legacy_port', "");
|
||||||
document.getElementById('server-checkbox').checked = await Store.get('legacy_is_server', false);
|
document.getElementById('server-checkbox').checked = await Store.get('legacy_is_server', false);
|
||||||
|
|
||||||
|
const installDir = await getInstallDir();
|
||||||
|
document.getElementById('install-path-input').value = installDir;
|
||||||
|
|
||||||
if (process.platform === 'linux' || process.platform === 'darwin') {
|
if (process.platform === 'linux' || process.platform === 'darwin') {
|
||||||
document.getElementById('compat-option-container').style.display = 'block';
|
document.getElementById('compat-option-container').style.display = 'block';
|
||||||
scanCompatibilityLayers();
|
scanCompatibilityLayers();
|
||||||
|
|
@ -315,46 +425,99 @@ window.onload = async () => {
|
||||||
|
|
||||||
fetchGitHubData();
|
fetchGitHubData();
|
||||||
checkForLauncherUpdates();
|
checkForLauncherUpdates();
|
||||||
|
loadSplashText();
|
||||||
|
MusicManager.init();
|
||||||
GamepadManager.init();
|
GamepadManager.init();
|
||||||
|
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'F9') {
|
||||||
|
checkForLauncherUpdates(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function checkForLauncherUpdates() {
|
async function loadSplashText() {
|
||||||
|
const splashEl = document.getElementById('splash-text');
|
||||||
|
if (!splashEl) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filePath = path.join(__dirname, 'strings.txt');
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
const content = fs.readFileSync(filePath, 'utf-8');
|
||||||
|
const lines = content.split('\n').map(l => l.trim()).filter(l => l !== '');
|
||||||
|
if (lines.length > 0) {
|
||||||
|
const randomSplash = lines[Math.floor(Math.random() * lines.length)];
|
||||||
|
splashEl.textContent = randomSplash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to load splash text:", e);
|
||||||
|
splashEl.textContent = "Welcome!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isNewerVersion(latest, current) {
|
||||||
|
const lParts = latest.split('.').map(Number);
|
||||||
|
const cParts = current.split('.').map(Number);
|
||||||
|
for (let i = 0; i < Math.max(lParts.length, cParts.length); i++) {
|
||||||
|
const l = lParts[i] || 0;
|
||||||
|
const c = cParts[i] || 0;
|
||||||
|
if (l > c) return true;
|
||||||
|
if (l < c) return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkForLauncherUpdates(manual = false) {
|
||||||
try {
|
try {
|
||||||
const currentVersion = require('./package.json').version;
|
const currentVersion = require('./package.json').version;
|
||||||
const res = await fetch(`https://api.github.com/repos/${LAUNCHER_REPO}/releases/latest`);
|
const res = await fetch(`https://api.github.com/repos/${LAUNCHER_REPO}/releases/latest`);
|
||||||
if (!res.ok) return;
|
if (!res.ok) {
|
||||||
|
if (manual) showToast("Could not check for updates.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const latestRelease = await res.json();
|
const latestRelease = await res.json();
|
||||||
const latestVersion = latestRelease.tag_name.replace('v', '');
|
const latestVersion = latestRelease.tag_name.replace('v', '');
|
||||||
|
|
||||||
if (latestVersion !== currentVersion) {
|
if (isNewerVersion(latestVersion, currentVersion)) {
|
||||||
const updateConfirmed = await promptLauncherUpdate(latestRelease.tag_name);
|
const updateConfirmed = await promptLauncherUpdate(latestRelease.tag_name, latestRelease.body);
|
||||||
if (updateConfirmed) {
|
if (updateConfirmed) {
|
||||||
downloadAndInstallLauncherUpdate(latestRelease);
|
downloadAndInstallLauncherUpdate(latestRelease);
|
||||||
}
|
}
|
||||||
|
} else if (manual) {
|
||||||
|
showToast("Launcher is up to date!");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Launcher update check failed:", e);
|
console.error("Launcher update check failed:", e);
|
||||||
|
if (manual) showToast("Update check failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function promptLauncherUpdate(version) {
|
async function promptLauncherUpdate(version, changelog) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const modal = document.getElementById('update-modal');
|
const modal = document.getElementById('update-modal');
|
||||||
const confirmBtn = document.getElementById('btn-confirm-update');
|
const confirmBtn = document.getElementById('btn-confirm-update');
|
||||||
const skipBtn = document.getElementById('btn-skip-update');
|
const skipBtn = document.getElementById('btn-skip-update');
|
||||||
const closeBtn = document.getElementById('btn-close-update');
|
const closeBtn = document.getElementById('btn-close-update');
|
||||||
|
const modalText = document.getElementById('update-modal-text');
|
||||||
|
|
||||||
document.getElementById('update-modal-text').innerHTML =
|
if (modalText) {
|
||||||
`A new Launcher version <b>${version}</b> is available.<br><br>` +
|
modalText.innerHTML = `<span class="update-tag">NEW UPDATE: v${version}</span><br>` +
|
||||||
`Would you like to download and install it now?`;
|
`<div class="pn-body" style="font-size: 16px; max-height: 200px; overflow-y: auto; background: rgba(0,0,0,0.2); padding: 10px; margin-top: 5px;">${changelog || "No changelog provided."}</div>`;
|
||||||
|
modalText.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.activeElement?.blur();
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
modal.style.opacity = '1';
|
modal.style.opacity = '1';
|
||||||
|
|
||||||
const cleanup = (result) => {
|
const cleanup = (result) => {
|
||||||
modal.style.opacity = '0';
|
modal.style.opacity = '0';
|
||||||
setTimeout(() => modal.style.display = 'none', 300);
|
setTimeout(() => {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
if (modalText) modalText.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
confirmBtn.onclick = null;
|
confirmBtn.onclick = null;
|
||||||
skipBtn.onclick = null;
|
skipBtn.onclick = null;
|
||||||
closeBtn.onclick = null;
|
closeBtn.onclick = null;
|
||||||
|
|
@ -474,10 +637,32 @@ function updateCompatDisplay() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getInstalledPath() {
|
async function getInstallDir() {
|
||||||
const homeDir = require('os').homedir();
|
const homeDir = require('os').homedir();
|
||||||
|
const defaultPath = path.join(homeDir, 'Documents', 'LegacyClient');
|
||||||
|
return await Store.get('legacy_install_path', defaultPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function browseInstallDir() {
|
||||||
|
const dir = await Store.selectDirectory();
|
||||||
|
if (dir) {
|
||||||
|
document.getElementById('install-path-input').value = dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openGameDir() {
|
||||||
|
const dir = await getInstallDir();
|
||||||
|
if (fs.existsSync(dir)) {
|
||||||
|
shell.openPath(dir);
|
||||||
|
} else {
|
||||||
|
showToast("Directory does not exist yet!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getInstalledPath() {
|
||||||
|
const installDir = await getInstallDir();
|
||||||
const execPath = await Store.get('legacy_exec_path', DEFAULT_EXEC);
|
const execPath = await Store.get('legacy_exec_path', DEFAULT_EXEC);
|
||||||
return path.join(homeDir, 'Documents', 'LegacyClient', execPath);
|
return path.join(installDir, execPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkIsInstalled(tag) {
|
async function checkIsInstalled(tag) {
|
||||||
|
|
@ -525,16 +710,19 @@ async function monitorProcess(proc) {
|
||||||
if (!proc) return;
|
if (!proc) return;
|
||||||
const sessionStart = Date.now();
|
const sessionStart = Date.now();
|
||||||
setGameRunning(true);
|
setGameRunning(true);
|
||||||
|
MusicManager.stop();
|
||||||
|
|
||||||
proc.on('exit', async () => {
|
proc.on('exit', async () => {
|
||||||
const sessionDuration = Math.floor((Date.now() - sessionStart) / 1000);
|
const sessionDuration = Math.floor((Date.now() - sessionStart) / 1000);
|
||||||
const playtime = await Store.get('legacy_playtime', 0);
|
const playtime = await Store.get('legacy_playtime', 0);
|
||||||
await Store.set('legacy_playtime', playtime + sessionDuration);
|
await Store.set('legacy_playtime', playtime + sessionDuration);
|
||||||
setGameRunning(false);
|
setGameRunning(false);
|
||||||
|
if (MusicManager.enabled) MusicManager.start();
|
||||||
});
|
});
|
||||||
proc.on('error', (err) => {
|
proc.on('error', (err) => {
|
||||||
console.error("Process error:", err);
|
console.error("Process error:", err);
|
||||||
setGameRunning(false);
|
setGameRunning(false);
|
||||||
|
if (MusicManager.enabled) MusicManager.start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -691,19 +879,18 @@ async function promptUpdate(newTag) {
|
||||||
const confirmBtn = document.getElementById('btn-confirm-update');
|
const confirmBtn = document.getElementById('btn-confirm-update');
|
||||||
const skipBtn = document.getElementById('btn-skip-update');
|
const skipBtn = document.getElementById('btn-skip-update');
|
||||||
const closeBtn = document.getElementById('btn-close-update');
|
const closeBtn = document.getElementById('btn-close-update');
|
||||||
const installedTag = await Store.get('installed_version_tag', "Unknown");
|
const modalText = document.getElementById('update-modal-text');
|
||||||
|
|
||||||
document.getElementById('update-modal-text').innerHTML =
|
|
||||||
`New version <b>${newTag}</b> is available.<br><br>` +
|
|
||||||
`Currently installed: <b>${installedTag}</b>.<br><br>` +
|
|
||||||
`Would you like to update now?`;
|
|
||||||
|
|
||||||
|
document.activeElement?.blur();
|
||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
modal.style.opacity = '1';
|
modal.style.opacity = '1';
|
||||||
|
|
||||||
const cleanup = (result) => {
|
const cleanup = (result) => {
|
||||||
modal.style.opacity = '0';
|
modal.style.opacity = '0';
|
||||||
setTimeout(() => modal.style.display = 'none', 300);
|
setTimeout(() => {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
if (modalText) modalText.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
confirmBtn.onclick = null;
|
confirmBtn.onclick = null;
|
||||||
skipBtn.onclick = null;
|
skipBtn.onclick = null;
|
||||||
closeBtn.onclick = null;
|
closeBtn.onclick = null;
|
||||||
|
|
@ -836,10 +1023,10 @@ function updateProgress(percent, text) {
|
||||||
async function handleElectronFlow(url) {
|
async function handleElectronFlow(url) {
|
||||||
try {
|
try {
|
||||||
const homeDir = require('os').homedir();
|
const homeDir = require('os').homedir();
|
||||||
const docDir = path.join(homeDir, 'Documents');
|
const extractDir = await getInstallDir();
|
||||||
const zipPath = path.join(docDir, TARGET_FILE);
|
const parentDir = path.dirname(extractDir);
|
||||||
const extractDir = path.join(docDir, 'LegacyClient');
|
const zipPath = path.join(parentDir, TARGET_FILE);
|
||||||
const backupDir = path.join(docDir, 'LegacyClient_Backup');
|
const backupDir = path.join(parentDir, 'LegacyClient_Backup');
|
||||||
|
|
||||||
updateProgress(5, "Downloading " + TARGET_FILE + "...");
|
updateProgress(5, "Downloading " + TARGET_FILE + "...");
|
||||||
await downloadFile(url, zipPath);
|
await downloadFile(url, zipPath);
|
||||||
|
|
@ -883,6 +1070,10 @@ async function handleElectronFlow(url) {
|
||||||
|
|
||||||
await extractZip(zipPath, { dir: extractDir });
|
await extractZip(zipPath, { dir: extractDir });
|
||||||
|
|
||||||
|
// Refresh music playlist if it was empty
|
||||||
|
await MusicManager.scan();
|
||||||
|
if (MusicManager.enabled) MusicManager.start();
|
||||||
|
|
||||||
// Restore preserved files
|
// Restore preserved files
|
||||||
if (fs.existsSync(backupDir)) {
|
if (fs.existsSync(backupDir)) {
|
||||||
for (const item of preserveList) {
|
for (const item of preserveList) {
|
||||||
|
|
@ -1144,6 +1335,48 @@ async function saveOptions() {
|
||||||
const ip = document.getElementById('ip-input').value.trim();
|
const ip = document.getElementById('ip-input').value.trim();
|
||||||
const port = document.getElementById('port-input').value.trim();
|
const port = document.getElementById('port-input').value.trim();
|
||||||
const isServer = document.getElementById('server-checkbox').checked;
|
const isServer = document.getElementById('server-checkbox').checked;
|
||||||
|
const newInstallPath = document.getElementById('install-path-input').value.trim();
|
||||||
|
|
||||||
|
const oldInstallPath = await getInstallDir();
|
||||||
|
if (newInstallPath && newInstallPath !== oldInstallPath) {
|
||||||
|
// Move preserved files to new directory if they exist in old but not in new
|
||||||
|
if (fs.existsSync(oldInstallPath)) {
|
||||||
|
const preserveList = [
|
||||||
|
'options.txt',
|
||||||
|
'servers.txt',
|
||||||
|
'username.txt',
|
||||||
|
'settings.dat',
|
||||||
|
'UID.dat',
|
||||||
|
path.join('Windows64', 'GameHDD')
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!fs.existsSync(newInstallPath)) {
|
||||||
|
fs.mkdirSync(newInstallPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of preserveList) {
|
||||||
|
const src = path.join(oldInstallPath, item);
|
||||||
|
const dest = path.join(newInstallPath, item);
|
||||||
|
|
||||||
|
if (fs.existsSync(src)) {
|
||||||
|
const destDir = path.dirname(dest);
|
||||||
|
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
||||||
|
|
||||||
|
// Simple move; if cross-device it might fail, but let's try
|
||||||
|
try {
|
||||||
|
if (!fs.existsSync(dest)) {
|
||||||
|
fs.renameSync(src, dest);
|
||||||
|
} else {
|
||||||
|
console.log("Dest already exists, skipping move for: " + item);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Migration error for " + item + ": " + e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Store.set('legacy_install_path', newInstallPath);
|
||||||
|
}
|
||||||
|
|
||||||
if (newRepo) await Store.set('legacy_repo', newRepo);
|
if (newRepo) await Store.set('legacy_repo', newRepo);
|
||||||
if (newExec) await Store.set('legacy_exec_path', newExec);
|
if (newExec) await Store.set('legacy_exec_path', newExec);
|
||||||
|
|
@ -1180,6 +1413,10 @@ function showToast(msg) {
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function toggleMusic() {
|
||||||
|
await MusicManager.toggle();
|
||||||
|
}
|
||||||
|
|
||||||
// Global functions for HTML onclick
|
// Global functions for HTML onclick
|
||||||
window.minimizeWindow = minimizeWindow;
|
window.minimizeWindow = minimizeWindow;
|
||||||
window.toggleMaximize = toggleMaximize;
|
window.toggleMaximize = toggleMaximize;
|
||||||
|
|
@ -1195,3 +1432,6 @@ window.saveOptions = saveOptions;
|
||||||
window.saveProfile = saveProfile;
|
window.saveProfile = saveProfile;
|
||||||
window.updateCompatDisplay = updateCompatDisplay;
|
window.updateCompatDisplay = updateCompatDisplay;
|
||||||
window.checkForUpdatesManual = checkForUpdatesManual;
|
window.checkForUpdatesManual = checkForUpdatesManual;
|
||||||
|
window.browseInstallDir = browseInstallDir;
|
||||||
|
window.openGameDir = openGameDir;
|
||||||
|
window.toggleMusic = toggleMusic;
|
||||||
|
|
|
||||||
478
strings.txt
Normal file
478
strings.txt
Normal file
|
|
@ -0,0 +1,478 @@
|
||||||
|
Happy birthday, ez!
|
||||||
|
Happy birthday, Notch!
|
||||||
|
Let me tell you about Homestuck!
|
||||||
|
Let me tell you about Homestuck!
|
||||||
|
Let me tell you about Homestuck!
|
||||||
|
Merry X-mas!
|
||||||
|
Happy New Year!
|
||||||
|
As seen on TV!
|
||||||
|
A young man stands in his bedroom!
|
||||||
|
A young man stands in his bedroom!
|
||||||
|
A young woman stands in her bedroom!
|
||||||
|
A young woman stands in her bedroom!
|
||||||
|
Awesome!
|
||||||
|
100% pure!
|
||||||
|
Better than Prey!
|
||||||
|
More polygons!
|
||||||
|
Get the cruxite dowel!
|
||||||
|
Get the cruxite dowel!
|
||||||
|
Get the cruxite dowel!
|
||||||
|
Flashing letters!
|
||||||
|
Made by Notch!
|
||||||
|
It's here!
|
||||||
|
Best in class!
|
||||||
|
It's finished!
|
||||||
|
Kind of dragon free!
|
||||||
|
Excitement!
|
||||||
|
Where doing it man, where making this hapen!
|
||||||
|
Where doing it man, where making this hapen!
|
||||||
|
One of a kind!
|
||||||
|
Heaps of hits on YouTube!
|
||||||
|
Indev!
|
||||||
|
Spiders everywhere!
|
||||||
|
Check it out!
|
||||||
|
Holy cow, man!
|
||||||
|
It's a game!
|
||||||
|
Made in Sweden!
|
||||||
|
Uses LWJGL!
|
||||||
|
Reticulating splines!
|
||||||
|
Minecraft!
|
||||||
|
Yaaay!
|
||||||
|
413!
|
||||||
|
413!
|
||||||
|
413!
|
||||||
|
413!
|
||||||
|
Singleplayer!
|
||||||
|
Keyboard compatible!
|
||||||
|
Undocumented!
|
||||||
|
Ingots!
|
||||||
|
Exploding creepers!
|
||||||
|
That's no moon!
|
||||||
|
l33t!
|
||||||
|
Create!
|
||||||
|
Survive!
|
||||||
|
Dungeon!
|
||||||
|
I WARNED YOU ABOUT STAIRS BRO!!!!
|
||||||
|
I WARNED YOU ABOUT STAIRS BRO!!!!
|
||||||
|
I WARNED YOU ABOUT STAIRS BRO!!!!
|
||||||
|
Exclusive!
|
||||||
|
The bee's knees!
|
||||||
|
Closed source!
|
||||||
|
Classy!
|
||||||
|
Wow!
|
||||||
|
Not on steam!
|
||||||
|
Oh man!
|
||||||
|
Awesome community!
|
||||||
|
Pixels!
|
||||||
|
Teetsuuuuoooo!
|
||||||
|
Kaaneeeedaaaa!
|
||||||
|
Now with difficulty!
|
||||||
|
Enhanced!
|
||||||
|
90% bug free!
|
||||||
|
Pretty!
|
||||||
|
12 herbs and spices!
|
||||||
|
Fat free!
|
||||||
|
Absolutely no memes!
|
||||||
|
Free dental!
|
||||||
|
Cloud computing!
|
||||||
|
Hard to label!
|
||||||
|
Technically good!
|
||||||
|
Bringing home the bacon!
|
||||||
|
Indie!
|
||||||
|
GOTY!
|
||||||
|
Ceci n'est pas une title screen!
|
||||||
|
Euclidian!
|
||||||
|
Now in 3D!
|
||||||
|
Inspirational!
|
||||||
|
Herregud!
|
||||||
|
Complex cellular automata!
|
||||||
|
Yes, sir!
|
||||||
|
Played by cowboys!
|
||||||
|
Thousands of colors!
|
||||||
|
Try it!
|
||||||
|
Age of Wonders is better!
|
||||||
|
Try the mushroom stew!
|
||||||
|
Sensational!
|
||||||
|
Hot tamale, hot hot tamale!
|
||||||
|
Play him off, keyboard cat!
|
||||||
|
Guaranteed!
|
||||||
|
Alchemize ALL the things!
|
||||||
|
Alchemize ALL the things!
|
||||||
|
Macroscopic!
|
||||||
|
Bring it on!
|
||||||
|
Random splash!
|
||||||
|
Call your mother!
|
||||||
|
Monster infighting!
|
||||||
|
Loved by millions!
|
||||||
|
Ultimate edition!
|
||||||
|
Freaky!
|
||||||
|
Water proof!
|
||||||
|
Uninflammable!
|
||||||
|
Whoa, dude!
|
||||||
|
Roxy is best hacker!
|
||||||
|
Roxy is best hacker!
|
||||||
|
Roxy is best hacker!
|
||||||
|
All inclusive!
|
||||||
|
Tell your friends!
|
||||||
|
NP is not in P!
|
||||||
|
Notch <3 ez!
|
||||||
|
Music by C418!
|
||||||
|
Livestreamed!
|
||||||
|
Haunted!
|
||||||
|
Polynomial!
|
||||||
|
Terrestrial!
|
||||||
|
All is full of love!
|
||||||
|
Full of stars!
|
||||||
|
Scientific!
|
||||||
|
Cooler than Spock!
|
||||||
|
Collaborate and listen!
|
||||||
|
Never dig down!
|
||||||
|
Take frequent breaks!
|
||||||
|
Not linear!
|
||||||
|
Han shot first!
|
||||||
|
Nice to meet you!
|
||||||
|
Buckets of lava!
|
||||||
|
Ride the pig!
|
||||||
|
Larger than Earth!
|
||||||
|
sqrt(-1) love you!
|
||||||
|
Phobos anomaly!
|
||||||
|
Punching wood!
|
||||||
|
Falling off cliffs!
|
||||||
|
0% sugar!
|
||||||
|
150% hyperbole!
|
||||||
|
Synecdoche!
|
||||||
|
Let's danec!
|
||||||
|
Reference implementation!
|
||||||
|
Lewd with two dudes with food!
|
||||||
|
Kiss the sky!
|
||||||
|
20 GOTO 10!
|
||||||
|
Verlet intregration!
|
||||||
|
Peter Griffin!
|
||||||
|
Do not distribute!
|
||||||
|
Cogito ergo sum!
|
||||||
|
4815162342 lines of code!
|
||||||
|
A skeleton popped out!
|
||||||
|
The Work of Notch!
|
||||||
|
The sum of its parts!
|
||||||
|
BTAF used to be good!
|
||||||
|
I miss ADOM!
|
||||||
|
umop-apisdn!
|
||||||
|
OICU812!
|
||||||
|
Bring me Ray Cokes!
|
||||||
|
Finger-licking!
|
||||||
|
Thematic!
|
||||||
|
Pneumatic!
|
||||||
|
Sublime!
|
||||||
|
Octagonal!
|
||||||
|
Une baguette!
|
||||||
|
Gargamel plays it!
|
||||||
|
Rita is the new top dog!
|
||||||
|
SWM forever!
|
||||||
|
Representing Edsbyn!
|
||||||
|
Matt Damon!
|
||||||
|
Supercalifragilisticexpialidocious!
|
||||||
|
Consummate V's!
|
||||||
|
Cow Tools!
|
||||||
|
Double buffered!
|
||||||
|
Fan fiction!
|
||||||
|
Flaxkikare!
|
||||||
|
Jason! Jason! Jason!
|
||||||
|
Hotter than the sun!
|
||||||
|
Internet enabled!
|
||||||
|
Autonomous!
|
||||||
|
Engage!
|
||||||
|
Fantasy!
|
||||||
|
DRR! DRR! DRR!
|
||||||
|
Kick it root down!
|
||||||
|
Regional resources!
|
||||||
|
Woo, facepunch!
|
||||||
|
Woo, somethingawful!
|
||||||
|
Woo, /v/!
|
||||||
|
Woo, tigsource!
|
||||||
|
Woo, minecraftforum!
|
||||||
|
Woo, worldofminecraft!
|
||||||
|
Woo, reddit!
|
||||||
|
Woo, 2pp!
|
||||||
|
Google anlyticsed!
|
||||||
|
Now supports åäö!
|
||||||
|
Give us Gordon!
|
||||||
|
Tip your waiter!
|
||||||
|
Very fun!
|
||||||
|
12345 is a bad password!
|
||||||
|
Vote for net neutrality!
|
||||||
|
Lives in a pineapple under the sea!
|
||||||
|
MAP11 has two names!
|
||||||
|
Omnipotent!
|
||||||
|
Gasp!
|
||||||
|
...!
|
||||||
|
Bees, bees, bees, bees!
|
||||||
|
Jag känner en bot!
|
||||||
|
This text is hard to read if you play the game at the default resolution, but at 1080p it's fine!
|
||||||
|
Haha, LOL!
|
||||||
|
Hampsterdance!
|
||||||
|
Switches and ores!
|
||||||
|
Menger sponge!
|
||||||
|
idspispopd!
|
||||||
|
Eple (original edit)!
|
||||||
|
So fresh, so clean!
|
||||||
|
Slow acting portals!
|
||||||
|
Try the Nether!
|
||||||
|
Don't look directly at the bugs!
|
||||||
|
Oh, ok, Pigmen!
|
||||||
|
Finally with ladders!
|
||||||
|
Scary!
|
||||||
|
Play Minecraft, Watch Topgear, Get Pig!
|
||||||
|
Twittered about!
|
||||||
|
Jump up, jump up, and get down!
|
||||||
|
Joel is neat!
|
||||||
|
A riddle, wrapped in a mystery!
|
||||||
|
Huge tracts of land!
|
||||||
|
Welcome to your Doom!
|
||||||
|
Stay a while, stay forever!
|
||||||
|
Stay a while and listen!
|
||||||
|
Treatment for your rash!
|
||||||
|
"Autological" is!
|
||||||
|
Information wants to be free!
|
||||||
|
"Almost never" is an interesting concept!
|
||||||
|
Lots of truthiness!
|
||||||
|
The creeper is a spy!
|
||||||
|
Turing complete!
|
||||||
|
It's groundbreaking!
|
||||||
|
Let our battle's begin!
|
||||||
|
The sky is the limit!
|
||||||
|
Jeb has amazing hair!
|
||||||
|
Casual gaming!
|
||||||
|
Undefeated!
|
||||||
|
Kinda like Lemmings!
|
||||||
|
Follow the train, CJ!
|
||||||
|
Leveraging synergy!
|
||||||
|
This message will never appear on the splash screen, isn't that weird?
|
||||||
|
DungeonQuest is unfair!
|
||||||
|
110813!
|
||||||
|
90210!
|
||||||
|
Check out the far lands!
|
||||||
|
Tyrion would love it!
|
||||||
|
Also try VVVVVV!
|
||||||
|
Also try Super Meat Boy!
|
||||||
|
Also try Terraria!
|
||||||
|
Also try Mount And Blade!
|
||||||
|
Also try Project Zomboid!
|
||||||
|
Also try World of Goo!
|
||||||
|
Also try Limbo!
|
||||||
|
Also try Pixeljunk Shooter!
|
||||||
|
Also try Braid!
|
||||||
|
Also try Sburb!
|
||||||
|
Also try Sburb!
|
||||||
|
Also try Sburb!
|
||||||
|
That's super!
|
||||||
|
Bread is pain!
|
||||||
|
Read more books!
|
||||||
|
Khaaaaaaaaan!
|
||||||
|
Less addictive than TV Tropes!
|
||||||
|
More addictive than lemonade!
|
||||||
|
Bigger than a bread box!
|
||||||
|
Millions of peaches!
|
||||||
|
Fnord!
|
||||||
|
This is my true form!
|
||||||
|
Totally forgot about Dre!
|
||||||
|
Don't bother with the clones!
|
||||||
|
Pumpkinhead!
|
||||||
|
Hobo humping slobo babe!
|
||||||
|
Made by Jeb!
|
||||||
|
Has an ending!
|
||||||
|
Finally complete!
|
||||||
|
Feature packed!
|
||||||
|
Boots with the fur!
|
||||||
|
Stop, hammertime!
|
||||||
|
Testificates!
|
||||||
|
Conventional!
|
||||||
|
Homeomorphic to a 3-sphere!
|
||||||
|
Doesn't avoid double negatives!
|
||||||
|
Place ALL the blocks!
|
||||||
|
Does barrel rolls!
|
||||||
|
Meeting expectations!
|
||||||
|
PC gaming since 1873!
|
||||||
|
Ghoughpteighbteau tchoghs!
|
||||||
|
Déjà vu!
|
||||||
|
IT KEEPS HAPPENING!
|
||||||
|
IT KEEPS HAPPENING!
|
||||||
|
IT KEEPS HAPPENING!
|
||||||
|
I TOLD YOU DOG!
|
||||||
|
I TOLD YOU DOG!
|
||||||
|
Déjà vu!
|
||||||
|
Got your nose!
|
||||||
|
Afraid of the big, black bat!
|
||||||
|
Doesn't use the U-word!
|
||||||
|
Child's play!
|
||||||
|
See you next Friday or so!
|
||||||
|
From the streets of Södermalm!
|
||||||
|
150 bpm for 400000 minutes!
|
||||||
|
Technologic!
|
||||||
|
Funk soul brother!
|
||||||
|
Pumpa kungen!
|
||||||
|
Fetchstuck compatible!
|
||||||
|
Sylladex full!
|
||||||
|
Sylladex full!
|
||||||
|
Honk. HONK.
|
||||||
|
Honk. HONK.
|
||||||
|
You can't fight the Homestuck!
|
||||||
|
You can't fight the Homestuck!
|
||||||
|
==> Enter.
|
||||||
|
==> Enter.
|
||||||
|
STRIFE!
|
||||||
|
STRIFE!
|
||||||
|
8^y
|
||||||
|
8^y
|
||||||
|
Sweet Bro and Hella Jeff!
|
||||||
|
What pumpkin?
|
||||||
|
What pumpkin?
|
||||||
|
ABSCOND!
|
||||||
|
ABSCOND!
|
||||||
|
Check your Strife Specibus!
|
||||||
|
Ascend to God Tier!
|
||||||
|
Ascend to God Tier!
|
||||||
|
Got tiger!
|
||||||
|
Got tiger!
|
||||||
|
Motherfucking miracles!
|
||||||
|
Welcome to Skaia!
|
||||||
|
Welcome to Skaia!
|
||||||
|
Prospit or Derse?
|
||||||
|
Upgrading the Alchemiter!
|
||||||
|
Build Grist!
|
||||||
|
Build Grist!
|
||||||
|
Now with 100% more Faygo!
|
||||||
|
Sopor slime pie!
|
||||||
|
Grimdark!
|
||||||
|
Trickster mode engaged!
|
||||||
|
How HIGH do you even have to BE just to DO something like that........
|
||||||
|
Mayor of Can Town!
|
||||||
|
Spades Slick did nothing wrong!
|
||||||
|
It's hard and nobody understands.
|
||||||
|
Shenanigans!
|
||||||
|
The Scratch is happening!
|
||||||
|
612!
|
||||||
|
111111!
|
||||||
|
Jegus!
|
||||||
|
All the luck!
|
||||||
|
All the luck!
|
||||||
|
Dunkass!
|
||||||
|
Captchalogue this!
|
||||||
|
Captchalogue this!
|
||||||
|
Echeladder rung attained!
|
||||||
|
Megalovania originally played here!
|
||||||
|
Megalovania originally played here!
|
||||||
|
Music by Toby Fox!
|
||||||
|
Don't ask about the buckets!
|
||||||
|
Don't ask about the buckets!
|
||||||
|
Candy corn horns!
|
||||||
|
Your name is JOHN EGBERT.
|
||||||
|
Let me guess, your zodiac sign is a troll?
|
||||||
|
Put the bunny back in the box!
|
||||||
|
Do the windy thing!
|
||||||
|
Do the windy thing!
|
||||||
|
Betty Crocker is evil!
|
||||||
|
Betty Crocker is evil!
|
||||||
|
Beware the Batterwitch!
|
||||||
|
He is already here.
|
||||||
|
He is already here.
|
||||||
|
Doc Scratch is watching.
|
||||||
|
Con Air is a masterpiece!
|
||||||
|
Karkalicious!
|
||||||
|
SGRUB!
|
||||||
|
Sburb Beta!
|
||||||
|
Sburb Beta!
|
||||||
|
Knight of Time!
|
||||||
|
Seer of Light!
|
||||||
|
Heir of Breath!
|
||||||
|
Witch of Space!
|
||||||
|
Flipping the frog switch!
|
||||||
|
Forge the Bilious Sliver!
|
||||||
|
Midnight Crew!
|
||||||
|
We have the cue ball!
|
||||||
|
th1s 1s r3d1culous.
|
||||||
|
wweh...
|
||||||
|
glub glub...
|
||||||
|
DAVE: this is stupid
|
||||||
|
WHAT THE FUCK IS A CREEPER.
|
||||||
|
I AM GOING TO THROW A TANTRUM.
|
||||||
|
H3H3H3! 1 C4N SM3LL TH3 D14MOND 0R3!
|
||||||
|
T4ST3S L1K3 CH3RRY!
|
||||||
|
uHH, pLEASE DONT MINE THAT,,, iTS MINE.
|
||||||
|
ii jju2t want two play a game.
|
||||||
|
two much iinformatiion.
|
||||||
|
:33 < ac goes on a purrfect mining trip!
|
||||||
|
:33 < furrealsies!
|
||||||
|
I Cannot Believe You Just Mined That Dirt.
|
||||||
|
Please Stop Being Ridiculous.
|
||||||
|
All 8 of my 8lue diamonds! ::::::::)
|
||||||
|
You're w8ing for something?
|
||||||
|
D --> That block is insufficiently STRONG
|
||||||
|
D --> e%cuse me
|
||||||
|
tHaT sHiT iS mOtHeRfUcKiNg MiRaCuLoUs.
|
||||||
|
mY mOtHeRfUcKiNg BrOtHeR.
|
||||||
|
wwhats the point of minin anywway.
|
||||||
|
38) This is so GLUBBING exciting!
|
||||||
|
the dead p0pulati0n is b0thering me.
|
||||||
|
0k. i am t0tally fine with this.
|
||||||
|
ROXY: wonk ;)
|
||||||
|
ROXY: obfuscation!!!
|
||||||
|
ROXY: i am the best hacker
|
||||||
|
ROXY: meow
|
||||||
|
ROXY: dirk u there
|
||||||
|
ROXY: i am going to save u
|
||||||
|
ROXY: wtf is this block
|
||||||
|
ROXY: where r the fucking cats
|
||||||
|
ROXY: im kinda drunk
|
||||||
|
ROXY: the magic is real
|
||||||
|
ROXY: sweet catch!
|
||||||
|
ROXY: frigglish!
|
||||||
|
ROXY: where are all the wizards
|
||||||
|
ROXY: im putting on my god tier pjs
|
||||||
|
ROXY: pumpkins r legally outlawed
|
||||||
|
ROXY: mutieeeee
|
||||||
|
ROXY: cant wake up
|
||||||
|
ROXY: sup
|
||||||
|
ROXY: wonk ;)
|
||||||
|
JOHN: wow, okay.
|
||||||
|
JOHN: wow, okay.
|
||||||
|
JOHN: i am a true prankster!
|
||||||
|
JOHN: what are you even talking about?
|
||||||
|
JOHN: let's go do some ghostbusting!
|
||||||
|
JOHN: i'm not a homosexual!
|
||||||
|
JOHN: i am a true prankster!
|
||||||
|
Prankster's Gambit!
|
||||||
|
Prankster's Gambit!
|
||||||
|
Ectobiology!
|
||||||
|
Ectobiology!
|
||||||
|
JADE: hooray!!!
|
||||||
|
JADE: <3 <3 <3
|
||||||
|
JADE: beep beep meow
|
||||||
|
JADE: im going to build a tall tower!
|
||||||
|
JADE: hooray!!!
|
||||||
|
JADE: <3 <3 <3
|
||||||
|
Becquerel is a good boy!
|
||||||
|
Becquerel is a good boy!
|
||||||
|
Good dog. Best friend.
|
||||||
|
Good dog. Best friend.
|
||||||
|
Squiddleknit!
|
||||||
|
Squiddles!
|
||||||
|
DAVE: i am not a hero
|
||||||
|
DAVE: ironically of course
|
||||||
|
DAVE: time shenanigans
|
||||||
|
DAVE: lets drop it like its hot
|
||||||
|
DAVE: apple juice
|
||||||
|
DAVE: sweet catch
|
||||||
|
ROSE: Let the record state that I am not a fan of this.
|
||||||
|
ROSE: I will tear this game apart.
|
||||||
|
ROSE: The plot thickens.
|
||||||
|
ROSE: We are playing a game.
|
||||||
|
Pony Pals!
|
||||||
|
DIRK: You can't escape the miles.
|
||||||
|
DIRK: Sup.
|
||||||
|
DIRK: im going to build a robot.
|
||||||
|
Auto-Responder!
|
||||||
|
JAKE: Tally ho!
|
||||||
|
JAKE: Pip pip!
|
||||||
|
JAKE: By jove!
|
||||||
|
JAKE: Egads!
|
||||||
|
JAKE: Jolly good show
|
||||||
81
style.css
81
style.css
|
|
@ -255,11 +255,33 @@ body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.splash-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 45%;
|
||||||
|
left: 90%;
|
||||||
|
width: fit-content;
|
||||||
|
color: #ffff00;
|
||||||
|
font-size: 20px;
|
||||||
|
text-shadow: 2px 2px 0 #3f3f00;
|
||||||
|
transform: translate(-50%, -50%) rotate(-20deg);
|
||||||
|
animation: splashBounce 0.2s infinite alternate ease-in-out;
|
||||||
|
pointer-events: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 5;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes splashBounce {
|
||||||
|
from { transform: translate(-50%, -50%) rotate(-20deg) scale(1); }
|
||||||
|
to { transform: translate(-50%, -50%) rotate(-20deg) scale(1.1); }
|
||||||
|
}
|
||||||
|
|
||||||
.mc-logo-img {
|
.mc-logo-img {
|
||||||
width: 650px;
|
width: 650px;
|
||||||
max-width: 95%;
|
max-width: 95%;
|
||||||
filter: drop-shadow(6px 6px 0px rgba(0,0,0,0.6));
|
filter: drop-shadow(6px 6px 0px rgba(0,0,0,0.6));
|
||||||
margin-bottom: 50px;
|
margin-top: -40px;
|
||||||
|
margin-bottom: 70px;
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -435,22 +457,38 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 150;
|
z-index: 2000;
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-box {
|
.modal-box {
|
||||||
width: 750px;
|
width: 60vw;
|
||||||
max-width: 95%;
|
max-width: 850px;
|
||||||
|
min-width: 600px;
|
||||||
|
max-height: 85vh;
|
||||||
background: var(--mc-gui-bg);
|
background: var(--mc-gui-bg);
|
||||||
border: 4px solid #000;
|
border: 4px solid #000;
|
||||||
padding: 50px;
|
padding: clamp(20px, 4vw, 50px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-shadow: inset 4px 4px 0 #fff;
|
box-shadow: inset 4px 4px 0 #fff;
|
||||||
animation: modalPop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
animation: modalPop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-box::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-box::-webkit-scrollbar-track {
|
||||||
|
background: rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-box::-webkit-scrollbar-thumb {
|
||||||
|
background: #888;
|
||||||
|
border: 2px solid var(--mc-gui-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close-btn {
|
.modal-close-btn {
|
||||||
|
|
@ -571,6 +609,39 @@ body {
|
||||||
100% { transform: rotate(360deg); }
|
100% { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.music-btn {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
background: var(--mc-button-bg);
|
||||||
|
border: 2px solid #000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: inset -2px -2px 0 #333, inset 2px 2px 0 #aaa;
|
||||||
|
z-index: 1000;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-btn:hover:not(.disabled) {
|
||||||
|
background-color: var(--mc-button-hover);
|
||||||
|
outline: 2px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-btn.muted {
|
||||||
|
opacity: 0.6;
|
||||||
|
background: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.music-btn.muted #music-icon {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
#toast {
|
#toast {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 80px;
|
bottom: 80px;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue