From 615ee5cadc888db359ba1baf91b966e8e7c5b1fc Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 08:19:13 +0800 Subject: [PATCH 01/17] fix: resolve cross-platform EPERM permissions errors modManager.js: - Switch from hardcoded 'junction' to dynamic symlink type based on OS (fixing Linux EPERM). - Add retry logic for directory removal to handle file locking race conditions. - Improve broken symlink detection during profile sync. gameManager.js: - Implement retry loop (3 attempts) for game directory removal in updateGameFiles to prevent EBUSY/EPERM errors on Windows. paths.js: - Prevent fs.mkdirSync failure in getModsPath by pre-checking for broken symbolic links. --- backend/core/paths.js | 13 ++++++++++-- backend/managers/gameManager.js | 16 ++++++++++++++- backend/managers/modManager.js | 35 +++++++++++++++++++++++++-------- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/backend/core/paths.js b/backend/core/paths.js index 17a7b92..b6aa309 100644 --- a/backend/core/paths.js +++ b/backend/core/paths.js @@ -179,8 +179,17 @@ async function getModsPath(customInstallPath = null) { const profilesPath = path.join(userDataPath, 'Profiles'); if (!fs.existsSync(modsPath)) { - // Ensure the Mods directory exists - fs.mkdirSync(modsPath, { recursive: true }); + // Check for broken symlink to avoid EEXIST/EPERM on mkdir + let isBrokenLink = false; + try { + const stats = fs.lstatSync(modsPath); + if (stats.isSymbolicLink()) isBrokenLink = true; + } catch (e) { /* ignore */ } + + if (!isBrokenLink) { + // Ensure the Mods directory exists + fs.mkdirSync(modsPath, { recursive: true }); + } } if (!fs.existsSync(disabledModsPath)) { fs.mkdirSync(disabledModsPath, { recursive: true }); diff --git a/backend/managers/gameManager.js b/backend/managers/gameManager.js index 2fb8b62..963bbdd 100644 --- a/backend/managers/gameManager.js +++ b/backend/managers/gameManager.js @@ -365,7 +365,21 @@ async function updateGameFiles(newVersion, progressCallback, gameDir = GAME_DIR, if (fs.existsSync(gameDir)) { console.log('Removing old game files...'); - fs.rmSync(gameDir, { recursive: true, force: true }); + let retries = 3; + while (retries > 0) { + try { + fs.rmSync(gameDir, { recursive: true, force: true }); + break; + } catch (err) { + if ((err.code === 'EPERM' || err.code === 'EBUSY') && retries > 0) { + retries--; + console.log(`[UpdateGameFiles] Removal failed with ${err.code}, retrying in 1s... (${retries} retries left)`); + await new Promise(resolve => setTimeout(resolve, 1000)); + } else { + throw err; + } + } + } } fs.renameSync(tempUpdateDir, gameDir); diff --git a/backend/managers/modManager.js b/backend/managers/modManager.js index 7929e8a..631db7f 100644 --- a/backend/managers/modManager.js +++ b/backend/managers/modManager.js @@ -2,6 +2,7 @@ const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const axios = require('axios'); +const { getOS } = require('../utils/platformUtils'); const { getModsPath, getProfilesDir } = require('../core/paths'); const { saveModsToConfig, loadModsFromConfig } = require('../core/config'); const profileManager = require('./profileManager'); @@ -307,11 +308,16 @@ async function syncModsForCurrentProfile() { // 2. Symlink / Migration Logic let needsLink = false; + let globalStats = null; + + try { + globalStats = fs.lstatSync(globalModsPath); + } catch (e) { + // Path doesn't exist + } - if (fs.existsSync(globalModsPath)) { - const stats = fs.lstatSync(globalModsPath); - - if (stats.isSymbolicLink()) { + if (globalStats) { + if (globalStats.isSymbolicLink()) { const linkTarget = fs.readlinkSync(globalModsPath); // Normalize paths for comparison if (path.resolve(linkTarget) !== path.resolve(profileModsPath)) { @@ -319,7 +325,7 @@ async function syncModsForCurrentProfile() { fs.unlinkSync(globalModsPath); needsLink = true; } - } else if (stats.isDirectory()) { + } else if (globalStats.isDirectory()) { // MIGRATION: It's a real directory. Move contents to profile. console.log('[ModManager] Migrating global mods folder to profile folder...'); const files = fs.readdirSync(globalModsPath); @@ -349,7 +355,20 @@ async function syncModsForCurrentProfile() { // Remove the directory so we can link it try { - fs.rmSync(globalModsPath, { recursive: true, force: true }); + let retries = 3; + while (retries > 0) { + try { + fs.rmSync(globalModsPath, { recursive: true, force: true }); + break; + } catch (err) { + if ((err.code === 'EPERM' || err.code === 'EBUSY') && retries > 0) { + retries--; + await new Promise(resolve => setTimeout(resolve, 500)); + } else { + throw err; + } + } + } needsLink = true; } catch (e) { console.error('Failed to remove global mods dir:', e); @@ -364,8 +383,8 @@ async function syncModsForCurrentProfile() { if (needsLink) { console.log(`[ModManager] Creating symlink: ${globalModsPath} -> ${profileModsPath}`); try { - // 'junction' is key for Windows without admin - fs.symlinkSync(profileModsPath, globalModsPath, 'junction'); + const symlinkType = getOS() === 'windows' ? 'junction' : 'dir'; + fs.symlinkSync(profileModsPath, globalModsPath, symlinkType); } catch (err) { // If we can't create the symlink, try creating the directory first console.error('[ModManager] Failed to create symlink. Falling back to direct folder mode.'); From b99b22e8bfd9bcf7388cd0b726b0c899538f7905 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 09:23:15 +0800 Subject: [PATCH 02/17] fix: missing pacman builds --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 04eabb7..d643760 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,6 +35,7 @@ jobs: dist/*.AppImage.blockmap dist/*.deb dist/*.rpm + dist/*.pacman dist/*.pkg.tar.zst dist/latest-linux.yml From 17e15c17f049711bcd3f6d0eb42ceba976003e6a Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 09:34:16 +0800 Subject: [PATCH 03/17] prepare release for 2.1.1 minor fix for EPERM error permission --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b1fcf7..5937ba6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hytale-f2p-launcher", - "version": "2.1.0", + "version": "2.1.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", From 653d4429ed5e58d09fea8bcc3dd27e2c4fefe2d1 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 09:36:03 +0800 Subject: [PATCH 04/17] prepare release 2.1.1 minor fix EPERM permission error --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 12d6ac3..3a3df94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hytale-f2p-launcher", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hytale-f2p-launcher", - "version": "2.1.0", + "version": "2.1.1", "license": "MIT", "dependencies": { "adm-zip": "^0.5.10", From b668bdb45a7a735aaa27d6f919d4cc651cc56799 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 09:48:26 +0800 Subject: [PATCH 05/17] prepare release 2.1.1 --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a7bcb2..1839f1a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@
-

🎮 Hytale F2P Launcher | Cross-Platform Multiplayer 🖥️

+

🎮 Hytale F2P Launcher 🚀

+

💻 Cross-Platform Multiplayer 🖥️

Available for Windows 🪟, macOS 🍎, and Linux 🐧

An unofficial cross-platform launcher for Hytale with automatic updates and multiplayer support (all OS supported)

-![Version](https://img.shields.io/badge/Version-2.1.0-green?style=for-the-badge) +![Version](https://img.shields.io/badge/Version-2.1.1-green?style=for-the-badge) ![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20Linux-orange?style=for-the-badge) ![License](https://img.shields.io/badge/License-Educational-blue?style=for-the-badge) @@ -17,10 +18,10 @@ ### ⚠️ **READ [QUICK START](https://github.com/amiayweb/Hytale-F2P/tree/main?tab=readme-ov-file#-quick-start) before Downloading & Installing the Launcher!** ⚠️ -🛑 **Found a problem? Join the Discord and Select #Open-A-Ticket!: https://discord.gg/gME8rUy3MB** 🛑 +#### 🛑 **Found a problem? Join the Discord and Select #Open-A-Ticket!: https://discord.gg/gME8rUy3MB** 🛑

- If you like the project, feel free to support us via Buy Me a Coffee! + 👍 If you like the project, feel free to support us via Buy Me a Coffee!
Any support is appreciated and helps keep the project going.

From 375b422c732aa635832c93354994f19141836cdf Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 11:33:00 +0800 Subject: [PATCH 06/17] Update README.md Windows Prequisites for ARM64 builds --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1839f1a..ac43863 100644 --- a/README.md +++ b/README.md @@ -161,9 +161,15 @@ ### 🪟 Windows Prequisites -* **Java JDK 25:** Download via [Adoptium](https://adoptium.net/temurin/releases/?version=25) or [Oracle](https://www.oracle.com/java/technologies/downloads/#jdk25-windows) -* **Latest Visual Studio Redist:** Download via [Microsoft Visual C++ Redistributable](https://aka.ms/vc14/vc_redist.x64.exe) or [All-in-One by Techpowerup](https://www.techpowerup.com/download/visual-c-redistributable-runtime-package-all-in-one/) -* **ENABLE MULTIPLAYER:** // TODO MULTIPLAYER GUIDE; FIREWALL GUIDE AND SUCH +* ** +* **Java JDK 25:** + * [Oracle](https://www.oracle.com/java/technologies/downloads/#jdk25-windows), **no** support for Windows ARM64 in both version 25 and 21. + * [Adoptium](https://adoptium.net/temurin/releases/?version=25), has Windows ARM64 support in version 21 only. + * [Microsoft](https://learn.microsoft.com/en-us/java/openjdk/download), has Windows ARM64 support in version 25. + * Download from any vendor if your OS is not Windows with ARM64 architecture. +* **Latest Visual Studio Redist:** + * Download via [Microsoft Visual C++ Redistributable](https://aka.ms/vc14/vc_redist.x64.exe) + * Or [All-in-One by Techpowerup](https://www.techpowerup.com/download/visual-c-redistributable-runtime-package-all-in-one/) ### 🐧 Linux Prequisites From 20faf36b372317da8d58c8888603b626d907266b Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 12:01:46 +0800 Subject: [PATCH 07/17] fix: remove broken symlink after detected --- backend/core/paths.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/core/paths.js b/backend/core/paths.js index b6aa309..147bc46 100644 --- a/backend/core/paths.js +++ b/backend/core/paths.js @@ -187,9 +187,10 @@ async function getModsPath(customInstallPath = null) { } catch (e) { /* ignore */ } if (!isBrokenLink) { - // Ensure the Mods directory exists - fs.mkdirSync(modsPath, { recursive: true }); + fs.unlinkSync(modsPath); // Remove broken symlink } + // Ensure the Mods directory exists + fs.mkdirSync(modsPath, { recursive: true }); } if (!fs.existsSync(disabledModsPath)) { fs.mkdirSync(disabledModsPath, { recursive: true }); From 94d4586b97ae774190e50255a706dbc75278d133 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 12:09:48 +0800 Subject: [PATCH 08/17] fix: add pathexists for paths.js to check symlink --- backend/core/paths.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/core/paths.js b/backend/core/paths.js index 147bc46..bd381b4 100644 --- a/backend/core/paths.js +++ b/backend/core/paths.js @@ -181,16 +181,26 @@ async function getModsPath(customInstallPath = null) { if (!fs.existsSync(modsPath)) { // Check for broken symlink to avoid EEXIST/EPERM on mkdir let isBrokenLink = false; + let pathExists = false; try { - const stats = fs.lstatSync(modsPath); - if (stats.isSymbolicLink()) isBrokenLink = true; - } catch (e) { /* ignore */ } + const stats = fs.lstatSync(modsPath); + pathExists = true; + if (stats.isSymbolicLink()) { + // Check if target exists + try { + fs.statSync(modsPath); + } catch { + isBrokenLink = true; + } + } + } catch (e) { /* path doesn't exist at all */ } if (!isBrokenLink) { fs.unlinkSync(modsPath); // Remove broken symlink } - // Ensure the Mods directory exists - fs.mkdirSync(modsPath, { recursive: true }); + if (!pathExists || isBrokenLink) { + fs.mkdirSync(modsPath, { recursive: true }); + } } if (!fs.existsSync(disabledModsPath)) { fs.mkdirSync(disabledModsPath, { recursive: true }); From eff6fcd520048d352bac70f181dc6b383567b2fc Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 12:24:24 +0800 Subject: [PATCH 09/17] fix: isbrokenlink should be true to remove the symlink --- backend/core/paths.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/core/paths.js b/backend/core/paths.js index bd381b4..78a5289 100644 --- a/backend/core/paths.js +++ b/backend/core/paths.js @@ -195,7 +195,7 @@ async function getModsPath(customInstallPath = null) { } } catch (e) { /* path doesn't exist at all */ } - if (!isBrokenLink) { + if (isBrokenLink) { fs.unlinkSync(modsPath); // Remove broken symlink } if (!pathExists || isBrokenLink) { From aed00cd0673da1f8b414733d4176d00bdf44f31c Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 13:52:18 +0800 Subject: [PATCH 10/17] add arch package .pkg.tar.zst for release --- .github/workflows/release.yml | 48 ++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d643760..1e2845b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,6 +9,51 @@ on: workflow_dispatch: jobs: + build-arch: + runs-on: ubuntu-latest + + container: + image: archlinux:latest + + steps: + - name: Install base packages + run: | + pacman -Syu --noconfirm + pacman -S --noconfirm \ + base-devel \ + git \ + nodejs \ + npm \ + rpm-tools \ + libxcrypt-compat + + - name: Create build user + run: | + useradd -m builder + echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Fix permissions + run: chown -R builder:builder . + + - name: Build Arch Package + run: | + sudo -u builder bash << 'EOF' + set -e + makepkg -s --noconfirm + EOF + - uses: actions/upload-artifact@v4 + with: + name: arch-package + path: | + *.pkg.tar.zst + *.src.tar.zst + .SRCINFO + build-linux: runs-on: ubuntu-latest steps: @@ -36,7 +81,6 @@ jobs: dist/*.deb dist/*.rpm dist/*.pacman - dist/*.pkg.tar.zst dist/latest-linux.yml build-windows: @@ -115,6 +159,8 @@ jobs: # If it's the 'release' branch, use 'v2.0.2-beta.r42' # name: ${{ github.ref_type == 'tag' && github.ref_name || format('v{0}-beta.r{1}', steps.pkg_version.outputs.VERSION, github.run_number) }} files: | + artifacts/arch-package/*.pkg.tar.zst + artifacts/arch-package/*.src.tar.zst artifacts/linux-builds/**/* artifacts/windows-builds/**/* artifacts/macos-builds/**/* From b39877f5612a2bbd8cecda3b107cc79f02d5b456 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 17:46:40 +0800 Subject: [PATCH 11/17] fix: release workflow for build-arch and build-linux * build-arch job now only build arch .pkg.tar.zst package instead of the whole generic linux. * build-linux job now exclude .pacman package since its deprecated and should not be used. --- .github/workflows/release.yml | 154 +++++++++++++++++----------------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e2845b..ee466e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,80 +9,6 @@ on: workflow_dispatch: jobs: - build-arch: - runs-on: ubuntu-latest - - container: - image: archlinux:latest - - steps: - - name: Install base packages - run: | - pacman -Syu --noconfirm - pacman -S --noconfirm \ - base-devel \ - git \ - nodejs \ - npm \ - rpm-tools \ - libxcrypt-compat - - - name: Create build user - run: | - useradd -m builder - echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers - - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Fix permissions - run: chown -R builder:builder . - - - name: Build Arch Package - run: | - sudo -u builder bash << 'EOF' - set -e - makepkg -s --noconfirm - EOF - - uses: actions/upload-artifact@v4 - with: - name: arch-package - path: | - *.pkg.tar.zst - *.src.tar.zst - .SRCINFO - - build-linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install build dependencies - run: | - sudo apt-get update - sudo apt-get install -y libarchive-tools - - - uses: actions/setup-node@v4 - with: - node-version: '22' - cache: 'npm' - - run: npm ci - - - name: Build Linux Packages - run: | - npx electron-builder --linux --x64 --arm64 --publish never - - uses: actions/upload-artifact@v4 - with: - name: linux-builds - path: | - dist/*.AppImage - dist/*.AppImage.blockmap - dist/*.deb - dist/*.rpm - dist/*.pacman - dist/latest-linux.yml - build-windows: runs-on: windows-latest steps: @@ -123,8 +49,82 @@ jobs: dist/*.zip dist/latest-mac.yml + build-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install -y libarchive-tools + + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + - run: npm ci + + - name: Build Linux Packages + run: | + npx electron-builder --linux AppImage deb rpm --x64 --arm64 --publish never + - uses: actions/upload-artifact@v4 + with: + name: linux-builds + path: | + dist/*.AppImage + dist/*.AppImage.blockmap + dist/*.deb + dist/*.rpm + dist/latest-linux.yml + + build-arch: + runs-on: ubuntu-latest + container: + image: archlinux:latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install base packages + run: | + pacman -Syu --noconfirm + pacman -S --noconfirm \ + base-devel \ + git \ + nodejs \ + npm \ + rpm-tools \ + libxcrypt-compat + + - name: Create build user + run: | + useradd -m builder + echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + + - name: Fix Permissions + run: chown -R builder:builder . + + - name: Build Arch Package + run: | + sudo -u builder bash << 'EOF' + set -e + makepkg --printsrcinfo > .SRCINFO + makepkg -s --noconfirm + EOF + + - name: Upload Arch Package + uses: actions/upload-artifact@v4 + with: + name: arch-package + path: | + *.pkg.tar.zst + *.src.tar.zst + .SRCINFO + release: - needs: [build-linux, build-windows, build-macos] + needs: [build-windows, build-macos, build-linux, build-arch] runs-on: ubuntu-latest if: | startsWith(github.ref, 'refs/tags/v') || @@ -154,13 +154,15 @@ jobs: - name: Create Release uses: softprops/action-gh-release@v2 with: + tag_name: ${{ github.ref_name }} # If it's a tag, use the tag. - tag_name: ${{ github.ref_type == 'tag' && github.ref_name || format('v{0}.r{1}', steps.pkg_version.outputs.VERSION, github.run_number) }} + # tag_name: ${{ github.ref_type == 'tag' && github.ref_name || format('v{0}.r{1}', steps.pkg_version.outputs.VERSION, github.run_number) }} # If it's the 'release' branch, use 'v2.0.2-beta.r42' # name: ${{ github.ref_type == 'tag' && github.ref_name || format('v{0}-beta.r{1}', steps.pkg_version.outputs.VERSION, github.run_number) }} files: | artifacts/arch-package/*.pkg.tar.zst artifacts/arch-package/*.src.tar.zst + artifacts/arch-package/.SRCINFO artifacts/linux-builds/**/* artifacts/windows-builds/**/* artifacts/macos-builds/**/* From 131de1dcd7210aa58c31c1940e25528e68aa0981 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 17:56:44 +0800 Subject: [PATCH 12/17] fix: removes pacman build as it replaced by tar.zst and adds build:arch shortcut for pkgbuild --- package.json | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 5937ba6..83a319b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,11 @@ "build:win": "electron-builder --win", "build:linux": "electron-builder --linux", "build:mac": "electron-builder --mac", - "build:all": "electron-builder --win --linux --mac" + "build:all": "electron-builder --win --linux --mac", + "build:arch": "electron-builder --linux dir", + "build:appimage": "electron-builder --linux AppImage --publish never", + "build:deb": "electron-builder --linux deb --publish never", + "build:rpm": "electron-builder --linux rpm --publish never" }, "keywords": [ "hytale", @@ -82,7 +86,7 @@ ] } ], - "icon": "icon.ico" + "icon": "build/icon.ico" }, "linux": { "target": [ @@ -106,13 +110,6 @@ "x64", "arm64" ] - }, - { - "target": "pacman", - "arch": [ - "x64", - "arm64" - ] } ], "icon": "build/icon.png", From 78f76afe0a2e0d6525f373c627768852b41c61ab Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 18:20:37 +0800 Subject: [PATCH 13/17] aur: add proper VCS (-git) PKGBUILD created clean VCS-based PKGBUILD following arch packaging conventions. this explicitly marked as a rolling (-git) build and derives its version dynamically from git tags and commit history via pkgver(). previous hybrid approach has been changed. key changes: - use -git suffix to clearly indicate rolling source builds - set pkgver=0 and compute the actual version via pkgver() - build only a directory layout using electron-builder (--dir) - avoid generating AppImage, deb, rpm, or pacman installers - align build and package steps with Arch packaging guidelines note: this PKGBUILD is intended for development and AUR use only and is not suitable for binary redistribution or release artifacts. --- PKGBUILD | 33 --------------------------------- PKGBUILD-git | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 33 deletions(-) delete mode 100644 PKGBUILD create mode 100644 PKGBUILD-git diff --git a/PKGBUILD b/PKGBUILD deleted file mode 100644 index 12f6707..0000000 --- a/PKGBUILD +++ /dev/null @@ -1,33 +0,0 @@ -# Maintainer: Terromur -pkgname=Hytale-F2P-git -_pkgname=Hytale-F2P -pkgver=2.0.12.r150.gb62ffc1 -pkgrel=1 -pkgdesc="Hytale-F2P - unofficial Hytale Launcher for free to play with multiplayer support" -arch=('x86_64') -url="https://github.com/amiayweb/Hytale-F2P" -license=('custom') -makedepends=('npm' 'git' 'rpm-tools' 'libxcrypt-compat') -source=("git+$url.git" "Hytale-F2P.desktop") -sha256sums=('SKIP' '46488fada4775d9976d7b7b62f8d1f1f8d9a9a9d8f8aa9af4f2e2153019f6a30') - -pkgver() { - cd "$_pkgname" - version=$(git describe --abbrev=0 --tags --match "v[0-9]*") - commits=$(git rev-list --count HEAD) - hash=$(git rev-parse --short HEAD) - printf "%s.r%s.g%s" "${version#v}" "$commits" "$hash" -} - -build() { - cd "$_pkgname" - npm ci - npm run build:linux -} - -package() { - mkdir -p "$pkgdir/opt/$_pkgname" - cp -r "$_pkgname/dist/linux-unpacked/"* "$pkgdir/opt/$_pkgname" - install -Dm644 "$_pkgname.desktop" "$pkgdir/usr/share/applications/$_pkgname.desktop" - install -Dm644 "$_pkgname/GUI/icon.png" "$pkgdir/usr/share/icons/hicolor/256x256/apps/$_pkgname.png" -} diff --git a/PKGBUILD-git b/PKGBUILD-git new file mode 100644 index 0000000..26da67a --- /dev/null +++ b/PKGBUILD-git @@ -0,0 +1,33 @@ +# Maintainer: Terromur +pkgname=Hytale-F2P-git +_pkgname=Hytale-F2P +pkgver=0 +pkgrel=1 +pkgdesc="Hytale-F2P - Unofficial Hytale Launcher for free to play with multiplayer support (rolling git build)" +arch=('x86_64') +url="https://github.com/amiayweb/Hytale-F2P" +license=('custom') +depends=('gtk3' 'nss' 'libxcrypt-compat') +makedepends=('git' 'npm') +source=("git+$url.git" "$_pkgname.desktop") +sha256sums=('SKIP' '46488fada4775d9976d7b7b62f8d1f1f8d9a9a9d8f8aa9af4f2e2153019f6a30') + +pkgver() { + cd "$srcdir/$_pkgname" + git describe --tags --long | sed 's/^v//;s/-/.r/;s/-/./' +} + +build() { + cd "$srcdir/$_pkgname" + npm ci + npm run build:arch +} + +package() { + cd "$srcdir/$_pkgname" + install -d "$pkgdir/opt/$_pkgname" + cp -r "$_pkgname/dist/linux-unpacked/"* "$pkgdir/opt/$_pkgname" + + install -Dm644 "$srcdir/$_pkgname.desktop" "$pkgdir/usr/share/applications/$_pkgname.desktop" + install -Dm644 GUI/icon.png "$pkgdir/usr/share/icons/hicolor/256x256/apps/$_pkgname.png" +} From e4266906328574660ed65d9aa9b3e0330fc92ede Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 18:33:07 +0800 Subject: [PATCH 14/17] ci: add fixed-version PKGBUILD for Arch Linux releases this PKGBUILD intended for CI and GitHub release artifacts. targets tagged releases only and uses a fixed pkgver that matches the corresponding git tag. all of the VCS logic has been removed to PKGBUILD-git to ensure reproducible builds and stable versioning suitable for binary distribution. the build process relies on electron-builder directory output (--dir) and packages only the unpacked application into a standard Arch Linux package (.pkg.tar.zst). other distro format are excluded from this path and handled separately. this change establishes a clear separation between: - rolling AUR development builds (-git) - CI-generated, versioned Arch Linux release packages the result is predictable artifact naming, correct version alignment, and Arch-compliant packaging for downstream users. --- PKGBUILD | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 PKGBUILD diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..5eea283 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,27 @@ +# Maintainer: Fazri Gading +# This PKGBUILD is for Github Releases +pkgname=Hytale-F2P +pkgver=2.1.1 +pkgrel=1 +pkgdesc="Hytale-F2P - unofficial Hytale Launcher for free to play with multiplayer support" +arch=('x86_64') +url="https://github.com/amiayweb/Hytale-F2P" +license=('custom') +depends=('gtk3' 'nss' 'libxcrypt-compat') +makedepends=('npm') +source=("$url/archive/v$pkgver.tar.gz" "Hytale-F2P.desktop") +sha256sums=('SKIP' '46488fada4775d9976d7b7b62f8d1f1f8d9a9a9d8f8aa9af4f2e2153019f6a30') + +build() { + cd "$_pkgname-$pkgver" + npm ci + npm run build:arch +} + +package() { + cd "$_pkgname-$pkgver" + install -d "$pkgdir/opt/$_pkgname" + cp -r dist/linux-unpacked/* "$pkgdir/opt/$_pkgname" + install -Dm644 "$srcdir/$_pkgname.desktop" "$pkgdir/usr/share/applications/$_pkgname.desktop" + install -Dm644 GUI/icon.png "$pkgdir/usr/share/icons/hicolor/256x256/apps/$_pkgname.png" +} From 75a450c9ecd8057442895627ffecbe01bc4765c2 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Mon, 26 Jan 2026 18:54:53 +0800 Subject: [PATCH 15/17] Update README.md adds information for Arch build --- README.md | 58 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ac43863..b172ce6 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ Windows 10/11 (64-bit; X64/ARM64) | Linux (x64/ARM64) | macOS (Apple Silicon only)
- ⚠️ Note: macOS Intel (x86) is not yet supported 1 + ⚠️ Note: macOS Intel (x86) is not yet supported 1 @@ -131,7 +131,7 @@ 🧠 RAM - 8GB (Dedicated) / 12GB (iGPU) + 8GB (dGPU)2 /
12GB (iGPU)3 16 GB 32 GB @@ -156,7 +156,9 @@
-

1 Hytale did not provide game files for macOS Intel, yet.

+

Note 1 Hytale did not provide game files for macOS Intel, yet.

+

Note 2 Using Discrete/Dedicated GPU (dGPU) must have 8 GB RAM minimum.

+

Note 3 Using Integrated GPU (dGPU) must have 12 GB RAM minimum.

@@ -209,24 +211,36 @@ 3. **Permissions & Execution:** * **AppImage:** Make the file executable and run it: ```bash - chmod +x Hytale-F2P-Launcher.AppImage - ./Hytale-F2P-Launcher.AppImage + chmod +x hytale-f2p-launcher.AppImage + ./hytale-f2p-launcher.AppImage ``` - * **Fedora (dnf):** Install the RPM: + * **Ubuntu/Debian-based or Fedora/RHEL-based:** Install the DEB/RPM: ```bash - sudo dnf install ./Hytale-F2P-Launcher.rpm - ``` - * **Debian/Ubuntu (apt):** Install the DEB: - ```bash - sudo apt install ./Hytale-F2P-Launcher.deb + # Fedora/RHEL-based + sudo dnf install ./hytale-f2p-launcher.rpm + # Debian/Ubuntu + sudo apt install ./hytale-f2p-launcher.deb ``` * **Arch Linux (pacman):** Install the package using: ```bash - sudo pacman -U /path/to/Hytale-F2P-Launcher.pkg.tar.zst + # Stable Build + sudo pacman -U hytale-f2p-launcher.pkg.tar.zst + # Development Build + yay -S hytale-f2p-git # or + paru -S hytale-f2p-git + # Manual Build + git clone https://aur.archlinux.org/hytale-f2p-git.git + cd hytale-f2p-git + makepkg -si ``` + +> [!NOTE] +> Make sure to adjust the filename correctly with the version and the architecture type. + 4. **Troubleshooting:** * **FUSE:** If the AppImage fails to launch on newer distributions, ensure `libfuse2` (or `fuse2` on Arch/Fedora) is installed. * **Desktop Entry:** After installing via `.rpm`, `.deb`, or `.pkg.tar.zst`, the launcher should automatically appear in your App Library/Grid. + * Missing libxcrypt.so.1: Install `libxcrypt-compat` using your package manager --- @@ -292,20 +306,20 @@ See [BUILD.md](BUILD.md) for comprehensive build instructions. ## 📋 Changelog -### 🆕 v2.1.0 - -- 🚨 **Auto-Retry Downloads and Auto-Patch Files** — -- ⚡ **Hardware Acceleration** — -- 👨‍💻 **In-App Logging** — -- 🛠️ **Repair Button** — Y -- 🔎 **Browse CurseForge Mods** — Browsing mods now easier with our dedicated CurseForge API Key. -- 🌎 **Fixes and Release New Translation** — Fixed 🇪🇸 🇧🇷 and added more translation for current build. Turkish 🇹🇷 language now added. - - +### 🆕 v2.1.1 +- 🛠️ **Fix EPERM** Issue +- 🅰️ **Adds Better Arch Build** +-
Click here to see older Changelogs +### 🆕 v2.1.0 +- 🚨 **Auto-Retry Downloads and Auto-Patch Files** — +- ⚡ **Hardware Acceleration** — +- 🔎 **Browse CurseForge Mods** — Browsing mods now easier with our dedicated CurseForge API Key. +- 🌎 **Fixes and Release New Translation** — Fixed 🇪🇸 🇧🇷 and added more translation for current build. Turkish 🇹🇷 language now added. + ### 🆕 v2.0.2b *(Minor Update: Performance & Utilities)* - 🌎 **Language Translation** — A big welcome for Spanish 🇪🇸 and Portuguese (Brazil) 🇧🇷 players! **Language setting can be found in the bottom part of Settings pane.** - 💻 **Laptop/Hybrid GPU Performance Issue Fix** — Added automatic GPU detection system and options to choose which GPU will be used for the game, *specifically for Linux users*. From cc1c6c334c5ce0f01200a75b6483ce728c000303 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Tue, 27 Jan 2026 00:14:53 +0800 Subject: [PATCH 16/17] Update PKGBUILD --- PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/PKGBUILD b/PKGBUILD index 5eea283..1bcb516 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,3 +1,4 @@ +# Maintainer: Terromur # Maintainer: Fazri Gading # This PKGBUILD is for Github Releases pkgname=Hytale-F2P From 782845463128bfb7c76b3e0b11523a6bb3f3ff04 Mon Sep 17 00:00:00 2001 From: Fazri Gading Date: Tue, 27 Jan 2026 00:15:25 +0800 Subject: [PATCH 17/17] Update PKGBUILD-git --- PKGBUILD-git | 1 + 1 file changed, 1 insertion(+) diff --git a/PKGBUILD-git b/PKGBUILD-git index 26da67a..d3e690d 100644 --- a/PKGBUILD-git +++ b/PKGBUILD-git @@ -1,4 +1,5 @@ # Maintainer: Terromur +# Maintainer: Fazri Gading pkgname=Hytale-F2P-git _pkgname=Hytale-F2P pkgver=0