@momoyu-ink/kit 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bindings/AnimationFormat.js +0 -1
- package/dist/bindings/AnimationFrameCallbackEvent.js +0 -1
- package/dist/bindings/AnimationProps.js +0 -1
- package/dist/bindings/AudioCommand.d.ts +1 -0
- package/dist/bindings/AudioCommand.js +0 -1
- package/dist/bindings/AudioSettings.js +0 -1
- package/dist/bindings/BackdropProps.js +0 -1
- package/dist/bindings/BeforeUnloadEvent.d.ts +1 -1
- package/dist/bindings/BeforeUnloadEvent.js +0 -1
- package/dist/bindings/ClipProps.js +0 -1
- package/dist/bindings/CustomEvent.js +0 -1
- package/dist/bindings/EffectParams.js +0 -1
- package/dist/bindings/FilterKind.js +0 -1
- package/dist/bindings/FilterProps.js +0 -1
- package/dist/bindings/FocusEvent.js +0 -1
- package/dist/bindings/FocusEventKind.js +0 -1
- package/dist/bindings/FullScreenEvent.js +0 -1
- package/dist/bindings/FullscreenEventKind.js +0 -1
- package/dist/bindings/GameEvent.js +0 -1
- package/dist/bindings/Gamepad.js +0 -1
- package/dist/bindings/GamepadButton.js +0 -1
- package/dist/bindings/GamepadCommand.js +0 -1
- package/dist/bindings/GamepadEvent.js +0 -1
- package/dist/bindings/GamepadHapticActuator.js +0 -1
- package/dist/bindings/KeyboardEventKind.js +0 -1
- package/dist/bindings/KeyboardLocation.js +0 -1
- package/dist/bindings/Literal.d.ts +1 -1
- package/dist/bindings/Literal.js +0 -1
- package/dist/bindings/MouseEventKind.js +0 -1
- package/dist/bindings/MoyuCursor.js +0 -1
- package/dist/bindings/NineSliceMode.js +0 -1
- package/dist/bindings/NodeEvent.js +0 -1
- package/dist/bindings/NodeProps.js +0 -1
- package/dist/bindings/RawKeyboardEvent.js +0 -1
- package/dist/bindings/RawMouseEvent.js +0 -1
- package/dist/bindings/RawTouchEvent.js +0 -1
- package/dist/bindings/RawWheelEvent.d.ts +1 -0
- package/dist/bindings/RawWheelEvent.js +0 -1
- package/dist/bindings/ResizeEvent.js +0 -1
- package/dist/bindings/ResolvedArgument.js +0 -1
- package/dist/bindings/ResolvedCommandLine.js +0 -1
- package/dist/bindings/ResolvedSystemCallLine.js +0 -1
- package/dist/bindings/ScenarioCommand.d.ts +15 -2
- package/dist/bindings/ScenarioCommand.js +0 -1
- package/dist/bindings/ScenarioEvent.js +0 -1
- package/dist/bindings/SpriteMode.js +0 -1
- package/dist/bindings/SpriteProps.js +0 -1
- package/dist/bindings/SystemCommand.d.ts +2 -0
- package/dist/bindings/SystemCommand.js +0 -1
- package/dist/bindings/TextCommand.js +0 -1
- package/dist/bindings/TextEvent.js +0 -1
- package/dist/bindings/TextLine.js +0 -1
- package/dist/bindings/TextPrintMode.js +0 -1
- package/dist/bindings/TextProps.js +0 -1
- package/dist/bindings/TouchEventKind.js +0 -1
- package/dist/bindings/VideoCommand.d.ts +21 -0
- package/dist/bindings/VideoCommand.js +3 -0
- package/dist/bindings/VideoEvent.d.ts +1 -0
- package/dist/bindings/VideoEvent.js +3 -0
- package/dist/bindings/VideoProps.d.ts +7 -0
- package/dist/bindings/VideoProps.js +3 -0
- package/dist/bindings/WheelEventDeltaMode.js +0 -1
- package/dist/bindings/WindowState.js +0 -1
- package/dist/bindings/serde_json/JsonValue.d.ts +1 -1
- package/dist/bindings/serde_json/JsonValue.js +0 -1
- package/dist/commands.js +0 -1
- package/dist/components/navigation.js +0 -1
- package/dist/declaration.d.ts +6 -0
- package/dist/declaration.js +0 -1
- package/dist/events/base.js +0 -1
- package/dist/events/globals.js +2 -3
- package/dist/events/keyboard.js +0 -1
- package/dist/events/listener.js +0 -1
- package/dist/events/mouse.js +0 -1
- package/dist/events/touch.js +0 -1
- package/dist/events/wheel.d.ts +9 -0
- package/dist/events/wheel.js +2 -0
- package/dist/events.d.ts +1 -0
- package/dist/events.js +1 -1
- package/dist/hooks/useFadeInOut.js +0 -1
- package/dist/hooks/useScenario.js +0 -1
- package/dist/hooks/useSoundEffect.js +0 -1
- package/dist/hooks/useStage.d.ts +45 -4
- package/dist/hooks/useStage.js +335 -38
- package/dist/hooks.js +0 -1
- package/dist/lib.d.ts +1 -0
- package/dist/lib.js +1 -1
- package/dist/moyu.d.ts +1 -0
- package/dist/moyu.js +0 -1
- package/dist/node.js +0 -1
- package/dist/react.js +0 -1
- package/dist/runtime-globals.d.ts +2 -0
- package/dist/runtime-globals.js +0 -1
- package/dist/sandbox.d.ts +1 -0
- package/dist/sandbox.js +88 -0
- package/dist/spring/animated.js +0 -1
- package/dist/spring/index.js +0 -1
- package/dist/spring/primitives.js +10 -2
- package/dist/state.js +0 -1
- package/dist/utils.js +0 -1
- package/package.json +5 -3
- package/dist/bindings/AnimationFormat.js.map +0 -1
- package/dist/bindings/AnimationFrameCallbackEvent.js.map +0 -1
- package/dist/bindings/AnimationProps.js.map +0 -1
- package/dist/bindings/AudioCommand.js.map +0 -1
- package/dist/bindings/AudioSettings.js.map +0 -1
- package/dist/bindings/BackdropProps.js.map +0 -1
- package/dist/bindings/BeforeUnloadEvent.js.map +0 -1
- package/dist/bindings/ClipProps.js.map +0 -1
- package/dist/bindings/CustomEvent.js.map +0 -1
- package/dist/bindings/EffectParams.js.map +0 -1
- package/dist/bindings/FilterKind.js.map +0 -1
- package/dist/bindings/FilterProps.js.map +0 -1
- package/dist/bindings/FocusEvent.js.map +0 -1
- package/dist/bindings/FocusEventKind.js.map +0 -1
- package/dist/bindings/FullScreenEvent.js.map +0 -1
- package/dist/bindings/FullscreenEventKind.js.map +0 -1
- package/dist/bindings/GameEvent.js.map +0 -1
- package/dist/bindings/Gamepad.js.map +0 -1
- package/dist/bindings/GamepadButton.js.map +0 -1
- package/dist/bindings/GamepadCommand.js.map +0 -1
- package/dist/bindings/GamepadEvent.js.map +0 -1
- package/dist/bindings/GamepadHapticActuator.js.map +0 -1
- package/dist/bindings/KeyboardEventKind.js.map +0 -1
- package/dist/bindings/KeyboardLocation.js.map +0 -1
- package/dist/bindings/Literal.js.map +0 -1
- package/dist/bindings/MouseEventKind.js.map +0 -1
- package/dist/bindings/MoyuCursor.js.map +0 -1
- package/dist/bindings/NineSliceMode.js.map +0 -1
- package/dist/bindings/NodeEvent.js.map +0 -1
- package/dist/bindings/NodeProps.js.map +0 -1
- package/dist/bindings/RawKeyboardEvent.js.map +0 -1
- package/dist/bindings/RawMouseEvent.js.map +0 -1
- package/dist/bindings/RawTouchEvent.js.map +0 -1
- package/dist/bindings/RawWheelEvent.js.map +0 -1
- package/dist/bindings/ResizeEvent.js.map +0 -1
- package/dist/bindings/ResolvedArgument.js.map +0 -1
- package/dist/bindings/ResolvedCommandLine.js.map +0 -1
- package/dist/bindings/ResolvedSystemCallLine.js.map +0 -1
- package/dist/bindings/ScenarioCommand.js.map +0 -1
- package/dist/bindings/ScenarioEvent.js.map +0 -1
- package/dist/bindings/SpriteMode.js.map +0 -1
- package/dist/bindings/SpriteProps.js.map +0 -1
- package/dist/bindings/SystemCommand.js.map +0 -1
- package/dist/bindings/TextCommand.js.map +0 -1
- package/dist/bindings/TextEvent.js.map +0 -1
- package/dist/bindings/TextLine.js.map +0 -1
- package/dist/bindings/TextPrintMode.js.map +0 -1
- package/dist/bindings/TextProps.js.map +0 -1
- package/dist/bindings/TouchEventKind.js.map +0 -1
- package/dist/bindings/WheelEventDeltaMode.js.map +0 -1
- package/dist/bindings/WindowState.js.map +0 -1
- package/dist/bindings/serde_json/JsonValue.js.map +0 -1
- package/dist/commands.js.map +0 -1
- package/dist/components/navigation.js.map +0 -1
- package/dist/declaration.js.map +0 -1
- package/dist/events/base.js.map +0 -1
- package/dist/events/globals.js.map +0 -1
- package/dist/events/keyboard.js.map +0 -1
- package/dist/events/listener.js.map +0 -1
- package/dist/events/mouse.js.map +0 -1
- package/dist/events/touch.js.map +0 -1
- package/dist/events.js.map +0 -1
- package/dist/hooks/useFadeInOut.js.map +0 -1
- package/dist/hooks/useScenario.js.map +0 -1
- package/dist/hooks/useSoundEffect.js.map +0 -1
- package/dist/hooks/useStage.js.map +0 -1
- package/dist/hooks.js.map +0 -1
- package/dist/lib.js.map +0 -1
- package/dist/moyu.js.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/runtime-globals.js.map +0 -1
- package/dist/spring/animated.js.map +0 -1
- package/dist/spring/index.js.map +0 -1
- package/dist/spring/primitives.js.map +0 -1
- package/dist/state.js.map +0 -1
- package/dist/utils.js.map +0 -1
package/dist/hooks/useStage.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ZodType } from 'zod';
|
|
2
|
-
import { TextLine } from '../events';
|
|
2
|
+
import { ResolvedCommandLine, TextLine } from '../events';
|
|
3
3
|
/** Flow control interface passed to every handler. */
|
|
4
4
|
export interface GameControl {
|
|
5
5
|
/** Timed wait — blocks auto-advance. Engine fires scenariowaitingcancelled on timeout or skip. */
|
|
@@ -10,6 +10,8 @@ export interface GameControl {
|
|
|
10
10
|
nextLine(): void;
|
|
11
11
|
/** Mark this dispatch cycle as unskippable. If skipping, hold() will stop skip instead of advancing. */
|
|
12
12
|
unskippable(): void;
|
|
13
|
+
/** Record the current runtime snapshot for backlog usage. */
|
|
14
|
+
record(meta: Record<string, any>): string;
|
|
13
15
|
}
|
|
14
16
|
export interface ScenarioCommandBaseType {
|
|
15
17
|
command: string;
|
|
@@ -19,12 +21,28 @@ export interface ScenarioCommandBaseType {
|
|
|
19
21
|
export type CommandHandler<T extends ScenarioCommandBaseType = ScenarioCommandBaseType> = (cmd: T, control: GameControl) => void;
|
|
20
22
|
/** Text line handler function. */
|
|
21
23
|
export type TextLineHandler = (text: TextLine, control: GameControl) => void;
|
|
24
|
+
export interface AutoTicketOptions {
|
|
25
|
+
label?: string;
|
|
26
|
+
tailMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface AutoTicketHandle {
|
|
29
|
+
done(): void;
|
|
30
|
+
cancel(): void;
|
|
31
|
+
}
|
|
22
32
|
/** Reactive skip state. Actors read via useIsSkipping(). */
|
|
23
33
|
export declare const skipState: {
|
|
24
34
|
active: boolean;
|
|
25
35
|
};
|
|
36
|
+
/** Reactive auto state. Actors read via useIsAutoing(). */
|
|
37
|
+
export declare const autoState: {
|
|
38
|
+
active: boolean;
|
|
39
|
+
};
|
|
26
40
|
/** Reactively returns whether skip (Ctrl fast-forward) is active. */
|
|
27
41
|
export declare function useIsSkipping(): boolean;
|
|
42
|
+
/** Reactively returns whether auto mode is active. */
|
|
43
|
+
export declare function useIsAutoing(): boolean;
|
|
44
|
+
/** Set the default tail delay in milliseconds for newly created auto tickets. */
|
|
45
|
+
export declare function setDefaultAutoTailMs(ms: number): void;
|
|
28
46
|
export declare function createStage(): {
|
|
29
47
|
registerCommandSchema: <T extends ZodType>(schema: T) => () => void;
|
|
30
48
|
registerCommand: <T extends ScenarioCommandBaseType>(commands: string | string[], handler: CommandHandler<T>) => () => void;
|
|
@@ -32,11 +50,16 @@ export declare function createStage(): {
|
|
|
32
50
|
addSkipCallback: (cb: () => void) => () => void;
|
|
33
51
|
addInterruptCallback: (cb: () => boolean) => () => void;
|
|
34
52
|
addSkipBlocker: (cb: () => boolean) => () => void;
|
|
35
|
-
|
|
53
|
+
addAutoBlocker: (cb: () => boolean) => () => void;
|
|
54
|
+
addBeforeHandleCommandCallback: (cb: (upcomingCommand: ResolvedCommandLine) => void) => () => void;
|
|
55
|
+
issueAutoTicket: (options?: AutoTicketOptions) => AutoTicketHandle | null;
|
|
36
56
|
tryInterrupt: () => boolean;
|
|
37
57
|
startSkip: () => void;
|
|
38
58
|
stopSkip: () => void;
|
|
39
59
|
isSkipping: () => boolean;
|
|
60
|
+
startAuto: () => void;
|
|
61
|
+
stopAuto: () => void;
|
|
62
|
+
isAutoing: () => boolean;
|
|
40
63
|
bindEvents: () => () => void;
|
|
41
64
|
};
|
|
42
65
|
export type StageInstance = ReturnType<typeof createStage>;
|
|
@@ -52,11 +75,16 @@ export declare function StageContextProvider({ stage, children }: {
|
|
|
52
75
|
addSkipCallback: (cb: () => void) => () => void;
|
|
53
76
|
addInterruptCallback: (cb: () => boolean) => () => void;
|
|
54
77
|
addSkipBlocker: (cb: () => boolean) => () => void;
|
|
55
|
-
|
|
78
|
+
addAutoBlocker: (cb: () => boolean) => () => void;
|
|
79
|
+
addBeforeHandleCommandCallback: (cb: (upcomingCommand: ResolvedCommandLine) => void) => () => void;
|
|
80
|
+
issueAutoTicket: (options?: AutoTicketOptions) => AutoTicketHandle | null;
|
|
56
81
|
tryInterrupt: () => boolean;
|
|
57
82
|
startSkip: () => void;
|
|
58
83
|
stopSkip: () => void;
|
|
59
84
|
isSkipping: () => boolean;
|
|
85
|
+
startAuto: () => void;
|
|
86
|
+
stopAuto: () => void;
|
|
87
|
+
isAutoing: () => boolean;
|
|
60
88
|
bindEvents: () => () => void;
|
|
61
89
|
} | null>>;
|
|
62
90
|
/**
|
|
@@ -78,8 +106,21 @@ export declare function useInterruptCallback(callback: () => boolean): void;
|
|
|
78
106
|
* NOTE: `callback` must be a stable reference (wrap with `useCallback`).
|
|
79
107
|
*/
|
|
80
108
|
export declare function useSkipBlocker(callback: () => boolean): void;
|
|
109
|
+
/**
|
|
110
|
+
* Register an auto blocker callback. Return `true` to block auto mode.
|
|
111
|
+
* Automatically removed on unmount.
|
|
112
|
+
*
|
|
113
|
+
* NOTE: `callback` must be a stable reference (wrap with `useCallback`).
|
|
114
|
+
*/
|
|
115
|
+
export declare function useAutoBlocker(callback: () => boolean): void;
|
|
116
|
+
/**
|
|
117
|
+
* Get a function that issues an auto ticket for the current active barrier.
|
|
118
|
+
* Returns `null` when auto is inactive or the collection window has closed.
|
|
119
|
+
*/
|
|
120
|
+
export declare function useAutoTicket(): (options?: AutoTicketOptions) => AutoTicketHandle | null;
|
|
81
121
|
/**
|
|
82
122
|
* Register a callback to be invoked before handling each command.
|
|
123
|
+
* The callback receives the upcoming command object, allowing conditional logic.
|
|
83
124
|
* Automatically removed on unmount.
|
|
84
125
|
*/
|
|
85
|
-
export declare function useBeforeHandleCommandCallback(callback: () => void): void;
|
|
126
|
+
export declare function useBeforeHandleCommandCallback(callback: (upcomingCommand: ResolvedCommandLine) => void): void;
|
package/dist/hooks/useStage.js
CHANGED
|
@@ -1,28 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.skipState = void 0;
|
|
3
|
+
exports.autoState = exports.skipState = void 0;
|
|
4
4
|
exports.useIsSkipping = useIsSkipping;
|
|
5
|
+
exports.useIsAutoing = useIsAutoing;
|
|
6
|
+
exports.setDefaultAutoTailMs = setDefaultAutoTailMs;
|
|
5
7
|
exports.createStage = createStage;
|
|
6
8
|
exports.useStageContext = useStageContext;
|
|
7
9
|
exports.StageContextProvider = StageContextProvider;
|
|
8
10
|
exports.useSkipCallback = useSkipCallback;
|
|
9
11
|
exports.useInterruptCallback = useInterruptCallback;
|
|
10
12
|
exports.useSkipBlocker = useSkipBlocker;
|
|
13
|
+
exports.useAutoBlocker = useAutoBlocker;
|
|
14
|
+
exports.useAutoTicket = useAutoTicket;
|
|
11
15
|
exports.useBeforeHandleCommandCallback = useBeforeHandleCommandCallback;
|
|
12
16
|
const react_1 = require("react");
|
|
13
17
|
const valtio_1 = require("valtio");
|
|
14
18
|
const useScenario_1 = require("./useScenario");
|
|
15
19
|
const events_1 = require("../events");
|
|
20
|
+
const moyu_1 = require("../moyu");
|
|
16
21
|
// ---------------------------------------------------------------------------
|
|
17
22
|
// Skip state — independent valtio proxy (not serialized with game saves)
|
|
18
23
|
// ---------------------------------------------------------------------------
|
|
19
24
|
const SKIP_INTERVAL_MS = 5;
|
|
25
|
+
const autoRuntime = {
|
|
26
|
+
defaultTailMs: 0,
|
|
27
|
+
};
|
|
20
28
|
/** Reactive skip state. Actors read via useIsSkipping(). */
|
|
21
29
|
exports.skipState = (0, valtio_1.proxy)({ active: false });
|
|
30
|
+
/** Reactive auto state. Actors read via useIsAutoing(). */
|
|
31
|
+
exports.autoState = (0, valtio_1.proxy)({ active: false });
|
|
22
32
|
/** Reactively returns whether skip (Ctrl fast-forward) is active. */
|
|
23
33
|
function useIsSkipping() {
|
|
24
34
|
return (0, valtio_1.useSnapshot)(exports.skipState).active;
|
|
25
35
|
}
|
|
36
|
+
/** Reactively returns whether auto mode is active. */
|
|
37
|
+
function useIsAutoing() {
|
|
38
|
+
return (0, valtio_1.useSnapshot)(exports.autoState).active;
|
|
39
|
+
}
|
|
40
|
+
/** Set the default tail delay in milliseconds for newly created auto tickets. */
|
|
41
|
+
function setDefaultAutoTailMs(ms) {
|
|
42
|
+
if (!Number.isFinite(ms)) {
|
|
43
|
+
autoRuntime.defaultTailMs = 0;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
autoRuntime.defaultTailMs = Math.max(0, ms);
|
|
47
|
+
}
|
|
26
48
|
// ---------------------------------------------------------------------------
|
|
27
49
|
// createStage — module-level infrastructure
|
|
28
50
|
// ---------------------------------------------------------------------------
|
|
@@ -34,8 +56,18 @@ function createStage() {
|
|
|
34
56
|
const skipCallbacks = [];
|
|
35
57
|
const interruptCallbacks = [];
|
|
36
58
|
const skipBlockers = [];
|
|
59
|
+
const autoBlockers = [];
|
|
37
60
|
const beforeHandleCommandCallbacks = [];
|
|
38
61
|
// --- registration functions ---
|
|
62
|
+
/** Push `item` to `registry` and return a function that removes it. */
|
|
63
|
+
function addToRegistry(registry, item) {
|
|
64
|
+
registry.push(item);
|
|
65
|
+
return () => {
|
|
66
|
+
const idx = registry.indexOf(item);
|
|
67
|
+
if (idx !== -1)
|
|
68
|
+
registry.splice(idx, 1);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
39
71
|
/**
|
|
40
72
|
* Register command schema.
|
|
41
73
|
* Returns an unregister function.
|
|
@@ -76,24 +108,14 @@ function createStage() {
|
|
|
76
108
|
* Returns an unregister function.
|
|
77
109
|
*/
|
|
78
110
|
function registerTextLine(handler) {
|
|
79
|
-
textLineHandlers
|
|
80
|
-
return () => {
|
|
81
|
-
const idx = textLineHandlers.indexOf(handler);
|
|
82
|
-
if (idx !== -1)
|
|
83
|
-
textLineHandlers.splice(idx, 1);
|
|
84
|
-
};
|
|
111
|
+
return addToRegistry(textLineHandlers, handler);
|
|
85
112
|
}
|
|
86
113
|
/**
|
|
87
114
|
* Add a skip callback (called when scenariowaitingcancelled fires).
|
|
88
115
|
* Returns a remove function.
|
|
89
116
|
*/
|
|
90
117
|
function addSkipCallback(cb) {
|
|
91
|
-
skipCallbacks
|
|
92
|
-
return () => {
|
|
93
|
-
const idx = skipCallbacks.indexOf(cb);
|
|
94
|
-
if (idx !== -1)
|
|
95
|
-
skipCallbacks.splice(idx, 1);
|
|
96
|
-
};
|
|
118
|
+
return addToRegistry(skipCallbacks, cb);
|
|
97
119
|
}
|
|
98
120
|
/**
|
|
99
121
|
* Add an interrupt callback (called on user click, in order).
|
|
@@ -101,12 +123,7 @@ function createStage() {
|
|
|
101
123
|
* Returns a remove function.
|
|
102
124
|
*/
|
|
103
125
|
function addInterruptCallback(cb) {
|
|
104
|
-
interruptCallbacks
|
|
105
|
-
return () => {
|
|
106
|
-
const idx = interruptCallbacks.indexOf(cb);
|
|
107
|
-
if (idx !== -1)
|
|
108
|
-
interruptCallbacks.splice(idx, 1);
|
|
109
|
-
};
|
|
126
|
+
return addToRegistry(interruptCallbacks, cb);
|
|
110
127
|
}
|
|
111
128
|
/**
|
|
112
129
|
* Try to interrupt: iterate through interrupt callbacks until one returns true.
|
|
@@ -130,12 +147,7 @@ function createStage() {
|
|
|
130
147
|
* Returns a remove function.
|
|
131
148
|
*/
|
|
132
149
|
function addSkipBlocker(cb) {
|
|
133
|
-
skipBlockers
|
|
134
|
-
return () => {
|
|
135
|
-
const idx = skipBlockers.indexOf(cb);
|
|
136
|
-
if (idx !== -1)
|
|
137
|
-
skipBlockers.splice(idx, 1);
|
|
138
|
-
};
|
|
150
|
+
return addToRegistry(skipBlockers, cb);
|
|
139
151
|
}
|
|
140
152
|
/** Returns true if any registered skip blocker is active. */
|
|
141
153
|
function isAnyBlockerActive() {
|
|
@@ -150,19 +162,230 @@ function createStage() {
|
|
|
150
162
|
}
|
|
151
163
|
return false;
|
|
152
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Add an auto blocker callback. Return `true` from the callback to block auto mode.
|
|
167
|
+
* Returns a remove function.
|
|
168
|
+
*/
|
|
169
|
+
function addAutoBlocker(cb) {
|
|
170
|
+
return addToRegistry(autoBlockers, cb);
|
|
171
|
+
}
|
|
172
|
+
/** Returns true if any registered auto blocker is active. */
|
|
173
|
+
function isAnyAutoBlockerActive() {
|
|
174
|
+
for (const cb of autoBlockers) {
|
|
175
|
+
try {
|
|
176
|
+
if (cb())
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
console.error('Error in auto blocker callback:', err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
153
185
|
/** Add a callback to be invoked before handling each command. */
|
|
154
186
|
function addBeforeHandleCommandCallback(cb) {
|
|
155
|
-
beforeHandleCommandCallbacks
|
|
156
|
-
return () => {
|
|
157
|
-
const idx = beforeHandleCommandCallbacks.indexOf(cb);
|
|
158
|
-
if (idx !== -1)
|
|
159
|
-
beforeHandleCommandCallbacks.splice(idx, 1);
|
|
160
|
-
};
|
|
187
|
+
return addToRegistry(beforeHandleCommandCallbacks, cb);
|
|
161
188
|
}
|
|
162
189
|
// --- skip (Ctrl fast-forward) management ---
|
|
163
190
|
let _skipTimer = null;
|
|
191
|
+
let _autoTimer = null;
|
|
192
|
+
let _autoBarrier = null;
|
|
193
|
+
let _autoResumeTimer = null;
|
|
194
|
+
let _autoCollectFrame = null;
|
|
195
|
+
let _autoBarrierSeq = 0;
|
|
196
|
+
let _autoTicketSeq = 0;
|
|
197
|
+
const _pendingAutoTickets = new Map();
|
|
198
|
+
function clearAutoResumeTimer() {
|
|
199
|
+
if (_autoResumeTimer !== null) {
|
|
200
|
+
clearTimeout(_autoResumeTimer);
|
|
201
|
+
_autoResumeTimer = null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function clearAutoCollectFrame() {
|
|
205
|
+
if (_autoCollectFrame !== null) {
|
|
206
|
+
cancelAnimationFrame(_autoCollectFrame);
|
|
207
|
+
_autoCollectFrame = null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function clearAutoBarrier() {
|
|
211
|
+
clearAutoCollectFrame();
|
|
212
|
+
clearAutoResumeTimer();
|
|
213
|
+
_autoBarrier = null;
|
|
214
|
+
}
|
|
215
|
+
function clearPendingAutoTickets() {
|
|
216
|
+
_pendingAutoTickets.clear();
|
|
217
|
+
}
|
|
218
|
+
function getActiveAutoBarrier(barrierId) {
|
|
219
|
+
if (_autoBarrier === null || _autoBarrier.id !== barrierId) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
return _autoBarrier;
|
|
223
|
+
}
|
|
224
|
+
function scheduleAutoResume(barrierId, delayMs) {
|
|
225
|
+
clearAutoResumeTimer();
|
|
226
|
+
const safeDelayMs = Number.isFinite(delayMs) ? Math.max(0, delayMs) : 0;
|
|
227
|
+
_autoResumeTimer = setTimeout(() => {
|
|
228
|
+
_autoResumeTimer = null;
|
|
229
|
+
if (!exports.autoState.active)
|
|
230
|
+
return;
|
|
231
|
+
if (_autoBarrier === null || _autoBarrier.id !== barrierId)
|
|
232
|
+
return;
|
|
233
|
+
_autoBarrier = null;
|
|
234
|
+
void (0, useScenario_1.nextLine)();
|
|
235
|
+
}, safeDelayMs);
|
|
236
|
+
}
|
|
237
|
+
function trySettleAutoBarrier(barrier) {
|
|
238
|
+
if (barrier.collecting || barrier.settled)
|
|
239
|
+
return;
|
|
240
|
+
const activeTickets = [...barrier.tickets.values()].filter((ticket) => !ticket.canceled);
|
|
241
|
+
const hasPending = activeTickets.some((ticket) => ticket.doneAt === null);
|
|
242
|
+
if (hasPending)
|
|
243
|
+
return;
|
|
244
|
+
const latestTicketReadyAt = activeTickets.reduce((maxReadyAt, ticket) => {
|
|
245
|
+
const ticketReadyAt = (ticket.doneAt ?? barrier.openedAt) + ticket.tailMs;
|
|
246
|
+
return Math.max(maxReadyAt, ticketReadyAt);
|
|
247
|
+
}, barrier.fallbackReadyAt);
|
|
248
|
+
barrier.settled = true;
|
|
249
|
+
scheduleAutoResume(barrier.id, latestTicketReadyAt - Date.now());
|
|
250
|
+
}
|
|
251
|
+
function closeAutoCollection(barrierId) {
|
|
252
|
+
const barrier = getActiveAutoBarrier(barrierId);
|
|
253
|
+
if (barrier === null || barrier.settled)
|
|
254
|
+
return;
|
|
255
|
+
barrier.collecting = false;
|
|
256
|
+
trySettleAutoBarrier(barrier);
|
|
257
|
+
}
|
|
258
|
+
function scheduleAutoCollectionClose(barrierId) {
|
|
259
|
+
queueMicrotask(() => {
|
|
260
|
+
const barrier = getActiveAutoBarrier(barrierId);
|
|
261
|
+
if (barrier === null || barrier.settled)
|
|
262
|
+
return;
|
|
263
|
+
_autoCollectFrame = requestAnimationFrame(() => {
|
|
264
|
+
_autoCollectFrame = null;
|
|
265
|
+
closeAutoCollection(barrierId);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function markAutoTicketDone(ticket) {
|
|
270
|
+
if (ticket.canceled || ticket.doneAt !== null)
|
|
271
|
+
return;
|
|
272
|
+
ticket.doneAt = Date.now();
|
|
273
|
+
if (ticket.barrierId === null)
|
|
274
|
+
return;
|
|
275
|
+
const barrier = getActiveAutoBarrier(ticket.barrierId);
|
|
276
|
+
if (barrier === null || barrier.settled)
|
|
277
|
+
return;
|
|
278
|
+
trySettleAutoBarrier(barrier);
|
|
279
|
+
}
|
|
280
|
+
function cancelAutoTicket(ticket) {
|
|
281
|
+
if (ticket.canceled)
|
|
282
|
+
return;
|
|
283
|
+
ticket.canceled = true;
|
|
284
|
+
if (ticket.barrierId === null) {
|
|
285
|
+
_pendingAutoTickets.delete(ticket.id);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const barrier = getActiveAutoBarrier(ticket.barrierId);
|
|
289
|
+
if (barrier === null || barrier.settled)
|
|
290
|
+
return;
|
|
291
|
+
trySettleAutoBarrier(barrier);
|
|
292
|
+
}
|
|
293
|
+
function createAutoTicketHandle(ticket) {
|
|
294
|
+
return {
|
|
295
|
+
done() {
|
|
296
|
+
markAutoTicketDone(ticket);
|
|
297
|
+
},
|
|
298
|
+
cancel() {
|
|
299
|
+
cancelAutoTicket(ticket);
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function schedulePendingAutoTicketExpiry(ticketId) {
|
|
304
|
+
queueMicrotask(() => {
|
|
305
|
+
requestAnimationFrame(() => {
|
|
306
|
+
_pendingAutoTickets.delete(ticketId);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
function createPendingAutoTicket(options) {
|
|
311
|
+
const ticketId = ++_autoTicketSeq;
|
|
312
|
+
const ticket = {
|
|
313
|
+
id: ticketId,
|
|
314
|
+
label: options?.label,
|
|
315
|
+
tailMs: options?.tailMs ?? autoRuntime.defaultTailMs,
|
|
316
|
+
doneAt: null,
|
|
317
|
+
canceled: false,
|
|
318
|
+
barrierId: null,
|
|
319
|
+
};
|
|
320
|
+
_pendingAutoTickets.set(ticketId, ticket);
|
|
321
|
+
schedulePendingAutoTicketExpiry(ticketId);
|
|
322
|
+
return createAutoTicketHandle(ticket);
|
|
323
|
+
}
|
|
324
|
+
function adoptPendingAutoTickets(barrier) {
|
|
325
|
+
for (const [ticketId, ticket] of _pendingAutoTickets) {
|
|
326
|
+
_pendingAutoTickets.delete(ticketId);
|
|
327
|
+
if (ticket.canceled)
|
|
328
|
+
continue;
|
|
329
|
+
ticket.barrierId = barrier.id;
|
|
330
|
+
barrier.tickets.set(ticketId, ticket);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function openAutoBarrier(reason, fallbackMs) {
|
|
334
|
+
const safeFallbackMs = Number.isFinite(fallbackMs) ? Math.max(0, fallbackMs) : 0;
|
|
335
|
+
clearAutoBarrier();
|
|
336
|
+
_autoBarrier = {
|
|
337
|
+
id: ++_autoBarrierSeq,
|
|
338
|
+
reason,
|
|
339
|
+
collecting: true,
|
|
340
|
+
openedAt: Date.now(),
|
|
341
|
+
fallbackReadyAt: Date.now() + safeFallbackMs,
|
|
342
|
+
tickets: new Map(),
|
|
343
|
+
settled: false,
|
|
344
|
+
};
|
|
345
|
+
adoptPendingAutoTickets(_autoBarrier);
|
|
346
|
+
scheduleAutoCollectionClose(_autoBarrier.id);
|
|
347
|
+
}
|
|
348
|
+
function issueAutoTicket(options) {
|
|
349
|
+
if (!exports.autoState.active) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
if (_autoBarrier === null) {
|
|
353
|
+
return createPendingAutoTicket(options);
|
|
354
|
+
}
|
|
355
|
+
if (!_autoBarrier.collecting || _autoBarrier.settled) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
const ticketId = ++_autoTicketSeq;
|
|
359
|
+
const ticket = {
|
|
360
|
+
id: ticketId,
|
|
361
|
+
label: options?.label,
|
|
362
|
+
tailMs: options?.tailMs ?? autoRuntime.defaultTailMs,
|
|
363
|
+
doneAt: null,
|
|
364
|
+
canceled: false,
|
|
365
|
+
barrierId: _autoBarrier.id,
|
|
366
|
+
};
|
|
367
|
+
_autoBarrier.tickets.set(ticketId, ticket);
|
|
368
|
+
return createAutoTicketHandle(ticket);
|
|
369
|
+
}
|
|
370
|
+
/** Schedule a delayed nextLine() call for the auto. */
|
|
371
|
+
function scheduleAutoNextLine() {
|
|
372
|
+
if (_autoTimer !== null)
|
|
373
|
+
clearTimeout(_autoTimer);
|
|
374
|
+
_autoTimer = setTimeout(() => {
|
|
375
|
+
_autoTimer = null;
|
|
376
|
+
if (!exports.autoState.active)
|
|
377
|
+
return;
|
|
378
|
+
if (isAnyAutoBlockerActive()) {
|
|
379
|
+
stopAuto();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (_autoBarrier === null) {
|
|
383
|
+
void (0, useScenario_1.nextLine)();
|
|
384
|
+
}
|
|
385
|
+
}, autoRuntime.defaultTailMs);
|
|
386
|
+
}
|
|
164
387
|
/** Schedule a delayed nextLine() call for the skip chain. */
|
|
165
|
-
function
|
|
388
|
+
function scheduleSkipNextLine() {
|
|
166
389
|
if (_skipTimer !== null)
|
|
167
390
|
clearTimeout(_skipTimer);
|
|
168
391
|
_skipTimer = setTimeout(() => {
|
|
@@ -180,7 +403,7 @@ function createStage() {
|
|
|
180
403
|
exports.skipState.active = true;
|
|
181
404
|
invokeSkipCallbacks(); // finish current animations
|
|
182
405
|
tryInterrupt(); // finish current printing
|
|
183
|
-
|
|
406
|
+
scheduleSkipNextLine(); // kick off the chain
|
|
184
407
|
}
|
|
185
408
|
/** Exit skip mode. Called when Ctrl is released, window blurs, or Stage unmounts. */
|
|
186
409
|
function stopSkip() {
|
|
@@ -195,6 +418,27 @@ function createStage() {
|
|
|
195
418
|
function isSkipping() {
|
|
196
419
|
return exports.skipState.active;
|
|
197
420
|
}
|
|
421
|
+
function startAuto() {
|
|
422
|
+
if (exports.autoState.active)
|
|
423
|
+
return;
|
|
424
|
+
if (isAnyAutoBlockerActive())
|
|
425
|
+
return;
|
|
426
|
+
exports.autoState.active = true;
|
|
427
|
+
tryInterrupt(); // finish current printing
|
|
428
|
+
scheduleAutoNextLine(); // kick off the chain
|
|
429
|
+
}
|
|
430
|
+
function stopAuto() {
|
|
431
|
+
exports.autoState.active = false;
|
|
432
|
+
if (_autoTimer !== null) {
|
|
433
|
+
clearTimeout(_autoTimer);
|
|
434
|
+
_autoTimer = null;
|
|
435
|
+
}
|
|
436
|
+
clearAutoBarrier();
|
|
437
|
+
clearPendingAutoTickets();
|
|
438
|
+
}
|
|
439
|
+
function isAutoing() {
|
|
440
|
+
return exports.autoState.active;
|
|
441
|
+
}
|
|
198
442
|
// --- internal helpers ---
|
|
199
443
|
/** Build a one-shot GameControl for a single dispatch cycle. */
|
|
200
444
|
function buildControl() {
|
|
@@ -206,7 +450,16 @@ function createStage() {
|
|
|
206
450
|
if (exports.skipState.active) {
|
|
207
451
|
// Skip mode: finish residual animations and continue the chain
|
|
208
452
|
invokeSkipCallbacks();
|
|
209
|
-
|
|
453
|
+
scheduleSkipNextLine();
|
|
454
|
+
}
|
|
455
|
+
else if (exports.autoState.active) {
|
|
456
|
+
if (isAnyAutoBlockerActive()) {
|
|
457
|
+
stopAuto();
|
|
458
|
+
(0, useScenario_1.setWaiting)(time, skippable);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
openAutoBarrier('wait', time);
|
|
462
|
+
}
|
|
210
463
|
}
|
|
211
464
|
else {
|
|
212
465
|
(0, useScenario_1.setWaiting)(time, skippable);
|
|
@@ -219,12 +472,20 @@ function createStage() {
|
|
|
219
472
|
stopSkip();
|
|
220
473
|
}
|
|
221
474
|
else {
|
|
222
|
-
|
|
475
|
+
scheduleSkipNextLine();
|
|
223
476
|
}
|
|
224
477
|
}
|
|
225
478
|
else if (exports.skipState.active && unskippableFlag) {
|
|
226
479
|
stopSkip();
|
|
227
480
|
}
|
|
481
|
+
else if (exports.autoState.active) {
|
|
482
|
+
if (isAnyAutoBlockerActive()) {
|
|
483
|
+
stopAuto();
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
openAutoBarrier('hold', 0);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
228
489
|
// When not skipping: do nothing (normal hold behavior)
|
|
229
490
|
},
|
|
230
491
|
nextLine() {
|
|
@@ -234,6 +495,16 @@ function createStage() {
|
|
|
234
495
|
unskippable() {
|
|
235
496
|
unskippableFlag = true;
|
|
236
497
|
},
|
|
498
|
+
record(meta) {
|
|
499
|
+
const result = (0, moyu_1.executePluginCommand)('scenario', {
|
|
500
|
+
subCommand: 'record',
|
|
501
|
+
meta,
|
|
502
|
+
});
|
|
503
|
+
if (result && typeof result.then === 'function') {
|
|
504
|
+
throw new Error('Scenario record command unexpectedly returned a Promise');
|
|
505
|
+
}
|
|
506
|
+
return result;
|
|
507
|
+
},
|
|
237
508
|
};
|
|
238
509
|
return { control, wasHandled: () => handled };
|
|
239
510
|
}
|
|
@@ -253,10 +524,9 @@ function createStage() {
|
|
|
253
524
|
}
|
|
254
525
|
/** Dispatch a scenariocommandline event. */
|
|
255
526
|
function dispatchCommand(e) {
|
|
256
|
-
// execute beforeHandleCommand callbacks
|
|
257
527
|
for (const cb of beforeHandleCommandCallbacks) {
|
|
258
528
|
try {
|
|
259
|
-
cb();
|
|
529
|
+
cb(e);
|
|
260
530
|
}
|
|
261
531
|
catch (err) {
|
|
262
532
|
console.error('Error in beforeHandleCommand callback:', err);
|
|
@@ -333,11 +603,16 @@ function createStage() {
|
|
|
333
603
|
addSkipCallback,
|
|
334
604
|
addInterruptCallback,
|
|
335
605
|
addSkipBlocker,
|
|
606
|
+
addAutoBlocker,
|
|
336
607
|
addBeforeHandleCommandCallback,
|
|
608
|
+
issueAutoTicket,
|
|
337
609
|
tryInterrupt,
|
|
338
610
|
startSkip,
|
|
339
611
|
stopSkip,
|
|
340
612
|
isSkipping,
|
|
613
|
+
startAuto,
|
|
614
|
+
stopAuto,
|
|
615
|
+
isAutoing,
|
|
341
616
|
bindEvents,
|
|
342
617
|
};
|
|
343
618
|
}
|
|
@@ -396,8 +671,31 @@ function useSkipBlocker(callback) {
|
|
|
396
671
|
return stage.addSkipBlocker(callback);
|
|
397
672
|
}, [stage, callback]);
|
|
398
673
|
}
|
|
674
|
+
/**
|
|
675
|
+
* Register an auto blocker callback. Return `true` to block auto mode.
|
|
676
|
+
* Automatically removed on unmount.
|
|
677
|
+
*
|
|
678
|
+
* NOTE: `callback` must be a stable reference (wrap with `useCallback`).
|
|
679
|
+
*/
|
|
680
|
+
function useAutoBlocker(callback) {
|
|
681
|
+
const stage = useStageContext();
|
|
682
|
+
(0, react_1.useEffect)(() => {
|
|
683
|
+
return stage.addAutoBlocker(callback);
|
|
684
|
+
}, [stage, callback]);
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Get a function that issues an auto ticket for the current active barrier.
|
|
688
|
+
* Returns `null` when auto is inactive or the collection window has closed.
|
|
689
|
+
*/
|
|
690
|
+
function useAutoTicket() {
|
|
691
|
+
const stage = useStageContext();
|
|
692
|
+
return (0, react_1.useCallback)((options) => {
|
|
693
|
+
return stage.issueAutoTicket(options);
|
|
694
|
+
}, [stage]);
|
|
695
|
+
}
|
|
399
696
|
/**
|
|
400
697
|
* Register a callback to be invoked before handling each command.
|
|
698
|
+
* The callback receives the upcoming command object, allowing conditional logic.
|
|
401
699
|
* Automatically removed on unmount.
|
|
402
700
|
*/
|
|
403
701
|
function useBeforeHandleCommandCallback(callback) {
|
|
@@ -406,4 +704,3 @@ function useBeforeHandleCommandCallback(callback) {
|
|
|
406
704
|
return stage.addBeforeHandleCommandCallback(callback);
|
|
407
705
|
}, [stage, callback]);
|
|
408
706
|
}
|
|
409
|
-
//# sourceMappingURL=useStage.js.map
|
package/dist/hooks.js
CHANGED
package/dist/lib.d.ts
CHANGED
package/dist/lib.js
CHANGED
|
@@ -40,6 +40,7 @@ exports.moyu = exports.executePluginCommand = exports.executeNodeCommand = void
|
|
|
40
40
|
__exportStar(require("./react"), exports);
|
|
41
41
|
const moyu = __importStar(require("./moyu"));
|
|
42
42
|
exports.moyu = moyu;
|
|
43
|
+
require("./sandbox");
|
|
43
44
|
var moyu_1 = require("./moyu");
|
|
44
45
|
Object.defineProperty(exports, "executeNodeCommand", { enumerable: true, get: function () { return moyu_1.executeNodeCommand; } });
|
|
45
46
|
Object.defineProperty(exports, "executePluginCommand", { enumerable: true, get: function () { return moyu_1.executePluginCommand; } });
|
|
@@ -50,4 +51,3 @@ __exportStar(require("./commands"), exports);
|
|
|
50
51
|
__exportStar(require("./runtime-globals"), exports);
|
|
51
52
|
__exportStar(require("./components/navigation"), exports);
|
|
52
53
|
__exportStar(require("./hooks"), exports);
|
|
53
|
-
//# sourceMappingURL=lib.js.map
|
package/dist/moyu.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ declare global {
|
|
|
5
5
|
moyu: any;
|
|
6
6
|
}
|
|
7
7
|
var __moyu_receive_event: (event: MoyuEvent) => void;
|
|
8
|
+
var __moyu_eval_sandbox: (code: string) => any;
|
|
8
9
|
}
|
|
9
10
|
export declare function createInstance(nodeType: string, label: string | undefined, props: Record<string, any>): number;
|
|
10
11
|
export declare function destroyInstance(nodeId: number): void;
|
package/dist/moyu.js
CHANGED
package/dist/node.js
CHANGED
package/dist/react.js
CHANGED
|
@@ -60,4 +60,6 @@ declare global {
|
|
|
60
60
|
function cancelAnimationFrame(handle: number): void;
|
|
61
61
|
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DedicatedWorkerGlobalScope/requestAnimationFrame) */
|
|
62
62
|
function requestAnimationFrame(callback: FrameRequestCallback): number;
|
|
63
|
+
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/queueMicrotask) */
|
|
64
|
+
function queueMicrotask(callback: () => void): void;
|
|
63
65
|
}
|
package/dist/runtime-globals.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|