// Adds a Modrinth mod (and its required dependencies, recursively) to this packwiz pack. // node tools/add-mod.mjs [...] → latest NeoForge 1.21.1 version // node tools/add-mod.mjs @ → that exact version // Writes mods/.pw.toml, then run: node tools/reindex.mjs import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const UA = { 'User-Agent': 'Pinecraft-CreateRP/add-mod' }; const api = p => fetch('https://api.modrinth.com/v2' + p, { headers: UA }).then(r => { if (!r.ok) throw new Error(`${p}: HTTP ${r.status}`); return r.json(); }); const q = s => JSON.stringify(s); const existing = new Set(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 (t.match(/^mod-id = "([^"]+)"/m) || [])[1]; }).filter(Boolean)); const sideOf = p => p.server_side === 'unsupported' ? 'client' : p.client_side === 'unsupported' ? 'server' : 'both'; async function add(spec, depth = 0) { const [ref, wanted] = spec.split('@'); const project = await api(`/project/${ref}`); const pad = ' '.repeat(depth); if (existing.has(project.id)) { console.log(`${pad}= ${project.title} — already in the pack`); return; } const versions = await api(`/project/${project.id}/version?loaders=${encodeURIComponent('["neoforge"]')}&game_versions=${encodeURIComponent('["1.21.1"]')}`); const v = wanted ? versions.find(x => x.version_number === wanted) : versions[0]; if (!v) throw new Error(`${project.title}: no NeoForge 1.21.1 version${wanted ? ' ' + wanted : ''}`); const f = v.files.find(x => x.primary) || v.files[0]; const toml = [ `name = ${q(project.title)}`, `filename = ${q(f.filename)}`, `side = ${q(sideOf(project))}`, '', '[download]', `url = ${q(f.url)}`, 'hash-format = "sha512"', `hash = ${q(f.hashes.sha512)}`, '', '[update]', '[update.modrinth]', `mod-id = ${q(project.id)}`, `version = ${q(v.id)}`, '' ].join('\n'); fs.writeFileSync(path.join(root, 'mods', `${project.slug}.pw.toml`), toml); existing.add(project.id); console.log(`${pad}+ ${project.title} ${v.version_number} (${sideOf(project)})`); for (const d of v.dependencies.filter(d => d.dependency_type === 'required' && d.project_id)) { await add(d.project_id, depth + 1); } } for (const spec of process.argv.slice(2)) await add(spec);