From 60088f312ef60f601af76a00226ede3645d2138e Mon Sep 17 00:00:00 2001 From: helloyork Date: Tue, 3 Dec 2024 20:33:52 -0800 Subject: [PATCH 1/8] update: added `image.setTags` and `image.setPosition` --- CHANGELOG.md | 9 +++- .../nlcore/action/actions/controlAction.ts | 26 +++++----- src/game/nlcore/elements/displayable/image.ts | 52 ++++++++++++++----- .../elements/displayable/Displayable.tsx | 30 +++++------ 4 files changed, 75 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c44a487..fa7908f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog -## [0.2.1] +## [0.2.3] + +### Added + +- `image.setTags` +- `image.setPosition` + +## [0.2.2] - 2024/12/02 ### _Feature_ diff --git a/src/game/nlcore/action/actions/controlAction.ts b/src/game/nlcore/action/actions/controlAction.ts index 466932f..b21493f 100644 --- a/src/game/nlcore/action/actions/controlAction.ts +++ b/src/game/nlcore/action/actions/controlAction.ts @@ -42,15 +42,17 @@ export class ControlAction { const next = state.game.getLiveGame().executeAction(state, action); if (Awaitable.isAwaitable(next)) { - const {node} = await new Promise((r) => { - next.then((_) => r(next.result as any)); + return new Promise((r) => { + next.then((_) => { + state.logger.debug("Control - Next Action (single)", next); + r(next.result?.node || null); + }); }); - return node; } else { - return next; + return Promise.resolve(next?.contentNode || null); } } @@ -96,14 +98,14 @@ export class ControlAction(v => v); - (async () => { - await Promise.all(content.map(action => this.executeSingleAction(state, action))); - awaitable.resolve({ - type: this.type, - node: this.contentNode.getChild() + Promise.all(content.map(action => this.executeSingleAction(state, action))) + .then(() => { + awaitable.resolve({ + type: this.type, + node: this.contentNode.getChild() + }); + state.stage.next(); }); - state.stage.next(); - })(); return awaitable; } else if (this.type === ControlActionTypes.allAsync) { (async () => { diff --git a/src/game/nlcore/elements/displayable/image.ts b/src/game/nlcore/elements/displayable/image.ts index ad21ee0..c6ab7b7 100644 --- a/src/game/nlcore/elements/displayable/image.ts +++ b/src/game/nlcore/elements/displayable/image.ts @@ -332,20 +332,16 @@ export class Image< * @chainable */ public applyTransform(transform: Transform): Proxied> { - return this.combineActions(new Control(), chain => { - const action = new ImageAction( - chain, - ImageAction.ActionTypes.applyTransform, - new ContentNode().setContent([ - void 0, - transform.copy(), - getCallStack() - ]) - ); - return chain - .chain(action) - .chain(this._flush()); - }); + const chain = this.chain(); + return chain.chain(new ImageAction( + chain, + ImageAction.ActionTypes.applyTransform, + new ContentNode().setContent([ + void 0, + transform.copy(), + getCallStack() + ]) + )); } /** @@ -426,6 +422,34 @@ export class Image< }); } + /** + * Alia of {@link Image.setAppearance} + * @chainable + */ + public setTags( + tags: Tags extends TagGroupDefinition ? FlexibleTuple> : string[], + transition?: IImageTransition + ): Proxied> { + return this.setAppearance(tags, transition); + } + + /** + * Set Image Position + * @chainable + */ + public setPosition( + position: TransformDefinitions.ImageTransformProps["position"], + duration?: number, + easing?: TransformDefinitions.EasingDefinition + ): Proxied> { + return this.applyTransform(new Transform({ + position, + }, { + duration, + ease: easing, + })); + } + /** * Add a wearable to the image * @param children - Wearable image or images diff --git a/src/game/player/elements/displayable/Displayable.tsx b/src/game/player/elements/displayable/Displayable.tsx index a19be67..6a73448 100644 --- a/src/game/player/elements/displayable/Displayable.tsx +++ b/src/game/player/elements/displayable/Displayable.tsx @@ -131,47 +131,47 @@ export default function Displayable( } } - function applyTransition(transition: ITransition) { - setTransition(transition); - if (!transition) { + function applyTransition(newTransition: ITransition) { + setTransition(newTransition); + if (!newTransition) { gameState.logger.warn("transition not set"); return Promise.resolve(); } return new Promise(resolve => { - const eventToken = transition.events.onEvents([ + const eventToken = newTransition.events.onEvents([ { type: TransitionEventTypes.update, - listener: transition.events.on(TransitionEventTypes.update, (progress) => { + listener: newTransition.events.on(TransitionEventTypes.update, (progress) => { setTransitionProps(progress); }), }, { type: TransitionEventTypes.end, - listener: transition.events.on(TransitionEventTypes.end, () => { + listener: newTransition.events.on(TransitionEventTypes.end, () => { setTransition(null); - gameState.logger.debug("transition end", transition); + gameState.logger.debug("transition end", newTransition); }) }, { type: TransitionEventTypes.start, - listener: transition.events.on(TransitionEventTypes.start, () => { - gameState.logger.debug("transition start", transition); + listener: newTransition.events.on(TransitionEventTypes.start, () => { + gameState.logger.debug("transition start", newTransition); }) } ]); - transition.start(() => { + newTransition.start(() => { eventToken.cancel(); resolve(); }); }); } - async function applyTransform(transform: Transform) { - assignStyle(transform.propToCSS(gameState, displayableState.state, displayable.transformOverwrites)); + async function applyTransform(newTransform: Transform) { + assignStyle(newTransform.propToCSS(gameState, displayableState.state, displayable.transformOverwrites)); - setTransform(transform); - await transform.animate({ + setTransform(newTransform); + await newTransform.animate({ scope, target: displayableState, overwrites: displayable.transformOverwrites @@ -180,7 +180,7 @@ export default function Displayable( displayableState.state = deepMerge(displayableState.state, after); setTransformProps({ - style: transform.propToCSS(gameState, displayableState.state, displayable.transformOverwrites) as any, + style: newTransform.propToCSS(gameState, displayableState.state, displayable.transformOverwrites) as any, }); setTransform(null); From 37fc262ae033fa444ac136552fbb890606fb6f33 Mon Sep 17 00:00:00 2001 From: helloyork Date: Wed, 4 Dec 2024 21:38:31 -0800 Subject: [PATCH 2/8] added: utility component: `Full` --- CHANGELOG.md | 1 + src/game/nlcore/game.ts | 1 + src/game/nlcore/gameTypes.ts | 4 ++++ src/game/player/elements/Player.tsx | 1 + src/game/player/lib/PlayerFrames.tsx | 31 ++++++++++++++++++++++++++++ src/game/player/lib/isolated.tsx | 1 - src/game/player/libElements.ts | 3 ++- 7 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa7908f..fccbd1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - `image.setTags` - `image.setPosition` +- Utility component: `Full` ## [0.2.2] - 2024/12/02 diff --git a/src/game/nlcore/game.ts b/src/game/nlcore/game.ts index a5562ba..db7bd40 100644 --- a/src/game/nlcore/game.ts +++ b/src/game/nlcore/game.ts @@ -59,6 +59,7 @@ export class Game { cursor: null, cursorHeight: 30, cursorWidth: 30, + showOverflow: false, }, elements: { say: { diff --git a/src/game/nlcore/gameTypes.ts b/src/game/nlcore/gameTypes.ts index 76ac67c..f9303eb 100644 --- a/src/game/nlcore/gameTypes.ts +++ b/src/game/nlcore/gameTypes.ts @@ -106,6 +106,10 @@ export type GameConfig = { * Cursor height in pixels */ cursorHeight: number; + /** + * Show overflowed content + */ + showOverflow: boolean; }; elements: { say: { diff --git a/src/game/player/elements/Player.tsx b/src/game/player/elements/Player.tsx index b293688..55b8b66 100644 --- a/src/game/player/elements/Player.tsx +++ b/src/game/player/elements/Player.tsx @@ -191,6 +191,7 @@ export default function Player( {game.config.player.cursor && ( ; const BottomRight = (props: FrameComponentProps) => ; +function Full({children, className}: ForwardChildren & ForwardClassName) { + const {ratio} = useRatio(); + const {game} = useGame(); + + return ( + +
+
+ {children} +
+
+
+ ); +} + const Top = { Left: TopLeft, Center: TopCenter, @@ -82,4 +112,5 @@ export { Top, Center, Bottom, + Full, }; diff --git a/src/game/player/lib/isolated.tsx b/src/game/player/lib/isolated.tsx index c8b6fe8..71269fc 100644 --- a/src/game/player/lib/isolated.tsx +++ b/src/game/player/lib/isolated.tsx @@ -35,7 +35,6 @@ export default function Isolated( style={{ ...styles, position: "relative", - overflow: "hidden", ...(props?.style || {}), ...(style || {}), }} diff --git a/src/game/player/libElements.ts b/src/game/player/libElements.ts index 1af1be4..7087f67 100644 --- a/src/game/player/libElements.ts +++ b/src/game/player/libElements.ts @@ -1,6 +1,6 @@ import Isolated from "@player/lib/isolated"; import Say from "@player/elements/say/Say"; -import {Top, Center, Bottom} from "@player/lib/PlayerFrames"; +import {Top, Center, Bottom, Full} from "@player/lib/PlayerFrames"; import {VBox, HBox} from "@player/lib/UtilComponents"; export { @@ -11,4 +11,5 @@ export { Bottom, VBox, HBox, + Full, }; \ No newline at end of file From 449d603f42185e3059231f7907c07b9478c3b6d9 Mon Sep 17 00:00:00 2001 From: helloyork Date: Wed, 4 Dec 2024 22:59:30 -0800 Subject: [PATCH 3/8] feature: use `usePreference` to manage preference easier --- CHANGELOG.md | 5 +++++ src/game/nlcore/elements/persistent.ts | 6 +++--- src/game/nlcore/game/preference.ts | 6 +++++- src/game/player/lib/preferences.tsx | 24 ++++++++++++++++++++++++ src/game/player/libElements.ts | 2 ++ src/util/data.ts | 4 ++-- 6 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 src/game/player/lib/preferences.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index fccbd1c..d70cbf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,16 @@ ## [0.2.3] +### _Feature_ + +- Use `usePreference` to manage preference easier + ### Added - `image.setTags` - `image.setPosition` - Utility component: `Full` +- `usePreference` hook ## [0.2.2] - 2024/12/02 diff --git a/src/game/nlcore/elements/persistent.ts b/src/game/nlcore/elements/persistent.ts index c9bbfcd..da1665b 100644 --- a/src/game/nlcore/elements/persistent.ts +++ b/src/game/nlcore/elements/persistent.ts @@ -4,7 +4,7 @@ import {Chained, Proxied} from "@core/action/chain"; import {LogicAction} from "@core/game"; import {PersistentActionContentType, PersistentActionTypes} from "@core/action/actionTypes"; import {PersistentAction} from "@core/action/actions/persistentAction"; -import {BooleanKeys, StringKeyOf, Values} from "@lib/util/data"; +import {BooleanValueKeyOf, StringKeyOf, Values} from "@lib/util/data"; import {ContentNode} from "@core/action/tree/actionTree"; import {Lambda} from "@core/elements/condition"; import {Word} from "@core/elements/character/word"; @@ -77,7 +77,7 @@ export class Persistent /** * Determine whether the value is true, can be used in {@link Condition} */ - public isTrue>>(key: K): Lambda { + public isTrue>>(key: K): Lambda { return new Lambda(({storable}) => { return storable.getNamespace(this.namespace).equals(key, true); }); @@ -86,7 +86,7 @@ export class Persistent /** * Determine whether the value is false, can be used in {@link Condition} */ - public isFalse>>(key: K): Lambda { + public isFalse>>(key: K): Lambda { return new Lambda(({storable}) => { return storable.getNamespace(this.namespace).equals(key, false); }); diff --git a/src/game/nlcore/game/preference.ts b/src/game/nlcore/game/preference.ts index a4a3563..53ade56 100644 --- a/src/game/nlcore/game/preference.ts +++ b/src/game/nlcore/game/preference.ts @@ -1,4 +1,4 @@ -import {EventDispatcher} from "@lib/util/data"; +import {BooleanValueKeyOf, EventDispatcher} from "@lib/util/data"; type PreferenceEventToken = { cancel: () => void; @@ -73,4 +73,8 @@ export class Preference>(key: K) { + this.setPreference(key, !this.getPreference(key) as T[K]); + } } diff --git a/src/game/player/lib/preferences.tsx b/src/game/player/lib/preferences.tsx new file mode 100644 index 0000000..68f8cae --- /dev/null +++ b/src/game/player/lib/preferences.tsx @@ -0,0 +1,24 @@ +import {StringKeyOf} from "@lib/util/data"; +import {GamePreference} from "@core/game"; +import React, {useEffect} from "react"; +import {useGame} from "@player/provider/game-state"; + +export function usePreference>( + key: K +): [GamePreference[K], (value: GamePreference[K]) => void] { + const {game} = useGame(); + const [currentValue, setCurrentValue] = React.useState(game.preference.getPreference(key)); + + const setPreference = (value: GamePreference[K]) => { + game.preference.setPreference(key, value); + setCurrentValue(value); + }; + + useEffect(() => { + return game.preference.onPreferenceChange(key, setCurrentValue).cancel; + }, []); + + return [currentValue, setPreference]; +} + + diff --git a/src/game/player/libElements.ts b/src/game/player/libElements.ts index 7087f67..5dd4c87 100644 --- a/src/game/player/libElements.ts +++ b/src/game/player/libElements.ts @@ -2,6 +2,7 @@ import Isolated from "@player/lib/isolated"; import Say from "@player/elements/say/Say"; import {Top, Center, Bottom, Full} from "@player/lib/PlayerFrames"; import {VBox, HBox} from "@player/lib/UtilComponents"; +import {usePreference} from "@player/lib/preferences"; export { Isolated, @@ -12,4 +13,5 @@ export { VBox, HBox, Full, + usePreference, }; \ No newline at end of file diff --git a/src/util/data.ts b/src/util/data.ts index 752537f..ddad6d6 100644 --- a/src/util/data.ts +++ b/src/util/data.ts @@ -694,9 +694,9 @@ export type StringKeyOf = Extract; export type ValuesWithin = { [K in keyof T]: T[K] extends U ? K : never; }[keyof T]; -export type BooleanKeys = { +export type BooleanValueKeyOf = Extract<{ [K in keyof T]: T[K] extends boolean ? K : never; -}[keyof T]; +}[keyof T], string>; export function createMicroTask(t: () => (() => void) | void): () => void { let executed = false; From 79558a3580d47216e6f7d2dfdeaa5d9523e94b80 Mon Sep 17 00:00:00 2001 From: helloyork Date: Tue, 10 Dec 2024 22:46:18 -0800 Subject: [PATCH 4/8] fixed: peerDependencies and class signature problems --- package.json | 8 ++++---- src/game/nlcore/common/elements.ts | 2 ++ src/game/nlcore/game/preference.ts | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5c28e3e..8d50c34 100644 --- a/package.json +++ b/package.json @@ -55,10 +55,10 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^5.1.0" }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, +"peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" +}, "files": [ "dist" ], diff --git a/src/game/nlcore/common/elements.ts b/src/game/nlcore/common/elements.ts index 11eb310..827b2e3 100644 --- a/src/game/nlcore/common/elements.ts +++ b/src/game/nlcore/common/elements.ts @@ -59,6 +59,7 @@ const Image: ImageConstructor = function ( config.tag as TagDefinitions | undefined ); } as unknown as ImageConstructor; +const AbstractImage = ImageClass; export { Character, @@ -78,4 +79,5 @@ export { Text, Pause, Persistent, + AbstractImage, }; \ No newline at end of file diff --git a/src/game/nlcore/game/preference.ts b/src/game/nlcore/game/preference.ts index 53ade56..02a6c8a 100644 --- a/src/game/nlcore/game/preference.ts +++ b/src/game/nlcore/game/preference.ts @@ -51,7 +51,7 @@ export class Preference) { for (const key in preferences) { From 7f9208d5370411262bb5a4d9aa76f845b9fb75b5 Mon Sep 17 00:00:00 2001 From: York Date: Thu, 26 Dec 2024 14:08:26 -0800 Subject: [PATCH 5/8] cleanup --- package.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8d50c34..e97de74 100644 --- a/package.json +++ b/package.json @@ -55,10 +55,10 @@ "webpack-cli": "^4.10.0", "webpack-dev-server": "^5.1.0" }, -"peerDependencies": { - "react": ">=17.0.0", - "react-dom": ">=17.0.0" -}, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + }, "files": [ "dist" ], @@ -78,5 +78,6 @@ "framer-motion": "^11.11.9", "howler": "^2.2.4", "prop-types": "^15.8.1" - } + }, + "packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" } From 24bf0224176ac9b6b2356ce72d34ea226a4fe3e5 Mon Sep 17 00:00:00 2001 From: York Date: Thu, 26 Dec 2024 20:15:24 -0800 Subject: [PATCH 6/8] update: some interfaces --- src/game/nlcore/common/Utils.ts | 6 +++ src/game/nlcore/elements/character.ts | 2 + src/game/nlcore/elements/character/pause.ts | 1 + .../nlcore/elements/character/sentence.ts | 8 ++++ src/game/nlcore/elements/condition.ts | 1 + src/game/nlcore/elements/control.ts | 1 + .../elements/displayable/displayable.ts | 2 + src/game/nlcore/elements/displayable/image.ts | 9 +++- src/game/nlcore/elements/displayable/text.ts | 3 +- src/game/nlcore/elements/menu.ts | 2 + src/game/nlcore/elements/persistent.ts | 3 ++ src/game/nlcore/elements/persistent/type.ts | 9 ++++ src/game/nlcore/elements/scene.ts | 7 +++ src/game/nlcore/elements/script.ts | 1 + src/game/nlcore/elements/sound.ts | 3 ++ src/game/nlcore/elements/story.ts | 2 +- .../nlcore/elements/transform/position.ts | 10 +++- .../nlcore/elements/transform/transform.ts | 12 +++++ src/game/nlcore/elements/transform/type.ts | 19 -------- src/game/nlcore/elements/transition/type.ts | 7 +++ src/game/nlcore/game/liveGame.ts | 1 + src/game/nlcore/game/preference.ts | 2 + .../elements/displayable/Displayable.tsx | 2 + .../elements/displayable/Displayables.tsx | 1 + src/game/player/elements/displayable/Text.tsx | 1 + src/game/player/elements/displayable/type.ts | 3 ++ .../elements/image/AspectScaleImage.tsx | 1 + src/game/player/elements/image/Image.tsx | 17 ++++--- src/game/player/elements/menu/Menu.tsx | 1 + .../elements/player/KeyEventAnnouncer.tsx | 1 + .../elements/player/SizeUpdateAnnouncer.tsx | 1 + src/game/player/elements/preload/Preload.tsx | 1 + src/game/player/elements/say/Say.tsx | 1 + src/game/player/elements/say/Sentence.tsx | 2 + src/game/player/elements/say/TypingEffect.tsx | 48 ------------------- src/game/player/elements/scene/Background.tsx | 12 +++-- .../elements/scene/BackgroundTransition.tsx | 2 + src/game/player/elements/scene/Scene.tsx | 1 + src/game/player/gameState.ts | 1 + src/game/player/gameState.type.ts | 3 ++ src/game/player/lib/UtilComponents.tsx | 2 +- src/game/player/provider/game-state.tsx | 3 ++ src/game/player/provider/preloaded.tsx | 2 + src/game/player/provider/ratio.tsx | 3 ++ 44 files changed, 134 insertions(+), 86 deletions(-) delete mode 100644 src/game/player/elements/say/TypingEffect.tsx diff --git a/src/game/nlcore/common/Utils.ts b/src/game/nlcore/common/Utils.ts index bb69e42..c7c046f 100644 --- a/src/game/nlcore/common/Utils.ts +++ b/src/game/nlcore/common/Utils.ts @@ -62,6 +62,7 @@ export class RGBColor { } } +/**@internal */ export class Utils { static RGBColor = RGBColor; @@ -118,6 +119,7 @@ export class Utils { } } +/**@internal */ export class UseError> extends Error { static isUseError(error: any): error is UseError { return error instanceof UseError; @@ -132,6 +134,7 @@ export class UseError> extends Error { } } +/**@internal */ export class StaticScriptWarning extends UseError<{ stack?: string; info?: any; @@ -150,6 +153,7 @@ type ImageState = { usedExternalSrc: boolean; }; +/**@internal */ export class StaticChecker { private readonly scene: Scene; @@ -257,6 +261,7 @@ export class StaticChecker { } } +/**@internal */ export class RuntimeScriptError extends Error { static toMessage(msg: string | string[], trace?: Action | Action[]) { const messages: string[] = []; @@ -282,6 +287,7 @@ export class RuntimeScriptError extends Error { } } +/**@internal */ export class RuntimeGameError extends Error { constructor(message: string) { super(message); diff --git a/src/game/nlcore/elements/character.ts b/src/game/nlcore/elements/character.ts index d956303..bd518f5 100644 --- a/src/game/nlcore/elements/character.ts +++ b/src/game/nlcore/elements/character.ts @@ -8,9 +8,11 @@ import {Sentence, SentencePrompt, SentenceUserConfig, SingleWord} from "@core/el import {CharacterAction} from "@core/action/actions/characterAction"; export type CharacterConfig = {} & Color; +/**@internal */ export type CharacterStateData = { name: string; }; +/**@internal */ export type CharacterState = { name: string; }; diff --git a/src/game/nlcore/elements/character/pause.ts b/src/game/nlcore/elements/character/pause.ts index 326a28e..bb86de2 100644 --- a/src/game/nlcore/elements/character/pause.ts +++ b/src/game/nlcore/elements/character/pause.ts @@ -2,6 +2,7 @@ export type PauseConfig = { duration?: number; }; +/**@internal */ export type PausingShortcut = typeof Pause; export type Pausing = Pause | PausingShortcut; diff --git a/src/game/nlcore/elements/character/sentence.ts b/src/game/nlcore/elements/character/sentence.ts index ae8035e..8c0f351 100644 --- a/src/game/nlcore/elements/character/sentence.ts +++ b/src/game/nlcore/elements/character/sentence.ts @@ -6,6 +6,7 @@ import {Color, Font} from "@core/types"; import type {ScriptCtx} from "@core/elements/script"; import {Pause, Pausing} from "@core/elements/character/pause"; +/**@internal */ export type SentenceConfig = { pause?: boolean | number; voice: Sound | null; @@ -13,22 +14,29 @@ export type SentenceConfig = { voiceId: string | number | null; } & Color & Font; +/**@internal */ export type SentenceDataRaw = { state: SentenceState; }; +/**@internal */ export type SentenceState = { display: boolean; }; export type SentenceUserConfig = Partial & { voice: Sound | string | null | undefined }>; +/**@internal */ export type DynamicWord = (ctx: ScriptCtx) => DynamicWordResult; +/**@internal */ export type DynamicWordResult = string | Word | Pausing | (string | Word | Pausing)[]; +/**@internal */ export type StaticWord = string | Pausing | Word; +/**@internal */ export type SingleWord = StaticWord | DynamicWord; +/**@internal */ export type SentencePrompt = SingleWord[] | SingleWord; export class Sentence { diff --git a/src/game/nlcore/elements/condition.ts b/src/game/nlcore/elements/condition.ts index a0d416a..7d85314 100644 --- a/src/game/nlcore/elements/condition.ts +++ b/src/game/nlcore/elements/condition.ts @@ -48,6 +48,7 @@ export class Lambda { } } +/**@internal */ export type ConditionData = { If: { condition: Lambda | null; diff --git a/src/game/nlcore/elements/control.ts b/src/game/nlcore/elements/control.ts index abd78fb..93f49e8 100644 --- a/src/game/nlcore/elements/control.ts +++ b/src/game/nlcore/elements/control.ts @@ -6,6 +6,7 @@ import {Chained, ChainedActions, Proxied} from "@core/action/chain"; import {ControlAction} from "@core/action/actions/controlAction"; +/**@internal */ type ChainedControl = Proxied>; export class Control extends Actionable { diff --git a/src/game/nlcore/elements/displayable/displayable.ts b/src/game/nlcore/elements/displayable/displayable.ts index f2101a7..5842048 100644 --- a/src/game/nlcore/elements/displayable/displayable.ts +++ b/src/game/nlcore/elements/displayable/displayable.ts @@ -9,12 +9,14 @@ import {Chained, Proxied} from "@core/action/chain"; import {LogicAction} from "@core/action/logicAction"; import {ContentNode} from "@core/action/tree/actionTree"; +/**@internal */ export type DisplayableEventTypes = { "event:displayable.applyTransition": [ITransition]; "event:displayable.applyTransform": [Transform]; "event:displayable.init": []; }; +/**@internal */ export abstract class Displayable< StateData extends Record, Self extends Actionable diff --git a/src/game/nlcore/elements/displayable/image.ts b/src/game/nlcore/elements/displayable/image.ts index c6ab7b7..32bcd74 100644 --- a/src/game/nlcore/elements/displayable/image.ts +++ b/src/game/nlcore/elements/displayable/image.ts @@ -29,6 +29,7 @@ import {Control} from "@core/elements/control"; import {ImageAction} from "@core/action/actions/imageAction"; import {Displayable, DisplayableEventTypes} from "@core/elements/displayable/displayable"; +/**@internal */ export type ImageConfig = { display: boolean; /**@internal */ @@ -42,10 +43,12 @@ export type ImageConfig = { autoInit: boolean; } & CommonDisplayable; +/**@internal */ export type ImageDataRaw = { state: Record; }; +/**@internal */ export type ImageEventTypes = { "event:wearable.create": [Image]; } & DisplayableEventTypes; @@ -54,7 +57,9 @@ export type TagDefinitions = groups: T; defaults: SelectElementFromEach; } : never; +/**@internal */ export type TagGroupDefinition = string[][]; +/**@internal */ export type TagSrcResolver = (...tags: SelectElementFromEach) => string; export type RichImageUserConfig = ImageConfig & { /**@internal */ @@ -70,8 +75,8 @@ export type RichImageUserConfig = ImageConf tag: TagDefinitions; } : never); -export type RichImageConfig = RichImageUserConfig & {}; -export type StaticRichConfig = RichImageUserConfig; +type RichImageConfig = RichImageUserConfig & {}; +type StaticRichConfig = RichImageUserConfig; export class Image< diff --git a/src/game/nlcore/elements/displayable/text.ts b/src/game/nlcore/elements/displayable/text.ts index cc20910..5a95c2e 100644 --- a/src/game/nlcore/elements/displayable/text.ts +++ b/src/game/nlcore/elements/displayable/text.ts @@ -26,10 +26,11 @@ export type TextConfig = { text: string; } & CommonDisplayable; +/**@internal */ export type TextDataRaw = { state: Record; }; - +/**@internal */ export type TextEventTypes = { "event:text.show": [Transform]; "event:text.hide": [Transform]; diff --git a/src/game/nlcore/elements/menu.ts b/src/game/nlcore/elements/menu.ts index 1727283..86eeb51 100644 --- a/src/game/nlcore/elements/menu.ts +++ b/src/game/nlcore/elements/menu.ts @@ -16,7 +16,9 @@ export type MenuChoice = { prompt: SentencePrompt | Sentence; }; +/**@internal */ type ChainedAction = Proxied>; +/**@internal */ type ChainedActions = (ChainedAction | ChainedAction[] | Actions | Actions[])[]; export type Choice = { diff --git a/src/game/nlcore/elements/persistent.ts b/src/game/nlcore/elements/persistent.ts index da1665b..c44702d 100644 --- a/src/game/nlcore/elements/persistent.ts +++ b/src/game/nlcore/elements/persistent.ts @@ -12,10 +12,13 @@ import {DynamicWord, DynamicWordResult} from "@core/elements/character/sentence" import {LambdaHandler} from "@core/elements/type"; import {Namespace, Storable} from "@core/elements/persistent/storable"; +/**@internal */ type PersistentContent = { [K in string]: StorableType; }; +/**@internal */ type ChainedPersistent = Proxied, Chained>; +/**@internal */ type DynamicPersistentData = { [K in string]: StorableType; }; diff --git a/src/game/nlcore/elements/persistent/type.ts b/src/game/nlcore/elements/persistent/type.ts index 47850e2..0751b45 100644 --- a/src/game/nlcore/elements/persistent/type.ts +++ b/src/game/nlcore/elements/persistent/type.ts @@ -2,25 +2,34 @@ export type StorableData = { [key in K]: number | boolean | string | StorableData | StorableData[] | undefined | null | Date; }; +/**@internal */ export type BaseStorableType = number | boolean | string | undefined | null | Date; +/**@internal */ export type UnserializableStorableType = Date; +/**@internal */ export type BaseStorableTypeName = "any" | "date"; +/**@internal */ export type StorableType = BaseStorableType | Record | Array; +/**@internal */ export type WrappedStorableData = { type: BaseStorableTypeName; data: T; } +/**@internal */ export type StorableTypeSerializer = (value: T) => WrappedStorableData; +/**@internal */ export type BaseStorableSerializeHandlers = { [K in BaseStorableTypeName]: K extends "any" ? StorableTypeSerializer> : K extends "date" ? StorableTypeSerializer : never; } +/**@internal */ export type BaseStorableDeserializeHandlers = { [K in BaseStorableTypeName]: K extends "any" ? (data: WrappedStorableData>) => Exclude : K extends "date" ? (data: WrappedStorableData) => Date : never; } +/**@internal */ export type NameSpaceContent = { [K in T]?: StorableType }; diff --git a/src/game/nlcore/elements/scene.ts b/src/game/nlcore/elements/scene.ts index 2cbf94a..15b7004 100644 --- a/src/game/nlcore/elements/scene.ts +++ b/src/game/nlcore/elements/scene.ts @@ -23,7 +23,9 @@ import ImageTransformProps = TransformDefinitions.ImageTransformProps; import GameElement = LogicAction.GameElement; import {DynamicPersistent} from "@core/elements/persistent"; +/**@internal */ export type UserImageInput = ImageSrc | RGBColor | ImageColor; +/**@internal */ export type SceneConfig = { invertY: boolean; invertX: boolean; @@ -43,6 +45,7 @@ export interface ISceneConfig { background?: ImageSrc | ImageColor; } +/**@internal */ export type SceneState = { backgroundImageProxy: VirtualImageProxy; }; @@ -51,9 +54,12 @@ export type JumpConfig = { unloadScene: boolean; } +/**@internal */ type ChainableAction = Proxied> | Actions; +/**@internal */ type ChainedScene = Proxied>; +/**@internal */ export type SceneDataRaw = { state: { backgroundMusic?: SoundDataRaw | null; @@ -62,6 +68,7 @@ export type SceneDataRaw = { backgroundImageState?: ImageDataRaw | null; } +/**@internal */ export type SceneEventTypes = { "event:scene.remove": []; "event:scene.load": [], diff --git a/src/game/nlcore/elements/script.ts b/src/game/nlcore/elements/script.ts index c4f8851..29e3b0a 100644 --- a/src/game/nlcore/elements/script.ts +++ b/src/game/nlcore/elements/script.ts @@ -16,6 +16,7 @@ export interface ScriptCtx { } type ScriptRun = (ctx: ScriptCtx) => ScriptCleaner | void; +/**@internal */ export type ScriptCleaner = () => void; export class Script extends Actionable { diff --git a/src/game/nlcore/elements/sound.ts b/src/game/nlcore/elements/sound.ts index a6a5c96..d6f65db 100644 --- a/src/game/nlcore/elements/sound.ts +++ b/src/game/nlcore/elements/sound.ts @@ -17,10 +17,13 @@ export enum SoundType { backgroundMusic = "backgroundMusic", } +/**@internal */ export type SoundDataRaw = { config: SoundConfig; }; +/**@internal */ export type VoiceIdMap = Record; +/**@internal */ export type VoiceSrcGenerator = (id: string | number) => string | Sound; export type SoundConfig = { diff --git a/src/game/nlcore/elements/story.ts b/src/game/nlcore/elements/story.ts index 8c162c0..3603bcd 100644 --- a/src/game/nlcore/elements/story.ts +++ b/src/game/nlcore/elements/story.ts @@ -10,8 +10,8 @@ import {Storable} from "@core/elements/persistent/storable"; /* eslint-disable @typescript-eslint/no-empty-object-type */ export type StoryConfig = {}; +/**@internal */ export type ElementStateRaw = Record; -export type NodeChildIdMap = Map; export class Story extends Constructable< SceneAction<"scene:action">, diff --git a/src/game/nlcore/elements/transform/position.ts b/src/game/nlcore/elements/transform/position.ts index b80e1d9..5bd75be 100644 --- a/src/game/nlcore/elements/transform/position.ts +++ b/src/game/nlcore/elements/transform/position.ts @@ -18,21 +18,25 @@ export interface IPosition { toCSS(): D2Position; } +/**@internal */ export type Coord2DPosition = { x: number | `${"-" | ""}${number}%`; y: number | `${"-" | ""}${number}%`; } & Partial; +/**@internal */ export type AlignPosition = { xalign: number; yalign: number; } & Partial; +/**@internal */ export type OffsetPosition = { xoffset: number; yoffset: number; } +/**@internal */ export type D2Position = { x: UnknownAble; y: UnknownAble; @@ -40,13 +44,15 @@ export type D2Position = { yoffset: UnknownAble; } +/**@internal */ export type RawPosition = CommonPositionType | (Coord2DPosition & { xalign?: never; yalign?: never }) | (AlignPosition & { x?: never; y?: never }); -export type Unknown = typeof PositionUtils.Unknown; -export type UnknownAble = T | Unknown; +type Unknown = typeof PositionUtils.Unknown; +type UnknownAble = T | Unknown; +/**@internal */ export class PositionUtils { static readonly Unknown: unique symbol = Symbol("Unknown"); diff --git a/src/game/nlcore/elements/transform/transform.ts b/src/game/nlcore/elements/transform/transform.ts index 683ed0a..6dc60d5 100644 --- a/src/game/nlcore/elements/transform/transform.ts +++ b/src/game/nlcore/elements/transform/transform.ts @@ -63,6 +63,18 @@ export class Transform { return CommonPosition.isCommonPositionType(position) || Coord2D.isCoord2DPosition(position) || Align.isAlignPosition(position); } + /** + * Apply transform immediately + */ + public static immediate( + props: SequenceProps, + ): Transform { + return new Transform(props, { + duration: 0, + ease: "linear", + }); + } + /** * Go to the left side of the stage */ diff --git a/src/game/nlcore/elements/transform/type.ts b/src/game/nlcore/elements/transform/type.ts index 6beb67e..b3c5db3 100644 --- a/src/game/nlcore/elements/transform/type.ts +++ b/src/game/nlcore/elements/transform/type.ts @@ -1,15 +1,5 @@ import {color, CommonDisplayable} from "@core/types"; import {DeepPartial} from "@lib/util/data"; -import type { - AnimationPlaybackControls, - AnimationScope, - AnimationSequence, - DOMKeyframesDefinition, - DynamicAnimationOptions, - ElementOrSelector, - MotionValue, - ValueAnimationTransition -} from "framer-motion"; export namespace TransformDefinitions { export type BezierDefinition = [number, number, number, number]; @@ -29,15 +19,6 @@ export namespace TransformDefinitions { | "backInOut" | "anticipate"; - export type GenericKeyframesTarget = [null, ...V[]] | V[]; - export type FramerAnimationScope = AnimationScope; - export type FramerAnimate = { - (from: V, to: V | GenericKeyframesTarget, options?: ValueAnimationTransition | undefined): AnimationPlaybackControls; - (value: MotionValue, keyframes: V_1 | GenericKeyframesTarget, options?: ValueAnimationTransition | undefined): AnimationPlaybackControls; - (value: ElementOrSelector, keyframes: DOMKeyframesDefinition, options?: DynamicAnimationOptions | undefined): AnimationPlaybackControls; - (sequence: AnimationSequence, options?: SequenceOptions | undefined): AnimationPlaybackControls; - } - export type CommonTransformProps = { duration: number; ease: EasingDefinition; diff --git a/src/game/nlcore/elements/transition/type.ts b/src/game/nlcore/elements/transition/type.ts index 7d625de..6b57573 100644 --- a/src/game/nlcore/elements/transition/type.ts +++ b/src/game/nlcore/elements/transition/type.ts @@ -3,15 +3,21 @@ import React from "react"; import type {AnimationPlaybackControls, DOMKeyframesDefinition} from "framer-motion"; import {ImageColor, ImageSrc} from "@core/types"; +/**@internal */ export type ElementProp = React.HTMLAttributes> = React.JSX.IntrinsicAttributes & React.ClassAttributes & React.HTMLAttributes & U; +/**@internal */ export type ImgElementProp = ElementProp>; +/**@internal */ export type SpanElementProp = ElementProp>; +/**@internal */ export type DivElementProp = ElementProp>; +/**@internal */ export type CSSElementProp = ElementProp & { style: T }; +/**@internal */ export type CSSProps = React.CSSProperties; export interface ITransition> { @@ -38,6 +44,7 @@ export interface ITextTransition extend copy(): ITextTransition; } +/**@internal */ export type EventTypes = { "start": [null]; "update": T; diff --git a/src/game/nlcore/game/liveGame.ts b/src/game/nlcore/game/liveGame.ts index 7087aa3..5c88820 100644 --- a/src/game/nlcore/game/liveGame.ts +++ b/src/game/nlcore/game/liveGame.ts @@ -16,6 +16,7 @@ import {LiveGameEventHandler, LiveGameEventToken} from "@core/types"; import {Character} from "@core/elements/character"; import {Sentence} from "@core/elements/character/sentence"; +/**@internal */ type LiveGameEvent = { "event:character.prompt": [{ /** diff --git a/src/game/nlcore/game/preference.ts b/src/game/nlcore/game/preference.ts index 02a6c8a..48fa0c4 100644 --- a/src/game/nlcore/game/preference.ts +++ b/src/game/nlcore/game/preference.ts @@ -1,9 +1,11 @@ import {BooleanValueKeyOf, EventDispatcher} from "@lib/util/data"; +/**@internal */ type PreferenceEventToken = { cancel: () => void; }; +/**@internal */ type StringKeyof = Extract; export class Preference> { diff --git a/src/game/player/elements/displayable/Displayable.tsx b/src/game/player/elements/displayable/Displayable.tsx index 6a73448..cb1bda9 100644 --- a/src/game/player/elements/displayable/Displayable.tsx +++ b/src/game/player/elements/displayable/Displayable.tsx @@ -6,6 +6,7 @@ import {Transform, TransformersMap, TransformHandler} from "@core/elements/trans import {GameState} from "@player/gameState"; import {deepMerge} from "@lib/util/data"; +/**@internal */ export type DisplayableProps = { displayable: { skipTransition?: boolean; @@ -26,6 +27,7 @@ export type DisplayableProps = { state: GameState; }; +/**@internal */ export default function Displayable( { state: gameState, diff --git a/src/game/player/elements/displayable/Displayables.tsx b/src/game/player/elements/displayable/Displayables.tsx index 6d931ed..05d9abc 100644 --- a/src/game/player/elements/displayable/Displayables.tsx +++ b/src/game/player/elements/displayable/Displayables.tsx @@ -7,6 +7,7 @@ import {Image as GameImage} from "@core/elements/displayable/image"; import {default as StageImage} from "@player/elements/image/Image"; +/**@internal */ export default function Displayables( {state, displayable}: Readonly<{ state: GameState; diff --git a/src/game/player/elements/displayable/Text.tsx b/src/game/player/elements/displayable/Text.tsx index 27e390d..557c072 100644 --- a/src/game/player/elements/displayable/Text.tsx +++ b/src/game/player/elements/displayable/Text.tsx @@ -11,6 +11,7 @@ import {TransformDefinitions} from "@core/elements/transform/type"; import Inspect from "@player/lib/Inspect"; import {useRatio} from "@player/provider/ratio"; +/**@internal */ export default function Text({state, text}: Readonly<{ state: GameState; text: GameText; diff --git a/src/game/player/elements/displayable/type.ts b/src/game/player/elements/displayable/type.ts index 47ac784..8a597d4 100644 --- a/src/game/player/elements/displayable/type.ts +++ b/src/game/player/elements/displayable/type.ts @@ -3,6 +3,7 @@ import React from "react"; import {Transform} from "@core/elements/transform/transform"; import {GameState} from "@player/gameState"; +/**@internal */ export type DisplayableChildProps = { transition: ITransition | null; transform: Transform | null; @@ -10,7 +11,9 @@ export type DisplayableChildProps = { transformRef: React.MutableRefObject; state: GameState; }; +/**@internal */ export type DisplayableChildHandler = (props: Readonly) => React.ReactElement; +/**@internal */ export type StatefulDisplayable = { state: Record; }; diff --git a/src/game/player/elements/image/AspectScaleImage.tsx b/src/game/player/elements/image/AspectScaleImage.tsx index 224f8c2..82b5ca2 100644 --- a/src/game/player/elements/image/AspectScaleImage.tsx +++ b/src/game/player/elements/image/AspectScaleImage.tsx @@ -5,6 +5,7 @@ import {usePreloaded} from "@player/provider/preloaded"; import {Image} from "@core/elements/displayable/image"; import {useGame} from "@core/common/player"; +/**@internal */ export default function AspectScaleImage( { props, diff --git a/src/game/player/elements/image/Image.tsx b/src/game/player/elements/image/Image.tsx index 72fb11f..e890987 100644 --- a/src/game/player/elements/image/Image.tsx +++ b/src/game/player/elements/image/Image.tsx @@ -10,13 +10,15 @@ import AspectScaleImage from "@player/elements/image/AspectScaleImage"; import {useRatio} from "@player/provider/ratio"; import clsx from "clsx"; -export default function Image({ - image, - state, - }: Readonly<{ - image: GameImage; - state: GameState; -}>) { +/**@internal */ +export default function Image( + { + image, + state, + }: Readonly<{ + image: GameImage; + state: GameState; + }>) { /** * Slow load warning */ @@ -42,6 +44,7 @@ export default function Image({ ); }; +/**@internal */ function DisplayableImage( { transition, diff --git a/src/game/player/elements/menu/Menu.tsx b/src/game/player/elements/menu/Menu.tsx index 917a342..9819adf 100644 --- a/src/game/player/elements/menu/Menu.tsx +++ b/src/game/player/elements/menu/Menu.tsx @@ -12,6 +12,7 @@ import {Word} from "@core/elements/character/word"; import {Pausing} from "@core/elements/character/pause"; import {Script} from "@core/elements/script"; +/**@internal */ export default function Menu( { prompt, diff --git a/src/game/player/elements/player/KeyEventAnnouncer.tsx b/src/game/player/elements/player/KeyEventAnnouncer.tsx index 8fff6df..42d3b12 100644 --- a/src/game/player/elements/player/KeyEventAnnouncer.tsx +++ b/src/game/player/elements/player/KeyEventAnnouncer.tsx @@ -4,6 +4,7 @@ import {GameState} from "@player/gameState"; import {throttle} from "@lib/util/data"; import {Game} from "@core/common/game"; +/**@internal */ export function KeyEventAnnouncer({state}: Readonly<{ state: GameState; }>) { diff --git a/src/game/player/elements/player/SizeUpdateAnnouncer.tsx b/src/game/player/elements/player/SizeUpdateAnnouncer.tsx index 022f670..c0ccd2c 100644 --- a/src/game/player/elements/player/SizeUpdateAnnouncer.tsx +++ b/src/game/player/elements/player/SizeUpdateAnnouncer.tsx @@ -1,6 +1,7 @@ import React, {useEffect} from "react"; import {useRatio} from "@player/provider/ratio"; +/**@internal */ export default function SizeUpdateAnnouncer( {containerRef}: Readonly<{ containerRef: React.RefObject }> ) { diff --git a/src/game/player/elements/preload/Preload.tsx b/src/game/player/elements/preload/Preload.tsx index c0bbcc0..67df0d1 100644 --- a/src/game/player/elements/preload/Preload.tsx +++ b/src/game/player/elements/preload/Preload.tsx @@ -6,6 +6,7 @@ import {Preloaded} from "@player/lib/Preloaded"; import {TaskPool} from "@lib/util/data"; import {useGame} from "@player/provider/game-state"; +/**@internal */ export function Preload( { state, diff --git a/src/game/player/elements/say/Say.tsx b/src/game/player/elements/say/Say.tsx index bee7844..0dc044e 100644 --- a/src/game/player/elements/say/Say.tsx +++ b/src/game/player/elements/say/Say.tsx @@ -8,6 +8,7 @@ import {useRatio} from "@player/provider/ratio"; import Inspect from "@player/lib/Inspect"; import {Game} from "@core/game"; +/**@internal */ export default function Say( { action, diff --git a/src/game/player/elements/say/Sentence.tsx b/src/game/player/elements/say/Sentence.tsx index e3f251e..f1c3f72 100644 --- a/src/game/player/elements/say/Sentence.tsx +++ b/src/game/player/elements/say/Sentence.tsx @@ -8,6 +8,7 @@ import {Pause, Pausing} from "@core/elements/character/pause"; import Inspect from "@player/lib/Inspect"; import {Script} from "@core/elements/script"; +/**@internal */ type SplitWord = { text: string; config: Partial; @@ -15,6 +16,7 @@ type SplitWord = { tag2?: any; } | "\n" | Pausing; +/**@internal */ export default function Sentence( { sentence, diff --git a/src/game/player/elements/say/TypingEffect.tsx b/src/game/player/elements/say/TypingEffect.tsx deleted file mode 100644 index cd94e12..0000000 --- a/src/game/player/elements/say/TypingEffect.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React, {useEffect, useState} from "react"; - -interface TypingEffectProps { - text: string; - color: string; - speed: number; - onComplete?: () => void; - className?: string; -} - -const TypingEffect: React.FC = ( - {text, speed, onComplete, className, color} -) => { - const [displayedText, setDisplayedText] = useState(""); - const [currentIndex, setCurrentIndex] = useState(0); - - useEffect(() => { - if (currentIndex < text.length) { - if (text[currentIndex] === " ") { - setDisplayedText((prev) => prev.concat(text[currentIndex])); - setCurrentIndex((prev) => prev + 1); - } else { - const timeoutId = setTimeout(() => { - setDisplayedText((prev) => prev.concat(text[currentIndex])); - setCurrentIndex((prev) => prev + 1); - }, speed); - return () => clearTimeout(timeoutId); - } - } else if (onComplete) { - onComplete(); - } - }, [currentIndex]); - - return ; -}; - -export function Lines({text}: { text: string }) { - return (<>{text.split("\n").map((line, index) => ( - - {line} -
-
- ))}); -} - -export default TypingEffect; \ No newline at end of file diff --git a/src/game/player/elements/scene/Background.tsx b/src/game/player/elements/scene/Background.tsx index 506ffeb..f0fcf2f 100644 --- a/src/game/player/elements/scene/Background.tsx +++ b/src/game/player/elements/scene/Background.tsx @@ -4,11 +4,13 @@ import type {ReactNode} from "react"; import React, {useEffect, useRef} from "react"; import {useGame} from "@player/provider/game-state"; -export default function Background({ - children - }: Readonly<{ - children: ReactNode; -}>) { +/**@internal */ +export default function Background( + { + children + }: Readonly<{ + children: ReactNode; + }>) { const {ratio} = useRatio(); const {game} = useGame(); const contentContainerRef = useRef(null); diff --git a/src/game/player/elements/scene/BackgroundTransition.tsx b/src/game/player/elements/scene/BackgroundTransition.tsx index a24f3e0..1c0dd31 100644 --- a/src/game/player/elements/scene/BackgroundTransition.tsx +++ b/src/game/player/elements/scene/BackgroundTransition.tsx @@ -11,6 +11,7 @@ import Displayable from "@player/elements/displayable/Displayable"; import {useRatio} from "@player/provider/ratio"; import {usePreloaded} from "@player/provider/preloaded"; +/**@internal */ export default function BackgroundTransition({scene, props, state}: { scene: GameScene, props: Record, @@ -34,6 +35,7 @@ export default function BackgroundTransition({scene, props, state}: { ); } +/**@internal */ function DisplayableBackground( { transformRef, diff --git a/src/game/player/elements/scene/Scene.tsx b/src/game/player/elements/scene/Scene.tsx index bf3cbbd..0b2b088 100644 --- a/src/game/player/elements/scene/Scene.tsx +++ b/src/game/player/elements/scene/Scene.tsx @@ -6,6 +6,7 @@ import {GameState} from "@player/gameState"; import {Sound} from "@core/elements/sound"; import {Utils} from "@core/common/Utils"; +/**@internal */ export default function Scene( { scene, diff --git a/src/game/player/gameState.ts b/src/game/player/gameState.ts index d725d38..f598ab5 100644 --- a/src/game/player/gameState.ts +++ b/src/game/player/gameState.ts @@ -40,6 +40,7 @@ export type PlayerStateData = { }; }[] }; +/**@internal */ export type PlayerAction = CalledActionResult; interface StageUtils { diff --git a/src/game/player/gameState.type.ts b/src/game/player/gameState.type.ts index 5517710..481383e 100644 --- a/src/game/player/gameState.type.ts +++ b/src/game/player/gameState.type.ts @@ -4,16 +4,19 @@ import {Sentence} from "@core/elements/character/sentence"; import {Word} from "@core/elements/character/word"; import {Pausing} from "@core/elements/character/pause"; +/**@internal */ export type Clickable = { action: T; onClick: U extends undefined ? () => void : (arg0: U) => void; }; +/**@internal */ export type TextElement = { character: Character | null; sentence: Sentence; id: string; words: Word[]; }; +/**@internal */ export type MenuElement = { prompt: Sentence; choices: Choice[]; diff --git a/src/game/player/lib/UtilComponents.tsx b/src/game/player/lib/UtilComponents.tsx index 49d3721..91f25d1 100644 --- a/src/game/player/lib/UtilComponents.tsx +++ b/src/game/player/lib/UtilComponents.tsx @@ -17,7 +17,7 @@ const ForwardClassNamePropType = { className: PropTypes.string, } as const; const ForwardChildrenPropType = { - children: PropTypes.node, + children: PropTypes.element, } as const; function forwardBox( diff --git a/src/game/player/provider/game-state.tsx b/src/game/player/provider/game-state.tsx index a407663..779cf98 100644 --- a/src/game/player/provider/game-state.tsx +++ b/src/game/player/provider/game-state.tsx @@ -10,6 +10,9 @@ type GameContextType = { const GameContext = React.createContext(null); +/** + * @internal + */ export function GameProvider({children, game}: { children?: ReactNode, game?: Game }) { "use client"; const DefaultValue = new Game({}); diff --git a/src/game/player/provider/preloaded.tsx b/src/game/player/provider/preloaded.tsx index f26bbaa..6d5d32e 100644 --- a/src/game/player/provider/preloaded.tsx +++ b/src/game/player/provider/preloaded.tsx @@ -11,6 +11,7 @@ type PreloadedContextType = { const Context = createContext(null); +/**@internal */ export function PreloadedProvider({children}: { children: React.ReactNode }) { @@ -26,6 +27,7 @@ export function PreloadedProvider({children}: { ); } +/**@internal */ export function usePreloaded(): PreloadedContextType { if (!Context) throw new Error("usePreloaded must be used within a PreloadedProvider"); return useContext(Context) as PreloadedContextType; diff --git a/src/game/player/provider/ratio.tsx b/src/game/player/provider/ratio.tsx index 06758bc..ba6cd0b 100644 --- a/src/game/player/provider/ratio.tsx +++ b/src/game/player/provider/ratio.tsx @@ -3,6 +3,7 @@ import React, {createContext, useContext, useEffect, useReducer, useState} from "react"; import {EventDispatcher} from "@lib/util/data"; +/**@internal */ export type AspectRatioState = { width: number; height: number; @@ -121,6 +122,7 @@ class AspectRatio { const RatioContext = createContext(null); +/**@internal */ export function RatioProvider({children}: { children: React.ReactNode }) { @@ -133,6 +135,7 @@ export function RatioProvider({children}: { ); } +/**@internal */ export function useRatio(): { ratio: AspectRatio } { const context = useContext(RatioContext); if (!RatioContext || !context) throw new Error("useRatio must be used within a RatioProvider"); From ff2d8a2a2f972ebc4c02b1129b72275b2f8bbc55 Mon Sep 17 00:00:00 2001 From: York Date: Thu, 26 Dec 2024 20:48:55 -0800 Subject: [PATCH 7/8] update: upgrade to react v19 --- package.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e97de74..7c0c72b 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,8 @@ "husky": "^9.1.6", "jest": "^27.0.6", "postcss-loader": "^8.1.1", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", "rimraf": "^6.0.1", "style-loader": "^4.0.0", "tailwindcss": "^3.4.11", @@ -56,8 +56,9 @@ "webpack-dev-server": "^5.1.0" }, "peerDependencies": { - "react": ">=17.0.0", - "react-dom": ">=17.0.0" + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" }, "files": [ "dist" From cbb0606cbe28d97863f6629ce9dfe84f84ccc349 Mon Sep 17 00:00:00 2001 From: York Date: Fri, 27 Dec 2024 12:20:33 -0800 Subject: [PATCH 8/8] update: `Player` component now doesn't require a `story` prop --- CHANGELOG.md | 4 ++++ src/game/nlcore/elements/story.ts | 5 +++++ src/game/nlcore/game/liveGame.ts | 5 +++++ src/game/player/elements/Player.tsx | 7 ++++--- src/game/player/elements/type.ts | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d70cbf8..5cbe7f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ - Utility component: `Full` - `usePreference` hook +### Updated + +- `Player` component now doesn't require a `story` prop + ## [0.2.2] - 2024/12/02 ### _Feature_ diff --git a/src/game/nlcore/elements/story.ts b/src/game/nlcore/elements/story.ts index 3603bcd..8bc149a 100644 --- a/src/game/nlcore/elements/story.ts +++ b/src/game/nlcore/elements/story.ts @@ -22,6 +22,11 @@ export class Story extends Constructable< /**@internal */ static MAX_DEPTH = 10000; + /**@internal */ + public static empty(): Story { + return new Story("empty").entry(new Scene("empty")); + } + /**@internal */ readonly name: string; /**@internal */ diff --git a/src/game/nlcore/game/liveGame.ts b/src/game/nlcore/game/liveGame.ts index 5c88820..3a057f5 100644 --- a/src/game/nlcore/game/liveGame.ts +++ b/src/game/nlcore/game/liveGame.ts @@ -366,6 +366,11 @@ export class LiveGame { return nextAction; } + /**@internal */ + isPlaying() { + return !!this.currentAction; + } + /**@internal */ abortAwaiting() { if (this.lockedAwaiting) { diff --git a/src/game/player/elements/Player.tsx b/src/game/player/elements/Player.tsx index 55b8b66..6eb3bfb 100644 --- a/src/game/player/elements/Player.tsx +++ b/src/game/player/elements/Player.tsx @@ -23,6 +23,7 @@ import Displayables from "@player/elements/displayable/Displayables"; import {ErrorBoundary} from "@player/lib/ErrorBoundary"; import SizeUpdateAnnouncer from "@player/elements/player/SizeUpdateAnnouncer"; import Cursor from "@player/lib/Cursor"; +import {Story} from "@core/elements/story"; function handleAction(state: GameState, action: PlayerAction) { return state.handle(action); @@ -30,7 +31,7 @@ function handleAction(state: GameState, action: PlayerAction) { export default function Player( { - story, + story = Story.empty(), width, height, className, @@ -83,14 +84,14 @@ export default function Player( useEffect(() => { game.getLiveGame().setGameState(state); - if (story) { + if (story && !game.getLiveGame().isPlaying()) { game.getLiveGame().loadStory(story); } return () => { game.getLiveGame().setGameState(undefined); }; - }, [game]); + }, [game, story]); useEffect(() => { return createMicroTask(() => { diff --git a/src/game/player/elements/type.ts b/src/game/player/elements/type.ts index 6d72c8c..667b37a 100644 --- a/src/game/player/elements/type.ts +++ b/src/game/player/elements/type.ts @@ -29,7 +29,7 @@ export type PlayerEventContext = { } export interface PlayerProps { - story: Story; + story?: Story; width?: string | number; height?: string | number; className?: clsx.ClassValue;