69 lines
4.4 KiB
JavaScript
69 lines
4.4 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');
|
|
|
|
// Isolated asset review: real GLB/KTX2 loading and production material preparation,
|
|
// with the runtime palettes. This does not simulate combat, navigation or a full clear.
|
|
const output = path.resolve('artifacts/playtest/rom-environment-quality');
|
|
const requested = new Set(process.argv.slice(2));
|
|
const recipes = fs.readdirSync('scripts/runewaker-pipeline/recipes')
|
|
.filter((name) => name.endsWith('.json') && !name.endsWith('-population.json'))
|
|
.map((name) => JSON.parse(fs.readFileSync(path.join('scripts/runewaker-pipeline/recipes', name), 'utf8')))
|
|
.filter((recipe) => recipe.source?.wdb && (!requested.size || requested.has(recipe.slug)))
|
|
.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
fs.mkdirSync(output, { recursive: true });
|
|
|
|
(async () => {
|
|
const browser = await chromium.launch({ channel: 'msedge', headless: true });
|
|
const resultsFile = path.join(output, 'results.json');
|
|
const results = requested.size && fs.existsSync(resultsFile)
|
|
? JSON.parse(fs.readFileSync(resultsFile, 'utf8')).results.filter((entry) => !requested.has(entry.slug)) : [];
|
|
try {
|
|
for (const recipe of recipes) {
|
|
const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });
|
|
const page = await context.newPage();
|
|
const errors = [];
|
|
page.on('pageerror', (error) => errors.push(error.message));
|
|
page.on('console', (message) => {
|
|
if (message.type() === 'error') errors.push(message.text());
|
|
});
|
|
try {
|
|
await page.goto(`http://127.0.0.1:4207/scripts/runewaker-pipeline/environment-preview.html?dungeon=${recipe.slug}`, { waitUntil: 'domcontentloaded' });
|
|
await page.waitForFunction(() => window.romEnvironmentReview?.ready, null, { timeout: 180_000 });
|
|
const data = await page.evaluate(() => ({ viewpoints: window.romEnvironmentReview.viewpoints, presentation: window.romEnvironmentReview.presentation }));
|
|
await page.waitForTimeout(500);
|
|
await page.evaluate(() => window.romEnvironmentReview.lighting(true));
|
|
await page.waitForTimeout(250);
|
|
await page.screenshot({ path: path.join(output, `${recipe.slug}-before.png`) });
|
|
await page.evaluate(() => window.romEnvironmentReview.lighting(false));
|
|
const views = [0, Math.floor((data.viewpoints.length - 1) / 2), data.viewpoints.length - 1];
|
|
for (const [index, viewpoint] of views.entries()) {
|
|
await page.evaluate((value) => window.romEnvironmentReview.view(value), viewpoint);
|
|
await page.waitForTimeout(300);
|
|
await page.screenshot({ path: path.join(output, `${recipe.slug}-view-${index}.png`) });
|
|
}
|
|
await page.evaluate(() => window.romEnvironmentReview.view(0, Math.PI));
|
|
await page.waitForTimeout(300);
|
|
await page.screenshot({ path: path.join(output, `${recipe.slug}-entrance-reverse.png`) });
|
|
const drawCalls = await page.evaluate(() => window.romEnvironmentReview.drawCalls());
|
|
await page.evaluate(() => window.romEnvironmentReview.resetFrameSample());
|
|
await page.waitForTimeout(1000);
|
|
const frameSample = await page.evaluate(() => window.romEnvironmentReview.frameSample());
|
|
results.push({ slug: recipe.slug, status: errors.length ? 'error' : 'loaded', drawCalls, frameSample, errors, ...data });
|
|
console.log(`${recipe.slug}: ${errors.length ? 'ERROR' : 'loaded'}; ${data.viewpoints.length} available viewpoints`);
|
|
} catch (error) {
|
|
results.push({ slug: recipe.slug, status: 'error', errors: [...errors, error.message] });
|
|
console.error(`${recipe.slug}: ${error.message}`);
|
|
await page.screenshot({ path: path.join(output, `${recipe.slug}-failure.png`) }).catch(() => {});
|
|
} finally {
|
|
await context.close();
|
|
results.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
fs.writeFileSync(resultsFile, `${JSON.stringify({ scope: 'isolated environment asset review; entrance, midpoint boss, final boss and reverse entrance; no navigation or combat certification', results }, null, 2)}\n`);
|
|
}
|
|
}
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
if (results.some((result) => result.status === 'error')) process.exitCode = 1;
|
|
})().catch((error) => { console.error(error); process.exitCode = 1; });
|