Files
ModelTest20260714/Kimi-K3/tools/dbg16.mjs
T

132 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// dbg16:复现「面包无法提交」与「第一天睡觉卡死」
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,600)));
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 dlgText = () => ev(() => { const u = window.__game.scene.getScene('UIScene'); return u && u.dlgBody ? u.dlgBody.text : ''; });
async function drain(maxIter = 40) {
const texts = [];
for (let i = 0; i < maxIter; i++) {
if (!(await dlgOpen())) break;
texts.push(await dlgText());
const choosing = await ev(() => { const u = window.__game.scene.getScene('UIScene'); return u.showingChoices; });
await tap(choosing ? 'Digit1' : 'KeyE');
await sleep(160);
}
return texts;
}
async function startScene(k, spawn='default') {
await ev((k,s) => {
const sm = window.__game.scene;
for (const sc of sm.getScenes(true)) { const kk = sc.scene.key; if (kk !== 'UIScene' && kk !== k) sm.stop(kk); }
sm.start(k, { spawn: s });
}, k, spawn);
await page.waitForFunction((kk) => window.__game.scene.isActive(kk), { timeout: 9000 }, k);
await sleep(500);
}
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);
}
const dstate = () => ev(() => ({
day: window.__director.day,
breadTaken: window.__director.taskProgress['breadTaken'] ?? 0,
breadTo: [...(window.__director.taskSetProgress['breadTo'] ?? [])],
done: [...window.__director.tasksDone],
canSleep: window.__director.canSleep,
dlg: window.__director.dialogueActive,
}));
await sleep(600);
console.log('\n=== A. 面包任务提交 ===');
// 1. 面包房取面包
await startScene('BakeryScene');
await drain();
// counter_bread 交互区在地图对象里:从 JSON 读坐标
const cbObj = await ev(() => window.__game.scene.getScene('BakeryScene').interactZones.find(z => z.id === 'counter_bread'));
console.log('counter_bread zone:', cbObj);
await setPlayer('BakeryScene', cbObj.x + 40, cbObj.y + 40);
await setPlayer('BakeryScene', cbObj.x, cbObj.y + 8);
await tap('KeyE'); await sleep(400);
const t1 = await drain();
console.log('取面包对话:', t1);
console.log('状态:', await dstate());
// 2. 送 dabaoplaza
await startScene('PlazaScene');
await drain();
const dabao = await ev(() => { const s = window.__game.scene.getScene('PlazaScene'); const a = s.actors.find(a => a.def.id === 'dabao'); return { x: a.sprite.x, y: a.sprite.y }; });
await setPlayer('PlazaScene', dabao.x + 40, dabao.y + 40);
await setPlayer('PlazaScene', dabao.x, dabao.y + 8);
await tap('KeyE'); await sleep(400);
const t2 = await drain();
console.log('dabao 对话:', t2);
console.log('状态:', await dstate());
// 3. 送 mimishop)与 guiyeyelake
await startScene('ShopScene');
await drain();
const mimi = await ev(() => { const s = window.__game.scene.getScene('ShopScene'); const a = s.actors.find(a => a.def.id === 'mimi'); return { x: a.sprite.x, y: a.sprite.y }; });
await setPlayer('ShopScene', mimi.x + 40, mimi.y + 40);
await setPlayer('ShopScene', mimi.x, mimi.y + 8);
await tap('KeyE'); await sleep(400);
console.log('mimi 对话:', await drain());
console.log('状态:', await dstate());
await startScene('LakeScene');
await drain();
const gui = await ev(() => { const s = window.__game.scene.getScene('LakeScene'); const a = s.actors.find(a => a.def.id === 'guiyeye'); return { x: a.sprite.x, y: a.sprite.y }; });
await setPlayer('LakeScene', gui.x + 40, gui.y + 40);
await setPlayer('LakeScene', gui.x, gui.y + 8);
await tap('KeyE'); await sleep(400);
console.log('guiyeye 对话:', await drain());
console.log('状态:', await dstate());
console.log('\n=== B. 第一天睡觉(用户场景:任务未全了结,靠黄昏计时) ===');
await startScene('HouseScene');
await drain();
// 强制黄昏计时,使 canSleep=true(模拟用户等满 5 分钟)
await ev(() => { window.__director.dayElapsedMs = 300000; });
console.log('睡前状态:', await dstate());
// 走到床边按 E
const bed = await ev(() => window.__game.scene.getScene('HouseScene').interactZones.find(z => z.id === 'bed'));
await setPlayer('HouseScene', bed.x + 40, bed.y + 40);
await setPlayer('HouseScene', bed.x, bed.y + 8);
await tap('KeyE'); await sleep(400);
console.log('床交互后对话:', await drain());
// 采样 20 秒:场景序列与卡死点
for (let i = 0; i < 20; i++) {
const s = await ev(() => {
const sm = window.__game.scene;
return {
active: sm.getScenes(true).map(sc => sc.scene.key),
day: window.__director.day,
dlg: window.__director.dialogueActive,
uiPayload: (() => { const u = sm.getScene('UIScene'); return u && u.payload ? (u.payload.lines?.[0] ?? '').slice(0, 20) : null; })(),
};
});
console.log(`t+${(i+1)}s`, JSON.stringify(s));
// 模拟玩家按 E 推进梦境对话
if (s.uiPayload) { await tap('KeyE'); }
await sleep(1000);
}
console.log('最终状态:', await dstate());
await browser.close();
process.exit(0);