feat: player runtime for the Phone library and That New Teacher
CI / frontend (push) Failing after 17s
CI / backend (push) Failing after 34s

Named stores (PyNamespace: dotted access, functions that see their own store first, restored after a
save is loaded), real generators run step by step (next, send, yield as an expression), len/bool through
__len__/__bool__, os/calendar/itertools/pygame_sdl2 helpers, Skip and ToggleLocalVariable actions,
text tags {glitch} and {wave} and plain display of explode/gradient/ruby, SnowBlossom and anim.Blink,
RoundedCorners as a transform, transforms listed in `at`, ATL choice weights that are flags, and
renpy.image_size from the converter's picture sizes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-26 22:39:16 +03:00
1 parent 83cc7fdd5c
commit 11f87df712
15 files changed
+457 -24

No files matched your search

+32
View File
@@ -8,6 +8,38 @@ const runtime = original ? JSON.parse(readFileSync(original, "utf8")) : null;
const click = (element) => element.onclick({ stopPropagation() {}, preventDefault() {} });
const enter = (engine, label) => engine.restart(() => engine.guardedJump(label));
test("MIST's actual movie Skip survives a queued redraw and returns before its timer", { skip: !runtime }, async () => {
const { engine, root, window } = makeEngine(runtime);
globalThis.HTMLVideoElement = window.HTMLVideoElement ?? class {};
const played = [], stopped = [];
engine.audio.play = (...args) => played.push(args);
engine.audio.stop = (...args) => stopped.push(args);
engine.audio.mediaOf = () => null;
try {
engine.newStore();
Object.assign(engine.store, { movielength: 63, movieplaying: "images/animations/movies/Intro_Movie.webm" });
const completed = engine.exec({ op: "call_screen", name: "custommoviescreen", args: [], kw: {} });
const button = [...root.querySelectorAll(".pg-sbtn")].find((element) => element.textContent === "Skip");
assert.ok(button);
assert.equal(button.classList.contains("pg-sdisabled"), false);
engine.screens.refresh();
window.dispatchEvent(new window.Event("pointerdown"));
await until(() => engine.store.movielength < 63);
assert.equal(button.isConnected, true);
window.dispatchEvent(new window.Event("pointerup"));
click(button);
await completed;
assert.equal(engine.store._return, 0);
assert.ok(engine.store.movielength > 60, "Skip returns without waiting for the movie timer");
assert.equal(root.querySelector(".pg-sbtn"), null);
assert.equal(played[0][0], "movie");
assert.equal(stopped.at(-1)[0], "movie");
} finally {
window.dispatchEvent(new window.Event("pointercancel"));
engine.destroy();
}
});
test("MIST's actual raise-hand loop accepts screen input and resumes after a save", { skip: !runtime }, async () => {
const { engine, root } = makeEngine(runtime);
try {