Files
deepseek 764da2ee6c Dino Isle Online: multiplayer dino survival game (The Isle-like)
- Zero-dependency Node server: HTTP static + hand-rolled RFC6455 WebSocket + 20Hz authoritative simulation
- Seeded island worldgen (tiles, forest decor, spawns)
- 4 playable species, needs (food/water/stamina), rest, growth stages Hatchling->Apex
- AI fauna: critters, fish shoals, Dryosaurus/Psittacosaurus herds; carcass feasting
- PvP with knockback, kill feed, chat, leaderboard, minimap, day/night cycle
- True top-down procedural dino renderer shared by menu cards and in-game
- Developer mode (` key): god-mode, x6 XP, instant evolve, spawn AI, Alt+Click tp
- Headless smoke tests, real-browser visual tests, pixel match checks
2026-08-23 07:00:08 +00:00

58 lines
2.8 KiB
JavaScript

// Decode screenshots in headless chromium and verify expected pixel signatures.
'use strict';
import { createRequire } from 'node:module';
import { readFileSync } from 'node:fs';
const require = createRequire('/root/kidcraft/node_modules/');
const { chromium } = require('playwright-core');
const EXE = '/root/.cache/ms-playwright/chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell';
let failures = 0;
const ok = (c, l) => { console.log(`${c ? 'PASS' : 'FAIL'} ${l}`); if (!c) failures++; };
async function stats(page, path, x0, y0, x1, y1) {
const b64 = readFileSync(path).toString('base64');
return await page.evaluate(async ({ b64, x0, y0, x1, y1 }) => {
const img = new Image();
img.src = 'data:image/png;base64,' + b64;
await new Promise(r => { img.onload = r; });
const cv = document.createElement('canvas');
cv.width = img.width; cv.height = img.height;
const cx = cv.getContext('2d');
cx.drawImage(img, 0, 0);
const d = cx.getImageData(x0, y0, x1 - x0, y1 - y0).data;
let blue = 0, green = 0, tan = 0, red = 0, dark = 0, n = 0;
for (let i = 0; i < d.length; i += 4) {
const [r, g, b] = [d[i], d[i + 1], d[i + 2]]; n++;
if (b > r + 20 && b > g + 10) blue++;
else if (g > r + 15 && g > b + 15) green++;
else if (r > 150 && g > 130 && b < g) tan++;
else if (r > 140 && r > g + 50 && r > b + 50) red++;
if (r + g + b < 120) dark++;
}
return { w: img.width, h: img.height, frac: { blue: blue / n, green: green / n, tan: tan / n, red: red / n, dark: dark / n } };
}, { b64, x0, y0, x1, y1 });
}
const browser = await chromium.launch({ executablePath: EXE, args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.goto('about:blank');
// ---- menu ----
const menu = await stats(page, '/tmp/shot-menu.png', 0, 0, 1280, 800);
ok(menu.w === 1280 && menu.h === 800, `menu screenshot size ${menu.w}x${menu.h}`);
ok(menu.frac.dark < 0.98, 'menu is not a black screen');
// ---- gameplay full frame ----
const game = await stats(page, '/tmp/shot-game-a.png', 0, 0, 1280, 800);
ok(game.frac.blue > 0.05 || game.frac.green > 0.05, `island terrain painted (blue ${game.frac.blue.toFixed(2)}, green ${game.frac.green.toFixed(2)})`);
// bottom-left vitals region should contain red-ish HP fill
const vitals = await stats(page, '/tmp/shot-game-a.png', 16, 800 - 160, 256, 790);
ok(vitals.frac.red > 0.02, `HP bar red present (${vitals.frac.red.toFixed(3)})`);
// top-right minimap region not empty
const mm = await stats(page, '/tmp/shot-game-a.png', 1116, 14, 1266, 178);
ok(mm.frac.dark < 0.95 && (mm.frac.blue > 0.03 || mm.frac.green > 0.03), 'minimap rendered island');
await browser.close();
console.log(failures === 0 ? '\nPIXEL CHECKS PASSED' : `\n${failures} PIXEL CHECK(S) FAILED`);
process.exit(failures ? 1 : 0);