From 9fcf603e08f7fdfbe0b181d3ffa48965dcc7f73b Mon Sep 17 00:00:00 2001 From: AMIAY Date: Sun, 18 Jan 2026 15:42:20 +0100 Subject: [PATCH] Add files via upload --- README.md | 26 ++++---- SERVER.md | 174 +++++++++++++++++++++++++-------------------------- main.js | 141 +++++++++++++++++++++++++++++++++++++---- package.json | 3 +- preload.js | 9 ++- 5 files changed, 237 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index 01c8cf6..eced181 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,9 @@
-![Version](https://img.shields.io/badge/Version-2.0.0-green?style=for-the-badge) +![Version](https://img.shields.io/badge/Version-2.0.1-green?style=for-the-badge) ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey?style=for-the-badge) ![License](https://img.shields.io/badge/License-Educational-blue?style=for-the-badge) -[![Join Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/MHkEjepMQ7) **A modern, cross-platform offline launcher for Hytale with automatic updates and multiplayer support (windows users & non-premium only)** @@ -67,12 +66,6 @@ See [BUILD.md](BUILD.md) for detailed build instructions or [**Releases**](https #### 🖥️ How to create server (Windows Only)? See [SERVER.md](SERVER.md) -### 🎮 Usage - -1. **Enter your player name** -2. **Click "PLAY"** -3. **Automatic setup** - The launcher handles everything automatically -4. **Game launches** - Enjoy playing Hytale! --- @@ -84,7 +77,17 @@ See [BUILD.md](BUILD.md) for comprehensive build instructions. ## 📋 Changelog -### 🆕 v2.0.0 *(Latest)* +### 🆕 v2.0.1 *(Latest)* +- 📊 **Advanced Logging System** - Complete logging with timestamps, file rotation, and session tracking +- 🔧 **Play Button Fix** - Resolved issue where play button could get stuck in "CHECKING..." state +- 💬 **Discord Integration** - Added closable Discord notification for community engagement +- 📁 **Game Location Access** - New "Open Game Location" button in settings for easy file access +- 🎯 **UI Polish** - Removed bounce animation from player counter for smoother experience +- 🛡️ **Stability Improvements** - Enhanced error handling and process lifecycle management +- ⚡ **Performance Optimizations** - Faster startup times and better resource management +- 🔄 **Timeout Protection** - Added safety timeouts to prevent launcher freezing + +### 🔄 v2.0.0 - ✅ **Automatic Game Update System** - Smart version checking and seamless updates - ✅ **Partial Automatic Launcher Update System** - This will inform you when I release a new update. - 🛡️ **UserData Preservation** - Intelligent backup/restore of game saves during updates @@ -184,11 +187,6 @@ This launcher is created for **educational purposes only**. --- -## 📬 Contact - -[![Discord](https://img.shields.io/badge/Discord-amiay3-5865F2?logo=discord&logoColor=white)](https://discord.com/users/1433515183606599873) - -
**⭐ Star this project if you found it helpful! ⭐** diff --git a/SERVER.md b/SERVER.md index ef3fba3..510edb5 100644 --- a/SERVER.md +++ b/SERVER.md @@ -1,87 +1,87 @@ -# Hytale F2P Server Setup Guide - -## Server File Setup - -**Download server file:** -``` -http://3.10.208.30:3002/server -``` - -**Replace the file here:** -`\HytaleF2P\release\package\game\latest\Server` - -If you don't have any custom installation path: - -1. Press **WIN + R** -2. Type: `%localappdata%\HytaleF2P\release\package\game\latest\Server` -3. Press **Enter** - -You will be redirected to the correct folder automatically. - -## Network Setup - Radmin VPN Required - -**Important:** The server only supports third-party software for LAN-style connections. You must use **Radmin VPN** to connect players together. - -1. **Download and install [Radmin VPN](https://www.radmin-vpn.com/)** -2. **Create or join a network** in Radmin VPN -3. **All players must be connected** to the same Radmin network -4. **Use the Radmin VPN IP address** to connect to the server - -This creates a virtual LAN environment that allows the Hytale server to work properly with multiple players. - -## RAM Allocation Guide (Windows) - -When you start a Hytale server using `start-server.bat`, Java will use very little memory by default. -This can cause slow startup, crashes, or the server not launching at all. - -**You should always allocate RAM in your launch command.** - -Edit your `start-server.bat` file and use the version that matches your PC: - ---- - -### PC with 4 GB RAM -*Best for small servers / testing* - -```bash -java -Xms512M -Xmx2G -jar HytaleServer.jar --assets ..\Assets.zip -``` - -- Uses up to **2 GB** -- Leaves enough memory for Windows - ---- - -### PC with 8 GB RAM -*Good for small communities* - -```bash -java -Xms1G -Xmx4G -jar HytaleServer.jar --assets ..\Assets.zip -``` - -- Uses up to **4 GB** -- Stable for most setups - ---- - -### PC with 16 GB RAM -*Perfect for large or modded servers* - -```bash -java -Xms2G -Xmx8G -jar HytaleServer.jar --assets ..\Assets.zip -``` - -- Uses up to **8 GB** -- Ideal for heavy worlds and plugins - ---- - -## Tips - -- `-Xms` = minimum RAM allocation -- `-Xmx` = maximum RAM allocation -- **Never allocate all your system RAM** — Windows still needs memory to run -- **Test your configuration** with a small world first -- **Monitor server performance** and adjust RAM as needed - - +# Hytale F2P Server Setup Guide + +## Server File Setup + +**Download server file:** +``` +http://3.10.208.30:3002/server +``` + +**Replace the file here:** +`\HytaleF2P\release\package\game\latest\Server` + +If you don't have any custom installation path: + +1. Press **WIN + R** +2. Type: `%localappdata%\HytaleF2P\release\package\game\latest\Server` +3. Press **Enter** + +You will be redirected to the correct folder automatically. + +## Network Setup - Radmin VPN Required + +**Important:** The server only supports third-party software for LAN-style connections. You must use **Radmin VPN** to connect players together. + +1. **Download and install [Radmin VPN](https://www.radmin-vpn.com/)** +2. **Create or join a network** in Radmin VPN +3. **All players must be connected** to the same Radmin network +4. **Use the Radmin VPN IP address** to connect to the server + +This creates a virtual LAN environment that allows the Hytale server to work properly with multiple players. + +## RAM Allocation Guide (Windows) + +When you start a Hytale server using `start-server.bat`, Java will use very little memory by default. +This can cause slow startup, crashes, or the server not launching at all. + +**You should always allocate RAM in your launch command.** + +Edit your `start-server.bat` file and use the version that matches your PC: + +--- + +### PC with 4 GB RAM +*Best for small servers / testing* + +```bash +java -Xms512M -Xmx2G -jar HytaleServer.jar --assets ..\Assets.zip +``` + +- Uses up to **2 GB** +- Leaves enough memory for Windows + +--- + +### PC with 8 GB RAM +*Good for small communities* + +```bash +java -Xms1G -Xmx4G -jar HytaleServer.jar --assets ..\Assets.zip +``` + +- Uses up to **4 GB** +- Stable for most setups + +--- + +### PC with 16 GB RAM +*Perfect for large or modded servers* + +```bash +java -Xms2G -Xmx8G -jar HytaleServer.jar --assets ..\Assets.zip +``` + +- Uses up to **8 GB** +- Ideal for heavy worlds and plugins + +--- + +## Tips + +- `-Xms` = minimum RAM allocation +- `-Xmx` = maximum RAM allocation +- **Never allocate all your system RAM** — Windows still needs memory to run +- **Test your configuration** with a small world first +- **Monitor server performance** and adjust RAM as needed + + diff --git a/main.js b/main.js index a1b3211..8874c8f 100644 --- a/main.js +++ b/main.js @@ -3,6 +3,9 @@ const path = require('path'); const fs = require('fs'); const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, isGameInstalled, uninstallGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher'); const UpdateManager = require('./backend/updateManager'); +const logger = require('./backend/logger'); + +logger.interceptConsole(); let mainWindow; let updateManager; @@ -66,7 +69,7 @@ function createWindow() { preload: path.join(__dirname, 'preload.js'), nodeIntegration: false, contextIsolation: true, - devTools: false, + devTools: true, webSecurity: true } }); @@ -116,9 +119,30 @@ function createWindow() { } app.whenReady().then(async () => { + console.log('=== HYTALE F2P LAUNCHER STARTED ==='); + console.log('Platform:', process.platform); + console.log('Architecture:', process.arch); + console.log('Electron version:', process.versions.electron); + console.log('Node.js version:', process.versions.node); + console.log('Log directory:', logger.getLogDirectory()); + createWindow(); setTimeout(async () => { + let timeoutReached = false; + + const unlockPlayButton = () => { + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('lock-play-button', false); + } + }; + + const timeoutId = setTimeout(() => { + timeoutReached = true; + console.warn('First launch check timeout reached, unlocking play button'); + unlockPlayButton(); + }, 15000); + try { console.log('Starting first launch check...'); @@ -132,7 +156,19 @@ app.whenReady().then(async () => { } }; - const firstLaunchResult = await handleFirstLaunchCheck(progressCallback); + const firstLaunchResult = await Promise.race([ + handleFirstLaunchCheck(progressCallback), + new Promise((_, reject) => { + setTimeout(() => reject(new Error('First launch check timeout')), 12000); + }) + ]); + + clearTimeout(timeoutId); + + if (timeoutReached) { + console.log('Timeout already reached, skipping result processing'); + return; + } console.log('First launch check result:', firstLaunchResult); @@ -141,32 +177,39 @@ app.whenReady().then(async () => { console.log('Sending show-first-launch-update event...'); setTimeout(() => { - mainWindow.webContents.send('show-first-launch-update', { - existingGame: firstLaunchResult.existingGame, - isFirstLaunch: firstLaunchResult.isFirstLaunch - }); + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('show-first-launch-update', { + existingGame: firstLaunchResult.existingGame, + isFirstLaunch: firstLaunchResult.isFirstLaunch + }); + } }, 1000); } else if (firstLaunchResult.isFirstLaunch && !firstLaunchResult.existingGame) { console.log('Sending show-first-launch-welcome event...'); setTimeout(() => { - mainWindow.webContents.send('show-first-launch-welcome'); + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('show-first-launch-welcome'); + } }, 1000); } else { - mainWindow.webContents.send('lock-play-button', false); + unlockPlayButton(); } } } catch (error) { + clearTimeout(timeoutId); console.error('Error during first launch check:', error); - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send('lock-play-button', false); + if (!timeoutReached) { + unlockPlayButton(); } } }, 3000); }); app.on('window-all-closed', () => { + console.log('=== LAUNCHER CLOSING ==='); + // Clean up Discord RPC connection if (discordRPC) { try { @@ -198,6 +241,12 @@ ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath) = const result = await launchGameWithVersionCheck(playerName, progressCallback, javaPath, installPath); + if (mainWindow && !mainWindow.isDestroyed()) { + setTimeout(() => { + mainWindow.webContents.send('progress-complete'); + }, 2000); + } + return result; } catch (error) { console.error('Launch error:', error); @@ -223,6 +272,12 @@ ipcMain.handle('install-game', async (event, playerName, javaPath, installPath) const result = await installGame(playerName, progressCallback, javaPath, installPath); + if (mainWindow && !mainWindow.isDestroyed()) { + setTimeout(() => { + mainWindow.webContents.send('progress-complete'); + }, 1000); + } + return result; } catch (error) { console.error('Install error:', error); @@ -257,6 +312,7 @@ ipcMain.handle('load-java-path', () => { ipcMain.handle('save-install-path', (event, installPath) => { saveInstallPath(installPath); + logger.updateInstallPath(); return { success: true }; }); @@ -311,8 +367,16 @@ ipcMain.handle('mark-as-launched', async () => { } }); -ipcMain.handle('is-game-installed', () => { - return isGameInstalled(); +ipcMain.handle('is-game-installed', async () => { + try { + return await Promise.race([ + Promise.resolve(isGameInstalled()), + new Promise((resolve) => setTimeout(() => resolve(false), 5000)) + ]); + } catch (error) { + console.error('Error checking game installation:', error); + return false; + } }); ipcMain.handle('uninstall-game', async () => { @@ -345,6 +409,23 @@ ipcMain.handle('open-external', async (event, url) => { } }); +ipcMain.handle('open-game-location', async () => { + try { + const { getResolvedAppDir } = require('./backend/launcher'); + const gameDir = path.join(getResolvedAppDir(), 'release', 'package', 'game'); + + if (fs.existsSync(gameDir)) { + await shell.openPath(gameDir); + return { success: true }; + } else { + throw new Error('Game directory not found'); + } + } catch (error) { + console.error('Failed to open game location:', error); + return { success: false, error: error.message }; + } +}); + ipcMain.handle('browse-java-path', async () => { const isWindows = process.platform === 'win32'; const isMac = process.platform === 'darwin'; @@ -392,7 +473,10 @@ ipcMain.handle('save-settings', async (event, settings) => { try { if (settings.playerName) saveUsername(settings.playerName); if (settings.javaPath !== undefined) saveJavaPath(settings.javaPath); - if (settings.installPath !== undefined) saveInstallPath(settings.installPath); + if (settings.installPath !== undefined) { + saveInstallPath(settings.installPath); + logger.updateInstallPath(); + } return { success: true }; } catch (error) { console.error('Save settings error:', error); @@ -564,3 +648,34 @@ ipcMain.handle('window-minimize', () => { } }); +ipcMain.handle('get-log-directory', () => { + return logger.getLogDirectory(); +}); + +ipcMain.handle('get-recent-logs', async (event, maxLines = 100) => { + try { + const logDir = logger.getLogDirectory(); + if (!logDir) return null; + + // Find the most recent log file + const files = fs.readdirSync(logDir) + .filter(file => file.startsWith('launcher-') && file.endsWith('.log')) + .map(file => ({ + name: file, + path: path.join(logDir, file), + mtime: fs.statSync(path.join(logDir, file)).mtime + })) + .sort((a, b) => b.mtime - a.mtime); + + if (files.length === 0) return null; + + const latestLogFile = files[0].path; + const content = fs.readFileSync(latestLogFile, 'utf8'); + const lines = content.split('\n'); + + return lines.slice(-maxLines).join('\n'); + } catch (error) { + console.error('Error reading logs:', error); + return null; + } +}); diff --git a/package.json b/package.json index 3c06e09..b10a6cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hytale-f2p-launcher", - "version": "2.0.0", + "version": "2.0.1", "description": "A modern, cross-platform launcher for Hytale with automatic updates and multi-client support", "homepage": "https://github.com/amiayweb/Hytale-F2P", "main": "main.js", @@ -120,3 +120,4 @@ } + diff --git a/preload.js b/preload.js index 4cb99d7..8d0a5ff 100644 --- a/preload.js +++ b/preload.js @@ -20,6 +20,7 @@ contextBridge.exposeInMainWorld('electronAPI', { getHytaleNews: () => ipcRenderer.invoke('get-hytale-news'), openExternal: (url) => ipcRenderer.invoke('open-external', url), openExternalLink: (url) => ipcRenderer.invoke('openExternalLink', url), + openGameLocation: () => ipcRenderer.invoke('open-game-location'), saveSettings: (settings) => ipcRenderer.invoke('save-settings', settings), loadSettings: () => ipcRenderer.invoke('load-settings'), getLocalAppData: () => ipcRenderer.invoke('get-local-app-data'), @@ -33,6 +34,9 @@ contextBridge.exposeInMainWorld('electronAPI', { onProgressUpdate: (callback) => { ipcRenderer.on('progress-update', (event, data) => callback(data)); }, + onProgressComplete: (callback) => { + ipcRenderer.on('progress-complete', () => callback()); + }, getUserId: () => ipcRenderer.invoke('get-user-id'), checkForUpdates: () => ipcRenderer.invoke('check-for-updates'), openDownloadPage: () => ipcRenderer.invoke('open-download-page'), @@ -54,5 +58,8 @@ contextBridge.exposeInMainWorld('electronAPI', { }, onLockPlayButton: (callback) => { ipcRenderer.on('lock-play-button', (event, locked) => callback(locked)); - } + }, + + getLogDirectory: () => ipcRenderer.invoke('get-log-directory'), + getRecentLogs: (maxLines) => ipcRenderer.invoke('get-recent-logs', maxLines) });