104 lines
4.2 KiB
JavaScript
104 lines
4.2 KiB
JavaScript
'use strict';
|
||
|
||
/*
|
||
* loaders.js – Mod-Loader-Profile auflösen
|
||
* ----------------------------------------
|
||
* Fabric & Quilt liefern über ihre Meta-API ein fertiges Profil-JSON
|
||
* (mainClass, zusätzliche Libraries als Maven-Koordinaten, Argumente,
|
||
* inheritsFrom = Vanilla-Version). Das mergen wir beim Start mit der Vanilla-Version.
|
||
*
|
||
* Forge & NeoForge liefern KEIN einfaches Profil, sondern einen Installer,
|
||
* der Prozessoren ausführt und den Client patcht -> deutlich aufwändiger,
|
||
* daher hier noch als „in Arbeit" gekennzeichnet.
|
||
*/
|
||
|
||
const UA = 'AeroMC-Launcher/0.5';
|
||
|
||
const META = {
|
||
fabric: 'https://meta.fabricmc.net/v2',
|
||
quilt: 'https://meta.quiltmc.org/v3',
|
||
};
|
||
|
||
async function fetchJson(url) {
|
||
const res = await fetch(url, { headers: { 'User-Agent': UA, Accept: 'application/json' } });
|
||
if (!res.ok) throw new Error('HTTP ' + res.status + ' bei ' + url);
|
||
return res.json();
|
||
}
|
||
|
||
async function fetchText(url) {
|
||
const res = await fetch(url, { headers: { 'User-Agent': UA } });
|
||
if (!res.ok) throw new Error('HTTP ' + res.status + ' bei ' + url);
|
||
return res.text();
|
||
}
|
||
|
||
const FORGE_META = 'https://maven.minecraftforge.net/net/minecraftforge/forge/maven-metadata.xml';
|
||
const NEOFORGE_META = 'https://maven.neoforged.net/releases/net/neoforged/neoforge/maven-metadata.xml';
|
||
|
||
// NeoForge kodiert die MC-Version im Loader-Namen: 1.21.4 -> 21.4.x
|
||
function neoforgePrefix(mcVersion) {
|
||
const p = mcVersion.split('.');
|
||
return `${p[1]}.${p[2] || '0'}.`;
|
||
}
|
||
|
||
// "group:artifact:version[:classifier]" -> { relPath, url }
|
||
function mavenToUrl(base, name) {
|
||
const parts = name.split(':');
|
||
const group = parts[0].replace(/\./g, '/');
|
||
const artifact = parts[1];
|
||
const version = parts[2];
|
||
const classifier = parts[3] ? '-' + parts[3] : '';
|
||
const file = `${artifact}-${version}${classifier}.jar`;
|
||
const relPath = `${group}/${artifact}/${version}/${file}`;
|
||
const root = (base || 'https://libraries.minecraft.net/').replace(/\/$/, '');
|
||
return { relPath, url: `${root}/${relPath}` };
|
||
}
|
||
|
||
// verfügbare Loader-Versionen (für die Anzeige/Auswahl)
|
||
async function listLoaderVersions(loader, mcVersion) {
|
||
if (loader === 'fabric' || loader === 'quilt') {
|
||
const list = await fetchJson(`${META[loader]}/versions/loader/${mcVersion}`);
|
||
return list.map((l) => ({ version: l.loader.version, stable: !!l.loader.stable }));
|
||
}
|
||
if (loader === 'forge') {
|
||
const xml = await fetchText(FORGE_META);
|
||
const all = [...xml.matchAll(/<version>([^<]+)<\/version>/g)].map((m) => m[1]);
|
||
const prefix = mcVersion + '-';
|
||
const versions = all.filter((v) => v.startsWith(prefix)).map((v) => v.slice(prefix.length)).reverse();
|
||
return versions.map((v, i) => ({ version: v, stable: i === 0 }));
|
||
}
|
||
if (loader === 'neoforge') {
|
||
const xml = await fetchText(NEOFORGE_META);
|
||
const all = [...xml.matchAll(/<version>([^<]+)<\/version>/g)].map((m) => m[1]);
|
||
const prefix = neoforgePrefix(mcVersion);
|
||
const versions = all.filter((v) => v.startsWith(prefix)).reverse();
|
||
return versions.map((v, i) => ({ version: v, stable: i === 0 && !/beta/i.test(v) }));
|
||
}
|
||
return [];
|
||
}
|
||
|
||
// löst das Profil (mainClass, libraries, arguments) auf
|
||
async function resolveLoaderProfile(loader, mcVersion, loaderVersion) {
|
||
if (loader === 'fabric' || loader === 'quilt') {
|
||
let lv = loaderVersion;
|
||
if (!lv) {
|
||
const list = await fetchJson(`${META[loader]}/versions/loader/${mcVersion}`);
|
||
if (!list.length) throw new Error(`Kein ${loader}-Loader für Minecraft ${mcVersion} verfügbar.`);
|
||
const stable = list.find((l) => l.loader && l.loader.stable) || list[0];
|
||
lv = stable.loader.version;
|
||
}
|
||
const profile = await fetchJson(`${META[loader]}/versions/loader/${mcVersion}/${lv}/profile/json`);
|
||
return { profile, loaderVersion: lv };
|
||
}
|
||
if (loader === 'forge' || loader === 'neoforge') {
|
||
const e = new Error(
|
||
`${loader === 'forge' ? 'Forge' : 'NeoForge'}-Installation ist noch in Arbeit ` +
|
||
'(braucht Installer + Prozessoren). Fabric und Quilt funktionieren bereits vollständig.',
|
||
);
|
||
e.notImplemented = true;
|
||
throw e;
|
||
}
|
||
throw new Error('Unbekannter Loader: ' + loader);
|
||
}
|
||
|
||
module.exports = { resolveLoaderProfile, listLoaderVersions, mavenToUrl };
|