Modpack aus dem Katalog installieren oder als Datei importieren.
-
Katalog-Suche läuft über Modrinth oder CurseForge. Für CurseForge wird ein eigener API-Key in den Netzwerk-Einstellungen gebraucht (die Weiterleitung reicht nur für den Datei-Import). Datei-Import unterstützt zusätzlich CurseForge-ZIP (manifest.json).
+
Katalog-Suche läuft über Modrinth oder CurseForge. Datei-Import unterstützt zusätzlich CurseForge-ZIP (manifest.json).
diff --git a/src/main.js b/src/main.js
index c5a6b65..a79896d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -4214,6 +4214,13 @@ ipcMain.handle('modpack:installFromCurseForge', async (_e, project) => {
const gameVersion = (project && project.gameVersion) || '';
broadcast('launch:progress', { phase: 'modpack', detail: 'Modpack-Version wird ermittelt …' });
const file = await services.curseforgeResolveModpackFile(zugang, modId, gameVersion);
+ if (file && file.gesperrt) {
+ return {
+ ok: false,
+ message: 'Der Autor erlaubt kein Laden dieses Modpacks über Launcher. Bitte von Hand laden und über „Importieren“ einlesen: '
+ + services.cfProjektSeite(modId),
+ };
+ }
if (!file || !file.url) {
return {
ok: false,
diff --git a/src/services.js b/src/services.js
index 0b9f854..75c62d8 100644
--- a/src/services.js
+++ b/src/services.js
@@ -586,8 +586,8 @@ function cfLoaderType(loader) {
}
/*
- * CurseForge-Katalogsuche. Braucht direkten API-Key (modus === 'direkt').
- * Die Weiterleitung deckt absichtlich nur Dateiauflösung und Download ab.
+ * CurseForge-Katalogsuche – mit eigenem API-Key (modus 'direkt') oder über die
+ * Weiterleitung (modus 'weiterleitung'); beide haben dieselben Pfade unter zugang.basis.
*/
/*
@@ -653,13 +653,13 @@ async function curseforgeSearch(zugang, {
query = '', gameVersion = '', loader = '', sort = 'popularity',
limit = 30, offset = 0, art = 'mod',
} = {}) {
- if (!zugang || zugang.modus !== 'direkt') {
+ // Direkt (eigener Key) und über die Weiterleitung laufen über dieselben Pfade
+ if (!zugang) {
return {
total: 0,
hits: [],
needKey: true,
- error: 'Für die CurseForge-Suche brauchst du einen eigenen API-Key in den Netzwerk-Einstellungen. '
- + 'Die Weiterleitung reicht für Downloads, nicht für den Katalog.',
+ error: 'Kein CurseForge-Zugang eingerichtet. Trage unter Optionen → Netzwerk die Adresse der Weiterleitung oder einen eigenen API-Key ein.',
};
}
if (!CF_CLASS[art]) {
@@ -668,7 +668,7 @@ async function curseforgeSearch(zugang, {
return { total: 0, hits: [], error: 'CurseForge unterstützt diese Inhaltsart hier nicht – bitte Modrinth nutzen.' };
}
const classId = CF_CLASS[art];
- const url = new URL(CURSEFORGE + '/mods/search');
+ const url = new URL(zugang.basis + '/mods/search');
url.searchParams.set('gameId', '432');
url.searchParams.set('classId', String(classId));
if (query) url.searchParams.set('searchFilter', query);
@@ -696,13 +696,16 @@ async function curseforgeSearch(zugang, {
return {
total: 0,
hits: [],
- needKey: true,
- error: 'CurseForge lehnt den API-Key ab (HTTP ' + res.status + '). '
- + 'Bitte unter Optionen → Netzwerk einen gültigen Schlüssel von console.curseforge.com eintragen. '
- + 'Das Proxy-Token ist kein API-Key.'
- + (detail ? ' (' + detail + ')' : ''),
+ needKey: zugang.modus === 'direkt',
+ error: zugang.modus === 'direkt'
+ ? 'CurseForge lehnt den API-Key ab (HTTP ' + res.status + '). '
+ + 'Bitte unter Optionen → Netzwerk einen gültigen Schlüssel von console.curseforge.com eintragen. '
+ + 'Das Proxy-Token ist kein API-Key.'
+ + (detail ? ' (' + detail + ')' : '')
+ : 'Der CurseForge-Server weist die Anfrage zurück (HTTP ' + res.status + ').',
};
}
+ if (res.status === 429) throw new Error('Zu viele Anfragen – bitte einen Moment warten.');
throw new Error('CurseForge-Suche fehlgeschlagen: HTTP ' + res.status + (detail ? ' – ' + detail : ''));
}
const data = await res.json();
@@ -750,12 +753,12 @@ function cfFileMatches(file, gameVersion, loader, art) {
}
async function curseforgePickFile(zugang, modId, gameVersion, loader, art) {
- if (!zugang || zugang.modus !== 'direkt') {
- const err = new Error('CurseForge-Dateiauswahl braucht einen eigenen API-Key.');
+ if (!zugang) {
+ const err = new Error('Kein CurseForge-Zugang eingerichtet.');
err.code = 'need-key';
throw err;
}
- const url = new URL(CURSEFORGE + '/mods/' + modId + '/files');
+ const url = new URL(zugang.basis + '/mods/' + modId + '/files');
url.searchParams.set('pageSize', '50');
url.searchParams.set('index', '0');
if (gameVersion) url.searchParams.set('gameVersion', gameVersion);