MCPcopy Create free account
hub / github.com/Monogatari/Monogatari / run

Function run

src/engine/lifecycle.ts:342–488  ·  view source on GitHub ↗
(engine: VisualNovelEngine, statement: unknown, shouldAdvance = true)

Source from the content-addressed store, hash-verified

340 * if it couldn't be run correctly.
341 */
342export async function run (engine: VisualNovelEngine, statement: unknown, shouldAdvance = true): Promise<{ advance: boolean }> {
343 // Capture current position at the start to detect if another advance happened
344 // during async operations (e.g., user click during Notification's willApply)
345 const initialStep = engine.state ('step') as number;
346 const initialLabel = engine.state ('label') as string;
347
348 const actions = engine.actions ();
349 const before: Promise<void>[] = actions.map (action => action.beforeRun ({ advance: shouldAdvance }));
350
351 await Promise.all (before);
352
353 // Don't allow null as a valid statement
354 if (statement === null) {
355 engine.debug.trace ();
356 engine.debug.groupEnd ();
357 throw new Error ('Statement was null.');
358 }
359
360 engine.debug.debug ('Preparing Action', statement);
361
362 if (typeof statement === 'function') {
363 engine.debug.groupCollapsed (`Run Cycle [JS Function]`);
364
365 // Block the game while the function is being run
366 engine.global ('block', true);
367
368 // Run the function asynchronously and after it has run, unblock
369 // the game so it can continue.
370 try {
371 const returnValue = await Util.callAsync (statement as (...args: unknown[]) => unknown, engine);
372
373 engine.global ('block', false);
374
375 engine.debug.groupEnd ();
376
377 if (shouldAdvance && returnValue !== false) {
378 // Only advance if we're still on the same step - another action might have
379 // already advanced the game (e.g., user clicked during async function)
380 const currentStep = engine.state ('step') as number;
381 const currentLabel = engine.state ('label') as string;
382 if (currentStep === initialStep && currentLabel === initialLabel) {
383 // TODO: Do we need to return here? We don't do it in the other run methods.
384 return engine.next ().then (() => ({ advance: true }));
385 } else {
386 engine.debug.debug ('Skipping auto-advance: game already advanced by another action');
387 }
388 }
389
390 return Promise.resolve ({ advance: false });
391 } catch (e: unknown) {
392 const error: FancyErrorProps = {
393 'Label': String(engine.state ('label')),
394 'Step': Number(engine.state ('step')),
395 'Help': {
396 '_': 'Check the code for your function, there may be additional information in the console.',
397 }
398 };
399

Callers 1

bindMethod · 0.85

Calls 14

prepareActionFunction · 0.85
stateMethod · 0.80
debugMethod · 0.80
globalMethod · 0.80
nextMethod · 0.80
triggerMethod · 0.80
afterRunMethod · 0.80
actionsMethod · 0.45
beforeRunMethod · 0.45
allMethod · 0.45
showMethod · 0.45
willApplyMethod · 0.45

Tested by

no test coverage detected