Files
healer-man/scripts/playtest-wow-visual-candidate.cjs
2026-10-07 13:05:04 -04:00

89 lines
4.9 KiB
JavaScript

const { chromium } = require('C:/Users/phenom/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
const fs = require('node:fs');
const path = require('node:path');
const id = process.argv[2];
if (!id || !/^[a-z0-9-]+$/.test(id)) throw new Error('Provide a dungeon ID for this targeted asset review.');
function option(name) {
const index = process.argv.indexOf(name);
if (index < 0) return null;
if (!process.argv[index + 1]) throw new Error(`${name} requires a value.`);
return process.argv[index + 1];
}
const override = option('--visual-override');
const hotspotsFile = option('--hotspots');
const runtimePreparation = process.argv.includes('--runtime-preparation');
const sampleMs = Number(option('--sample-ms') || 0);
if (!Number.isFinite(sampleMs) || sampleMs < 0 || sampleMs > 10_000) {
throw new Error('--sample-ms must be between 0 and 10000.');
}
const label = override ? path.basename(override, '.glb') : 'shipping';
const output = path.resolve(option('--output-dir')
|| `artifacts/playtest/wow-environment-quality/continuation/${id}-${label}${runtimePreparation ? '-runtime-prepared' : ''}`);
const hotspots = hotspotsFile ? JSON.parse(fs.readFileSync(hotspotsFile, 'utf8')) : [];
fs.mkdirSync(output, { recursive: true });
(async () => {
const browser = await chromium.launch({ channel: 'msedge', headless: true });
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
const errors = [];
page.on('pageerror', (error) => errors.push(error.message));
const params = new URLSearchParams({ dungeon: id });
if (override) params.set('visualOverride', override);
if (runtimePreparation) params.set('runtimePreparation', '1');
const baseUrl = process.env.WOW_ENVIRONMENT_REVIEW_URL || 'http://127.0.0.1:4208';
try {
await page.goto(`${baseUrl}/scripts/dungeon-pipeline/environment-preview.html?${params}`, {
waitUntil: 'domcontentloaded', timeout: 180_000,
});
await page.waitForFunction(() => window.wowEnvironmentReview?.ready, null, { timeout: 180_000 });
if (runtimePreparation && !(await page.evaluate(() => window.wowEnvironmentReview.diagnostics().runtimePreparation === true))) {
throw new Error('The preview renderer is stale; restart the preview server before runtime-prepared checks.');
}
await page.evaluate(() => window.wowEnvironmentReview.setQuality('high'));
const ground = await page.evaluate(() => window.wowEnvironmentReview.groundSamples());
const viewpoints = await page.evaluate(() => window.wowEnvironmentReview.viewpoints);
const captures = [];
async function diagnostics() {
if (sampleMs) {
await page.evaluate(() => window.wowEnvironmentReview.resetFrameSample());
await page.waitForTimeout(sampleMs);
}
return page.evaluate((sampled) => ({ ...window.wowEnvironmentReview.diagnostics(),
...(sampled ? { frameSample: window.wowEnvironmentReview.frameSample() } : {}) }), Boolean(sampleMs));
}
const indices = [...new Set([0, Math.floor((viewpoints.length - 1) / 2), viewpoints.length - 1])];
for (const index of indices) {
for (const [heading, yaw] of [['forward', 0], ['side', Math.PI / 2], ['reverse', Math.PI]]) {
await page.evaluate(({ index, yaw }) => window.wowEnvironmentReview.view(index, yaw), { index, yaw });
await page.waitForTimeout(500);
const file = `view-${index}-${heading}.png`;
await page.screenshot({ path: path.join(output, file) });
captures.push({ name: viewpoints[index].name, heading, file, diagnostics: await diagnostics() });
}
}
for (const [index, hotspot] of hotspots.entries()) {
if (!Array.isArray(hotspot.eye) || !Array.isArray(hotspot.target)
|| [...hotspot.eye, ...hotspot.target].length !== 6
|| ![...hotspot.eye, ...hotspot.target].every(Number.isFinite)) {
throw new Error(`Hotspot ${index} requires finite eye and target triples.`);
}
await page.evaluate(({ eye, target }) => window.wowEnvironmentReview.setCamera(eye, target), hotspot);
await page.waitForTimeout(500);
const file = `hotspot-${index}.png`;
await page.screenshot({ path: path.join(output, file) });
captures.push({ ...hotspot, file, diagnostics: await diagnostics() });
}
const result = { scope: 'targeted isolated asset review; no gameplay certification', id, override,
runtimePreparation, sampleMs, errors, ground, captures };
fs.writeFileSync(path.join(output, 'results.json'), `${JSON.stringify(result, null, 2)}\n`);
if (errors.length) throw new Error(errors.join('\n'));
console.log(JSON.stringify({ id, override, output, captures: captures.length, errors }));
} catch (error) {
await page.screenshot({ path: path.join(output, 'failure.png') }).catch(() => {});
throw error;
} finally {
await browser.close();
}
})().catch((error) => { console.error(error); process.exitCode = 1; });