Compare commits

...

8 Commits

Author SHA1 Message Date
sanasol
0b1716c168 v2.4.3: Replace Discord links with Community Chat & Telegram
Discord server was DMCA'd. All Discord links replaced with:
- Community Chat (Stoat): chat.sanhost.net
- Telegram Channel: @hf2p_og
- Telegram Group: @sanhostnet

Launcher UI: added community links on main screen, renamed
Discord nav to Community Chat, updated popup modal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 01:05:49 +01:00
sanasol
9628363455 Update default wrapper config: remove -XX:+UseCompactObjectHeaders strip flag 2026-02-24 19:32:25 +01:00
amiay
4932a7a51c v2.4.2: Update Mods manager 2026-02-24 17:55:28 +01:00
amiay
5170f453ea Merge pull request 'added search bar in "my mods"' (#3) from amiay/hytale-f2p:develop into develop
Reviewed-on: https://git.sanhost.net/sanasol/hytale-f2p/pulls/3
2026-02-24 16:31:54 +00:00
amiay
db3b2fc966 added search bar in my mods
added search bar in my mods
2026-02-24 17:31:13 +01:00
amiay
2f5820e850 Merge pull request 'Mods update' (#2) from amiay/hytale-f2p:develop into develop
Reviewed-on: https://git.sanhost.net/sanasol/hytale-f2p/pulls/2
2026-02-24 16:22:55 +00:00
dsqd2505-netizen
4abb455e0f update "My mods" 2026-02-24 17:15:47 +01:00
dsqd2505-netizen
d5828463f9 Added mods version selector
Added mods version selector
2026-02-24 17:04:46 +01:00
18 changed files with 367 additions and 50 deletions

View File

@@ -36,7 +36,8 @@ This Code of Conduct applies within all community spaces, and also applies when
## Enforcement ## 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/Fhbb9Yk5WW). 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 [Community Chat, message Founders/Devs](https://chat.sanhost.net/invite/Tfz4jCK4).
<!-- Discord: 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. All community leaders are obligated to respect the privacy and security of the reporter of any incident.

View File

@@ -22,7 +22,7 @@ body:
value: | value: |
If you need help or support with using the launcher, please fill out this support request. 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. 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/Fhbb9Yk5WW)! **Need a quick assistance?** Join our [Community Chat](https://chat.sanhost.net/invite/Tfz4jCK4) or [Telegram](https://t.me/hf2p_og)!
- type: textarea - type: textarea
id: question id: question

View File

@@ -57,8 +57,8 @@
<span class="nav-tooltip">Logs</span> <span class="nav-tooltip">Logs</span>
</div> </div>
<div class="nav-item" onclick="openDiscordExternal()"> <div class="nav-item" onclick="openDiscordExternal()">
<i class="fab fa-discord"></i> <i class="fas fa-comments"></i>
<span class="nav-tooltip">Discord</span> <span class="nav-tooltip">Community Chat</span>
</div> </div>
</div> </div>
@@ -199,6 +199,21 @@
<i class="fas fa-play"></i> <i class="fas fa-play"></i>
<span data-i18n="play.playButton">PLAY HYTALE</span> <span data-i18n="play.playButton">PLAY HYTALE</span>
</button> </button>
<div style="display: flex; justify-content: center; align-items: center; gap: 8px; margin-top: 12px; font-size: 12px;">
<span style="color: #93a3b8;">Telegram:</span>
<a href="#" onclick="window.electronAPI?.openExternal('https://t.me/sanhostnet'); return false;" style="color: #93a3b8; text-decoration: none; display: flex; align-items: center; gap: 4px; transition: color 0.2s;" onmouseover="this.style.color='#60a5fa'" onmouseout="this.style.color='#93a3b8'">
<i class="fas fa-users"></i> Group
</a>
<span style="color: #4b5563;">|</span>
<a href="#" onclick="window.electronAPI?.openExternal('https://t.me/hf2p_og'); return false;" style="color: #93a3b8; text-decoration: none; display: flex; align-items: center; gap: 4px; transition: color 0.2s;" onmouseover="this.style.color='#60a5fa'" onmouseout="this.style.color='#93a3b8'">
<i class="fab fa-telegram"></i> Channel
</a>
<span style="color: #4b5563;">|</span>
<a href="#" onclick="openDiscordExternal(); return false;" style="color: #93a3b8; text-decoration: none; display: flex; align-items: center; gap: 4px; transition: color 0.2s;" onmouseover="this.style.color='#60a5fa'" onmouseout="this.style.color='#93a3b8'">
<i class="fas fa-comments"></i> Community Chat
</a>
</div>
</div> </div>
</div> </div>
@@ -663,7 +678,11 @@
<i class="fas fa-times"></i> <i class="fas fa-times"></i>
</button> </button>
</div> </div>
<div class="mods-modal-body"> <div class="mods-modal-body" style="padding-top: 0;">
<div class="mods-search-container" style="margin: 1.5rem; margin-bottom: 1rem;">
<i class="fas fa-search"></i>
<input type="text" id="myModsSearch" placeholder="Search installed mods..." class="mods-search" />
</div>
<div id="installedModsList" class="installed-mods-list"> <div id="installedModsList" class="installed-mods-list">
</div> </div>
</div> </div>
@@ -833,14 +852,14 @@
<div class="modal-content discord-popup-modal"> <div class="modal-content discord-popup-modal">
<div class="modal-header"> <div class="modal-header">
<div class="discord-popup-header"> <div class="discord-popup-header">
<i class="fab fa-discord"></i> <i class="fas fa-comments"></i>
<h2 class="modal-title">Join Our Discord Community</h2> <h2 class="modal-title">Join Our Community</h2>
</div> </div>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="discord-popup-body"> <div class="discord-popup-body">
<p class="discord-popup-text"> <p class="discord-popup-text">
Join our community of over <strong>5000 members</strong> and stay connected! Join our community and stay connected!
</p> </p>
<p class="discord-popup-text"> <p class="discord-popup-text">
Get the latest news, updates, and announcements about the launcher. Get the latest news, updates, and announcements about the launcher.
@@ -848,11 +867,11 @@
<p class="discord-popup-text"> <p class="discord-popup-text">
Find help, report bugs, share your feedback, and connect with other players. Find help, report bugs, share your feedback, and connect with other players.
</p> </p>
<div class="discord-popup-actions"> <div class="discord-popup-actions">
<button class="discord-popup-btn primary" onclick="joinDiscord()"> <button class="discord-popup-btn primary" onclick="joinDiscord()">
<i class="fab fa-discord"></i> <i class="fas fa-comments"></i>
Join Discord Join Community Chat
</button> </button>
<button class="discord-popup-btn secondary" onclick="closeDiscordPopup()"> <button class="discord-popup-btn secondary" onclick="closeDiscordPopup()">
Maybe Later Maybe Later
@@ -867,6 +886,25 @@
<script src="js/featured.js"></script> <script src="js/featured.js"></script>
<script type="module" src="js/settings.js"></script> <script type="module" src="js/settings.js"></script>
<script type="module" src="js/update.js"></script> <script type="module" src="js/update.js"></script>
<!-- Version Selection Modal (Isolated Container) -->
<div id="versionSelectModal" class="modal-overlay" style="display: none; position: fixed; inset: 0; z-index: 9999; background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(5px); align-items: center; justify-content: center;">
<div class="glass-panel" style="width: 100%; max-width: 600px; max-height: 80vh; display: flex; flex-direction: column; border-radius: 12px; overflow: hidden; margin: 20px;">
<div class="modal-header" style="display: flex; justify-content: space-between; align-items: center; padding: 1.5rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1);">
<h3 style="margin: 0; font-size: 1.25rem;">Select Version</h3>
<button id="closeVersionModal" class="modal-close" style="background: none; border: none; color: #a0a0a0; font-size: 1.25rem; cursor: pointer;"><i class="fas fa-times"></i></button>
</div>
<div class="modal-body" style="padding: 1.5rem; overflow-y: auto;">
<div id="versionList" class="version-list-container">
<div class="loading-versions" style="display: flex; flex-direction: column; align-items: center; gap: 1rem; color: #a0a0a0;">
<i class="fas fa-spinner fa-spin fa-2x"></i>
<span>Loading versions...</span>
</div>
</div>
</div>
</div>
</div>
<!-- updater.js disabled - using update.js instead which has skip button and macOS handling --> <!-- updater.js disabled - using update.js instead which has skip button and macOS handling -->
</body> </body>

View File

@@ -49,6 +49,18 @@ function setupModsEventListeners() {
closeModalBtn.addEventListener('click', closeMyModsModal); closeModalBtn.addEventListener('click', closeMyModsModal);
} }
const myModsSearchInput = document.getElementById('myModsSearch');
if (myModsSearchInput) {
let myModsSearchTimeout;
myModsSearchInput.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase().trim();
clearTimeout(myModsSearchTimeout);
myModsSearchTimeout = setTimeout(() => {
filterInstalledMods(query);
}, 300);
});
}
const modal = document.getElementById('myModsModal'); const modal = document.getElementById('myModsModal');
if (modal) { if (modal) {
modal.addEventListener('click', (e) => { modal.addEventListener('click', (e) => {
@@ -78,12 +90,30 @@ function setupModsEventListeners() {
} }
}); });
} }
const browseContainer = document.getElementById('browseModsList');
if (browseContainer) {
browseContainer.addEventListener('click', (e) => {
const installBtn = e.target.closest('[data-install-mod-id]');
if (installBtn) {
const modId = installBtn.getAttribute('data-install-mod-id');
const mod = browseMods.find(m => m.id == modId);
if (mod) {
openVersionSelectModal(mod);
}
}
});
}
} }
function openMyModsModal() { function openMyModsModal() {
const modal = document.getElementById('myModsModal'); const modal = document.getElementById('myModsModal');
if (modal) { if (modal) {
modal.classList.add('active'); modal.classList.add('active');
const searchInput = document.getElementById('myModsSearch');
if (searchInput) {
searchInput.value = '';
}
loadInstalledMods(); loadInstalledMods();
} }
} }
@@ -92,6 +122,10 @@ function closeMyModsModal() {
const modal = document.getElementById('myModsModal'); const modal = document.getElementById('myModsModal');
if (modal) { if (modal) {
modal.classList.remove('active'); modal.classList.remove('active');
const searchInput = document.getElementById('myModsSearch');
if (searchInput) {
searchInput.value = '';
}
} }
} }
@@ -113,19 +147,39 @@ async function loadInstalledMods() {
} }
} }
function filterInstalledMods(query) {
if (!query || query === '') {
displayInstalledMods(installedMods);
return;
}
const filtered = installedMods.filter(mod => {
const nameMatch = mod.name?.toLowerCase().includes(query);
const fileNameMatch = mod.fileName?.toLowerCase().includes(query);
const descriptionMatch = mod.description?.toLowerCase().includes(query);
const authorMatch = mod.author?.toLowerCase().includes(query);
return nameMatch || fileNameMatch || descriptionMatch || authorMatch;
});
displayInstalledMods(filtered);
}
function displayInstalledMods(mods) { function displayInstalledMods(mods) {
const modsContainer = document.getElementById('installedModsList'); const modsContainer = document.getElementById('installedModsList');
if (!modsContainer) return; if (!modsContainer) return;
if (mods.length === 0) { if (mods.length === 0) {
const searchInput = document.getElementById('myModsSearch');
const isSearching = searchInput && searchInput.value.trim() !== '';
modsContainer.innerHTML = ` modsContainer.innerHTML = `
<div class=\"empty-installed-mods\"> <div class=\"empty-installed-mods\">
<i class=\"fas fa-box-open\"></i> <i class=\"fas fa-${isSearching ? 'search' : 'box-open'}\"></i>
<h4 data-i18n="mods.noModsInstalled">No Mods Installed</h4> <h4 data-i18n="${isSearching ? 'mods.noModsFound' : 'mods.noModsInstalled'}">${isSearching ? 'No Mods Found' : 'No Mods Installed'}</h4>
<p data-i18n="mods.noModsInstalledDesc">Add mods from CurseForge or import local files</p> <p data-i18n="${isSearching ? 'mods.noModsFoundDesc' : 'mods.noModsInstalledDesc'}">${isSearching ? 'Try a different search term' : 'Add mods from CurseForge or import local files'}</p>
</div> </div>
`; `;
if (window.i18n) { if (window.i18n && !isSearching) {
const container = modsContainer.querySelector('.empty-installed-mods'); const container = modsContainer.querySelector('.empty-installed-mods');
container.querySelector('h4').textContent = window.i18n.t('mods.noModsInstalled'); container.querySelector('h4').textContent = window.i18n.t('mods.noModsInstalled');
container.querySelector('p').textContent = window.i18n.t('mods.noModsInstalledDesc'); container.querySelector('p').textContent = window.i18n.t('mods.noModsInstalledDesc');
@@ -165,7 +219,7 @@ function createInstalledModCard(mod) {
<div class="installed-mod-info"> <div class="installed-mod-info">
<div class="installed-mod-header"> <div class="installed-mod-header">
<h4 class="installed-mod-name">${mod.name}</h4> <h4 class="installed-mod-name">${mod.name}</h4>
<span class="installed-mod-version">v${mod.version}</span> <span class="installed-mod-version">${mod.fileName || 'v' + mod.version}</span>
</div> </div>
<p class="installed-mod-description">${mod.description || (window.i18n ? window.i18n.t('mods.noDescription') : 'No description available')}</p> <p class="installed-mod-description">${mod.description || (window.i18n ? window.i18n.t('mods.noDescription') : 'No description available')}</p>
</div> </div>
@@ -295,13 +349,6 @@ function displayBrowseMods(mods) {
} }
browseContainer.innerHTML = mods.map(mod => createBrowseModCard(mod)).join(''); browseContainer.innerHTML = mods.map(mod => createBrowseModCard(mod)).join('');
mods.forEach(mod => {
const installBtn = document.getElementById(`install-${mod.id}`);
if (installBtn) {
installBtn.addEventListener('click', () => downloadAndInstallMod(mod));
}
});
} }
function createBrowseModCard(mod) { function createBrowseModCard(mod) {
@@ -350,12 +397,12 @@ function createBrowseModCard(mod) {
${window.i18n ? window.i18n.t('mods.view') : 'VIEW'} ${window.i18n ? window.i18n.t('mods.view') : 'VIEW'}
</button> </button>
${!isInstalled ? ${!isInstalled ?
`<button id="install-${mod.id}" class="mod-btn-toggle bg-primary text-black hover:bg-primary/80"> `<button data-install-mod-id=\"${mod.id}\" class=\"mod-btn-toggle bg-primary text-black hover:bg-primary/80\">
<i class="fas fa-download"></i> <i class=\"fas fa-download\"></i>
${window.i18n ? window.i18n.t('mods.install') : 'INSTALL'} ${window.i18n ? window.i18n.t('mods.install') : 'INSTALL'}
</button>` : </button>` :
`<button class="mod-btn-toggle bg-white/10 text-white" disabled> `<button class=\"mod-btn-toggle bg-white/10 text-white\" disabled>
<i class="fas fa-check"></i> <i class=\"fas fa-check\"></i>
${window.i18n ? window.i18n.t('mods.installed') : 'INSTALLED'} ${window.i18n ? window.i18n.t('mods.installed') : 'INSTALLED'}
</button>` </button>`
} }
@@ -364,6 +411,104 @@ function createBrowseModCard(mod) {
`; `;
} }
let currentSelectedMod = null;
function openVersionSelectModal(mod) {
currentSelectedMod = mod;
const modal = document.getElementById('versionSelectModal');
const closeBtn = document.getElementById('closeVersionModal');
const versionList = document.getElementById('versionList');
if (modal) {
modal.style.display = 'flex';
modal.classList.add('active');
const closeHandler = () => {
modal.classList.remove('active');
setTimeout(() => {
modal.style.display = 'none';
}, 300);
currentSelectedMod = null;
};
if (closeBtn) {
closeBtn.onclick = closeHandler;
}
modal.onclick = (e) => {
if (e.target === modal) closeHandler();
};
loadModVersions(mod.id, versionList);
}
}
async function loadModVersions(modId, container) {
container.innerHTML = `
<div class="loading-versions">
<i class="fas fa-spinner fa-spin fa-2x" style="margin-bottom: 10px; display: block;"></i>
<span>Loading versions...</span>
</div>
`;
try {
const versions = await window.electronAPI.getModFiles(modId);
if (!versions || versions.length === 0) {
container.innerHTML = `<div class="p-4 text-center text-gray-400" style="padding: 2rem;">No versions found for this mod.</div>`;
return;
}
// Sort versions by date desc (API returns desc but ensure)
versions.sort((a, b) => new Date(b.fileDate) - new Date(a.fileDate));
container.innerHTML = versions.map(file => `
<div class="version-item">
<div class="version-info">
<div class="version-name">${file.displayName}</div>
<div class="version-meta">
<span><i class="fas fa-calendar"></i> ${new Date(file.fileDate).toLocaleDateString()}</span>
<span><i class="fas fa-download"></i> ${formatNumber(file.downloadCount)}</span>
<span><i class="fas fa-file-archive"></i> ${(file.fileLength / 1024 / 1024).toFixed(2)} MB</span>
</div>
</div>
<div class="version-actions">
<button class="btn-install" data-file-id="${file.id}">
Install
</button>
</div>
</div>
`).join('');
// Add event listeners securely
container.querySelectorAll('.btn-install').forEach((btn, index) => {
const file = versions[index]; // Map index to file data
btn.onclick = () => installVersion(file);
});
} catch (error) {
console.error('Error loading versions:', error);
container.innerHTML = `<div class="p-4 text-center text-red-400" style="padding: 2rem;">Error loading versions.<br><small>${error.message}</small></div>`;
}
}
async function installVersion(file) {
if (!currentSelectedMod) return;
const modal = document.getElementById('versionSelectModal');
modal.style.display = 'none';
const modInfo = {
...currentSelectedMod,
fileId: file.id,
downloadUrl: file.downloadUrl,
fileName: file.fileName,
fileSize: file.fileLength
};
await downloadAndInstallMod(modInfo);
currentSelectedMod = null;
}
async function downloadAndInstallMod(modInfo) { async function downloadAndInstallMod(modInfo) {
try { try {
const downloadMsg = window.i18n ? window.i18n.t('notifications.modsDownloading').replace('{name}', modInfo.name) : `Downloading ${modInfo.name}...`; const downloadMsg = window.i18n ? window.i18n.t('notifications.modsDownloading').replace('{name}', modInfo.name) : `Downloading ${modInfo.name}...`;
@@ -762,7 +907,10 @@ window.modsManager = {
closeMyModsModal, closeMyModsModal,
viewModPage, viewModPage,
loadInstalledMods, loadInstalledMods,
loadBrowseMods loadBrowseMods,
openVersionSelectModal
}; };
document.addEventListener('DOMContentLoaded', initModsManager); // Remove auto-init since we are now calling it from script.js explicitly
// which guarantees order and environment readiness
// document.addEventListener('DOMContentLoaded', initModsManager);

View File

@@ -2,7 +2,7 @@ import './ui.js';
import './install.js'; import './install.js';
import './launcher.js'; import './launcher.js';
import './news.js'; import './news.js';
import './mods.js'; import { initModsManager } from './mods.js';
import './players.js'; import './players.js';
import './settings.js'; import './settings.js';
import './logs.js'; import './logs.js';
@@ -15,6 +15,12 @@ let i18nInitialized = false;
if (document.readyState === 'complete' || document.readyState === 'interactive') { if (document.readyState === 'complete' || document.readyState === 'interactive') {
updateLanguageSelector(); updateLanguageSelector();
initModsManager();
} else {
document.addEventListener('DOMContentLoaded', () => {
updateLanguageSelector();
initModsManager();
});
} }
})(); })();
@@ -53,7 +59,8 @@ window.closeDiscordPopup = function() {
}; };
window.joinDiscord = async function() { window.joinDiscord = async function() {
await window.electronAPI?.openExternal('https://discord.gg/Fhbb9Yk5WW'); // await window.electronAPI?.openExternal('https://discord.gg/Fhbb9Yk5WW');
await window.electronAPI?.openExternal('https://chat.sanhost.net/invite/Tfz4jCK4');
try { try {
await window.electronAPI?.saveConfig({ discordPopup: true }); await window.electronAPI?.saveConfig({ discordPopup: true });

View File

@@ -1103,7 +1103,8 @@ function getRetryContextMessage() {
} }
window.openDiscordExternal = function() { window.openDiscordExternal = function() {
window.electronAPI?.openExternal('https://discord.gg/Fhbb9Yk5WW'); // window.electronAPI?.openExternal('https://discord.gg/Fhbb9Yk5WW');
window.electronAPI?.openExternal('https://chat.sanhost.net/invite/Tfz4jCK4');
}; };
window.toggleMaximize = toggleMaximize; window.toggleMaximize = toggleMaximize;

View File

@@ -6610,3 +6610,85 @@ input[type="text"].uuid-input,
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
} }
/* Version Selection Styles */
.version-list-container::-webkit-scrollbar {
width: 6px;
}
.version-list-container::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
}
.version-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
margin-bottom: 0.5rem;
transition: all 0.2s ease;
}
.version-item:hover {
background: rgba(255, 255, 255, 0.1);
transform: translateX(4px);
}
.version-info {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.version-name {
font-weight: 600;
color: #fff;
font-size: 0.95rem;
}
.version-meta {
font-size: 0.8rem;
color: #a0a0a0;
display: flex;
gap: 1rem;
align-items: center;
}
.version-meta span {
display: flex;
align-items: center;
gap: 0.35rem;
}
.version-meta i {
font-size: 0.8em;
opacity: 0.7;
}
.version-actions .btn-install {
padding: 0.5rem 1.25rem;
background: linear-gradient(135deg, #3b82f6, #2563eb);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
font-size: 0.85rem;
transition: all 0.2s;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
}
.version-actions .btn-install:hover {
transform: translateY(-1px);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.3);
background: linear-gradient(135deg, #4f93f6, #3b82f6);
}
.loading-versions {
padding: 3rem;
text-align: center;
}

View File

@@ -18,7 +18,8 @@
### ⚠️ **WARNING: READ [QUICK START](#-quick-start) before Downloading & Installing the Launcher!** ⚠️ ### ⚠️ **WARNING: READ [QUICK START](#-quick-start) before Downloading & Installing the Launcher!** ⚠️
#### 🛑 **Found a problem? [Join the HF2P Discord](https://discord.gg/Fhbb9Yk5WW) and head to `#-⚠️-community-help`** 🛑 #### 🛑 **Found a problem? [Join the Community Chat](https://chat.sanhost.net/invite/Tfz4jCK4) | [TG Channel](https://t.me/hf2p_og) | [TG Group](https://t.me/sanhostnet)** 🛑
<!-- #### 🛑 **Found a problem? [Join the HF2P Discord](https://discord.gg/Fhbb9Yk5WW) and head to `#-⚠️-community-help`** 🛑 -->
<p> <p>
👍 If you like the project, <b>feel free to support us via Buy Me a Coffee!</b> ☕<br> 👍 If you like the project, <b>feel free to support us via Buy Me a Coffee!</b> ☕<br>
@@ -455,7 +456,8 @@ See [BUILD.md](docs/BUILD.md) for comprehensive build instructions.
<div align="center"> <div align="center">
**Questions? Ads? Collaboration? Endorsement? Other business-related?** **Questions? Ads? Collaboration? Endorsement? Other business-related?**
Message the founders at https://discord.gg/Fhbb9Yk5WW Message the founders at https://chat.sanhost.net/invite/Tfz4jCK4 | [TG Channel](https://t.me/hf2p_og) | [TG Group](https://t.me/sanhostnet)
<!-- Message the founders at https://discord.gg/Fhbb9Yk5WW -->
</div> </div>

View File

@@ -2,7 +2,8 @@
Play with friends online! This guide covers both easy in-game hosting and advanced dedicated server setup. 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/Fhbb9Yk5WW** ### **DOWNLOAD SERVER FILES (JAR/RAR/SCRIPTS) HERE: https://chat.sanhost.net/invite/Tfz4jCK4**
<!-- ### **DOWNLOAD SERVER FILES (JAR/RAR/SCRIPTS) HERE: https://discord.gg/Fhbb9Yk5WW** -->
**Table of Contents** **Table of Contents**

View File

@@ -1,6 +1,7 @@
# Hytale F2P Launcher - Troubleshooting Guide # 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/Fhbb9Yk5WW). 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 [Community Chat](https://chat.sanhost.net/invite/Tfz4jCK4) | [TG Channel](https://t.me/hf2p_og) | [TG Group](https://t.me/sanhostnet).
<!-- Discord: https://discord.gg/Fhbb9Yk5WW -->
--- ---
@@ -437,7 +438,8 @@ Game sessions have a 10-hour TTL. This is by design for security.
If your issue isn't resolved by this guide: If your issue isn't resolved by this guide:
1. **Check existing issues:** [GitHub Issues](https://github.com/amiayweb/Hytale-F2P/issues) 1. **Check existing issues:** [GitHub Issues](https://github.com/amiayweb/Hytale-F2P/issues)
2. **Join Discord:** [discord.gg/Fhbb9Yk5WW](https://discord.gg/Fhbb9Yk5WW) 2. **Join Community:** [Chat](https://chat.sanhost.net/invite/Tfz4jCK4) | [Telegram](https://t.me/hf2p_og)
<!-- Discord: https://discord.gg/Fhbb9Yk5WW -->
3. **Open a new issue** with: 3. **Open a new issue** with:
- Your operating system and version - Your operating system and version
- Launcher version - Launcher version

View File

@@ -863,7 +863,7 @@ function checkLaunchReady() {
// ============================================================================= // =============================================================================
const DEFAULT_WRAPPER_CONFIG = { const DEFAULT_WRAPPER_CONFIG = {
stripFlags: ['-XX:+UseCompactObjectHeaders'], stripFlags: [],
injectArgs: [ injectArgs: [
{ arg: '--disable-sentry', condition: 'server' } { arg: '--disable-sentry', condition: 'server' }
] ]

View File

@@ -84,7 +84,8 @@ const {
loadInstalledMods, loadInstalledMods,
downloadMod, downloadMod,
uninstallMod, uninstallMod,
toggleMod toggleMod,
getModFiles
} = require('./managers/modManager'); } = require('./managers/modManager');
// Services // Services
@@ -187,6 +188,7 @@ module.exports = {
downloadMod, downloadMod,
uninstallMod, uninstallMod,
toggleMod, toggleMod,
getModFiles,
saveModsToConfig, saveModsToConfig,
loadModsFromConfig, loadModsFromConfig,

View File

@@ -285,6 +285,27 @@ async function toggleMod(modId, modsPath) {
} }
} }
async function getModFiles(modId) {
try {
const response = await axios.get(`https://api.curseforge.com/v1/mods/${modId}/files`, {
headers: {
'x-api-key': API_KEY,
'Accept': 'application/json'
},
params: {
pageSize: 20,
sortOrder: 'desc'
}
});
return response.data.data;
} catch (error) {
console.error('Error fetching mod files:', error);
return [];
}
}
async function syncModsForCurrentProfile() { async function syncModsForCurrentProfile() {
try { try {
const activeProfile = profileManager.getActiveProfile(); const activeProfile = profileManager.getActiveProfile();
@@ -455,5 +476,6 @@ module.exports = {
syncModsForCurrentProfile, syncModsForCurrentProfile,
generateModId, generateModId,
extractModName, extractModName,
extractVersion extractVersion,
}; getModFiles
};

16
main.js
View File

@@ -88,8 +88,9 @@ function setDiscordActivity() {
url: 'https://git.sanhost.net/sanasol/hytale-f2p/releases' url: 'https://git.sanhost.net/sanasol/hytale-f2p/releases'
}, },
{ {
label: 'Discord', label: 'Community',
url: 'https://discord.gg/Fhbb9Yk5WW' // url: 'https://discord.gg/Fhbb9Yk5WW'
url: 'https://chat.sanhost.net/invite/Tfz4jCK4'
} }
] ]
}); });
@@ -1068,7 +1069,7 @@ ipcMain.handle('load-settings', async () => {
} }
}); });
const { getModsPath, loadInstalledMods, downloadMod, uninstallMod, toggleMod, getCurrentUuid, getAllUuidMappings, setUuidForUser, generateNewUuid, deleteUuidForUser, resetCurrentUserUuid } = require('./backend/launcher'); const { getModsPath, loadInstalledMods, downloadMod, uninstallMod, toggleMod, getModFiles, getCurrentUuid, getAllUuidMappings, setUuidForUser, generateNewUuid, deleteUuidForUser, resetCurrentUserUuid } = require('./backend/launcher');
const os = require('os'); const os = require('os');
ipcMain.handle('get-local-app-data', async () => { ipcMain.handle('get-local-app-data', async () => {
@@ -1118,6 +1119,15 @@ ipcMain.handle('download-mod', async (event, modInfo) => {
} }
}); });
ipcMain.handle('get-mod-files', async (event, modId) => {
try {
return await getModFiles(modId);
} catch (error) {
console.error('Error getting mod files:', error);
return { success: false, error: error.message };
}
});
ipcMain.handle('uninstall-mod', async (event, modId, modsPath) => { ipcMain.handle('uninstall-mod', async (event, modId, modsPath) => {
try { try {
return await uninstallMod(modId, modsPath); return await uninstallMod(modId, modsPath);

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "hytale-f2p-launcher", "name": "hytale-f2p-launcher",
"version": "2.2.0", "version": "2.4.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "hytale-f2p-launcher", "name": "hytale-f2p-launcher",
"version": "2.2.0", "version": "2.4.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"adm-zip": "^0.5.10", "adm-zip": "^0.5.10",

View File

@@ -1,6 +1,6 @@
{ {
"name": "hytale-f2p-launcher", "name": "hytale-f2p-launcher",
"version": "2.4.1", "version": "2.4.3",
"description": "A modern, cross-platform launcher for Hytale with automatic updates and multi-client support", "description": "A modern, cross-platform launcher for Hytale with automatic updates and multi-client support",
"homepage": "https://git.sanhost.net/sanasol/hytale-f2p", "homepage": "https://git.sanhost.net/sanasol/hytale-f2p",
"main": "main.js", "main": "main.js",
@@ -26,7 +26,6 @@
"electron", "electron",
"auto-update", "auto-update",
"mod-manager" "mod-manager"
], ],
"maintainers": [ "maintainers": [
{ {

View File

@@ -45,6 +45,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
loadInstalledMods: (modsPath) => ipcRenderer.invoke('load-installed-mods', modsPath), loadInstalledMods: (modsPath) => ipcRenderer.invoke('load-installed-mods', modsPath),
downloadMod: (modInfo) => ipcRenderer.invoke('download-mod', modInfo), downloadMod: (modInfo) => ipcRenderer.invoke('download-mod', modInfo),
uninstallMod: (modId, modsPath) => ipcRenderer.invoke('uninstall-mod', modId, modsPath), uninstallMod: (modId, modsPath) => ipcRenderer.invoke('uninstall-mod', modId, modsPath),
getModFiles: (modId) => ipcRenderer.invoke('get-mod-files', modId),
toggleMod: (modId, modsPath) => ipcRenderer.invoke('toggle-mod', modId, modsPath), toggleMod: (modId, modsPath) => ipcRenderer.invoke('toggle-mod', modId, modsPath),
selectModFiles: () => ipcRenderer.invoke('select-mod-files'), selectModFiles: () => ipcRenderer.invoke('select-mod-files'),
copyModFile: (sourcePath, modsPath) => ipcRenderer.invoke('copy-mod-file', sourcePath, modsPath), copyModFile: (sourcePath, modsPath) => ipcRenderer.invoke('copy-mod-file', sourcePath, modsPath),

View File

@@ -128,6 +128,7 @@ your-folder/
| Out of memory | Set more RAM: `JVM_XMX=4G ./start.sh` | | Out of memory | Set more RAM: `JVM_XMX=4G ./start.sh` |
| Friends can't connect | Forward port 5520 (TCP+UDP) on your router, or use [playit.gg](https://playit.gg) if you can't port forward | | Friends can't connect | Forward port 5520 (TCP+UDP) on your router, or use [playit.gg](https://playit.gg) if you can't port forward |
## Discord ## Community
Need help? Join the community: https://discord.gg/Fhbb9Yk5WW Need help? Join the community: https://chat.sanhost.net/invite/Tfz4jCK4 | TG Channel: https://t.me/hf2p_og | TG Group: https://t.me/sanhostnet
<!-- Discord: https://discord.gg/Fhbb9Yk5WW -->