Files
fvtt-chroniques-de-l-etrange/tools/compendiums.mjs
LeRatierBretonnier 01861340ad feat: Add NPC compendium with 49 PNJs from the rulebook
- 9 esprits-animaux nommés (James Kam, Karen Sen, Susan Chow, Hyun Ci, Michelle Chun, Scott Zang, Pui Gan, Bui Hok, Sonia Tsui)
- 8 fantômes (Phil Mok, Tony Meng + 4 archétypes génériques)
- 13 démons (Je Maan, Good Boy, Charlie Fei, Zoeng, Ban Daan + 8 archétypes génériques)
- 4 jiugwaai (Juk Lyun + archétypes gaaujan, gwat jyun)
- 2 divinités (Ruby Jin Jin / tinneoi, Jing Tin)
- 3 mortels initiés nommés (Laureen Zoeng, Julian Po, John Wa)
- 8 PNJ du scénario L'Année du Lion (Alexander Weng, Maximilian Pang, Ginny Ching, Ken Luan, Jeffrey Chiu, Paul Fei, Leonie Fei, Carrie Suet)
- 3 archétypes mortels génériques (Fat si sorcier, Intermédiaire, Consultant ésotérique)
- Suppression du fichier modèle npc_Modele_Creature.json
- Recompilation du pack cde-npcs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 22:58:35 +02:00

83 lines
2.9 KiB
JavaScript

/**
* Chroniques de l'Étrange — Système FoundryVTT
* Édité par Antre-Monde Éditions
* @file tools/compendiums.mjs — Compile / extrait les compendiums LevelDB
* @author LeRatierBretonnien
* @copyright 2025 LeRatierBretonnien
* @license CC BY-NC-SA 4.0
* @description Ce système a été réalisé avec l'autorisation d'Antre-Monde Éditions.
* Le jeu Chroniques de l'Étrange est un jeu de rôle édité par Antre-Monde Éditions.
*
* Usage:
* npm run pack:compile — compile packs-src/ → packs/ (JSON → LevelDB)
* npm run pack:extract — extrait packs/ → packs-src/ (LevelDB → JSON)
*
* Format des fichiers source JSON :
* Chaque document DOIT contenir un champ `_key` de la forme :
* - Items : `"_key": "!items!<_id>"`
* - Actors : `"_key": "!actors!<_id>"`
* Sans ce champ, le document est ignoré silencieusement par compilePack.
*/
import { compilePack, extractPack } from "@foundryvtt/foundryvtt-cli";
import { promises as fs } from "fs";
import path from "path";
const ROOT = new URL("..", import.meta.url).pathname;
const SRC_DIR = path.join(ROOT, "packs-src");
const DIST_DIR = path.join(ROOT, "packs");
const action = process.argv[2] ?? "compile";
if (action === "compile") {
await compileAll();
} else if (action === "extract") {
await extractAll();
} else {
console.error(`Action inconnue : ${action}. Utiliser "compile" ou "extract".`);
process.exit(1);
}
/**
* Compile tous les sous-dossiers de packs-src/ vers packs/ (JSON → LevelDB).
*/
async function compileAll() {
const packs = await fs.readdir(SRC_DIR);
for (const pack of packs) {
const src = path.join(SRC_DIR, pack);
const dist = path.join(DIST_DIR, pack);
const stat = await fs.stat(src);
if (!stat.isDirectory()) continue;
console.log(`📦 Compilation : ${pack}`);
// Supprime l'ancien LevelDB avant recompilation (évite l'erreur LEVEL_ITERATOR_NOT_OPEN)
await fs.rm(dist, { recursive: true, force: true });
await compilePack(src, dist, { yaml: false });
}
console.log("✅ Compilation terminée.");
}
/**
* Extrait tous les packs LevelDB de packs/ vers packs-src/ (LevelDB → JSON).
*/
async function extractAll() {
const packs = await fs.readdir(DIST_DIR);
for (const pack of packs) {
const dist = path.join(DIST_DIR, pack);
const src = path.join(SRC_DIR, pack);
const stat = await fs.stat(dist).catch(() => null);
if (!stat?.isDirectory()) continue;
console.log(`📂 Extraction : ${pack}`);
await fs.mkdir(src, { recursive: true });
await extractPack(dist, src, {
yaml: false,
transformName: doc => {
const safeName = doc.name.replace(/[^a-zA-Z0-9À-ÿ]/g, "_");
const docType = doc._key?.split("!")[1] ?? "doc";
const prefix = ["actors", "items"].includes(docType) ? doc.type : docType;
return `${prefix}_${safeName}_${doc._id}.json`;
},
});
}
console.log("✅ Extraction terminée.");
}