first commit

This commit is contained in:
lucasdpt
2026-06-14 12:32:29 +02:00
commit cc4f90e840
32 changed files with 9729 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
import { spawn } from 'child_process'
import { parse as parseToml } from 'smol-toml'
import { paths } from './paths'
import { config } from '../shared/config'
import { fetchText } from './download'
import { emit } from './events'
/**
* Gestion du modpack côté launcher :
* - lecture du pack.toml packwiz distant (versions MC/NeoForge = source de vérité)
* - sync incrémentale des mods/configs via packwiz-installer-bootstrap.
*
* packwiz-installer garde un manifeste local (packwiz.json dans l'instance) et
* ne re-télécharge QUE les fichiers dont le hash a changé — c'est exactement le
* comportement "pas de re-download complet à chaque update" recherché.
*/
export interface PackMeta {
name: string
version: string
minecraft: string
neoforge: string
}
/** Télécharge et parse le pack.toml distant. */
export async function fetchPackMeta(): Promise<PackMeta> {
emit.progress({ phase: 'pack-meta', message: 'Lecture du modpack…', progress: undefined })
if (!config.packTomlUrl || config.packTomlUrl.includes('CHANGE_ME')) {
throw new Error(
'URL du pack.toml non configurée. Renseigne packTomlUrl dans src/shared/config.ts.'
)
}
const raw = await fetchText(config.packTomlUrl)
const data = parseToml(raw) as {
name?: string
version?: string
versions?: { minecraft?: string; neoforge?: string }
}
const minecraft = data.versions?.minecraft
const neoforge = data.versions?.neoforge
if (!minecraft || !neoforge) {
throw new Error(
'pack.toml invalide : [versions] doit contenir "minecraft" et "neoforge".'
)
}
return {
name: data.name ?? 'Modpack',
version: data.version ?? '0',
minecraft,
neoforge
}
}
/**
* Lance packwiz-installer-bootstrap pour synchroniser l'instance.
* `java` = chemin du binaire Java 21 géré (réutilisé pour faire tourner le jar).
*/
export async function syncModpack(javaPath: string): Promise<void> {
emit.progress({ phase: 'modpack', message: 'Synchronisation du modpack…', progress: undefined })
await new Promise<void>((resolve, reject) => {
const child = spawn(
javaPath,
['-jar', paths.packwizBootstrapJar, '-g', '-s', 'client', config.packTomlUrl],
{ cwd: paths.instanceDir }
)
// On garde les dernières lignes de sortie pour pouvoir afficher la VRAIE
// erreur de packwiz si le process échoue.
const recent: string[] = []
const onLine = (buf: Buffer): void => {
for (const line of buf.toString().split(/\r?\n/)) {
const text = line.trim()
if (!text) continue
recent.push(text)
if (recent.length > 25) recent.shift()
emit.progress({ phase: 'modpack', message: text, progress: undefined })
// Visible aussi dans la console du launcher.
emit.gameLog({ stream: 'stdout', line: `[packwiz] ${text}` })
}
}
child.stdout.on('data', onLine)
child.stderr.on('data', onLine)
child.on('error', reject)
child.on('close', (code) => {
if (code === 0) return resolve()
const tail = recent.slice(-12).join('\n')
reject(
new Error(
`packwiz-installer a échoué (code ${code}).` +
(tail ? `\nDernières lignes :\n${tail}` : '')
)
)
})
})
emit.progress({ phase: 'modpack', message: 'Modpack à jour.', progress: 1 })
}