96 lines
5.4 KiB
JavaScript
96 lines
5.4 KiB
JavaScript
import { launch, CDP } from './cdpshot.mjs';
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
const { url: wsUrl, kill } = await launch('http://localhost:8080/index.html', undefined, 1280, 720, 5000);
|
|
const cdp = new CDP(wsUrl);
|
|
await cdp.open();
|
|
await cdp.send('Runtime.enable');
|
|
const ev = async (expression) => {
|
|
const r = await cdp.send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: true });
|
|
if (r.exceptionDetails) throw new Error('eval: ' + (r.exceptionDetails.exception?.description ?? r.exceptionDetails.text));
|
|
return r.result?.value;
|
|
};
|
|
const toClient = (x, y) =>
|
|
`(() => { const c = window.game.canvas; const r = c.getBoundingClientRect(); const z = r.width / c.width; return [r.left + ${x} * z, r.top + ${y} * z]; })()`;
|
|
async function click(cx, cy) {
|
|
await cdp.send('Input.dispatchMouseEvent', { type: 'mouseMoved', x: cx, y: cy });
|
|
await sleep(70);
|
|
await cdp.send('Input.dispatchMouseEvent', { type: 'mousePressed', x: cx, y: cy, button: 'left', clickCount: 1 });
|
|
await sleep(100);
|
|
await cdp.send('Input.dispatchMouseEvent', { type: 'mouseReleased', x: cx, y: cy, button: 'left', clickCount: 1 });
|
|
await sleep(70);
|
|
}
|
|
const clickGame = async (x, y) => { const [cx, cy] = await ev(toClient(x, y)); await click(cx, cy); };
|
|
const log = (...a) => console.log(...a);
|
|
|
|
let menuUp = false;
|
|
for (let i = 0; i < 120 && !menuUp; i++) { await sleep(500); menuUp = await ev(`!!(window.game && window.game.scene.isActive('MenuScene'))`); }
|
|
await sleep(4600);
|
|
// seed a save first via direct call (faster) so the LOAD button is enabled
|
|
await ev(`(() => { const gs = window.game.scene; const m = gs.getScene('MenuScene'); return true; })()`);
|
|
const mb = await ev(`(() => { const m = window.game.scene.getScene('MenuScene'); return [m.newGameBtn.x, m.newGameBtn.y]; })()`);
|
|
await clickGame(mb[0], mb[1]);
|
|
let gameUp = false;
|
|
for (let i = 0; i < 240 && !gameUp; i++) { await sleep(500); gameUp = await ev(`!!(window.game && window.game.scene.isActive('GameScene') && window.game.scene.getScene('GameScene').ship)`); }
|
|
if (!gameUp) throw new Error('no game');
|
|
await sleep(1500);
|
|
|
|
// ack comms until deck live
|
|
async function deckLive() {
|
|
return await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const s = gs.actionBar.slots.find((x) => x.id === 'menu'); return !!(s && s.panel.input && s.panel.input.enabled); })()`);
|
|
}
|
|
for (let i = 0; i < 20 && !(await deckLive()); i++) {
|
|
const btn = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const b = gs.comms?.box; return b && b.button ? [b.x + b.button.x, b.y + b.button.y] : null; })()`);
|
|
if (btn) { await clickGame(btn[0], btn[1]); }
|
|
await sleep(1200);
|
|
}
|
|
log('deck live:', await deckLive());
|
|
|
|
// MENU open
|
|
const menuSlot = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const s = gs.actionBar.slots.find((s) => s.id === 'menu'); return [s.slot.x, s.slot.y]; })()`);
|
|
await clickGame(menuSlot[0], menuSlot[1]);
|
|
await sleep(700);
|
|
const sub = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const bar = gs.menuSubBar; return bar.isOpen ? bar.buttons.map((b) => [b.id, bar.x + b.btn.x, bar.y + b.btn.y]) : null; })()`);
|
|
log('sub-bar:', JSON.stringify(sub));
|
|
// SAVE to slot 3 first (so LOAD has data)
|
|
const saveBtn = sub.find((b) => b[0] === 'save');
|
|
await clickGame(saveBtn[1], saveBtn[2]);
|
|
await sleep(1400);
|
|
const cardS = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const c = gs.savePanel.cards[2]; return [gs.savePanel.x + c.x, gs.savePanel.y + c.y]; })()`);
|
|
await clickGame(cardS[0], cardS[1]);
|
|
await sleep(900);
|
|
log('slot3 saved:', await ev(`!!window.game.scene.getScene('GameScene').saveManager.get(3)`));
|
|
const cancelS = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const b = gs.savePanel.cancelBtn; return [gs.savePanel.x + b.x, gs.savePanel.y + b.y]; })()`);
|
|
await clickGame(cancelS[0], cancelS[1]);
|
|
await sleep(900);
|
|
// reopen MENU -> Load (sub-bar may still be open from the save step)
|
|
const subbarState = await ev(`window.game.scene.getScene('GameScene').menuSubBar?.isOpen`);
|
|
if (!subbarState) { await clickGame(menuSlot[0], menuSlot[1]); await sleep(700); }
|
|
const sub2 = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const bar = gs.menuSubBar; return bar.isOpen ? bar.buttons.map((b) => [b.id, bar.x + b.btn.x, bar.y + b.btn.y]) : null; })()`);
|
|
if (!sub2) throw new Error('sub-bar not open');
|
|
const loadBtn = sub2.find((b) => b[0] === 'load');
|
|
await clickGame(loadBtn[1], loadBtn[2]);
|
|
await sleep(1400);
|
|
log('panel state:', await ev(`window.game.scene.getScene('GameScene').savePanel.state`));
|
|
// click slot 3 card
|
|
const card = await ev(`(() => { const gs = window.game.scene.getScene('GameScene'); const c = gs.savePanel.cards[2]; return [gs.savePanel.x + c.x, gs.savePanel.y + c.y, c.disabled]; })()`);
|
|
log('card:', JSON.stringify(card));
|
|
await clickGame(card[0], card[1]);
|
|
await sleep(900);
|
|
// DUMP confirm overlay geometry chain
|
|
const geom = await ev(`(() => {
|
|
const gs = window.game.scene.getScene('GameScene');
|
|
const c = gs.savePanel.confirm;
|
|
const info = (o) => ({ x: o.x, y: o.y, w: o.width ?? null, h: o.height ?? null, input: o.input ? o.input.enabled : null });
|
|
return {
|
|
panel: { x: gs.savePanel.x, y: gs.savePanel.y },
|
|
confirm: info(c),
|
|
confirmBtn: info(c.confirmBtn),
|
|
cancelBtn: info(c.cancelBtn),
|
|
scrim: info(c.scrim),
|
|
confirmState: c.state,
|
|
};
|
|
})()`);
|
|
console.log(JSON.stringify(geom, null, 1));
|
|
cdp.close();
|
|
kill();
|