mirror of
https://git.sanhost.net/sanasol/hytale-f2p.git
synced 2026-02-26 06:41:47 -03:00
v2.4.1: Replace raw wrapper script editor with structured config UI
Replace the raw textarea script editor with a structured form for Java wrapper configuration. Users now manage two lists (JVM flags to strip, args to inject with server/always condition) instead of editing bash/batch scripts directly. Scripts are generated at launch time from the structured config. Includes collapsible script preview for power users.
This commit is contained in:
@@ -858,6 +858,212 @@ function checkLaunchReady() {
|
||||
};
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// JAVA WRAPPER CONFIGURATION (Structured)
|
||||
// =============================================================================
|
||||
|
||||
const DEFAULT_WRAPPER_CONFIG = {
|
||||
stripFlags: ['-XX:+UseCompactObjectHeaders'],
|
||||
injectArgs: [
|
||||
{ arg: '--disable-sentry', condition: 'server' }
|
||||
]
|
||||
};
|
||||
|
||||
function getDefaultWrapperConfig() {
|
||||
return JSON.parse(JSON.stringify(DEFAULT_WRAPPER_CONFIG));
|
||||
}
|
||||
|
||||
function loadWrapperConfig() {
|
||||
const config = loadConfig();
|
||||
if (config.javaWrapperConfig && typeof config.javaWrapperConfig === 'object') {
|
||||
const wc = config.javaWrapperConfig;
|
||||
if (Array.isArray(wc.stripFlags) && Array.isArray(wc.injectArgs)) {
|
||||
const loaded = JSON.parse(JSON.stringify(wc));
|
||||
// Normalize entries: ensure every injectArg has a valid condition
|
||||
for (const entry of loaded.injectArgs) {
|
||||
if (!['server', 'always'].includes(entry.condition)) {
|
||||
entry.condition = 'always';
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
return getDefaultWrapperConfig();
|
||||
}
|
||||
|
||||
function saveWrapperConfig(wrapperConfig) {
|
||||
if (!wrapperConfig || typeof wrapperConfig !== 'object') {
|
||||
throw new Error('Invalid wrapper config');
|
||||
}
|
||||
if (!Array.isArray(wrapperConfig.stripFlags) || !Array.isArray(wrapperConfig.injectArgs)) {
|
||||
throw new Error('Invalid wrapper config structure');
|
||||
}
|
||||
// Validate injectArgs entries
|
||||
for (const entry of wrapperConfig.injectArgs) {
|
||||
if (!entry.arg || typeof entry.arg !== 'string') {
|
||||
throw new Error('Each inject arg must have a string "arg" property');
|
||||
}
|
||||
if (!['server', 'always'].includes(entry.condition)) {
|
||||
throw new Error('Inject arg condition must be "server" or "always"');
|
||||
}
|
||||
}
|
||||
saveConfig({ javaWrapperConfig: wrapperConfig });
|
||||
console.log('[Config] Wrapper config saved');
|
||||
}
|
||||
|
||||
function resetWrapperConfig() {
|
||||
const config = loadConfig();
|
||||
delete config.javaWrapperConfig;
|
||||
delete config.javaWrapperScripts; // Clean up legacy key if present
|
||||
|
||||
// Write the cleaned config using the same atomic pattern as saveConfig.
|
||||
// We cannot use saveConfig() here because it merges (spread) which cannot remove keys.
|
||||
const data = JSON.stringify(config, null, 2);
|
||||
fs.writeFileSync(CONFIG_TEMP, data, 'utf8');
|
||||
if (fs.existsSync(CONFIG_FILE)) {
|
||||
fs.copyFileSync(CONFIG_FILE, CONFIG_BACKUP);
|
||||
}
|
||||
fs.renameSync(CONFIG_TEMP, CONFIG_FILE);
|
||||
console.log('[Config] Wrapper config reset to default');
|
||||
return getDefaultWrapperConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a platform-specific wrapper script from structured config
|
||||
* @param {Object} config - { stripFlags: string[], injectArgs: {arg, condition}[] }
|
||||
* @param {string} platform - 'darwin', 'win32', or 'linux'
|
||||
* @param {string|null} javaBin - Path to real java binary (required for darwin/linux)
|
||||
* @returns {string} Generated script content
|
||||
*/
|
||||
function generateWrapperScript(config, platform, javaBin) {
|
||||
const { stripFlags, injectArgs } = config;
|
||||
const alwaysArgs = injectArgs.filter(a => a.condition === 'always');
|
||||
const serverArgs = injectArgs.filter(a => a.condition === 'server');
|
||||
|
||||
if (platform === 'win32') {
|
||||
return _generateWindowsWrapper(stripFlags, alwaysArgs, serverArgs);
|
||||
} else {
|
||||
return _generateUnixWrapper(stripFlags, alwaysArgs, serverArgs, javaBin);
|
||||
}
|
||||
}
|
||||
|
||||
function _generateUnixWrapper(stripFlags, alwaysArgs, serverArgs, javaBin) {
|
||||
const lines = [
|
||||
'#!/bin/bash',
|
||||
'# Java wrapper - generated by HytaleF2P launcher',
|
||||
`REAL_JAVA="${javaBin || '${JAVA_BIN}'}"`,
|
||||
'ARGS=("$@")',
|
||||
''
|
||||
];
|
||||
|
||||
// Strip flags
|
||||
if (stripFlags.length > 0) {
|
||||
lines.push('# Strip JVM flags');
|
||||
lines.push('FILTERED_ARGS=()');
|
||||
lines.push('for arg in "${ARGS[@]}"; do');
|
||||
lines.push(' case "$arg" in');
|
||||
for (const flag of stripFlags) {
|
||||
lines.push(` "${flag}") echo "[Wrapper] Stripped: $arg" ;;`);
|
||||
}
|
||||
lines.push(' *) FILTERED_ARGS+=("$arg") ;;');
|
||||
lines.push(' esac');
|
||||
lines.push('done');
|
||||
} else {
|
||||
lines.push('FILTERED_ARGS=("${ARGS[@]}")');
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// Always-inject args
|
||||
if (alwaysArgs.length > 0) {
|
||||
lines.push('# Inject args (always)');
|
||||
for (const a of alwaysArgs) {
|
||||
lines.push(`FILTERED_ARGS+=("${a.arg}")`);
|
||||
lines.push(`echo "[Wrapper] Injected ${a.arg}"`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
// Server-conditional args (appended after HytaleServer.jar if present)
|
||||
if (serverArgs.length > 0) {
|
||||
lines.push('# Inject args (server only)');
|
||||
lines.push('IS_SERVER=false');
|
||||
lines.push('for arg in "${FILTERED_ARGS[@]}"; do');
|
||||
lines.push(' if [[ "$arg" == *"HytaleServer.jar"* ]]; then');
|
||||
lines.push(' IS_SERVER=true');
|
||||
lines.push(' break');
|
||||
lines.push(' fi');
|
||||
lines.push('done');
|
||||
lines.push('if [ "$IS_SERVER" = true ]; then');
|
||||
for (const a of serverArgs) {
|
||||
lines.push(` FILTERED_ARGS+=("${a.arg}")`);
|
||||
lines.push(` echo "[Wrapper] Injected ${a.arg}"`);
|
||||
}
|
||||
lines.push('fi');
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
lines.push('echo "[Wrapper] Executing: $REAL_JAVA ${FILTERED_ARGS[*]}"');
|
||||
lines.push('exec "$REAL_JAVA" "${FILTERED_ARGS[@]}"');
|
||||
lines.push('');
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function _generateWindowsWrapper(stripFlags, alwaysArgs, serverArgs) {
|
||||
const lines = [
|
||||
'@echo off',
|
||||
'setlocal EnableDelayedExpansion',
|
||||
'',
|
||||
'REM Java wrapper - generated by HytaleF2P launcher',
|
||||
'set "REAL_JAVA=%~dp0java-original.exe"',
|
||||
'set "ARGS=%*"',
|
||||
''
|
||||
];
|
||||
|
||||
// Strip flags using string replacement
|
||||
if (stripFlags.length > 0) {
|
||||
lines.push('REM Strip JVM flags');
|
||||
for (const flag of stripFlags) {
|
||||
lines.push(`set "ARGS=!ARGS:${flag}=!"`);
|
||||
}
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
// Always-inject args
|
||||
const alwaysExtra = alwaysArgs.map(a => a.arg).join(' ');
|
||||
|
||||
// Server-conditional args
|
||||
if (serverArgs.length > 0) {
|
||||
const serverExtra = serverArgs.map(a => a.arg).join(' ');
|
||||
lines.push('REM Check if running HytaleServer.jar and inject server args');
|
||||
lines.push('echo !ARGS! | findstr /i "HytaleServer.jar" >nul 2>&1');
|
||||
lines.push('if "!ERRORLEVEL!"=="0" (');
|
||||
if (alwaysExtra) {
|
||||
lines.push(` echo [Wrapper] Injected ${alwaysExtra} ${serverExtra}`);
|
||||
lines.push(` "%REAL_JAVA%" !ARGS! ${alwaysExtra} ${serverExtra}`);
|
||||
} else {
|
||||
lines.push(` echo [Wrapper] Injected ${serverExtra}`);
|
||||
lines.push(` "%REAL_JAVA%" !ARGS! ${serverExtra}`);
|
||||
}
|
||||
lines.push(') else (');
|
||||
if (alwaysExtra) {
|
||||
lines.push(` "%REAL_JAVA%" !ARGS! ${alwaysExtra}`);
|
||||
} else {
|
||||
lines.push(' "%REAL_JAVA%" !ARGS!');
|
||||
}
|
||||
lines.push(')');
|
||||
} else if (alwaysExtra) {
|
||||
lines.push(`"%REAL_JAVA%" !ARGS! ${alwaysExtra}`);
|
||||
} else {
|
||||
lines.push('"%REAL_JAVA%" !ARGS!');
|
||||
}
|
||||
|
||||
lines.push('exit /b !ERRORLEVEL!');
|
||||
lines.push('');
|
||||
|
||||
return lines.join('\r\n');
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EXPORTS
|
||||
// =============================================================================
|
||||
@@ -924,6 +1130,13 @@ module.exports = {
|
||||
saveVersionBranch,
|
||||
loadVersionBranch,
|
||||
|
||||
// Java Wrapper Config
|
||||
getDefaultWrapperConfig,
|
||||
loadWrapperConfig,
|
||||
saveWrapperConfig,
|
||||
resetWrapperConfig,
|
||||
generateWrapperScript,
|
||||
|
||||
// Constants
|
||||
CONFIG_FILE,
|
||||
UUID_STORE_FILE
|
||||
|
||||
Reference in New Issue
Block a user