73 lines
3.3 KiB
JavaScript
73 lines
3.3 KiB
JavaScript
// Exports this packwiz pack as a Modrinth modpack (.mrpack) for Modrinth App / Prism "Import".
|
|
// node tools/export-mrpack.mjs → dist/CreateRP-<version>.mrpack
|
|
// Mods are referenced by their Modrinth CDN URL (sha1/sha512/size from the Modrinth API);
|
|
// config/ goes into overrides/. Zipping uses Windows' bsdtar (tar -a) or `zip` on Linux.
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { execFileSync } from 'child_process';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const UA = { 'User-Agent': 'Pinecraft-CreateRP/mrpack-export' };
|
|
const field = (toml, key) => (toml.match(new RegExp(`^${key}\\s*=\\s*"([^"]*)"`, 'm')) || [])[1];
|
|
|
|
const pack = fs.readFileSync(path.join(root, 'pack.toml'), 'utf8');
|
|
const packName = field(pack, 'name');
|
|
const packVersion = field(pack, 'version');
|
|
const mc = field(pack, 'minecraft');
|
|
const neoforge = field(pack, 'neoforge');
|
|
|
|
const metas = fs.readdirSync(path.join(root, 'mods')).filter(f => f.endsWith('.pw.toml')).map(f => {
|
|
const t = fs.readFileSync(path.join(root, 'mods', f), 'utf8');
|
|
return { file: f, filename: field(t, 'filename'), side: field(t, 'side') || 'both', url: field(t, 'url'), versionId: field(t, 'version') };
|
|
});
|
|
|
|
// sha1/sha512/size per version from Modrinth (batched)
|
|
const versionInfo = {};
|
|
const ids = metas.map(m => m.versionId).filter(Boolean);
|
|
for (let i = 0; i < ids.length; i += 100) {
|
|
const chunk = ids.slice(i, i + 100);
|
|
const res = await fetch('https://api.modrinth.com/v2/versions?ids=' + encodeURIComponent(JSON.stringify(chunk)), { headers: UA });
|
|
for (const v of await res.json()) versionInfo[v.id] = v;
|
|
}
|
|
|
|
const files = metas.map(m => {
|
|
const v = versionInfo[m.versionId];
|
|
const f = v?.files.find(x => x.url === m.url) || v?.files.find(x => x.filename === m.filename);
|
|
if (!f) throw new Error(`no Modrinth file for ${m.file}`);
|
|
return {
|
|
path: `mods/${f.filename}`,
|
|
hashes: { sha1: f.hashes.sha1, sha512: f.hashes.sha512 },
|
|
env: { client: m.side === 'server' ? 'unsupported' : 'required', server: m.side === 'client' ? 'unsupported' : 'required' },
|
|
downloads: [f.url],
|
|
fileSize: f.size
|
|
};
|
|
}).sort((a, b) => a.path.localeCompare(b.path));
|
|
|
|
const index = {
|
|
formatVersion: 1,
|
|
game: 'minecraft',
|
|
versionId: packVersion,
|
|
name: packName,
|
|
summary: 'Клієнтська збірка сервера Create RP',
|
|
files,
|
|
dependencies: { minecraft: mc, neoforge }
|
|
};
|
|
|
|
// staging dir → zip
|
|
const stage = path.join(root, 'dist', '.stage');
|
|
fs.rmSync(stage, { recursive: true, force: true });
|
|
fs.mkdirSync(path.join(stage, 'overrides'), { recursive: true });
|
|
fs.writeFileSync(path.join(stage, 'modrinth.index.json'), JSON.stringify(index, null, 2));
|
|
fs.cpSync(path.join(root, 'config'), path.join(stage, 'overrides', 'config'), { recursive: true });
|
|
|
|
const out = path.join(root, 'dist', `CreateRP-${packVersion}.mrpack`);
|
|
fs.rmSync(out, { force: true });
|
|
if (process.platform === 'win32') {
|
|
execFileSync('C:\\Windows\\System32\\tar.exe', ['--format', 'zip', '-c', '-f', out, '-C', stage, 'modrinth.index.json', 'overrides']);
|
|
} else {
|
|
execFileSync('zip', ['-qr', out, 'modrinth.index.json', 'overrides'], { cwd: stage });
|
|
}
|
|
fs.rmSync(stage, { recursive: true, force: true });
|
|
console.log(`${out}: ${files.length} mods, ${(fs.statSync(out).size / 1024).toFixed(0)} KiB`);
|