117 lines
6.6 KiB
JavaScript
117 lines
6.6 KiB
JavaScript
// dbg18:睡觉卡死根因验证(干净页面)
|
|
// A 基线:真实流程睡觉+连按 E,应正常过日到 D2
|
|
// B 嫌疑2:床淡出 400ms 内移动 30px 二次按 E → 是否双触发/卡死
|
|
// C 嫌疑1:梦境对话期间注入第二个 showDialogue → resolver 覆盖是否导致 run() 永久悬挂
|
|
import puppeteer from 'puppeteer-core';
|
|
import { spawn } from 'node:child_process';
|
|
import net from 'node:net';
|
|
const preview = spawn('npx', ['vite','preview','--host','127.0.0.1','--port','4815','--strictPort'], { stdio:'ignore' });
|
|
process.on('exit', () => { try{preview.kill()}catch{} });
|
|
for (let i=0;i<50;i++){ const ok = await new Promise(r=>{const s=net.connect(4815,'127.0.0.1');s.once('connect',()=>{s.end();r(true)});s.once('error',()=>r(false))}); if(ok)break; await new Promise(r=>setTimeout(r,300)); }
|
|
const browser = await puppeteer.launch({ executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', headless: true, args: ['--autoplay-policy=no-user-gesture-required','--mute-audio'] });
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 960, height: 560 });
|
|
page.on('pageerror', e => console.log('[pageerror]', (e.stack||e.message).slice(0,500)));
|
|
page.on('console', m => { if (m.type()==='error') console.log('[console.error]', m.text().slice(0,300)); });
|
|
await page.goto('http://127.0.0.1:4815/', { waitUntil: 'networkidle2' });
|
|
await page.waitForFunction('window.__game && window.__director', { timeout: 20000 });
|
|
await page.waitForFunction(() => window.__game.scene.isActive('TitleScene'), { timeout: 20000 });
|
|
await page.evaluate(() => { document.querySelector('#game input[type="text"]').closest('div').querySelector('button').click(); });
|
|
await page.waitForFunction(() => window.__game.scene.isActive('HouseScene'), { timeout: 15000 });
|
|
const sleep = (ms) => new Promise(r=>setTimeout(r,ms));
|
|
const tap = async (code, hold=90) => { await page.keyboard.down(code); await sleep(hold); await page.keyboard.up(code); await sleep(30); };
|
|
const ev = (fn, ...a) => page.evaluate(fn, ...a);
|
|
const dlgOpen = () => ev(() => { const u = window.__game.scene.getScene('UIScene'); return !!(u && u.payload); });
|
|
const state = (tag) => ev((tag) => {
|
|
const sm = window.__game.scene;
|
|
const d = window.__director;
|
|
return { tag, active: sm.getScenes(true).map(sc => sc.scene.key), day: d.day,
|
|
dlg: d.dialogueActive, celeb: d.celebrationActive, happy: d.happiness,
|
|
ui: (() => { const u = sm.getScene('UIScene'); return u && u.payload ? (u.payload.lines?.[0] ?? '').slice(0, 22) : null; })() };
|
|
}, tag).then(s => console.log(JSON.stringify(s)));
|
|
async function drain(maxIter = 30) {
|
|
for (let i = 0; i < maxIter; i++) { if (!(await dlgOpen())) break; await tap('KeyE'); await sleep(180); }
|
|
}
|
|
async function setPlayer(k, x, y) {
|
|
await ev((k,x,y) => { const s = window.__game.scene.getScene(k); s.player.setPosition(x, y); s.player.setVelocity(0,0); }, k, x, y);
|
|
await sleep(120);
|
|
}
|
|
async function restartHouse() {
|
|
await ev(() => {
|
|
window.__director.forceIdle();
|
|
const sm = window.__game.scene;
|
|
for (const sc of sm.getScenes(true)) { const k = sc.scene.key; if (k !== 'UIScene' && k !== 'HouseScene') sm.stop(k); }
|
|
if (!sm.isActive('HouseScene')) sm.start('HouseScene', { spawn: 'default' });
|
|
});
|
|
await page.waitForFunction(() => window.__game.scene.isActive('HouseScene'), { timeout: 9000 });
|
|
await sleep(400);
|
|
await drain();
|
|
}
|
|
await sleep(600);
|
|
|
|
console.log('\n=== A 基线:真实睡觉流程 + 连按 E ===');
|
|
await ev(() => { window.__director.dayElapsedMs = 300000; });
|
|
const bed = await ev(() => window.__game.scene.getScene('HouseScene').interactZones.find(z => z.id === 'bed'));
|
|
await setPlayer('HouseScene', bed.x, bed.y + 8);
|
|
await tap('KeyE');
|
|
let okA = false;
|
|
for (let i = 0; i < 24; i++) {
|
|
await sleep(500);
|
|
await state(`A t+${(i+1)*0.5}s`);
|
|
if (await dlgOpen()) await tap('KeyE');
|
|
const d = await ev(() => window.__director.day);
|
|
if (d === 2) { okA = true; console.log('A 结果: 正常过日到 D2 ✓'); break; }
|
|
}
|
|
if (!okA) console.log('A 结果: 卡死 ✗');
|
|
|
|
console.log('\n=== B 床淡出期间二次触发 ===');
|
|
await restartHouse();
|
|
await ev(() => { const d = window.__director; d.setDay(1); d.dayElapsedMs = 300000; });
|
|
await ev(() => { window.__dreamStarts = 0; const sm = window.__game.scene;
|
|
if (!sm.__patched) { const orig = sm.start.bind(sm); sm.start = (k, ...a) => { if (k === 'DreamScene') window.__dreamStarts++; return orig(k, ...a); }; sm.__patched = true; } });
|
|
const bedB = await ev(() => window.__game.scene.getScene('HouseScene').interactZones.find(z => z.id === 'bed'));
|
|
await setPlayer('HouseScene', bedB.x, bedB.y + 8);
|
|
await tap('KeyE');
|
|
await sleep(150);
|
|
await setPlayer('HouseScene', bedB.x + 40, bedB.y + 8); // 移开 >30px 重武装
|
|
await tap('KeyE'); // 二次按 E
|
|
let okB = false;
|
|
for (let i = 0; i < 24; i++) {
|
|
await sleep(500);
|
|
const extra = await ev(() => window.__dreamStarts);
|
|
await state(`B t+${(i+1)*0.5}s dreamStarts=${extra}`);
|
|
if (await dlgOpen()) await tap('KeyE');
|
|
const d = await ev(() => window.__director.day);
|
|
if (d === 2) { okB = true; console.log(`B 结果: 过日成功, DreamScene 启动次数=${extra}`); break; }
|
|
}
|
|
if (!okB) console.log('B 结果: 卡死 ✗');
|
|
|
|
console.log('\n=== C 梦境对话期间注入第二个 showDialogue ===');
|
|
await restartHouse();
|
|
await ev(() => { const d = window.__director; d.setDay(1); d.dayElapsedMs = 300000; });
|
|
const bedC = await ev(() => window.__game.scene.getScene('HouseScene').interactZones.find(z => z.id === 'bed'));
|
|
await setPlayer('HouseScene', bedC.x, bedC.y + 8);
|
|
await tap('KeyE');
|
|
await page.waitForFunction(() => window.__game.scene.isActive('DreamScene'), { timeout: 9000 });
|
|
await page.waitForFunction(() => { const u = window.__game.scene.getScene('UIScene'); return !!(u && u.payload); }, { timeout: 9000 });
|
|
await state('C 梦境第一行已开');
|
|
// 注入第二个 showDialogue(模拟resolver被覆盖)
|
|
await ev(() => { window.__injectedP = window.__director.showDialogue({ lines: ['【注入】测试对话'] }); window.__injectedP.then(r => { window.__injectedResolved = r; }); });
|
|
await sleep(300);
|
|
await state('C 注入后');
|
|
await drain(); // 按 E 关掉注入对话
|
|
await sleep(300);
|
|
await state('C 注入对话关闭后');
|
|
// 继续按 E 试图推进梦境
|
|
let okC = false;
|
|
for (let i = 0; i < 20; i++) {
|
|
await sleep(500);
|
|
await state(`C t+${(i+1)*0.5}s`);
|
|
if (await dlgOpen()) await tap('KeyE');
|
|
const d = await ev(() => window.__director.day);
|
|
if (d === 2) { okC = true; console.log('C 结果: 梦境继续并过日 ✓'); break; }
|
|
}
|
|
if (!okC) console.log('C 结果: 梦境 run() 永久悬挂 = 卡死根因证实 ✗');
|
|
await browser.close();
|
|
process.exit(0);
|