diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
index 5a490cf..45067b2 100644
--- a/.github/CODE_OF_CONDUCT.md
+++ b/.github/CODE_OF_CONDUCT.md
@@ -36,7 +36,7 @@ This Code of Conduct applies within all community spaces, and also applies when
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [Discord Server, message Founders/Devs](https://discord.gg/hf2pdc). All complaints will be reviewed and investigated promptly and fairly.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [Discord Server, message Founders/Devs](https://discord.gg/Fhbb9Yk5WW). All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
diff --git a/.github/ISSUE_TEMPLATE/support_request.yml b/.github/ISSUE_TEMPLATE/support_request.yml
index f7198f5..2b17e95 100644
--- a/.github/ISSUE_TEMPLATE/support_request.yml
+++ b/.github/ISSUE_TEMPLATE/support_request.yml
@@ -22,7 +22,7 @@ body:
value: |
If you need help or support with using the launcher, please fill out this support request.
Provide as much detail as possible so we can assist you effectively.
- **Need a quick assistance?** Please Open-A-Ticket in our [Discord Server](https://discord.gg/gME8rUy3MB)!
+ **Need a quick assistance?** Please Open-A-Ticket in our [Discord Server](https://discord.gg/Fhbb9Yk5WW)!
- type: textarea
id: question
diff --git a/GUI/js/script.js b/GUI/js/script.js
index cd4f8f8..a6bd492 100644
--- a/GUI/js/script.js
+++ b/GUI/js/script.js
@@ -53,7 +53,7 @@ window.closeDiscordPopup = function() {
};
window.joinDiscord = async function() {
- await window.electronAPI?.openExternal('https://discord.gg/hf2pdc');
+ await window.electronAPI?.openExternal('https://discord.gg/Fhbb9Yk5WW');
try {
await window.electronAPI?.saveConfig({ discordPopup: true });
diff --git a/GUI/js/ui.js b/GUI/js/ui.js
index 41fa239..f823b2f 100644
--- a/GUI/js/ui.js
+++ b/GUI/js/ui.js
@@ -1103,7 +1103,7 @@ function getRetryContextMessage() {
}
window.openDiscordExternal = function() {
- window.electronAPI?.openExternal('https://discord.gg/hf2pdc');
+ window.electronAPI?.openExternal('https://discord.gg/Fhbb9Yk5WW');
};
window.toggleMaximize = toggleMaximize;
diff --git a/README.md b/README.md
index bd538fd..79b4062 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
### ⚠️ **WARNING: READ [QUICK START](#-quick-start) before Downloading & Installing the Launcher!** ⚠️
-#### 🛑 **Found a problem? [Join the HF2P Discord](https://discord.gg/hf2pdc) and head to `#-⚠️-community-help`** 🛑
+#### 🛑 **Found a problem? [Join the HF2P Discord](https://discord.gg/Fhbb9Yk5WW) and head to `#-⚠️-community-help`** 🛑
👍 If you like the project, feel free to support us via Buy Me a Coffee! ☕
@@ -455,7 +455,7 @@ See [BUILD.md](docs/BUILD.md) for comprehensive build instructions.
**Questions? Ads? Collaboration? Endorsement? Other business-related?**
-Message the founders at https://discord.gg/hf2pdc
+Message the founders at https://discord.gg/Fhbb9Yk5WW
diff --git a/SERVER.md b/SERVER.md
index cbef39a..d8bf851 100644
--- a/SERVER.md
+++ b/SERVER.md
@@ -2,7 +2,7 @@
Play with friends online! This guide covers both easy in-game hosting and advanced dedicated server setup.
-### **DOWNLOAD SERVER FILES (JAR/RAR/SCRIPTS) HERE: https://discord.gg/hf2pdc**
+### **DOWNLOAD SERVER FILES (JAR/RAR/SCRIPTS) HERE: https://discord.gg/Fhbb9Yk5WW**
**Table of Contents**
diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md
index 345ee3e..0a3b5fc 100644
--- a/TROUBLESHOOTING.md
+++ b/TROUBLESHOOTING.md
@@ -1,6 +1,6 @@
# Hytale F2P Launcher - Troubleshooting Guide
-This guide covers common issues and their solutions. If your issue isn't listed here, please check [existing issues](https://github.com/amiayweb/Hytale-F2P/issues) or join our [Discord](https://discord.gg/gME8rUy3MB).
+This guide covers common issues and their solutions. If your issue isn't listed here, please check [existing issues](https://github.com/amiayweb/Hytale-F2P/issues) or join our [Discord](https://discord.gg/Fhbb9Yk5WW).
---
@@ -437,7 +437,7 @@ Game sessions have a 10-hour TTL. This is by design for security.
If your issue isn't resolved by this guide:
1. **Check existing issues:** [GitHub Issues](https://github.com/amiayweb/Hytale-F2P/issues)
-2. **Join Discord:** [discord.gg/gME8rUy3MB](https://discord.gg/gME8rUy3MB)
+2. **Join Discord:** [discord.gg/Fhbb9Yk5WW](https://discord.gg/Fhbb9Yk5WW)
3. **Open a new issue** with:
- Your operating system and version
- Launcher version
diff --git a/backend/managers/gameManager.js b/backend/managers/gameManager.js
index 873a1ca..1790353 100644
--- a/backend/managers/gameManager.js
+++ b/backend/managers/gameManager.js
@@ -64,7 +64,7 @@ async function safeRemoveDirectory(dirPath, maxRetries = 3) {
}
}
-async function downloadPWR(branch = 'release', fileName = 'v8', progressCallback, cacheDir = CACHE_DIR, manualRetry = false, directUrl = null) {
+async function downloadPWR(branch = 'release', fileName = 'v8', progressCallback, cacheDir = CACHE_DIR, manualRetry = false, directUrl = null, expectedSize = null) {
const osName = getOS();
const arch = getArch();
@@ -90,17 +90,47 @@ async function downloadPWR(branch = 'release', fileName = 'v8', progressCallback
console.log(`[DownloadPWR] Fallback URL: ${url}`);
}
}
-
+
+ // Look up expected file size from manifest if not provided
+ if (!expectedSize) {
+ try {
+ const { fetchMirrorManifest } = require('../services/versionManager');
+ const manifest = await fetchMirrorManifest();
+ // Try to match: "0_to_11" format or "v11" format
+ const versionMatch = fileName.match(/^(\d+)_to_(\d+)$/);
+ let manifestKey;
+ if (versionMatch) {
+ manifestKey = `${osName}/${arch}/${branch}/${fileName}.pwr`;
+ } else {
+ const buildNum = extractVersionNumber(fileName);
+ manifestKey = `${osName}/${arch}/${branch}/0_to_${buildNum}.pwr`;
+ }
+ if (manifest.files[manifestKey]) {
+ expectedSize = manifest.files[manifestKey].size;
+ console.log(`[PWR] Expected size from manifest: ${(expectedSize / 1024 / 1024).toFixed(2)} MB`);
+ }
+ } catch (e) {
+ console.log(`[PWR] Could not fetch expected size from manifest: ${e.message}`);
+ }
+ }
+
const dest = path.join(cacheDir, `${branch}_${fileName}.pwr`);
// Check if file exists and validate it
if (fs.existsSync(dest) && !manualRetry) {
const stats = fs.statSync(dest);
if (stats.size > 1024 * 1024) {
- console.log(`[PWR] Using cached file: ${dest} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
- return dest;
+ // Validate against expected size - reject if file is truncated (< 99% of expected)
+ if (expectedSize && stats.size < expectedSize * 0.99) {
+ console.log(`[PWR] Cached file truncated: ${(stats.size / 1024 / 1024).toFixed(2)} MB, expected ${(expectedSize / 1024 / 1024).toFixed(2)} MB. Deleting and re-downloading.`);
+ fs.unlinkSync(dest);
+ } else {
+ console.log(`[PWR] Using cached file: ${dest} (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
+ return dest;
+ }
+ } else {
+ console.log(`[PWR] Cached file too small (${stats.size} bytes), re-downloading`);
}
- console.log(`[PWR] Cached file too small (${stats.size} bytes), re-downloading`);
}
console.log(`[DownloadPWR] Downloading from: ${url}`);
@@ -129,7 +159,7 @@ async function downloadPWR(branch = 'release', fileName = 'v8', progressCallback
const retryStats = fs.statSync(dest);
console.log(`PWR file downloaded (auto-retry), size: ${(retryStats.size / 1024 / 1024).toFixed(2)} MB`);
- if (!validatePWRFile(dest)) {
+ if (!validatePWRFile(dest, expectedSize)) {
console.log(`[PWR Validation] PWR file validation failed after auto-retry, deleting corrupted file: ${dest}`);
fs.unlinkSync(dest);
throw new Error('Downloaded PWR file is corrupted or invalid after automatic retry. Please retry manually');
@@ -179,8 +209,8 @@ async function downloadPWR(branch = 'release', fileName = 'v8', progressCallback
// Enhanced PWR file validation
const stats = fs.statSync(dest);
console.log(`PWR file downloaded, size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
-
- if (!validatePWRFile(dest)) {
+
+ if (!validatePWRFile(dest, expectedSize)) {
console.log(`[PWR Validation] PWR file validation failed, deleting corrupted file: ${dest}`);
fs.unlinkSync(dest);
throw new Error('Downloaded PWR file is corrupted or invalid. Please retry');
@@ -440,7 +470,7 @@ async function updateGameFiles(newVersion, progressCallback, gameDir = GAME_DIR,
progressCallback(`Downloading patch ${i + 1}/${updatePlan.steps.length} (${stepName})...`, progress, null, null, null);
}
- const pwrFile = await downloadPWR(branch, stepName, progressCallback, cacheDir, false, step.url);
+ const pwrFile = await downloadPWR(branch, stepName, progressCallback, cacheDir, false, step.url, step.size);
if (!pwrFile) {
throw new Error(`Failed to download patch ${stepName}`);
@@ -891,7 +921,7 @@ function validateGameDirectory(gameDir, stagingDir) {
// Enhanced PWR file validation
// Accepts intermediate patches (50+ MB) and full installs (1.5+ GB)
-function validatePWRFile(filePath) {
+function validatePWRFile(filePath, expectedSize = null) {
try {
if (!fs.existsSync(filePath)) {
return false;
@@ -906,6 +936,13 @@ function validatePWRFile(filePath) {
return false;
}
+ // Validate against expected size if known (reject if < 99% of expected)
+ if (expectedSize && stats.size < expectedSize * 0.99) {
+ const expectedMB = expectedSize / 1024 / 1024;
+ console.log(`[PWR Validation] File truncated: ${sizeInMB.toFixed(2)} MB, expected ${expectedMB.toFixed(2)} MB`);
+ return false;
+ }
+
console.log(`[PWR Validation] File size: ${sizeInMB.toFixed(2)} MB - OK`);
return true;
} catch (error) {
diff --git a/main.js b/main.js
index 265052f..e15bdc7 100644
--- a/main.js
+++ b/main.js
@@ -89,7 +89,7 @@ function setDiscordActivity() {
},
{
label: 'Discord',
- url: 'https://discord.gg/hf2pdc'
+ url: 'https://discord.gg/Fhbb9Yk5WW'
}
]
});
diff --git a/package.json b/package.json
index 7da50bd..526c83f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "hytale-f2p-launcher",
- "version": "2.3.1",
+ "version": "2.3.2",
"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",