Files
combat-hud-hub/scripts/enable-in-world.mjs
Kaysser Taylor e6531ec569 v0.2.2: bump MODULE_VERSION in main.js to match module.json/package.json
Missed the 3-place version rule on the v0.2.2 bump. MODULE_VERSION
was still v0.2.0 in scripts/main.js, so Foundry's init log showed
the old version and the live system didn't have getFeed/clearFeed.
Caught during the e2e Playwright run when Foundry loaded v0.2.0
of the main.js but v0.2.2 of the module.json.
2026-06-22 17:06:35 -04:00

93 lines
3.6 KiB
JavaScript

// One-shot: enable combat-hud-hub in the active world via the GM
// settings UI. Logs in as Gamemaster, opens Game Settings → Manage
// Modules, toggles combat-hud-hub on, saves, then refreshes.
import { chromium } from "playwright-core";
const FOUNDRY_URL = process.env.FOUNDRY_URL ?? "http://localhost:30000";
const browser = await chromium.launch({
headless: true,
args: ["--no-sandbox", "--disable-gpu"],
});
const page = await browser.newPage();
page.on("console", (m) => {
const t = m.text();
if (m.type() === "error" || t.includes("[probe]") || t.includes("combat-hud-hub")) {
console.log(`[c.${m.type()}] ${t}`);
}
});
console.log("Joining as Gamemaster...");
await page.goto(FOUNDRY_URL);
await page.waitForSelector("#join-game-form");
const userOpts = await page.$$eval('select[name="userid"] option', (os) =>
os.map((o) => ({ value: o.value, label: o.textContent, disabled: o.disabled })),
);
const gm = userOpts.find((o) => o.label === "Gamemaster" && !o.disabled && o.value);
if (!gm) {
console.error("No Gamemaster slot available.");
process.exit(1);
}
await page.selectOption('select[name="userid"]', gm.value);
await page.fill('input[name="password"]', "");
await page.click('button[name="join"]');
await page.waitForSelector("#ui-left", { timeout: 30_000 });
console.log("Joined.");
// Wait for the world to be ready.
await page.waitForFunction(() => game?.ready === true, { timeout: 30_000 });
// Check current state.
const before = await page.evaluate(() => {
const m = game.modules.get("combat-hud-hub");
return m ? { active: m.active, found: true } : { found: false };
});
console.log("Before:", before);
if (before.found && before.active) {
console.log("combat-hud-hub already enabled.");
await browser.close();
process.exit(0);
}
// Open Game Settings (the gear icon).
console.log("Opening Game Settings...");
await page.evaluate(() => game.settings?.activateImportDialog ? null : null);
// The GM can call game.settings.sheet.render(true) — but better: click the menu.
const settingsOpened = await page.evaluate(() => {
// Try the menu path: Settings → Game Settings... → Modules
// The simplest API call is to manipulate core.moduleConfiguration directly.
// We can read the current config.
const cfg = game.settings.get("core", "moduleConfiguration");
return cfg ?? {};
});
console.log("Current moduleConfiguration:", Object.keys(settingsOpened).filter(k => settingsOpened[k]));
// Set the moduleConfiguration to include combat-hud-hub.
const result = await page.evaluate(() => {
const cfg = game.settings.get("core", "moduleConfiguration") ?? {};
if (cfg["combat-hud-hub"]) return { ok: true, reason: "already enabled" };
cfg["combat-hud-hub"] = true;
return game.settings.set("core", "moduleConfiguration", cfg)
.then(() => ({ ok: true }))
.catch((e) => ({ ok: false, reason: e.message }));
});
console.log("Set result:", result);
if (result.ok) {
console.log("combat-hud-hub enabled. The world needs a refresh for the new module to initialize.");
console.log("Refreshing in 2s...");
await new Promise(r => setTimeout(r, 2000));
await page.reload();
await page.waitForSelector("#join-game-form", { timeout: 30_000 });
console.log("Reloaded. Re-joining as Gamemaster...");
await page.selectOption('select[name="userid"]', gm.value);
await page.fill('input[name="password"]', "");
await page.click('button[name="join"]');
await page.waitForSelector("#ui-left", { timeout: 30_000 });
await page.waitForFunction(() => game?.modules?.get("combat-hud-hub")?.active === true, { timeout: 30_000 });
console.log("combat-hud-hub is now active.");
}
await browser.close();