Upload via GUI (39 Dateien)
This commit is contained in:
+56
-13
@@ -21,6 +21,7 @@ const { spawn, spawnSync } = require('child_process');
|
||||
const services = require('./services');
|
||||
const loaders = require('./loaders');
|
||||
const forge = require('./forge');
|
||||
const processwatchdog = require('./processwatchdog');
|
||||
|
||||
const UA = 'AeroMC-Launcher/0.2';
|
||||
const RESOURCES = 'https://resources.download.minecraft.net';
|
||||
@@ -253,20 +254,28 @@ async function prepareAssets(vj, sharedDir, onProgress) {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function pickJava(vj, preferredPath) {
|
||||
const required = (vj.javaVersion && vj.javaVersion.majorVersion) || 8;
|
||||
let preferred = null;
|
||||
if (preferredPath && preferredPath.trim()) {
|
||||
const info = services.probeJava(preferredPath);
|
||||
if (info) return { path: preferredPath, major: info.major, forced: true };
|
||||
if (info) {
|
||||
preferred = { path: preferredPath, major: info.major, forced: true };
|
||||
if (info.major === required) return preferred;
|
||||
}
|
||||
}
|
||||
const required = (vj.javaVersion && vj.javaVersion.majorVersion) || 8;
|
||||
const jvms = services.scanJava();
|
||||
// exakt passende oder nächsthöhere 64-bit-Version
|
||||
// Mod-Loader und Mods unterstützen neuere Java-Versionen nicht automatisch.
|
||||
// Deshalb ausschließlich die von Mojang angegebene Major-Version verwenden.
|
||||
const x64 = jvms.filter((j) => j.arch === 'x64');
|
||||
const exact = x64.find((j) => j.major === required);
|
||||
if (exact) return { path: exact.path, major: exact.major };
|
||||
const higher = x64.filter((j) => j.major >= required).sort((a, b) => a.major - b.major)[0];
|
||||
if (higher) return { path: higher.path, major: higher.major };
|
||||
const any = jvms[0];
|
||||
return any ? { path: any.path, major: any.major, mismatch: required } : null;
|
||||
const fallback = preferred || x64[0] || jvms[0];
|
||||
return fallback ? {
|
||||
path: fallback.path,
|
||||
major: fallback.major,
|
||||
forced: !!fallback.forced,
|
||||
mismatch: required,
|
||||
} : null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -387,6 +396,14 @@ async function prepareAndLaunch(opts, onProgress) {
|
||||
}
|
||||
}
|
||||
if (!java) return { ok: false, message: 'Keine Java-Installation gefunden. Bitte in den Einstellungen Java festlegen.' };
|
||||
if (java.mismatch) {
|
||||
return {
|
||||
ok: false,
|
||||
requiredJava: java.mismatch,
|
||||
message: `Minecraft ${vj.id} benötigt Java ${java.mismatch}, gefunden wurde nur Java ${java.major || 'unbekannt'}. `
|
||||
+ 'Bitte Auto-Java aktivieren oder eine passende Java-Installation auswählen.',
|
||||
};
|
||||
}
|
||||
|
||||
// Mod-Loader
|
||||
let effectiveVj = vj;
|
||||
@@ -503,14 +520,33 @@ async function prepareAndLaunch(opts, onProgress) {
|
||||
spawnArgs = [...w.slice(1), java.path, ...args];
|
||||
}
|
||||
const child = spawn(cmd, spawnArgs, { cwd: opts.gameDir, detached: false });
|
||||
child.stdout.on('data', (d) => emit('log', { line: d.toString() }));
|
||||
child.stderr.on('data', (d) => emit('log', { line: d.toString() }));
|
||||
const shutdownWatchdog = opts.wrapperCommand && opts.wrapperCommand.trim()
|
||||
? null
|
||||
: processwatchdog.createProcessWatchdog({
|
||||
isRunning: () => child.exitCode === null && child.signalCode === null,
|
||||
kill: () => child.kill(),
|
||||
onForce: (graceMs) => emit('log', {
|
||||
line: `[Launcher] Regulärer Client-Shutdown war nach ${graceMs / 1000} Sekunden noch nicht beendet; `
|
||||
+ 'verbliebenen Java-Prozess beendet.\n',
|
||||
}),
|
||||
onError: () => emit('log', {
|
||||
line: '[Launcher] Der nach dem regulären Client-Shutdown verbliebene Java-Prozess konnte nicht beendet werden.\n',
|
||||
}),
|
||||
});
|
||||
child.stdout.on('data', (d) => {
|
||||
emit('log', { line: d.toString() });
|
||||
if (shutdownWatchdog) shutdownWatchdog.feed(d, 'stdout');
|
||||
});
|
||||
child.stderr.on('data', (d) => {
|
||||
emit('log', { line: d.toString() });
|
||||
if (shutdownWatchdog) shutdownWatchdog.feed(d, 'stderr');
|
||||
});
|
||||
// Ende genau einmal melden – 'exit' und 'error' können beide kommen
|
||||
let beendetGemeldet = false;
|
||||
const meldeEnde = (code) => {
|
||||
const meldeEnde = (code, cleanShutdown) => {
|
||||
if (beendetGemeldet) return;
|
||||
beendetGemeldet = true;
|
||||
emit('exit', { code });
|
||||
emit('exit', { code, cleanShutdown: !!cleanShutdown });
|
||||
// Post-Exit-Befehl
|
||||
if (opts.postExitCommand && opts.postExitCommand.trim()) {
|
||||
emit('log', { line: '[Post-Exit] ' + opts.postExitCommand + '\n' });
|
||||
@@ -521,12 +557,19 @@ async function prepareAndLaunch(opts, onProgress) {
|
||||
} catch { /* egal */ }
|
||||
}
|
||||
};
|
||||
child.on('exit', (code) => meldeEnde(code));
|
||||
child.on('exit', (code) => {
|
||||
// vor end() lesen: sawCleanShutdown wird zwar nicht von end()/clear()
|
||||
// zurückgesetzt, aber so bleibt die Reihenfolge unabhängig von internen Details
|
||||
const cleanShutdown = !!(shutdownWatchdog && shutdownWatchdog.sawCleanShutdown);
|
||||
if (shutdownWatchdog) shutdownWatchdog.end();
|
||||
meldeEnde(shutdownWatchdog && shutdownWatchdog.forced ? 0 : code, cleanShutdown);
|
||||
});
|
||||
// ohne diesen Listener würde ein Fehlstart (z. B. falscher Java-Pfad) als
|
||||
// unbehandeltes 'error'-Ereignis den Hauptprozess beenden
|
||||
child.on('error', (err) => {
|
||||
if (shutdownWatchdog) shutdownWatchdog.end();
|
||||
emit('log', { line: '[Fehler] Minecraft konnte nicht gestartet werden: ' + err.message + '\n' });
|
||||
meldeEnde(-1);
|
||||
meldeEnde(-1, false);
|
||||
});
|
||||
|
||||
return { ok: true, pid: child.pid, java };
|
||||
|
||||
Reference in New Issue
Block a user