91 lines
3.4 KiB
JavaScript
91 lines
3.4 KiB
JavaScript
// act-gameplay.js — acts.html 上「玩法确实存在」的断言(M6 / issue #21)
|
||
//
|
||
// 这是 map-save-load.js 退役后,唯一还需要真浏览器的那部分:证明真地图场景里
|
||
// 怪物被生成进了世界、能被打死、掉落能被捡起、K/L 存读档走的是引擎的 tick 路径。
|
||
// 纯逻辑部分已经在 tests/engine-save-load.test.ts 与 tests/iso-terrain.test.ts 覆盖。
|
||
//
|
||
// CHROME=/usr/bin/google-chrome
|
||
// node scripts/browser/inspect-page.mjs "$CHROME" \
|
||
// "http://127.0.0.1:5173/acts.html?act=1" scripts/browser/checks/act-gameplay.js
|
||
(async () => {
|
||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
|
||
const press = (code, down) =>
|
||
window.dispatchEvent(new KeyboardEvent(down ? 'keydown' : 'keyup', { code, bubbles: true }))
|
||
const tap = async (code, ms) => { press(code, true); await sleep(ms); press(code, false); await sleep(60) }
|
||
|
||
const deadline = Date.now() + 120000
|
||
while (Date.now() < deadline) {
|
||
const s = window.__d2webAct
|
||
if (s && (s.ready || s.error)) break
|
||
await sleep(200)
|
||
}
|
||
const s = window.__d2webAct
|
||
if (s === undefined) return { error: 'no scene state' }
|
||
if (s.error) return { error: s.error }
|
||
|
||
await sleep(2000)
|
||
const spawned = {
|
||
monstersSpawned: s.monstersSpawned ?? null,
|
||
monstersAlive: s.monstersAlive ?? null,
|
||
npcs: s.npcs ?? null,
|
||
walkable: s.walkable,
|
||
}
|
||
|
||
// 追着打:四个方向各走一段并连续挥砍,直到有击杀或超时。
|
||
const dirs = ['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp']
|
||
const fightUntil = Date.now() + 40000
|
||
let round = 0
|
||
while (Date.now() < fightUntil && (window.__d2webAct?.kills ?? 0) === 0) {
|
||
const dir = dirs[round % dirs.length]
|
||
press(dir, true)
|
||
for (let i = 0; i < 6; i += 1) await tap('Space', 180)
|
||
press(dir, false)
|
||
await sleep(120)
|
||
round += 1
|
||
}
|
||
await sleep(400)
|
||
for (let i = 0; i < 8; i += 1) await tap('KeyE', 120)
|
||
await sleep(300)
|
||
|
||
const fought = {
|
||
kills: window.__d2webAct?.kills ?? null,
|
||
playerHits: window.__d2webAct?.playerHits ?? null,
|
||
dropsRolled: window.__d2webAct?.dropsRolled ?? null,
|
||
groundItems: window.__d2webAct?.groundItems ?? null,
|
||
pickups: window.__d2webAct?.pickups ?? null,
|
||
gold: window.__d2webAct?.gold ?? null,
|
||
bagItems: window.__d2webAct?.bagItems ?? null,
|
||
playerXp: window.__d2webAct?.playerXp ?? null,
|
||
playerHp: window.__d2webAct?.playerHp ?? null,
|
||
}
|
||
|
||
await tap('KeyK', 200)
|
||
await sleep(400)
|
||
const savedAt = { x: Math.round(window.__d2webAct?.x ?? 0), y: Math.round(window.__d2webAct?.y ?? 0), kills: window.__d2webAct?.kills ?? null }
|
||
|
||
press('ArrowRight', true); await sleep(2000); press('ArrowRight', false)
|
||
await sleep(400)
|
||
const drifted = { x: Math.round(window.__d2webAct?.x ?? 0), y: Math.round(window.__d2webAct?.y ?? 0) }
|
||
|
||
await tap('KeyL', 200)
|
||
await sleep(600)
|
||
const after = { x: Math.round(window.__d2webAct?.x ?? 0), y: Math.round(window.__d2webAct?.y ?? 0), kills: window.__d2webAct?.kills ?? null }
|
||
|
||
const gl = document.querySelector('#view')?.getContext('webgl2')
|
||
return {
|
||
source: s.source,
|
||
level: s.level,
|
||
spawned,
|
||
fought,
|
||
savedAt,
|
||
drifted,
|
||
after,
|
||
restored: after.x === savedAt.x && after.y === savedAt.y,
|
||
saves: window.__d2webAct?.saves ?? null,
|
||
loads: window.__d2webAct?.loads ?? null,
|
||
saveError: window.__d2webAct?.saveError ?? null,
|
||
tick: window.__d2webAct?.tick ?? null,
|
||
glError: gl ? gl.getError() : null,
|
||
}
|
||
})()
|