Compare commits
No commits in common. "main" and "release" have entirely different histories.
107
.github/workflows/ci.yml
vendored
|
|
@ -1,107 +0,0 @@
|
||||||
name: Release
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*.*.*"
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
jobs:
|
|
||||||
build-linux:
|
|
||||||
name: Build Linux AppImage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Install Linux build deps
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libarchive-tools rpm fakeroot
|
|
||||||
- name: Build AppImage
|
|
||||||
run: npm run dist
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload Linux artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: linux-dist
|
|
||||||
path: dist/*.AppImage
|
|
||||||
if-no-files-found: error
|
|
||||||
build-windows:
|
|
||||||
name: Build Windows Installer
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Build Windows installer
|
|
||||||
run: npm run dist:win
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload Windows artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows-dist
|
|
||||||
path: |
|
|
||||||
dist/*.exe
|
|
||||||
dist/*.msi
|
|
||||||
if-no-files-found: error
|
|
||||||
build-mac:
|
|
||||||
name: Build macOS DMG
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Clear electron-builder cache
|
|
||||||
run: rm -rf ~/Library/Caches/electron-builder
|
|
||||||
- name: Build macOS DMG
|
|
||||||
run: npm run dist:mac
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload macOS artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: mac-dist
|
|
||||||
path: dist/*.dmg
|
|
||||||
if-no-files-found: error
|
|
||||||
release:
|
|
||||||
name: Create GitHub Release
|
|
||||||
needs: [build-linux, build-windows, build-mac]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
path: artifacts
|
|
||||||
- name: Create release and upload assets
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
name: LegacyLauncher ${{ github.ref_name }}
|
|
||||||
draft: false
|
|
||||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
|
||||||
generate_release_notes: true
|
|
||||||
files: |
|
|
||||||
artifacts/linux-dist/*
|
|
||||||
artifacts/windows-dist/*
|
|
||||||
artifacts/mac-dist/*
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
129
.github/workflows/release.yml
vendored
|
|
@ -1,129 +0,0 @@
|
||||||
name: Release
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*.*.*"
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
jobs:
|
|
||||||
build-linux:
|
|
||||||
name: Build Linux AppImage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Install Linux build deps
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y libarchive-tools rpm fakeroot
|
|
||||||
- name: Build AppImage
|
|
||||||
run: npm run dist
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload Linux artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: linux-dist
|
|
||||||
path: dist/*.AppImage
|
|
||||||
if-no-files-found: error
|
|
||||||
build-windows:
|
|
||||||
name: Build Windows Installer
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Build Windows installer
|
|
||||||
run: npm run dist:win
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload Windows artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: windows-dist
|
|
||||||
path: |
|
|
||||||
dist/*.exe
|
|
||||||
dist/*.msi
|
|
||||||
if-no-files-found: error
|
|
||||||
build-mac:
|
|
||||||
name: Build macOS DMG (Apple Silicon)
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Build macOS DMG
|
|
||||||
run: npm run dist:mac
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload macOS artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: mac-dist
|
|
||||||
path: dist/*.dmg
|
|
||||||
if-no-files-found: error
|
|
||||||
build-mac-intel:
|
|
||||||
name: Build macOS DMG (Intel)
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "npm"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
- name: Build macOS DMG (Intel)
|
|
||||||
run: npm run dist:mac -- --x64
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Upload macOS Intel artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: mac-intel-dist
|
|
||||||
path: dist/*.dmg
|
|
||||||
if-no-files-found: error
|
|
||||||
release:
|
|
||||||
name: Create GitHub Release
|
|
||||||
needs: [build-linux, build-windows, build-mac, build-mac-intel]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
path: artifacts
|
|
||||||
- name: Create release and upload assets
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
name: LegacyLauncher ${{ github.ref_name }}
|
|
||||||
draft: false
|
|
||||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
|
||||||
generate_release_notes: true
|
|
||||||
files: |
|
|
||||||
artifacts/linux-dist/*
|
|
||||||
artifacts/windows-dist/*
|
|
||||||
artifacts/mac-dist/*
|
|
||||||
artifacts/mac-intel-dist/*
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
1
.gitignore
vendored
|
|
@ -1 +0,0 @@
|
||||||
node_modules/
|
|
||||||
BIN
256x256.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
21
LICENSE
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2026 gardenGnostic
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
BIN
Minecraft.ttf
Normal file
20
README.md
|
|
@ -2,11 +2,6 @@
|
||||||
|
|
||||||
A custom launcher for Minecraft Legacy Console Edition.
|
A custom launcher for Minecraft Legacy Console Edition.
|
||||||
|
|
||||||
<img width="1277" height="717" alt="image" src="https://github.com/user-attachments/assets/eaa9bae6-3b3b-4e39-a3c1-156e34abf3cc" />
|
|
||||||
|
|
||||||
[](https://ko-fi.com/gradengnostic)
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Minecraft-style GUI**: Authentic pixelated interface with Minecraft font and styling
|
- **Minecraft-style GUI**: Authentic pixelated interface with Minecraft font and styling
|
||||||
|
|
@ -79,11 +74,6 @@ The launcher supports several compatibility options for Linux:
|
||||||
- **extract-zip**: ZIP archive extraction
|
- **extract-zip**: ZIP archive extraction
|
||||||
- **Tailwind CSS**: UI styling (via CDN)
|
- **Tailwind CSS**: UI styling (via CDN)
|
||||||
|
|
||||||
## Assets
|
|
||||||
|
|
||||||
- Controller button sprites: [greatdocbrown](https://greatdocbrown.itch.io/gamepad-ui)
|
|
||||||
- UI Sounds: Using the free version of [JDSherbert's Ultimate UI SFX Pack on itch.io](https://jdsherbert.itch.io/ultimate-ui-sfx-pack)
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
The launcher is built with:
|
The launcher is built with:
|
||||||
|
|
@ -109,13 +99,3 @@ The launcher is built with:
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Feel free to submit issues and pull requests for improvements.</content>
|
Feel free to submit issues and pull requests for improvements.</content>
|
||||||
|
|
||||||
## Star History
|
|
||||||
|
|
||||||
<a href="https://www.star-history.com/?repos=gradenGnostic%2FLegacyLauncher&type=date&legend=top-left">
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/image?repos=gradenGnostic/LegacyLauncher&type=date&theme=dark&legend=top-left" />
|
|
||||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/image?repos=gradenGnostic/LegacyLauncher&type=date&legend=top-left" />
|
|
||||||
<img alt="Star History Chart" src="https://api.star-history.com/image?repos=gradenGnostic/LegacyLauncher&type=date&legend=top-left" />
|
|
||||||
</picture>
|
|
||||||
</a>
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 987 KiB |
|
Before Width: | Height: | Size: 24 KiB |
1444
index.html
204
main.js
|
|
@ -1,159 +1,103 @@
|
||||||
const { app, BrowserWindow, shell, ipcMain, dialog, globalShortcut, desktopCapturer } = require('electron');
|
const { app, BrowserWindow, shell, ipcMain } = require('electron');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const Store = require('electron-store');
|
const DiscordRPC = require('discord-rpc');
|
||||||
const fs = require('fs');
|
|
||||||
const https = require('https');
|
|
||||||
const extractZip = require('extract-zip');
|
|
||||||
const { exec } = require('child_process');
|
|
||||||
|
|
||||||
const store = new Store();
|
const clientId = '1346541144141103114';
|
||||||
let mainWindow = null;
|
let rpc;
|
||||||
let isGameRunning = false;
|
|
||||||
|
function initRPC() {
|
||||||
|
rpc = new DiscordRPC.Client({ transport: 'ipc' });
|
||||||
|
|
||||||
|
rpc.on('ready', () => {
|
||||||
|
console.log('Discord RPC ready');
|
||||||
|
setActivity();
|
||||||
|
});
|
||||||
|
|
||||||
|
rpc.on('error', (err) => {
|
||||||
|
console.error('Discord RPC Error:', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
rpc.on('disconnected', () => {
|
||||||
|
console.log('Discord RPC disconnected, retrying...');
|
||||||
|
setTimeout(connectRPC, 15000);
|
||||||
|
});
|
||||||
|
|
||||||
|
connectRPC();
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectRPC() {
|
||||||
|
rpc.login({ clientId }).catch(err => {
|
||||||
|
|
||||||
|
console.log('Discord RPC connection failed, retrying in 20s...');
|
||||||
|
setTimeout(connectRPC, 20000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
initRPC();
|
||||||
|
|
||||||
|
function setActivity(details = 'In Menus', state = 'Ready to Play', startTime = null) {
|
||||||
|
if (!rpc || !rpc.user) return;
|
||||||
|
|
||||||
|
const activity = {
|
||||||
|
details: details,
|
||||||
|
state: state,
|
||||||
|
largeImageKey: 'logo',
|
||||||
|
largeImageText: 'LegacyLauncher',
|
||||||
|
instance: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (startTime) {
|
||||||
|
activity.startTimestamp = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc.setActivity(activity).catch(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
width: 1280,
|
width: 1280,
|
||||||
height: 720,
|
height: 720,
|
||||||
minWidth: 1024,
|
minWidth: 1024,
|
||||||
minHeight: 600,
|
minHeight: 600,
|
||||||
center: true,
|
|
||||||
resizable: true,
|
resizable: true,
|
||||||
frame: false,
|
frame: false,
|
||||||
icon: path.join(__dirname, '512x512.png'),
|
icon: path.join(__dirname, '256x256.png'),
|
||||||
transparent: true,
|
transparent: true,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
contextIsolation: false,
|
contextIsolation: false,
|
||||||
enableRemoteModule: true
|
enableRemoteModule: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindow.loadFile('index.html');
|
win.maximize();
|
||||||
|
win.loadFile('index.html');
|
||||||
|
|
||||||
ipcMain.on('window-minimize', () => mainWindow.minimize());
|
// Handle window controls
|
||||||
|
ipcMain.on('window-minimize', () => win.minimize());
|
||||||
ipcMain.on('window-maximize', () => {
|
ipcMain.on('window-maximize', () => {
|
||||||
if (mainWindow.isMaximized()) {
|
if (win.isMaximized()) {
|
||||||
mainWindow.unmaximize();
|
win.unmaximize();
|
||||||
} else {
|
} else {
|
||||||
mainWindow.maximize();
|
win.maximize();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ipcMain.on('window-close', () => mainWindow.close());
|
ipcMain.on('window-close', () => win.close());
|
||||||
ipcMain.on('window-fullscreen', () => {
|
|
||||||
mainWindow.setFullScreen(!mainWindow.isFullScreen());
|
|
||||||
});
|
|
||||||
ipcMain.on('window-set-fullscreen', (event, enabled) => {
|
|
||||||
mainWindow.setFullScreen(Boolean(enabled));
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('take-screenshot', async (event) => {
|
|
||||||
try {
|
|
||||||
const screenshotsDir = path.join(app.getPath('userData'), 'Screenshots');
|
|
||||||
if (!fs.existsSync(screenshotsDir)) {
|
|
||||||
fs.mkdirSync(screenshotsDir, { recursive: true });
|
|
||||||
}
|
|
||||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
||||||
const fileName = `screenshot-${timestamp}.png`;
|
|
||||||
const filePath = path.join(screenshotsDir, fileName);
|
|
||||||
|
|
||||||
if (isGameRunning) {
|
|
||||||
const sources = await desktopCapturer.getSources({
|
|
||||||
types: ['window', 'screen'],
|
|
||||||
thumbnailSize: { width: 3840, height: 2160 } // High res for screenshot
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find Minecraft window or fallback to primary screen
|
|
||||||
const source = sources.find(s => s.name.toLowerCase().includes('minecraft')) ||
|
|
||||||
sources.find(s => s.id.startsWith('screen'));
|
|
||||||
|
|
||||||
if (source) {
|
|
||||||
fs.writeFileSync(filePath, source.thumbnail.toPNG());
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to launcher capture if game isn't running or not found
|
|
||||||
const win = BrowserWindow.fromWebContents(event.sender) || mainWindow;
|
|
||||||
if (!win) throw new Error("Window not found");
|
|
||||||
const image = await win.capturePage();
|
|
||||||
fs.writeFileSync(filePath, image.toPNG());
|
|
||||||
return filePath;
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Screenshot capture error:", err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('game-running-state', (event, running) => {
|
|
||||||
isGameRunning = running;
|
|
||||||
if (running) {
|
|
||||||
globalShortcut.register('F2', () => {
|
|
||||||
if (mainWindow) {
|
|
||||||
mainWindow.webContents.send('trigger-screenshot');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
globalShortcut.unregister('F2');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('list-screenshots', async () => {
|
|
||||||
const screenshotsDir = path.join(app.getPath('userData'), 'Screenshots');
|
|
||||||
if (!fs.existsSync(screenshotsDir)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const files = fs.readdirSync(screenshotsDir);
|
|
||||||
return files
|
|
||||||
.filter(f => f.toLowerCase().endsWith('.png'))
|
|
||||||
.sort((a, b) => {
|
|
||||||
try {
|
|
||||||
// Extract timestamp from 'screenshot-YYYY-MM-DDTHH-mm-ss-SSSZ.png'
|
|
||||||
const timeA = a.replace('screenshot-', '').replace('.png', '').replace(/-/g, ':');
|
|
||||||
const timeB = b.replace('screenshot-', '').replace('.png', '').replace(/-/g, ':');
|
|
||||||
return new Date(timeB) - new Date(timeA);
|
|
||||||
} catch (e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(f => ({
|
|
||||||
name: f,
|
|
||||||
path: path.join(screenshotsDir, f),
|
|
||||||
url: `file://${path.join(screenshotsDir, f)}`
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('delete-screenshot', async (event, fileName) => {
|
|
||||||
const filePath = path.join(app.getPath('userData'), 'Screenshots', fileName);
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
fs.unlinkSync(filePath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('open-screenshots-dir', async () => {
|
|
||||||
const screenshotsDir = path.join(app.getPath('userData'), 'Screenshots');
|
|
||||||
if (!fs.existsSync(screenshotsDir)) {
|
|
||||||
fs.mkdirSync(screenshotsDir, { recursive: true });
|
|
||||||
}
|
|
||||||
shell.openPath(screenshotsDir);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('store-get', (event, key) => store.get(key));
|
|
||||||
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];
|
|
||||||
});
|
|
||||||
|
|
||||||
mainWindow.on('maximize', () => mainWindow.webContents.send('window-is-maximized', true));
|
ipcMain.on('update-rpc', (event, data) => {
|
||||||
mainWindow.on('unmaximize', () => mainWindow.webContents.send('window-is-maximized', false));
|
setActivity(data.details, data.state, data.startTime);
|
||||||
|
});
|
||||||
|
|
||||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
win.on('maximize', () => win.webContents.send('window-is-maximized', true));
|
||||||
|
win.on('unmaximize', () => win.webContents.send('window-is-maximized', false));
|
||||||
|
|
||||||
|
|
||||||
|
win.webContents.setWindowOpenHandler(({ url }) => {
|
||||||
shell.openExternal(url);
|
shell.openExternal(url);
|
||||||
return { action: 'deny' };
|
return { action: 'deny' };
|
||||||
});
|
});
|
||||||
|
|
|
||||||
BIN
minecraft.jpg
Normal file
|
After Width: | Height: | Size: 300 KiB |
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
350
package-lock.json
generated
|
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"name": "legacylauncher",
|
"name": "legacylauncher",
|
||||||
"version": "3.5.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "legacylauncher",
|
"name": "legacylauncher",
|
||||||
"version": "3.5.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-store": "^6.0.1",
|
"discord-rpc": "^4.0.1",
|
||||||
"extract-zip": "^2.0.1"
|
"extract-zip": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -913,6 +913,7 @@
|
||||||
"version": "6.14.0",
|
"version": "6.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
|
||||||
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
|
@ -1197,15 +1198,6 @@
|
||||||
"node": ">= 4.0.0"
|
"node": ">= 4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/atomically": {
|
|
||||||
"version": "1.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
|
|
||||||
"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||||
|
|
@ -1237,6 +1229,16 @@
|
||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/bindings": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"file-uri-to-path": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bl": {
|
"node_modules/bl": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
|
@ -1710,42 +1712,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/conf": {
|
|
||||||
"version": "7.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/conf/-/conf-7.1.2.tgz",
|
|
||||||
"integrity": "sha512-r8/HEoWPFn4CztjhMJaWNAe5n+gPUCSaJ0oufbqDLFKsA1V8JjAG7G+p0pgoDFAws9Bpk2VtVLLXqOBA7WxLeg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ajv": "^6.12.2",
|
|
||||||
"atomically": "^1.3.1",
|
|
||||||
"debounce-fn": "^4.0.0",
|
|
||||||
"dot-prop": "^5.2.0",
|
|
||||||
"env-paths": "^2.2.0",
|
|
||||||
"json-schema-typed": "^7.0.3",
|
|
||||||
"make-dir": "^3.1.0",
|
|
||||||
"onetime": "^5.1.0",
|
|
||||||
"pkg-up": "^3.1.0",
|
|
||||||
"semver": "^7.3.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/conf/node_modules/semver": {
|
|
||||||
"version": "7.7.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
|
||||||
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
|
||||||
"license": "ISC",
|
|
||||||
"bin": {
|
|
||||||
"semver": "bin/semver.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/core-util-is": {
|
"node_modules/core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
|
|
@ -1812,30 +1778,6 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/debounce-fn": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"mimic-fn": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debounce-fn/node_modules/mimic-fn": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
|
|
@ -2013,6 +1955,19 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/discord-rpc": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord-rpc/-/discord-rpc-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-HOvHpbq5STRZJjQIBzwoKnQ0jHplbEWFWlPDwXXKm/bILh4nzjcg7mNqll0UY7RsjFoaXA7e/oYb/4lvpda2zA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"ws": "^7.3.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"register-scheme": "github:devsnek/node-register-scheme"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dmg-builder": {
|
"node_modules/dmg-builder": {
|
||||||
"version": "26.8.1",
|
"version": "26.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.8.1.tgz",
|
||||||
|
|
@ -2095,18 +2050,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dot-prop": {
|
|
||||||
"version": "5.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
|
|
||||||
"integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"is-obj": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dotenv": {
|
"node_modules/dotenv": {
|
||||||
"version": "16.6.1",
|
"version": "16.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||||
|
|
@ -2325,31 +2268,6 @@
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-store": {
|
|
||||||
"version": "6.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/electron-store/-/electron-store-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-8rdM0XEmDGsLuZM2oRABzsLX+XmD5x3rwxPMEPv0MrN9/BWanyy3ilb2v+tCrKtIZVF3MxUiZ9Bfqe8e0popKQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"conf": "^7.1.2",
|
|
||||||
"type-fest": "^0.16.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/electron-store/node_modules/type-fest": {
|
|
||||||
"version": "0.16.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
|
|
||||||
"integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
|
|
||||||
"license": "(MIT OR CC0-1.0)",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/electron-winstaller": {
|
"node_modules/electron-winstaller": {
|
||||||
"version": "5.4.0",
|
"version": "5.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
|
||||||
|
|
@ -2399,7 +2317,6 @@
|
||||||
"version": "0.1.13",
|
"version": "0.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -2419,6 +2336,7 @@
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||||
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
|
@ -2554,12 +2472,14 @@
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fast-json-stable-stringify": {
|
"node_modules/fast-json-stable-stringify": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fd-slicer": {
|
"node_modules/fd-slicer": {
|
||||||
|
|
@ -2589,6 +2509,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/file-uri-to-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/filelist": {
|
"node_modules/filelist": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz",
|
||||||
|
|
@ -2629,18 +2556,6 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/find-up": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"locate-path": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/foreground-child": {
|
"node_modules/foreground-child": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||||
|
|
@ -3097,7 +3012,7 @@
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
|
@ -3186,15 +3101,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-obj": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-unicode-supported": {
|
"node_modules/is-unicode-supported": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||||
|
|
@ -3299,14 +3205,9 @@
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/json-schema-typed": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==",
|
|
||||||
"license": "BSD-2-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/json-stringify-safe": {
|
"node_modules/json-stringify-safe": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||||
|
|
@ -3355,19 +3256,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/locate-path": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"p-locate": "^3.0.0",
|
|
||||||
"path-exists": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.23",
|
"version": "4.17.23",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||||
|
|
@ -3415,21 +3303,6 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/make-dir": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"semver": "^6.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/make-fetch-happen": {
|
"node_modules/make-fetch-happen": {
|
||||||
"version": "14.0.3",
|
"version": "14.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz",
|
||||||
|
|
@ -3517,6 +3390,7 @@
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
|
@ -3750,7 +3624,6 @@
|
||||||
"version": "1.7.2",
|
"version": "1.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
|
||||||
"integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==",
|
"integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
|
@ -3777,6 +3650,26 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-gyp": {
|
"node_modules/node-gyp": {
|
||||||
"version": "11.5.0",
|
"version": "11.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz",
|
||||||
|
|
@ -3868,6 +3761,7 @@
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mimic-fn": "^2.1.0"
|
"mimic-fn": "^2.1.0"
|
||||||
|
|
@ -3929,33 +3823,6 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/p-locate": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"p-limit": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/p-locate/node_modules/p-limit": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"p-try": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/p-map": {
|
"node_modules/p-map": {
|
||||||
"version": "7.0.4",
|
"version": "7.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz",
|
||||||
|
|
@ -3969,15 +3836,6 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/p-try": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/package-json-from-dist": {
|
"node_modules/package-json-from-dist": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||||
|
|
@ -3985,15 +3843,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BlueOak-1.0.0"
|
"license": "BlueOak-1.0.0"
|
||||||
},
|
},
|
||||||
"node_modules/path-exists": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/path-is-absolute": {
|
"node_modules/path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
|
@ -4079,18 +3928,6 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pkg-up": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"find-up": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/plist": {
|
"node_modules/plist": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
|
||||||
|
|
@ -4196,6 +4033,7 @@
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
|
@ -4242,6 +4080,17 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/register-scheme": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "git+ssh://git@github.com/devsnek/node-register-scheme.git#e7cc9a63a1f512565da44cb57316d9fb10750e17",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"bindings": "^1.3.0",
|
||||||
|
"node-addon-api": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/require-directory": {
|
"node_modules/require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
|
|
@ -4373,7 +4222,7 @@
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/sanitize-filename": {
|
"node_modules/sanitize-filename": {
|
||||||
|
|
@ -4400,6 +4249,7 @@
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
|
|
@ -4690,9 +4540,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tar": {
|
"node_modules/tar": {
|
||||||
"version": "7.5.11",
|
"version": "7.5.10",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.10.tgz",
|
||||||
"integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==",
|
"integrity": "sha512-8mOPs1//5q/rlkNSPcCegA6hiHJYDmSLEI8aMH/CdSQJNWztHC9WHNam5zdQlfpTwB9Xp7IBEsHfV5LKMJGVAw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -4837,6 +4687,12 @@
|
||||||
"tmp": "^0.2.0"
|
"tmp": "^0.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/truncate-utf8-bytes": {
|
"node_modules/truncate-utf8-bytes": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
|
||||||
|
|
@ -4908,6 +4764,7 @@
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||||
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
|
|
@ -4953,6 +4810,22 @@
|
||||||
"defaults": "^1.0.3"
|
"defaults": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz",
|
||||||
|
|
@ -5012,6 +4885,27 @@
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "7.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||||
|
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xmlbuilder": {
|
"node_modules/xmlbuilder": {
|
||||||
"version": "15.1.1",
|
"version": "15.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||||
|
|
|
||||||
34
package.json
|
|
@ -1,15 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "legacylauncher",
|
"name": "legacylauncher",
|
||||||
"version": "3.5.0",
|
"version": "1.0.0",
|
||||||
"description": "A Minecraft: Legacy Console Edition launcher",
|
"description": "",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
"dist": "electron-builder --linux AppImage",
|
"dist": "electron-builder --linux AppImage",
|
||||||
"dist:flatpak": "electron-builder --linux flatpak",
|
"dist:win": "electron-builder --win nsis"
|
||||||
"dist:win": "electron-builder --win nsis",
|
|
||||||
"dist:mac": "electron-builder --mac dmg"
|
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "com.legacylauncher.app",
|
"appId": "com.legacylauncher.app",
|
||||||
|
|
@ -18,7 +16,7 @@
|
||||||
"target": [
|
"target": [
|
||||||
"nsis"
|
"nsis"
|
||||||
],
|
],
|
||||||
"icon": "512x512.png"
|
"icon": "256x256.png"
|
||||||
},
|
},
|
||||||
"nsis": {
|
"nsis": {
|
||||||
"oneClick": false,
|
"oneClick": false,
|
||||||
|
|
@ -26,28 +24,10 @@
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": [
|
"target": [
|
||||||
"AppImage",
|
"AppImage"
|
||||||
"flatpak"
|
|
||||||
],
|
],
|
||||||
"category": "Game",
|
"category": "Game",
|
||||||
"icon": "512x512.png",
|
"icon": "256x256.png"
|
||||||
"desktop": {
|
|
||||||
"entry": {
|
|
||||||
"Name": "Minecraft LCE Launcher",
|
|
||||||
"GenericName": "Minecraft Launcher",
|
|
||||||
"Comment": "A Minecraft: Legacy Console Edition launcher",
|
|
||||||
"Categories": "Game;Emulation;",
|
|
||||||
"StartupNotify": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"executableName": "legacylauncher"
|
|
||||||
},
|
|
||||||
"mac": {
|
|
||||||
"target": [
|
|
||||||
"dmg"
|
|
||||||
],
|
|
||||||
"icon": "512x512.png",
|
|
||||||
"category": "public.app-category.games"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"**/*",
|
"**/*",
|
||||||
|
|
@ -58,7 +38,7 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-store": "^6.0.1",
|
"discord-rpc": "^4.0.1",
|
||||||
"extract-zip": "^2.0.1"
|
"extract-zip": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
2181
renderer.js
469
skin_manager.js
|
|
@ -1,469 +0,0 @@
|
||||||
// skin_manager.js
|
|
||||||
// Handles skin uploading, conversion, 3D preview, and saving to char.png
|
|
||||||
|
|
||||||
let mainMenuScene, mainMenuCamera, mainMenuRenderer, mainMenuPlayerGroup;
|
|
||||||
let isMainSkinDragging = false;
|
|
||||||
let mainMenuSkinRenderMode = '3d';
|
|
||||||
|
|
||||||
let skinScene, skinCamera, skinRenderer, skinPlayerGroup;
|
|
||||||
let isSkinDragging = false;
|
|
||||||
let previousSkinMousePosition = { x: 0, y: 0 };
|
|
||||||
let processedSkinDataUrl = null;
|
|
||||||
|
|
||||||
// Initialize when DOM is ready
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const skinInput = document.getElementById('skin-input');
|
|
||||||
const dropZone = document.getElementById('drop-zone');
|
|
||||||
const saveSkinBtn = document.getElementById('save-skin-btn');
|
|
||||||
const closeSkinBtn = document.getElementById('btn-close-skin');
|
|
||||||
|
|
||||||
if (skinInput) skinInput.addEventListener('change', (e) => handleSkinFile(e.target.files[0]));
|
|
||||||
|
|
||||||
if (dropZone) {
|
|
||||||
dropZone.addEventListener('click', () => skinInput?.click());
|
|
||||||
dropZone.addEventListener('keydown', (e) => {
|
|
||||||
if (e.key === 'Enter' || e.key === ' ') {
|
|
||||||
e.preventDefault();
|
|
||||||
skinInput?.click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dropZone.addEventListener('dragover', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
dropZone.classList.add('border-green-500');
|
|
||||||
});
|
|
||||||
dropZone.addEventListener('dragleave', () => dropZone.classList.remove('border-green-500'));
|
|
||||||
dropZone.addEventListener('drop', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
dropZone.classList.remove('border-green-500');
|
|
||||||
handleSkinFile(e.dataTransfer.files[0]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saveSkinBtn) {
|
|
||||||
saveSkinBtn.addEventListener('click', saveSkinToDisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (closeSkinBtn) {
|
|
||||||
closeSkinBtn.addEventListener('click', closeSkinManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize Main Menu Viewer
|
|
||||||
initMainMenuSkinViewer();
|
|
||||||
});
|
|
||||||
|
|
||||||
function initMainMenuSkinViewer() {
|
|
||||||
const container = document.getElementById('main-skin-viewer');
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
mainMenuScene = new THREE.Scene();
|
|
||||||
mainMenuCamera = new THREE.PerspectiveCamera(45, container.offsetWidth / container.offsetHeight, 0.1, 1000);
|
|
||||||
mainMenuCamera.position.set(0, 5, 60);
|
|
||||||
|
|
||||||
mainMenuRenderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
|
||||||
mainMenuRenderer.setSize(container.offsetWidth, container.offsetHeight);
|
|
||||||
mainMenuRenderer.setPixelRatio(window.devicePixelRatio);
|
|
||||||
mainMenuRenderer.outputEncoding = THREE.sRGBEncoding;
|
|
||||||
container.appendChild(mainMenuRenderer.domElement);
|
|
||||||
|
|
||||||
mainMenuScene.add(new THREE.AmbientLight(0xffffff, 1.1));
|
|
||||||
const dl = new THREE.DirectionalLight(0xffffff, 0.5);
|
|
||||||
dl.position.set(10, 20, 15);
|
|
||||||
mainMenuScene.add(dl);
|
|
||||||
|
|
||||||
mainMenuPlayerGroup = new THREE.Group();
|
|
||||||
mainMenuScene.add(mainMenuPlayerGroup);
|
|
||||||
|
|
||||||
// Interaction for Main Menu Viewer
|
|
||||||
let prevX = 0;
|
|
||||||
container.addEventListener('mousedown', (e) => {
|
|
||||||
if (mainMenuSkinRenderMode !== '3d') return;
|
|
||||||
isMainSkinDragging = true;
|
|
||||||
prevX = e.clientX;
|
|
||||||
});
|
|
||||||
window.addEventListener('mouseup', () => isMainSkinDragging = false);
|
|
||||||
window.addEventListener('mousemove', (e) => {
|
|
||||||
if (mainMenuSkinRenderMode === '3d' && isMainSkinDragging && mainMenuPlayerGroup) {
|
|
||||||
mainMenuPlayerGroup.rotation.y += (e.clientX - prevX) * 0.01;
|
|
||||||
prevX = e.clientX;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Auto-rotate slowly
|
|
||||||
function animateMain() {
|
|
||||||
requestAnimationFrame(animateMain);
|
|
||||||
if (mainMenuSkinRenderMode === '3d' && !isMainSkinDragging && mainMenuPlayerGroup) {
|
|
||||||
mainMenuPlayerGroup.rotation.y += 0.005;
|
|
||||||
}
|
|
||||||
if (mainMenuRenderer && mainMenuScene && mainMenuCamera) mainMenuRenderer.render(mainMenuScene, mainMenuCamera);
|
|
||||||
}
|
|
||||||
animateMain();
|
|
||||||
|
|
||||||
// Load current skin after short delay to ensure paths are ready
|
|
||||||
setTimeout(loadMainMenuSkin, 500);
|
|
||||||
|
|
||||||
// Handle window resize
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
if (mainMenuCamera && mainMenuRenderer && container) {
|
|
||||||
mainMenuCamera.aspect = container.offsetWidth / container.offsetHeight;
|
|
||||||
mainMenuCamera.updateProjectionMatrix();
|
|
||||||
mainMenuRenderer.setSize(container.offsetWidth, container.offsetHeight);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadMainMenuSkin() {
|
|
||||||
try {
|
|
||||||
// Ensure install dir is available (currentInstance might not be ready)
|
|
||||||
const installDir = await window.getInstallDir();
|
|
||||||
if (!installDir) return;
|
|
||||||
|
|
||||||
const skinPath = path.join(installDir, 'Common', 'res', 'mob', 'char.png');
|
|
||||||
|
|
||||||
if (fs.existsSync(skinPath)) {
|
|
||||||
const skinData = fs.readFileSync(skinPath);
|
|
||||||
const blob = new Blob([skinData]);
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
const img = new Image();
|
|
||||||
img.onload = () => {
|
|
||||||
const isLegacy = img.height === 32;
|
|
||||||
updateSkinModel(img.src, isLegacy, mainMenuPlayerGroup, mainMenuSkinRenderMode);
|
|
||||||
};
|
|
||||||
img.src = url;
|
|
||||||
} else {
|
|
||||||
console.log("No skin found at " + skinPath);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("Could not load main menu skin (startup race condition?):", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleMainSkinRenderMode() {
|
|
||||||
mainMenuSkinRenderMode = mainMenuSkinRenderMode === '3d' ? '2d' : '3d';
|
|
||||||
const modeButton = document.getElementById('btn-skin-render-mode');
|
|
||||||
if (modeButton) modeButton.textContent = mainMenuSkinRenderMode.toUpperCase();
|
|
||||||
|
|
||||||
const container = document.getElementById('main-skin-viewer');
|
|
||||||
if (container) {
|
|
||||||
container.style.cursor = mainMenuSkinRenderMode === '3d' ? 'grab' : 'default';
|
|
||||||
}
|
|
||||||
isMainSkinDragging = false;
|
|
||||||
|
|
||||||
if (mainMenuSkinRenderMode === '2d' && mainMenuPlayerGroup) {
|
|
||||||
mainMenuPlayerGroup.rotation.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadMainMenuSkin();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSkinModel(dataUrl, isLegacy, targetGroup, renderMode = '3d') {
|
|
||||||
if (!targetGroup) return;
|
|
||||||
|
|
||||||
new THREE.TextureLoader().load(dataUrl, (texture) => {
|
|
||||||
texture.magFilter = THREE.NearestFilter;
|
|
||||||
texture.minFilter = THREE.NearestFilter;
|
|
||||||
texture.encoding = THREE.sRGBEncoding;
|
|
||||||
|
|
||||||
// Clear existing children
|
|
||||||
while(targetGroup.children.length > 0) targetGroup.remove(targetGroup.children[0]);
|
|
||||||
|
|
||||||
const createFaceMaterial = (tex, x, y, w, h) => {
|
|
||||||
const texWidth = tex.image.width;
|
|
||||||
const texHeight = tex.image.height;
|
|
||||||
const matTex = tex.clone();
|
|
||||||
matTex.magFilter = THREE.NearestFilter;
|
|
||||||
matTex.minFilter = THREE.NearestFilter;
|
|
||||||
matTex.repeat.set(w / texWidth, h / texHeight);
|
|
||||||
matTex.offset.set(x / texWidth, 1 - (y + h) / texHeight);
|
|
||||||
matTex.needsUpdate = true;
|
|
||||||
return new THREE.MeshLambertMaterial({ map: matTex, transparent: true, alphaTest: 0.5, side: THREE.FrontSide });
|
|
||||||
};
|
|
||||||
|
|
||||||
const createBodyPart = (w, h, d, tex, uv, offset = 0) => {
|
|
||||||
const geometry = new THREE.BoxGeometry(w, h, d);
|
|
||||||
const materials = [
|
|
||||||
createFaceMaterial(tex, uv.left[0], uv.left[1], uv.left[2], uv.left[3]), // Left (Standard MC "Right")
|
|
||||||
createFaceMaterial(tex, uv.right[0], uv.right[1], uv.right[2], uv.right[3]), // Right (Standard MC "Left")
|
|
||||||
createFaceMaterial(tex, uv.top[0], uv.top[1], uv.top[2], uv.top[3]),
|
|
||||||
createFaceMaterial(tex, uv.bottom[0], uv.bottom[1], uv.bottom[2], uv.bottom[3]),
|
|
||||||
createFaceMaterial(tex, uv.front[0], uv.front[1], uv.front[2], uv.front[3]),
|
|
||||||
createFaceMaterial(tex, uv.back[0], uv.back[1], uv.back[2], uv.back[3])
|
|
||||||
];
|
|
||||||
const mesh = new THREE.Mesh(geometry, materials);
|
|
||||||
if (offset !== 0) mesh.scale.set(1 + offset, 1 + offset, 1 + offset);
|
|
||||||
return mesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
const limbUv = (x, y) => ({
|
|
||||||
top: [x+4, y, 4, 4], bottom: [x+8, y, 4, 4],
|
|
||||||
right: [x, y+4, 4, 12], front: [x+4, y+4, 4, 12],
|
|
||||||
left: [x+8, y+4, 4, 12], back: [x+12, y+4, 4, 12]
|
|
||||||
});
|
|
||||||
|
|
||||||
const create2DPart = (tex, uvFront, width, height, x, y, scale = 1) => {
|
|
||||||
const texWidth = tex.image.width;
|
|
||||||
const texHeight = tex.image.height;
|
|
||||||
const partTex = tex.clone();
|
|
||||||
partTex.magFilter = THREE.NearestFilter;
|
|
||||||
partTex.minFilter = THREE.NearestFilter;
|
|
||||||
partTex.repeat.set(uvFront[2] / texWidth, uvFront[3] / texHeight);
|
|
||||||
partTex.offset.set(uvFront[0] / texWidth, 1 - (uvFront[1] + uvFront[3]) / texHeight);
|
|
||||||
partTex.needsUpdate = true;
|
|
||||||
|
|
||||||
const geometry = new THREE.PlaneGeometry(width, height);
|
|
||||||
const material = new THREE.MeshBasicMaterial({ map: partTex, transparent: true, alphaTest: 0.5, side: THREE.DoubleSide });
|
|
||||||
const mesh = new THREE.Mesh(geometry, material);
|
|
||||||
mesh.position.set(x, y, 0);
|
|
||||||
mesh.scale.set(scale, scale, 1);
|
|
||||||
return mesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (renderMode === '2d') {
|
|
||||||
const frontParts = [
|
|
||||||
create2DPart(texture, [8, 8, 8, 8], 8, 8, 0, 10),
|
|
||||||
create2DPart(texture, [40, 8, 8, 8], 8, 8, 0, 10, 1.12),
|
|
||||||
create2DPart(texture, [20, 20, 8, 12], 8, 12, 0, 0),
|
|
||||||
create2DPart(texture, [44, 20, 4, 12], 4, 12, -6, 0),
|
|
||||||
create2DPart(texture, isLegacy ? [44, 20, 4, 12] : [36, 52, 4, 12], 4, 12, 6, 0),
|
|
||||||
create2DPart(texture, [4, 20, 4, 12], 4, 12, -2, -12),
|
|
||||||
create2DPart(texture, isLegacy ? [4, 20, 4, 12] : [20, 52, 4, 12], 4, 12, 2, -12)
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!isLegacy) {
|
|
||||||
frontParts.push(
|
|
||||||
create2DPart(texture, [20, 36, 8, 12], 8, 12, 0, 0, 1.05),
|
|
||||||
create2DPart(texture, [44, 36, 4, 12], 4, 12, -6, 0, 1.05),
|
|
||||||
create2DPart(texture, [52, 52, 4, 12], 4, 12, 6, 0, 1.05),
|
|
||||||
create2DPart(texture, [4, 36, 4, 12], 4, 12, -2, -12, 1.05),
|
|
||||||
create2DPart(texture, [4, 52, 4, 12], 4, 12, 2, -12, 1.05)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
frontParts.forEach((part) => targetGroup.add(part));
|
|
||||||
targetGroup.rotation.y = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Head
|
|
||||||
const headUvs = { top: [8, 0, 8, 8], bottom: [16, 0, 8, 8], right: [0, 8, 8, 8], left: [16, 8, 8, 8], front: [8, 8, 8, 8], back: [24, 8, 8, 8] };
|
|
||||||
const head = createBodyPart(8, 8, 8, texture, headUvs);
|
|
||||||
head.position.y = 10;
|
|
||||||
targetGroup.add(head);
|
|
||||||
|
|
||||||
// Hat
|
|
||||||
const hatUvs = { top: [40, 0, 8, 8], bottom: [48, 0, 8, 8], right: [32, 8, 8, 8], left: [48, 8, 8, 8], front: [40, 8, 8, 8], back: [56, 8, 8, 8] };
|
|
||||||
const hat = createBodyPart(8, 8, 8, texture, hatUvs, 0.12);
|
|
||||||
hat.position.y = 10;
|
|
||||||
targetGroup.add(hat);
|
|
||||||
|
|
||||||
// Torso
|
|
||||||
const torsoUvs = { top: [20, 16, 8, 4], bottom: [28, 16, 8, 4], right: [16, 20, 4, 12], left: [28, 20, 4, 12], front: [20, 20, 8, 12], back: [32, 20, 8, 12] };
|
|
||||||
targetGroup.add(createBodyPart(8, 12, 4, texture, torsoUvs));
|
|
||||||
|
|
||||||
// Jacket (non-legacy only)
|
|
||||||
if (!isLegacy) {
|
|
||||||
const jacketUvs = { top: [20, 32, 8, 4], bottom: [28, 32, 8, 4], right: [16, 36, 4, 12], left: [28, 36, 4, 12], front: [20, 36, 8, 12], back: [32, 36, 8, 12] };
|
|
||||||
targetGroup.add(createBodyPart(8, 12, 4, texture, jacketUvs, 0.05));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limbs
|
|
||||||
const limbs = [
|
|
||||||
{ pos: [-6, 0, 0], uv: limbUv(40, 16), layerUv: limbUv(40, 32) },
|
|
||||||
{ pos: [6, 0, 0], uv: isLegacy ? limbUv(40, 16) : limbUv(32, 48), layerUv: limbUv(48, 48) },
|
|
||||||
{ pos: [-2, -12, 0], uv: limbUv(0, 16), layerUv: limbUv(0, 32) },
|
|
||||||
{ pos: [2, -12, 0], uv: isLegacy ? limbUv(0, 16) : limbUv(16, 48), layerUv: limbUv(0, 48) }
|
|
||||||
];
|
|
||||||
|
|
||||||
limbs.forEach(l => {
|
|
||||||
const base = createBodyPart(4, 12, 4, texture, l.uv);
|
|
||||||
base.position.set(...l.pos);
|
|
||||||
targetGroup.add(base);
|
|
||||||
if (!isLegacy) {
|
|
||||||
const layer = createBodyPart(4, 12, 4, texture, l.layerUv, 0.05);
|
|
||||||
layer.position.set(...l.pos);
|
|
||||||
targetGroup.add(layer);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
targetGroup.rotation.y = 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function openSkinManager() {
|
|
||||||
const modal = document.getElementById('skin-modal');
|
|
||||||
modal.style.display = 'flex';
|
|
||||||
modal.style.opacity = '1';
|
|
||||||
|
|
||||||
// Clear previous state in modal
|
|
||||||
const previewContainer = document.getElementById('preview-container');
|
|
||||||
if (previewContainer) previewContainer.classList.add('hidden');
|
|
||||||
|
|
||||||
const sysMsg = document.getElementById('sys-message');
|
|
||||||
if (sysMsg) sysMsg.classList.add('hidden');
|
|
||||||
|
|
||||||
// Load current skin into preview (optional, maybe we only want to see uploaded ones)
|
|
||||||
// loadCurrentSkinToPreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeSkinManager() {
|
|
||||||
const modal = document.getElementById('skin-modal');
|
|
||||||
modal.style.opacity = '0';
|
|
||||||
setTimeout(() => {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
|
|
||||||
// Reset state
|
|
||||||
const prompt = document.getElementById('upload-prompt');
|
|
||||||
if (prompt) prompt.style.display = 'block';
|
|
||||||
|
|
||||||
const previewContainer = document.getElementById('preview-container');
|
|
||||||
if (previewContainer) previewContainer.classList.add('hidden');
|
|
||||||
|
|
||||||
processedSkinDataUrl = null;
|
|
||||||
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSkinFile(file) {
|
|
||||||
if (!file || !file.type.includes('png')) return window.showToast("Only PNG files are supported!");
|
|
||||||
|
|
||||||
const prompt = document.getElementById('upload-prompt');
|
|
||||||
if (prompt) prompt.style.display = 'none';
|
|
||||||
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = (e) => {
|
|
||||||
const img = new Image();
|
|
||||||
img.onload = () => {
|
|
||||||
processSkinImage(img, e.target.result);
|
|
||||||
};
|
|
||||||
img.onerror = () => {
|
|
||||||
window.showToast("Failed to load image");
|
|
||||||
if(prompt) prompt.style.display = 'block';
|
|
||||||
};
|
|
||||||
img.src = e.target.result;
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
function processSkinImage(img, srcUrl, isInitialLoad = false) {
|
|
||||||
const canvas = document.getElementById('skin-canvas');
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const formatLabel = document.getElementById('format-label');
|
|
||||||
const statusMessage = document.getElementById('status-message');
|
|
||||||
const previewContainer = document.getElementById('preview-container');
|
|
||||||
const saveBtn = document.getElementById('save-skin-btn');
|
|
||||||
const prompt = document.getElementById('upload-prompt');
|
|
||||||
|
|
||||||
if (img.width !== 64) {
|
|
||||||
if(prompt) prompt.style.display = 'block';
|
|
||||||
if(previewContainer) previewContainer.classList.add('hidden');
|
|
||||||
return window.showToast("Invalid skin width. Must be 64px.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(prompt) prompt.style.display = 'none';
|
|
||||||
|
|
||||||
const isLegacy = img.height === 32;
|
|
||||||
|
|
||||||
ctx.clearRect(0, 0, 64, 32);
|
|
||||||
ctx.drawImage(img, 0, 0, 64, 32, 0, 0, 64, 32);
|
|
||||||
processedSkinDataUrl = canvas.toDataURL('image/png');
|
|
||||||
|
|
||||||
previewContainer.classList.remove('hidden');
|
|
||||||
|
|
||||||
if (isInitialLoad) {
|
|
||||||
if(formatLabel) formatLabel.textContent = "Current Skin";
|
|
||||||
if(statusMessage) statusMessage.innerHTML = "<span class='text-blue-400 font-black' style='color: #60a5fa;'>LOADED FROM DISK</span>";
|
|
||||||
if(saveBtn) {
|
|
||||||
saveBtn.textContent = "SAVED";
|
|
||||||
saveBtn.classList.add('disabled');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(formatLabel) formatLabel.textContent = isLegacy ? "64x32 (Legacy)" : "64x64 (Modern)";
|
|
||||||
if(statusMessage) statusMessage.innerHTML = isLegacy ? "<span class='text-green-400 font-black' style='color: #4ade80;'>LEGACY READY</span>" : "<span class='text-yellow-400 font-black' style='color: #facc15;'>CONVERTED TO 64x32</span>";
|
|
||||||
if(saveBtn) {
|
|
||||||
saveBtn.textContent = "SAVE SKIN";
|
|
||||||
saveBtn.classList.remove('disabled');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skinScene) initPreviewEngine();
|
|
||||||
updateSkinModel(srcUrl, isLegacy, skinPlayerGroup, '3d');
|
|
||||||
}
|
|
||||||
|
|
||||||
function initPreviewEngine() {
|
|
||||||
const container = document.getElementById('skin-viewer-container');
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
skinScene = new THREE.Scene();
|
|
||||||
skinCamera = new THREE.PerspectiveCamera(35, container.offsetWidth / container.offsetHeight, 0.1, 1000);
|
|
||||||
skinCamera.position.set(0, 5, 70);
|
|
||||||
|
|
||||||
skinRenderer = new THREE.WebGLRenderer({ antialias: false, alpha: true });
|
|
||||||
skinRenderer.setSize(container.offsetWidth, container.offsetHeight);
|
|
||||||
skinRenderer.setPixelRatio(window.devicePixelRatio);
|
|
||||||
skinRenderer.outputEncoding = THREE.sRGBEncoding;
|
|
||||||
container.appendChild(skinRenderer.domElement);
|
|
||||||
|
|
||||||
skinScene.add(new THREE.AmbientLight(0xffffff, 0.9));
|
|
||||||
const dl = new THREE.DirectionalLight(0xffffff, 0.35);
|
|
||||||
dl.position.set(10, 20, 15);
|
|
||||||
skinScene.add(dl);
|
|
||||||
|
|
||||||
skinPlayerGroup = new THREE.Group();
|
|
||||||
skinScene.add(skinPlayerGroup);
|
|
||||||
|
|
||||||
container.addEventListener('mousedown', () => isSkinDragging = true);
|
|
||||||
window.addEventListener('mouseup', () => isSkinDragging = false);
|
|
||||||
window.addEventListener('mousemove', (e) => {
|
|
||||||
if (isSkinDragging && skinPlayerGroup) {
|
|
||||||
skinPlayerGroup.rotation.y += (e.movementX) * 0.01;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function animate() {
|
|
||||||
requestAnimationFrame(animate);
|
|
||||||
if (!isSkinDragging && skinPlayerGroup) skinPlayerGroup.rotation.y += 0.008;
|
|
||||||
if (skinRenderer && skinScene && skinCamera) skinRenderer.render(skinScene, skinCamera);
|
|
||||||
}
|
|
||||||
animate();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveSkinToDisk() {
|
|
||||||
if (!processedSkinDataUrl) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const installDir = await window.getInstallDir();
|
|
||||||
const savePath = path.join(installDir, 'Common', 'res', 'mob', 'char.png');
|
|
||||||
const dir = path.dirname(savePath);
|
|
||||||
|
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
const base64Data = processedSkinDataUrl.replace(/^data:image\/png;base64,/, "");
|
|
||||||
fs.writeFileSync(savePath, base64Data, 'base64');
|
|
||||||
|
|
||||||
window.showToast("Skin Saved Successfully!");
|
|
||||||
|
|
||||||
const saveBtn = document.getElementById('save-skin-btn');
|
|
||||||
if(saveBtn) {
|
|
||||||
saveBtn.textContent = "SAVED!";
|
|
||||||
saveBtn.classList.add('disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh main menu skin
|
|
||||||
loadMainMenuSkin();
|
|
||||||
|
|
||||||
// Close modal after short delay?
|
|
||||||
setTimeout(closeSkinManager, 1000);
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
window.showToast("Error Saving Skin: " + e.message);
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Global Export
|
|
||||||
window.openSkinManager = openSkinManager;
|
|
||||||
window.initMainMenuSkinViewer = initMainMenuSkinViewer;
|
|
||||||
window.loadMainMenuSkin = loadMainMenuSkin;
|
|
||||||
window.toggleMainSkinRenderMode = toggleMainSkinRenderMode;
|
|
||||||
483
strings.txt
|
|
@ -1,483 +0,0 @@
|
||||||
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
|
|
||||||
Jade Harley!!!
|
|
||||||
Jade Harley!!!
|
|
||||||
Jade Harley!!!
|
|
||||||
Jade Harley!!!
|
|
||||||
Jade Harley!!!
|
|
||||||