@rpgjs/client 5.0.0-beta.24 → 5.0.0-beta.26
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/CHANGELOG.md +64 -0
- package/dist/Game/Map.d.ts +1 -0
- package/dist/Game/Map.js +5 -0
- package/dist/Game/Map.js.map +1 -1
- package/dist/Gui/Gui.js +5 -0
- package/dist/Gui/Gui.js.map +1 -1
- package/dist/RpgClient.d.ts +2 -1
- package/dist/RpgClientEngine.d.ts +76 -0
- package/dist/RpgClientEngine.js +59 -4
- package/dist/RpgClientEngine.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +23 -2
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/index.d.ts +3 -1
- package/dist/components/gui/index.js +2 -0
- package/dist/components/gui/input-field.ce.js +123 -0
- package/dist/components/gui/input-field.ce.js.map +1 -0
- package/dist/components/gui/input.ce.js +40 -0
- package/dist/components/gui/input.ce.js.map +1 -0
- package/dist/components/scenes/draw-map.ce.js +5 -2
- package/dist/components/scenes/draw-map.ce.js.map +1 -1
- package/dist/components/scenes/weather-lifecycle-compat.d.ts +0 -0
- package/dist/components/scenes/weather-lifecycle-compat.js +11 -0
- package/dist/components/scenes/weather-lifecycle-compat.js.map +1 -0
- package/dist/components/scenes/weather-tick-lifecycle.d.ts +17 -0
- package/dist/components/scenes/weather-tick-lifecycle.js +44 -0
- package/dist/components/scenes/weather-tick-lifecycle.js.map +1 -0
- package/dist/components/scenes/weather-tick-lifecycle.spec.d.ts +1 -0
- package/dist/i18n.d.ts +12 -0
- package/dist/i18n.js +12 -0
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +15 -11
- package/dist/services/loadMap.d.ts +10 -2
- package/dist/services/loadMap.js +2 -1
- package/dist/services/loadMap.js.map +1 -1
- package/dist/services/mapStreaming.d.ts +85 -0
- package/dist/services/mapStreaming.js +210 -0
- package/dist/services/mapStreaming.js.map +1 -0
- package/dist/services/mapStreaming.spec.d.ts +1 -0
- package/dist/services/mmorpg.d.ts +6 -0
- package/dist/services/mmorpg.js +2 -2
- package/dist/services/mmorpg.js.map +1 -1
- package/package.json +4 -4
- package/src/Game/Map.ts +7 -0
- package/src/Gui/Gui.spec.ts +5 -0
- package/src/Gui/Gui.ts +5 -1
- package/src/RpgClient.ts +2 -1
- package/src/RpgClientEngine.ts +147 -6
- package/src/components/gui/dialogbox/index.ce +26 -1
- package/src/components/gui/index.ts +5 -1
- package/src/components/gui/input-field.ce +106 -0
- package/src/components/gui/input.ce +26 -0
- package/src/components/scenes/draw-map.ce +4 -1
- package/src/components/scenes/weather-lifecycle-compat.ts +8 -0
- package/src/components/scenes/weather-tick-lifecycle.spec.ts +60 -0
- package/src/components/scenes/weather-tick-lifecycle.ts +69 -0
- package/src/i18n.spec.ts +2 -1
- package/src/i18n.ts +12 -0
- package/src/index.ts +2 -0
- package/src/services/loadMap.ts +9 -2
- package/src/services/mapStreaming.spec.ts +240 -0
- package/src/services/mapStreaming.ts +275 -0
- package/src/services/mmorpg.ts +15 -2
- package/vite.config.ts +5 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { inject } from "../../../core/inject.js";
|
|
2
2
|
import { getKeyboardControlBind } from "../../../services/actionInput.js";
|
|
3
|
+
import __ce_component$1 from "../input-field.ce.js";
|
|
3
4
|
import { RpgClientEngine } from "../../../RpgClientEngine.js";
|
|
4
5
|
import { DOMContainer, DOMElement, DOMSprite, Navigation, computed, cond, createTabindexNavigator, effect, h, loop, mount, signal, useDefineEmits, useDefineProps, useProps } from "canvasengine";
|
|
5
6
|
import { delay } from "@rpgjs/common";
|
|
@@ -23,6 +24,8 @@ function component($$props) {
|
|
|
23
24
|
const position = computed(() => dialogData().position);
|
|
24
25
|
const typewriterEffect = computed(() => dialogData().typewriterEffect);
|
|
25
26
|
const fullWidth = computed(() => dialogData().fullWidth || false);
|
|
27
|
+
const dialogInput = computed(() => dialogData().input || null);
|
|
28
|
+
const hasInput = computed(() => !!dialogInput());
|
|
26
29
|
const resolveProp = (value) => typeof value === "function" ? value() : value;
|
|
27
30
|
const normalizeOpenId = (value) => {
|
|
28
31
|
const resolved = resolveProp(value);
|
|
@@ -76,7 +79,7 @@ function component($$props) {
|
|
|
76
79
|
startTypewriter(text);
|
|
77
80
|
});
|
|
78
81
|
const hasChoices = computed(() => dialogChoices().length > 0);
|
|
79
|
-
const showIndicator = computed(() => !hasChoices() && !isTyping());
|
|
82
|
+
const showIndicator = computed(() => !hasChoices() && !hasInput() && !isTyping());
|
|
80
83
|
const nav = createTabindexNavigator(selectedItem, { count: () => dialogChoices().length }, "wrap");
|
|
81
84
|
function selectChoice(index) {
|
|
82
85
|
return function() {
|
|
@@ -91,6 +94,10 @@ function component($$props) {
|
|
|
91
94
|
event?.stopPropagation?.();
|
|
92
95
|
};
|
|
93
96
|
const closeDialog = () => {
|
|
97
|
+
if (hasInput()) {
|
|
98
|
+
onInteraction?.("cancel");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
94
101
|
_onFinish();
|
|
95
102
|
};
|
|
96
103
|
const closeDialogFromPointer = (event) => {
|
|
@@ -100,6 +107,12 @@ function component($$props) {
|
|
|
100
107
|
const onSelect = (index) => {
|
|
101
108
|
_onFinish(index);
|
|
102
109
|
};
|
|
110
|
+
const submitInput = (payload) => {
|
|
111
|
+
onInteraction?.("submit", payload);
|
|
112
|
+
};
|
|
113
|
+
const cancelInput = () => {
|
|
114
|
+
onInteraction?.("cancel");
|
|
115
|
+
};
|
|
103
116
|
const canAcceptAction = () => Date.now() - openedAt >= ACTION_OPEN_GUARD_MS;
|
|
104
117
|
const controls = signal({
|
|
105
118
|
up: {
|
|
@@ -142,6 +155,7 @@ function component($$props) {
|
|
|
142
155
|
finishTyping();
|
|
143
156
|
return;
|
|
144
157
|
}
|
|
158
|
+
if (hasInput()) return;
|
|
145
159
|
if (hasChoices()) return;
|
|
146
160
|
_onFinish();
|
|
147
161
|
}
|
|
@@ -223,7 +237,14 @@ function component($$props) {
|
|
|
223
237
|
click: selectChoice(index)
|
|
224
238
|
},
|
|
225
239
|
textContent: choice.text
|
|
226
|
-
})))))
|
|
240
|
+
}))))),
|
|
241
|
+
cond(computed(() => hasInput()), () => h(__ce_component$1, {
|
|
242
|
+
data: dialogInput,
|
|
243
|
+
layout: "dialog",
|
|
244
|
+
showMessage: false,
|
|
245
|
+
submit: submitInput,
|
|
246
|
+
cancel: cancelInput
|
|
247
|
+
}))
|
|
227
248
|
]), cond(computed(() => hasFace()), () => h(DOMElement, {
|
|
228
249
|
element: "div",
|
|
229
250
|
attrs: { class: "rpg-ui-dialog-face" }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.ce.js","names":[],"sources":["../../../../src/components/gui/dialogbox/index.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={dialogControls}>\n <div class=\"rpg-ui-dialog-layer\" click={closeDialogFromPointer}>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close dialog\" click={closeDialogFromPointer}>x</button>\n <div\n class=\"rpg-ui-dialog-container\"\n data-position={dialogPosition()}\n data-full-width={isFullWidth() ? \"true\" : \"false\"}\n data-has-face={hasFace() ? \"true\" : \"false\"}\n >\n <div class=\"rpg-ui-dialog rpg-anim-fade-in\" click={stopEvent}>\n <div class=\"rpg-ui-dialog-body\">\n <div>\n @if (speakerName()) {\n <div class=\"rpg-ui-dialog-speaker\">{speakerName()}</div>\n }\n <div class=\"rpg-ui-dialog-content\">\n {displayMessage()}\n </div>\n @if (hasChoices()) {\n <Navigation tabindex={selectedItem} controls={controls}>\n <div class=\"rpg-ui-dialog-choices\">\n @for ((choice,index) of dialogChoices()) {\n <div\n class=\"rpg-ui-dialog-choice\"\n class={{active: selectedItem() === index}}\n tabindex={index}\n data-choice-index={index}\n click={selectChoice(index)}\n >{{ choice.text }}</div>\n }\n </div>\n </Navigation>\n }\n </div>\n @if (hasFace()) {\n <div class=\"rpg-ui-dialog-face\">\n <DOMSprite\n sheet={faceSheet(dialogFace())}\n width=\"100%\"\n height=\"100%\"\n objectFit=\"contain\"\n />\n </div>\n }\n </div>\n @if (showIndicator) {\n <div class=\"rpg-ui-dialog-indicator\"></div>\n }\n </div>\n </div>\n </div>\n</DOMContainer>\n \n<script>\n import { effect, signal, computed, createTabindexNavigator, mount } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const currentPlayer = engine.scene.currentPlayer\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n engine.stopProcessingInput = true;\n\n const selectedItem = signal(0)\n const ACTION_OPEN_GUARD_MS = 150;\n const openedAt = Date.now();\n\n const {\n data,\n onFinish,\n onInteraction,\n guiOpenId\n } = defineProps();\n\n const dialogData = computed(() => data() || {});\n const dialogChoices = computed(() => Array.isArray(dialogData().choices) ? dialogData().choices : []);\n const message = computed(() => dialogData().message);\n const speaker = computed(() => dialogData().speaker);\n const position = computed(() => dialogData().position);\n const typewriterEffect = computed(() => dialogData().typewriterEffect);\n const fullWidth = computed(() => dialogData().fullWidth || false);\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const normalizeOpenId = (value) => {\n const resolved = resolveProp(value);\n return typeof resolved === \"string\" && resolved.length > 0 ? resolved : undefined;\n };\n\n const speakerName = computed(() => {\n const value = resolveProp(speaker());\n return value ? String(value) : \"\";\n });\n\n const dialogPosition = computed(() => resolveProp(position()) || \"bottom\");\n const isFullWidth = computed(() => resolveProp(fullWidth) !== false);\n const dialogFace = computed(() => resolveProp(dialogData().face));\n const hasFace = computed(() => {\n const value = dialogFace();\n return !!(value && value.id);\n });\n\n const displayMessage = signal(\"\");\n const fullMessage = signal(\"\");\n const isTyping = signal(false);\n let typewriterTimer = null;\n let rootElement = null;\n\n mount((element) => {\n rootElement = element;\n });\n\n const startTypewriter = (text) => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n displayMessage.set(\"\");\n if (!text) return;\n let index = 0;\n isTyping.set(true);\n typewriterTimer = setInterval(() => {\n index += 1;\n displayMessage.set(text.slice(0, index));\n if (index >= text.length) {\n clearInterval(typewriterTimer);\n typewriterTimer = null;\n isTyping.set(false);\n }\n }, 20);\n };\n\n const finishTyping = () => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n typewriterTimer = null;\n displayMessage.set(fullMessage());\n isTyping.set(false);\n };\n\n effect(() => {\n const text = resolveProp(message()) || \"\";\n fullMessage.set(text);\n const useTypewriter = resolveProp(typewriterEffect()) !== false;\n if (!useTypewriter) {\n finishTyping();\n return;\n }\n startTypewriter(text);\n });\n\n\n const hasChoices = computed(() => dialogChoices().length > 0);\n const showIndicator = computed(() => !hasChoices() && !isTyping());\n const nav = createTabindexNavigator(selectedItem, { count: () => dialogChoices().length }, 'wrap');\n\n function selectChoice(index) {\n return function() {\n selectedItem.set(index);\n onSelect(index);\n }\n }\n\n function _onFinish(value) {\n if (onFinish) onFinish(value, normalizeOpenId(guiOpenId));\n }\n\n const stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const closeDialog = () => {\n _onFinish();\n };\n\n const closeDialogFromPointer = (event) => {\n stopEvent(event);\n closeDialog();\n };\n\n const onSelect = (index) => {\n _onFinish(index);\n };\n\n const canAcceptAction = () => Date.now() - openedAt >= ACTION_OPEN_GUARD_MS;\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!canAcceptAction()) {\n return;\n }\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (!hasChoices()) return;\n onSelect(selectedItem());\n }\n },\n gamepad: {\n enabled: true\n }\n });\n \n const dialogControls = signal({\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!canAcceptAction()) {\n return;\n }\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (hasChoices()) return;\n _onFinish();\n }\n },\n })\n\n const faceSheet = (faceValue) => {\n if (!faceValue || !faceValue.id) {\n return undefined;\n }\n return {\n definition: engine.getSpriteSheet(faceValue.id),\n playing: faceValue.expression || \"default\",\n };\n }\n\n mount((element) => {\n return () => {\n // Wait destroy is finished before start processing input\n delay(() => {\n engine.stopProcessingInput = false;\n })\n }\n })\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.ce.js","names":[],"sources":["../../../../src/components/gui/dialogbox/index.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={dialogControls}>\n <div class=\"rpg-ui-dialog-layer\" click={closeDialogFromPointer}>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close dialog\" click={closeDialogFromPointer}>x</button>\n <div\n class=\"rpg-ui-dialog-container\"\n data-position={dialogPosition()}\n data-full-width={isFullWidth() ? \"true\" : \"false\"}\n data-has-face={hasFace() ? \"true\" : \"false\"}\n >\n <div class=\"rpg-ui-dialog rpg-anim-fade-in\" click={stopEvent}>\n <div class=\"rpg-ui-dialog-body\">\n <div>\n @if (speakerName()) {\n <div class=\"rpg-ui-dialog-speaker\">{speakerName()}</div>\n }\n <div class=\"rpg-ui-dialog-content\">\n {displayMessage()}\n </div>\n @if (hasChoices()) {\n <Navigation tabindex={selectedItem} controls={controls}>\n <div class=\"rpg-ui-dialog-choices\">\n @for ((choice,index) of dialogChoices()) {\n <div\n class=\"rpg-ui-dialog-choice\"\n class={{active: selectedItem() === index}}\n tabindex={index}\n data-choice-index={index}\n click={selectChoice(index)}\n >{{ choice.text }}</div>\n }\n </div>\n </Navigation>\n }\n @if (hasInput()) {\n <InputField\n data={dialogInput}\n layout=\"dialog\"\n showMessage={false}\n submit={submitInput}\n cancel={cancelInput}\n />\n }\n </div>\n @if (hasFace()) {\n <div class=\"rpg-ui-dialog-face\">\n <DOMSprite\n sheet={faceSheet(dialogFace())}\n width=\"100%\"\n height=\"100%\"\n objectFit=\"contain\"\n />\n </div>\n }\n </div>\n @if (showIndicator) {\n <div class=\"rpg-ui-dialog-indicator\"></div>\n }\n </div>\n </div>\n </div>\n</DOMContainer>\n \n<script>\n import { effect, signal, computed, createTabindexNavigator, mount } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n import InputField from \"../input-field.ce\";\n\n const engine = inject(RpgClientEngine);\n const currentPlayer = engine.scene.currentPlayer\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n engine.stopProcessingInput = true;\n\n const selectedItem = signal(0)\n const ACTION_OPEN_GUARD_MS = 150;\n const openedAt = Date.now();\n\n const {\n data,\n onFinish,\n onInteraction,\n guiOpenId\n } = defineProps();\n\n const dialogData = computed(() => data() || {});\n const dialogChoices = computed(() => Array.isArray(dialogData().choices) ? dialogData().choices : []);\n const message = computed(() => dialogData().message);\n const speaker = computed(() => dialogData().speaker);\n const position = computed(() => dialogData().position);\n const typewriterEffect = computed(() => dialogData().typewriterEffect);\n const fullWidth = computed(() => dialogData().fullWidth || false);\n const dialogInput = computed(() => dialogData().input || null);\n const hasInput = computed(() => !!dialogInput());\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const normalizeOpenId = (value) => {\n const resolved = resolveProp(value);\n return typeof resolved === \"string\" && resolved.length > 0 ? resolved : undefined;\n };\n\n const speakerName = computed(() => {\n const value = resolveProp(speaker());\n return value ? String(value) : \"\";\n });\n\n const dialogPosition = computed(() => resolveProp(position()) || \"bottom\");\n const isFullWidth = computed(() => resolveProp(fullWidth) !== false);\n const dialogFace = computed(() => resolveProp(dialogData().face));\n const hasFace = computed(() => {\n const value = dialogFace();\n return !!(value && value.id);\n });\n\n const displayMessage = signal(\"\");\n const fullMessage = signal(\"\");\n const isTyping = signal(false);\n let typewriterTimer = null;\n let rootElement = null;\n\n mount((element) => {\n rootElement = element;\n });\n\n const startTypewriter = (text) => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n displayMessage.set(\"\");\n if (!text) return;\n let index = 0;\n isTyping.set(true);\n typewriterTimer = setInterval(() => {\n index += 1;\n displayMessage.set(text.slice(0, index));\n if (index >= text.length) {\n clearInterval(typewriterTimer);\n typewriterTimer = null;\n isTyping.set(false);\n }\n }, 20);\n };\n\n const finishTyping = () => {\n if (typewriterTimer) clearInterval(typewriterTimer);\n typewriterTimer = null;\n displayMessage.set(fullMessage());\n isTyping.set(false);\n };\n\n effect(() => {\n const text = resolveProp(message()) || \"\";\n fullMessage.set(text);\n const useTypewriter = resolveProp(typewriterEffect()) !== false;\n if (!useTypewriter) {\n finishTyping();\n return;\n }\n startTypewriter(text);\n });\n\n\n const hasChoices = computed(() => dialogChoices().length > 0);\n const showIndicator = computed(() => !hasChoices() && !hasInput() && !isTyping());\n const nav = createTabindexNavigator(selectedItem, { count: () => dialogChoices().length }, 'wrap');\n\n function selectChoice(index) {\n return function() {\n selectedItem.set(index);\n onSelect(index);\n }\n }\n\n function _onFinish(value) {\n if (onFinish) onFinish(value, normalizeOpenId(guiOpenId));\n }\n\n const stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const closeDialog = () => {\n if (hasInput()) {\n onInteraction?.(\"cancel\");\n return;\n }\n _onFinish();\n };\n\n const closeDialogFromPointer = (event) => {\n stopEvent(event);\n closeDialog();\n };\n\n const onSelect = (index) => {\n _onFinish(index);\n };\n\n const submitInput = (payload) => {\n onInteraction?.(\"submit\", payload);\n };\n\n const cancelInput = () => {\n onInteraction?.(\"cancel\");\n };\n\n const canAcceptAction = () => Date.now() - openedAt >= ACTION_OPEN_GUARD_MS;\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (!hasChoices()) return;\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!canAcceptAction()) {\n return;\n }\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (!hasChoices()) return;\n onSelect(selectedItem());\n }\n },\n gamepad: {\n enabled: true\n }\n });\n \n const dialogControls = signal({\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!canAcceptAction()) {\n return;\n }\n if (isTyping()) {\n finishTyping();\n return;\n }\n if (hasInput()) return;\n if (hasChoices()) return;\n _onFinish();\n }\n },\n })\n\n const faceSheet = (faceValue) => {\n if (!faceValue || !faceValue.id) {\n return undefined;\n }\n return {\n definition: engine.getSpriteSheet(faceValue.id),\n playing: faceValue.expression || \"default\",\n };\n }\n\n mount((element) => {\n return () => {\n // Wait destroy is finished before start processing input\n delay(() => {\n engine.stopProcessingInput = false;\n })\n }\n })\n</script>\n"],"mappings":"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"}
|
|
@@ -12,4 +12,6 @@ import { default as ExitMenuComponent } from './menu/exit-menu.ce';
|
|
|
12
12
|
import { default as NotificationComponent } from './notification/notification.ce';
|
|
13
13
|
import { default as TitleScreenComponent } from './title-screen.ce';
|
|
14
14
|
import { default as GameoverComponent } from './gameover.ce';
|
|
15
|
-
|
|
15
|
+
import { default as InputComponent } from './input.ce';
|
|
16
|
+
import { default as InputFieldComponent } from './input-field.ce';
|
|
17
|
+
export { DialogboxComponent, BoxComponent, ShopComponent, HudComponent, SaveLoadComponent, MainMenuComponent, ItemsMenuComponent, SkillsMenuComponent, EquipMenuComponent, OptionsMenuComponent, ExitMenuComponent, NotificationComponent, TitleScreenComponent, GameoverComponent, InputComponent, InputFieldComponent };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./input-field.ce.js";
|
|
1
2
|
import "./dialogbox/index.ce.js";
|
|
2
3
|
import "./box.ce.js";
|
|
3
4
|
import "./shop/shop.ce.js";
|
|
@@ -12,3 +13,4 @@ import "./menu/main-menu.ce.js";
|
|
|
12
13
|
import "./notification/notification.ce.js";
|
|
13
14
|
import "./title-screen.ce.js";
|
|
14
15
|
import "./gameover.ce.js";
|
|
16
|
+
import "./input.ce.js";
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { inject } from "../../core/inject.js";
|
|
2
|
+
import { RpgClientEngine } from "../../RpgClientEngine.js";
|
|
3
|
+
import { DOMElement, computed, cond, effect, h, signal, useDefineEmits, useDefineProps, useProps } from "canvasengine";
|
|
4
|
+
//#region src/components/gui/input-field.ce
|
|
5
|
+
function component($$props) {
|
|
6
|
+
useProps($$props);
|
|
7
|
+
const defineProps = useDefineProps($$props);
|
|
8
|
+
const defineEmits = useDefineEmits($$props);
|
|
9
|
+
const { t } = inject(RpgClientEngine).i18n();
|
|
10
|
+
const { data, layout, showMessage } = defineProps({
|
|
11
|
+
layout: "standalone",
|
|
12
|
+
showMessage: true
|
|
13
|
+
});
|
|
14
|
+
const { submit, cancel } = defineEmits();
|
|
15
|
+
const formData = computed(() => data() || {});
|
|
16
|
+
const value = signal(String(formData().defaultValue ?? ""));
|
|
17
|
+
const fieldId = computed(() => `rpg-input-value-${layout()}`);
|
|
18
|
+
const errorText = computed(() => formData().errorKey ? t(formData().errorKey, formData().errorParams || {}) : "");
|
|
19
|
+
const showCancelButton = computed(() => formData().cancelButton !== false);
|
|
20
|
+
let focused = false;
|
|
21
|
+
function submitForm(event, collectedData) {
|
|
22
|
+
const submittedValue = collectedData && Object.prototype.hasOwnProperty.call(collectedData, "value") ? collectedData.value : event?.currentTarget?.elements?.value?.value ?? value();
|
|
23
|
+
value.set(String(submittedValue ?? ""));
|
|
24
|
+
submit({ value: submittedValue ?? "" });
|
|
25
|
+
}
|
|
26
|
+
function cancelForm() {
|
|
27
|
+
cancel();
|
|
28
|
+
}
|
|
29
|
+
function handleKeydown(event) {
|
|
30
|
+
if (event?.key !== "Escape") return;
|
|
31
|
+
event.preventDefault?.();
|
|
32
|
+
event.stopPropagation?.();
|
|
33
|
+
cancelForm();
|
|
34
|
+
}
|
|
35
|
+
effect(() => {
|
|
36
|
+
if (focused) return;
|
|
37
|
+
focused = true;
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
document.getElementById(fieldId())?.focus?.();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return h(DOMElement, {
|
|
43
|
+
element: "form",
|
|
44
|
+
attrs: {
|
|
45
|
+
class: "rpg-ui-input-form",
|
|
46
|
+
"data-layout": computed(() => layout()),
|
|
47
|
+
submit: submitForm,
|
|
48
|
+
keydown: handleKeydown
|
|
49
|
+
}
|
|
50
|
+
}, [
|
|
51
|
+
cond(computed(() => showMessage()), () => h(DOMElement, {
|
|
52
|
+
element: "label",
|
|
53
|
+
attrs: {
|
|
54
|
+
class: "rpg-ui-input-message",
|
|
55
|
+
for: computed(() => fieldId())
|
|
56
|
+
},
|
|
57
|
+
textContent: computed(() => formData().message)
|
|
58
|
+
})),
|
|
59
|
+
cond(computed(() => formData().control === "textarea"), () => h(DOMElement, {
|
|
60
|
+
element: "textarea",
|
|
61
|
+
attrs: {
|
|
62
|
+
id: computed(() => fieldId()),
|
|
63
|
+
class: "rpg-ui-input rpg-ui-input-dialog-field",
|
|
64
|
+
name: "value",
|
|
65
|
+
value,
|
|
66
|
+
placeholder: computed(() => formData().placeholder || ""),
|
|
67
|
+
rows: computed(() => formData().rows || 4),
|
|
68
|
+
minlength: computed(() => formData().minLength),
|
|
69
|
+
maxlength: computed(() => formData().maxLength),
|
|
70
|
+
"aria-required": computed(() => formData().required ? "true" : "false")
|
|
71
|
+
}
|
|
72
|
+
}), () => h(DOMElement, {
|
|
73
|
+
element: "input",
|
|
74
|
+
attrs: {
|
|
75
|
+
id: computed(() => fieldId()),
|
|
76
|
+
class: "rpg-ui-input rpg-ui-input-dialog-field",
|
|
77
|
+
name: "value",
|
|
78
|
+
type: computed(() => formData().type || "text"),
|
|
79
|
+
value,
|
|
80
|
+
placeholder: computed(() => formData().placeholder || ""),
|
|
81
|
+
min: computed(() => formData().min),
|
|
82
|
+
max: computed(() => formData().max),
|
|
83
|
+
step: computed(() => formData().step),
|
|
84
|
+
minlength: computed(() => formData().minLength),
|
|
85
|
+
maxlength: computed(() => formData().maxLength),
|
|
86
|
+
"aria-required": computed(() => formData().required ? "true" : "false")
|
|
87
|
+
}
|
|
88
|
+
})),
|
|
89
|
+
cond(computed(() => errorText()), () => h(DOMElement, {
|
|
90
|
+
element: "div",
|
|
91
|
+
attrs: {
|
|
92
|
+
class: "rpg-ui-input-error",
|
|
93
|
+
role: "alert"
|
|
94
|
+
},
|
|
95
|
+
textContent: computed(() => errorText())
|
|
96
|
+
})),
|
|
97
|
+
h(DOMElement, {
|
|
98
|
+
element: "div",
|
|
99
|
+
attrs: { class: "rpg-ui-input-actions" }
|
|
100
|
+
}, [cond(computed(() => showCancelButton()), () => h(DOMElement, {
|
|
101
|
+
element: "button",
|
|
102
|
+
attrs: {
|
|
103
|
+
class: "rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-cancel",
|
|
104
|
+
type: "button",
|
|
105
|
+
click: cancelForm
|
|
106
|
+
},
|
|
107
|
+
textContent: computed(() => formData().cancelText || t("rpg.input.cancel"))
|
|
108
|
+
})), h(DOMElement, {
|
|
109
|
+
element: "button",
|
|
110
|
+
attrs: {
|
|
111
|
+
class: "rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-confirm",
|
|
112
|
+
"data-variant": "primary",
|
|
113
|
+
type: "submit"
|
|
114
|
+
},
|
|
115
|
+
textContent: computed(() => formData().confirmText || t("rpg.input.confirm"))
|
|
116
|
+
})])
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
var __ce_component = component;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { __ce_component as default };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=input-field.ce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-field.ce.js","names":[],"sources":["../../../src/components/gui/input-field.ce"],"sourcesContent":["<form\n class=\"rpg-ui-input-form\"\n data-layout={layout()}\n submit={submitForm}\n keydown={handleKeydown}\n>\n @if (showMessage()) {\n <label class=\"rpg-ui-input-message\" for={fieldId()}>{formData().message}</label>\n }\n @if (formData().control === \"textarea\") {\n <textarea\n id={fieldId()}\n class=\"rpg-ui-input rpg-ui-input-dialog-field\"\n name=\"value\"\n value={value}\n placeholder={formData().placeholder || \"\"}\n rows={formData().rows || 4}\n minlength={formData().minLength}\n maxlength={formData().maxLength}\n aria-required={formData().required ? \"true\" : \"false\"}\n ></textarea>\n }\n @else {\n <input\n id={fieldId()}\n class=\"rpg-ui-input rpg-ui-input-dialog-field\"\n name=\"value\"\n type={formData().type || \"text\"}\n value={value}\n placeholder={formData().placeholder || \"\"}\n min={formData().min}\n max={formData().max}\n step={formData().step}\n minlength={formData().minLength}\n maxlength={formData().maxLength}\n aria-required={formData().required ? \"true\" : \"false\"}\n />\n }\n @if (errorText()) {\n <div class=\"rpg-ui-input-error\" role=\"alert\">{errorText()}</div>\n }\n <div class=\"rpg-ui-input-actions\">\n @if (showCancelButton()) {\n <button class=\"rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-cancel\" type=\"button\" click={cancelForm}>\n {formData().cancelText || t(\"rpg.input.cancel\")}\n </button>\n }\n <button\n class=\"rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-confirm\"\n data-variant=\"primary\"\n type=\"submit\"\n >\n {formData().confirmText || t(\"rpg.input.confirm\")}\n </button>\n </div>\n</form>\n\n<script>\n import { computed, effect, signal } from \"canvasengine\";\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const { data, layout, showMessage } = defineProps({\n layout: \"standalone\",\n showMessage: true,\n });\n const { submit, cancel } = defineEmits();\n const formData = computed(() => data() || {});\n const value = signal(String(formData().defaultValue ?? \"\"));\n const fieldId = computed(() => `rpg-input-value-${layout()}`);\n const errorText = computed(() => formData().errorKey\n ? t(formData().errorKey, formData().errorParams || {})\n : \"\"\n );\n const showCancelButton = computed(() => formData().cancelButton !== false);\n let focused = false;\n\n function submitForm(event, collectedData) {\n const submittedValue = collectedData && Object.prototype.hasOwnProperty.call(collectedData, \"value\")\n ? collectedData.value\n : event?.currentTarget?.elements?.value?.value ?? value();\n value.set(String(submittedValue ?? \"\"));\n submit({ value: submittedValue ?? \"\" });\n }\n\n function cancelForm() {\n cancel();\n }\n\n function handleKeydown(event) {\n if (event?.key !== \"Escape\") return;\n event.preventDefault?.();\n event.stopPropagation?.();\n cancelForm();\n }\n\n effect(() => {\n if (focused) return;\n focused = true;\n setTimeout(() => {\n document.getElementById(fieldId())?.focus?.();\n });\n });\n</script>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import __ce_component$1 from "./input-field.ce.js";
|
|
2
|
+
import { DOMContainer, DOMElement, computed, cond, h, useDefineEmits, useDefineProps, useProps } from "canvasengine";
|
|
3
|
+
//#region src/components/gui/input.ce
|
|
4
|
+
function component($$props) {
|
|
5
|
+
useProps($$props);
|
|
6
|
+
const defineProps = useDefineProps($$props);
|
|
7
|
+
useDefineEmits($$props);
|
|
8
|
+
const { data, onInteraction } = defineProps();
|
|
9
|
+
const title = computed(() => data().title || "");
|
|
10
|
+
function submit(payload) {
|
|
11
|
+
onInteraction?.("submit", payload);
|
|
12
|
+
}
|
|
13
|
+
function cancel() {
|
|
14
|
+
onInteraction?.("cancel");
|
|
15
|
+
}
|
|
16
|
+
return h(DOMContainer, {
|
|
17
|
+
width: "100%",
|
|
18
|
+
height: "100%"
|
|
19
|
+
}, h(DOMElement, {
|
|
20
|
+
element: "div",
|
|
21
|
+
attrs: { class: "rpg-ui-input-layer" }
|
|
22
|
+
}, h(DOMElement, {
|
|
23
|
+
element: "div",
|
|
24
|
+
attrs: { class: "rpg-ui-input-dialog rpg-ui-window rpg-anim-fade-in" }
|
|
25
|
+
}, [cond(computed(() => title()), () => h(DOMElement, {
|
|
26
|
+
element: "div",
|
|
27
|
+
attrs: { class: "rpg-ui-window-title" },
|
|
28
|
+
textContent: computed(() => title())
|
|
29
|
+
})), h(__ce_component$1, {
|
|
30
|
+
data,
|
|
31
|
+
layout: "standalone",
|
|
32
|
+
submit,
|
|
33
|
+
cancel
|
|
34
|
+
})])));
|
|
35
|
+
}
|
|
36
|
+
var __ce_component = component;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { __ce_component as default };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=input.ce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.ce.js","names":[],"sources":["../../../src/components/gui/input.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-input-layer\">\n <div class=\"rpg-ui-input-dialog rpg-ui-window rpg-anim-fade-in\">\n @if (title()) {\n <div class=\"rpg-ui-window-title\">{title()}</div>\n }\n <InputField data={data} layout=\"standalone\" submit={submit} cancel={cancel} />\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { computed } from \"canvasengine\";\n import InputField from \"./input-field.ce\";\n\n const { data, onInteraction } = defineProps();\n const title = computed(() => data().title || \"\");\n\n function submit(payload) {\n onInteraction?.(\"submit\", payload);\n }\n\n function cancel() {\n onInteraction?.(\"cancel\");\n }\n</script>\n"],"mappings":";;;AAQI,SAAG,UAAA,SAAA;CACO,SAAA,OAAA;;CAEP,eAAA,OAAA;CACC,MAAG,EAAA,MAAW,kBAAkB,YAAC;CACzC,MAAE,QAAO,eAAmB,KAAM,EAAA,SAAS,EAAA;;EAEzC,gBAAc,UAAc,OAAI;CAClC;;EAEE,gBAAgB,QAAS;CAC3B;QACE,EAAA,cAAA;EAAA,OAAA;EAAA,QAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,qBAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,qDAAA;CAAA,GAAA,CAAA,KAAA,eAAA,MAAA,CAAA,SAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,sBAAA;EAAA,aAAA,eAAA,MAAA,CAAA;CAAA,CAAA,CAAA,GAAA,EAAA,kBAAA;EAAA;EAAA,QAAA;EAAA;EAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAEA;AAEA,IAAA,iBAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { inject } from "../../core/inject.js";
|
|
2
|
+
import "./weather-lifecycle-compat.js";
|
|
2
3
|
import { RpgClientEngine } from "../../RpgClientEngine.js";
|
|
3
4
|
import { Container, computed, cond, h, loop, useDefineEmits, useDefineProps, useProps } from "canvasengine";
|
|
4
5
|
import { Weather } from "@canvasengine/presets";
|
|
@@ -12,6 +13,8 @@ function component($$props) {
|
|
|
12
13
|
const componentAnimations = engine.componentAnimations;
|
|
13
14
|
const projectiles = engine.projectiles.current;
|
|
14
15
|
const map = engine.sceneMap?.data;
|
|
16
|
+
const emptySceneData = { params: {} };
|
|
17
|
+
const emptySceneParams = {};
|
|
15
18
|
const sceneComponent = computed(() => map()?.component);
|
|
16
19
|
const weather = engine.sceneMap.weather;
|
|
17
20
|
const backgroundMusic = computed(() => {
|
|
@@ -73,8 +76,8 @@ function component($$props) {
|
|
|
73
76
|
cond(computed(() => backgroundMusic()), () => h(Container, { sound: computed(() => backgroundMusic()) })),
|
|
74
77
|
cond(computed(() => backgroundAmbientSound()), () => h(Container, { sound: computed(() => backgroundAmbientSound()) })),
|
|
75
78
|
h(Container, null, cond(computed(() => map() && sceneComponent()), () => h(sceneComponent(), {
|
|
76
|
-
data: computed(() => map()
|
|
77
|
-
params: computed(() => map()
|
|
79
|
+
data: computed(() => map()?.data ?? emptySceneData),
|
|
80
|
+
params: computed(() => map()?.params ?? emptySceneParams)
|
|
78
81
|
}))),
|
|
79
82
|
loop(children, (child) => h(child)),
|
|
80
83
|
loop(componentAnimations, (componentAnimation) => h(Container, null, loop(componentAnimation.current, (animation) => h(componentAnimation.component, animation)))),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"draw-map.ce.js","names":[],"sources":["../../../src/components/scenes/draw-map.ce"],"sourcesContent":["<Container shake={shakeConfig} freeze={engine.gamePause}>\n @if (backgroundMusic()) {\n <Container sound={backgroundMusic()} />\n }\n\n @if (backgroundAmbientSound()) {\n <Container sound={backgroundAmbientSound()} />\n }\n\n <Container>\n @if (map() && sceneComponent()) {\n <sceneComponent() data={map()
|
|
1
|
+
{"version":3,"file":"draw-map.ce.js","names":[],"sources":["../../../src/components/scenes/draw-map.ce"],"sourcesContent":["<Container shake={shakeConfig} freeze={engine.gamePause}>\n @if (backgroundMusic()) {\n <Container sound={backgroundMusic()} />\n }\n\n @if (backgroundAmbientSound()) {\n <Container sound={backgroundAmbientSound()} />\n }\n\n <Container>\n @if (map() && sceneComponent()) {\n <sceneComponent() data={map()?.data ?? emptySceneData} params={map()?.params ?? emptySceneParams} />\n }\n </Container>\n\n @for (child of children) {\n <child />\n }\n\n @for (componentAnimation of componentAnimations) {\n <Container>\n @for (animation of componentAnimation.current) {\n <componentAnimation.component ...animation />\n }\n </Container>\n }\n\n <Container sortableChildren={true}>\n @for (projectile of projectiles() ; track projectile.props.id) {\n <projectile.component ...projectile.props />\n }\n </Container>\n\n @if (weatherProps()) {\n <Weather ...weatherProps() />\n }\n</Container>\n\n<script>\n import { computed, effect } from 'canvasengine'\n import './weather-lifecycle-compat'\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n import { Weather } from '@canvasengine/presets'\n\n const { children } = defineProps()\n const engine = inject(RpgClientEngine);\n const componentAnimations = engine.componentAnimations\n const projectiles = engine.projectiles.current\n const map = engine.sceneMap?.data\n const emptySceneData = { params: {} }\n const emptySceneParams = {}\n const sceneComponent = computed(() => map()?.component)\n const weather = engine.sceneMap.weather\n const backgroundMusic = computed(() => {\n const src = map()?.params?.backgroundMusic\n return src ? { src, autoplay: true, loop: true } : undefined\n })\n const backgroundAmbientSound = computed(() => {\n const src = map()?.params?.backgroundAmbientSound\n return src ? { src, autoplay: true, loop: true } : undefined\n })\n\n const shakeConfig = {\n trigger: engine.mapShakeTrigger,\n intensity: 10,\n duration: 500,\n frequency: 10,\n direction: 'both'\n }\n\n const weatherProps = computed(() => {\n const state = weather?.()\n if (!state) {\n return null\n }\n const validEffects = ['rain', 'snow', 'fog', 'cloud']\n if (!validEffects.includes(state.effect)) {\n return null\n }\n const params = state.params ?? {}\n return {\n effect: state.effect,\n speed: params.speed,\n windDirection: params.windDirection,\n windStrength: params.windStrength,\n density: params.density,\n maxDrops: params.maxDrops,\n height: params.height,\n scale: params.scale,\n sunIntensity: params.sunIntensity,\n sunAngle: params.sunAngle,\n raySpread: params.raySpread,\n rayTwinkle: params.rayTwinkle,\n rayTwinkleSpeed: params.rayTwinkleSpeed,\n zIndex: params.zIndex ?? 1000,\n alpha: params.alpha,\n blendMode: params.blendMode,\n }\n })\n</script>\n"],"mappings":";;;;;;AAUK,SAAU,UAAG,SAAgB;CACX,SAAO,OAAO;CACjC,MAAA,cAAA,eAAA,OAAA;CACS,eAAA,OAAA;;CAEb,MAAM,SAAQ,OAAG,eAAU;CAC3B,MAAK,sBAAO,OAAA;CACZ,MAAE,cAAA,OAAA,YAAA;;CAEF,MAAM,iBAAE,EAAA,QAAsB,CAAA,EAAA;CAC9B,MAAK,mBAAS,CAAA;CACd,MAAM,iBAAgB,eAAG,IAAA,GAAmB,SAAS;CACrD,MAAM,UAAG,OAAA,SAAmB;CAC5B,MAAM,kBAAA,eAAA;EACF,MAAE,MAAS,IAAA,GAAA,QAAA;EACb,OAAA,MAAA;GAAA;GAAA,UAAA;GAAA,MAAA;EAAA,IAAA,KAAA;;CAEF,MAAG,yBAA4B,eAAK;EAChC,MAAM,MAAA,IAAU,GAAG,QAAC;EACpB,OAAG,MAAU;GAAC;GAAA,UAAa;GAAA,MAAW;EAAO,IAAA,KAAA;CACjD,CAAC;CACD,MAAI,cAAS;;EAEV,WAAI;EACH,UAAU;EACZ,WAAA;EACA,WAAS;;CAEX,MAAC,eAAM,eAAA;EACH,MAAM,QAAG,UAAU;EACnB,IAAA,CAAA,OACA,OAAS;;GAEU;GAAO;GAAY;GAAC;4BAEvC,OAAQ;EAER,MAAM,SAAA,MAAA,UAAsB,CAAA;EAC5B,OAAM;GACN,QAAY,MAAM;GAClB,OAAM,OAAA;GACN,eAAM,OAAoB;GAC1B,cAAM,OAAiB;GACvB,SAAa,OAAG;GAChB,UAAM,OAAe;GACnB,QAAU,OAAO;GACjB,OAAO,OAAQ;GAChB,cAAA,OAAA;GACD,UAAM,OAAA;GACJ,WAAY,OAAO;GACnB,YAAc,OAAM;GACrB,iBAAA,OAAA;;GAED,OAAM,OAAY;GAChB,WAAS,OAAO;EAClB;CACJ,CAAC;CAEK,OADa,EAAA,WAAA;EAAA,OAAA;EAAA,QAAA,OAAA;CAAA,GAAA;EAAA,KAAA,eAAA,gBAAA,CAAA,SAAA,EAAA,WAAA,EAAA,OAAA,eAAA,gBAAA,CAAA,EAAA,CAAA,CAAA;EAAA,KAAA,eAAA,uBAAA,CAAA,SAAA,EAAA,WAAA,EAAA,OAAA,eAAA,uBAAA,CAAA,EAAA,CAAA,CAAA;EAAA,EAAA,WAAA,MAAA,KAAA,eAAA,IAAA,KAAA,eAAA,CAAA,SAAA,EAAA,eAAA,GAAA;GAAA,MAAA,eAAA,IAAA,GAAA,QAAA,cAAA;GAAA,QAAA,eAAA,IAAA,GAAA,UAAA,gBAAA;EAAA,CAAA,CAAA,CAAA;EAAA,KAAA,WAAA,UAAA,EAAA,KAAA,CAAA;EAAA,KAAA,sBAAA,uBAAA,EAAA,WAAA,MAAA,KAAA,mBAAA,UAAA,cAAA,EAAA,mBAAA,WAAA,SAAA,CAAA,CAAA,CAAA;EAAA,EAAA,WAAA,EAAA,kBAAA,KAAA,GAAA,KAAA,eAAA,YAAA,CAAA,IAAA,eAAA,EAAA,WAAA,WAAA,WAAA,KAAA,GAAA,EAAA,QAAA,eAAA,WAAA,MAAA,GAAA,CAAA,CAAA;EAAA,KAAA,eAAA,aAAA,CAAA,SAAA,EAAA,SAAA,aAAA,CAAA,CAAA;CAAA,CACD;AACd;AAEA,IAAM,iBAAe"}
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { patchWeatherTickLifecycle } from "./weather-tick-lifecycle.js";
|
|
2
|
+
import { createComponent } from "canvasengine";
|
|
3
|
+
import "@canvasengine/presets";
|
|
4
|
+
//#region src/components/scenes/weather-lifecycle-compat.ts
|
|
5
|
+
for (const tag of ["RainTextureLayer", "RainImpactLayer"]) {
|
|
6
|
+
const probe = createComponent(tag);
|
|
7
|
+
patchWeatherTickLifecycle(Object.getPrototypeOf(probe.componentInstance));
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=weather-lifecycle-compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather-lifecycle-compat.js","names":[],"sources":["../../../src/components/scenes/weather-lifecycle-compat.ts"],"sourcesContent":["import \"@canvasengine/presets\";\nimport { createComponent } from \"canvasengine\";\nimport { patchWeatherTickLifecycle } from \"./weather-tick-lifecycle\";\n\nfor (const tag of [\"RainTextureLayer\", \"RainImpactLayer\"]) {\n const probe = createComponent(tag);\n patchWeatherTickLifecycle(Object.getPrototypeOf(probe.componentInstance));\n}\n"],"mappings":";;;;AAIA,KAAK,MAAM,OAAO,CAAC,oBAAoB,iBAAiB,GAAG;CACzD,MAAM,QAAQ,gBAAgB,GAAG;CACjC,0BAA0B,OAAO,eAAe,MAAM,iBAAiB,CAAC;AAC1E"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare const PATCHED: unique symbol;
|
|
2
|
+
type TickSubscriptionPrototype = {
|
|
3
|
+
[PATCHED]?: boolean;
|
|
4
|
+
onMount?: (...args: any[]) => unknown;
|
|
5
|
+
onDestroy?: (...args: any[]) => unknown;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* CanvasEngine presets 2.0.0 can finish mounting a rain layer after that layer
|
|
9
|
+
* has already been destroyed. The late mount then leaves a tick subscription
|
|
10
|
+
* operating on a destroyed Pixi object. It can also overwrite an existing
|
|
11
|
+
* subscription when mounts overlap.
|
|
12
|
+
*
|
|
13
|
+
* Keep this compatibility patch local to the affected preset prototypes. It
|
|
14
|
+
* can be removed once the preset owns the same lifecycle guarantees.
|
|
15
|
+
*/
|
|
16
|
+
export declare function patchWeatherTickLifecycle(prototype: TickSubscriptionPrototype): void;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/components/scenes/weather-tick-lifecycle.ts
|
|
2
|
+
var PATCHED = Symbol.for("@rpgjs/client/weather-tick-lifecycle-patched");
|
|
3
|
+
var DISPOSED = Symbol("weather-tick-lifecycle-disposed");
|
|
4
|
+
var MOUNT_QUEUE = Symbol("weather-tick-lifecycle-mount-queue");
|
|
5
|
+
function stopTickSubscription(instance) {
|
|
6
|
+
instance.tickSubscription?.unsubscribe?.();
|
|
7
|
+
instance.tickSubscription = void 0;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* CanvasEngine presets 2.0.0 can finish mounting a rain layer after that layer
|
|
11
|
+
* has already been destroyed. The late mount then leaves a tick subscription
|
|
12
|
+
* operating on a destroyed Pixi object. It can also overwrite an existing
|
|
13
|
+
* subscription when mounts overlap.
|
|
14
|
+
*
|
|
15
|
+
* Keep this compatibility patch local to the affected preset prototypes. It
|
|
16
|
+
* can be removed once the preset owns the same lifecycle guarantees.
|
|
17
|
+
*/
|
|
18
|
+
function patchWeatherTickLifecycle(prototype) {
|
|
19
|
+
if (!prototype || prototype[PATCHED]) return;
|
|
20
|
+
const originalOnMount = prototype.onMount;
|
|
21
|
+
const originalOnDestroy = prototype.onDestroy;
|
|
22
|
+
if (!originalOnMount || !originalOnDestroy) return;
|
|
23
|
+
Object.defineProperty(prototype, PATCHED, { value: true });
|
|
24
|
+
prototype.onMount = function(...args) {
|
|
25
|
+
const mount = async () => {
|
|
26
|
+
if (this[DISPOSED] || this.destroyed) return;
|
|
27
|
+
stopTickSubscription(this);
|
|
28
|
+
await originalOnMount.apply(this, args);
|
|
29
|
+
if (this[DISPOSED] || this.destroyed) stopTickSubscription(this);
|
|
30
|
+
};
|
|
31
|
+
const pendingMount = (this[MOUNT_QUEUE] ?? Promise.resolve()).catch(() => void 0).then(mount);
|
|
32
|
+
this[MOUNT_QUEUE] = pendingMount;
|
|
33
|
+
return pendingMount;
|
|
34
|
+
};
|
|
35
|
+
prototype.onDestroy = function(...args) {
|
|
36
|
+
this[DISPOSED] = true;
|
|
37
|
+
stopTickSubscription(this);
|
|
38
|
+
return originalOnDestroy.apply(this, args);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { patchWeatherTickLifecycle };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=weather-tick-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weather-tick-lifecycle.js","names":[],"sources":["../../../src/components/scenes/weather-tick-lifecycle.ts"],"sourcesContent":["const PATCHED = Symbol.for(\"@rpgjs/client/weather-tick-lifecycle-patched\");\nconst DISPOSED = Symbol(\"weather-tick-lifecycle-disposed\");\nconst MOUNT_QUEUE = Symbol(\"weather-tick-lifecycle-mount-queue\");\n\ntype TickSubscription = {\n unsubscribe?: () => void;\n};\n\ntype TickSubscriptionInstance = {\n destroyed?: boolean;\n tickSubscription?: TickSubscription;\n [DISPOSED]?: boolean;\n [MOUNT_QUEUE]?: Promise<void>;\n};\n\ntype TickSubscriptionPrototype = {\n [PATCHED]?: boolean;\n onMount?: (...args: any[]) => unknown;\n onDestroy?: (...args: any[]) => unknown;\n};\n\nfunction stopTickSubscription(instance: TickSubscriptionInstance) {\n instance.tickSubscription?.unsubscribe?.();\n instance.tickSubscription = undefined;\n}\n\n/**\n * CanvasEngine presets 2.0.0 can finish mounting a rain layer after that layer\n * has already been destroyed. The late mount then leaves a tick subscription\n * operating on a destroyed Pixi object. It can also overwrite an existing\n * subscription when mounts overlap.\n *\n * Keep this compatibility patch local to the affected preset prototypes. It\n * can be removed once the preset owns the same lifecycle guarantees.\n */\nexport function patchWeatherTickLifecycle(prototype: TickSubscriptionPrototype) {\n if (!prototype || prototype[PATCHED]) return;\n\n const originalOnMount = prototype.onMount;\n const originalOnDestroy = prototype.onDestroy;\n if (!originalOnMount || !originalOnDestroy) return;\n\n Object.defineProperty(prototype, PATCHED, { value: true });\n\n prototype.onMount = function (this: TickSubscriptionInstance, ...args: any[]) {\n const mount = async () => {\n if (this[DISPOSED] || this.destroyed) return;\n\n stopTickSubscription(this);\n await originalOnMount.apply(this, args);\n\n if (this[DISPOSED] || this.destroyed) {\n stopTickSubscription(this);\n }\n };\n\n const pendingMount = (this[MOUNT_QUEUE] ?? Promise.resolve())\n .catch(() => undefined)\n .then(mount);\n this[MOUNT_QUEUE] = pendingMount;\n return pendingMount;\n };\n\n prototype.onDestroy = function (this: TickSubscriptionInstance, ...args: any[]) {\n this[DISPOSED] = true;\n stopTickSubscription(this);\n return originalOnDestroy.apply(this, args);\n };\n}\n"],"mappings":";AAAA,IAAM,UAAU,OAAO,IAAI,8CAA8C;AACzE,IAAM,WAAW,OAAO,iCAAiC;AACzD,IAAM,cAAc,OAAO,oCAAoC;AAmB/D,SAAS,qBAAqB,UAAoC;CAChE,SAAS,kBAAkB,cAAc;CACzC,SAAS,mBAAmB,KAAA;AAC9B;;;;;;;;;;AAWA,SAAgB,0BAA0B,WAAsC;CAC9E,IAAI,CAAC,aAAa,UAAU,UAAU;CAEtC,MAAM,kBAAkB,UAAU;CAClC,MAAM,oBAAoB,UAAU;CACpC,IAAI,CAAC,mBAAmB,CAAC,mBAAmB;CAE5C,OAAO,eAAe,WAAW,SAAS,EAAE,OAAO,KAAK,CAAC;CAEzD,UAAU,UAAU,SAA0C,GAAG,MAAa;EAC5E,MAAM,QAAQ,YAAY;GACxB,IAAI,KAAK,aAAa,KAAK,WAAW;GAEtC,qBAAqB,IAAI;GACzB,MAAM,gBAAgB,MAAM,MAAM,IAAI;GAEtC,IAAI,KAAK,aAAa,KAAK,WACzB,qBAAqB,IAAI;EAE7B;EAEA,MAAM,gBAAgB,KAAK,gBAAgB,QAAQ,QAAQ,GACxD,YAAY,KAAA,CAAS,EACrB,KAAK,KAAK;EACb,KAAK,eAAe;EACpB,OAAO;CACT;CAEA,UAAU,YAAY,SAA0C,GAAG,MAAa;EAC9E,KAAK,YAAY;EACjB,qBAAqB,IAAI;EACzB,OAAO,kBAAkB,MAAM,MAAM,IAAI;CAC3C;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/i18n.d.ts
CHANGED
|
@@ -39,6 +39,18 @@ export declare const RpgClientBuiltinI18n: {
|
|
|
39
39
|
"rpg.gameover.title": string;
|
|
40
40
|
"rpg.gameover.title-screen": string;
|
|
41
41
|
"rpg.gameover.load-game": string;
|
|
42
|
+
"rpg.input.confirm": string;
|
|
43
|
+
"rpg.input.cancel": string;
|
|
44
|
+
"rpg.input.error.invalid": string;
|
|
45
|
+
"rpg.input.error.required": string;
|
|
46
|
+
"rpg.input.error.number": string;
|
|
47
|
+
"rpg.input.error.min": string;
|
|
48
|
+
"rpg.input.error.max": string;
|
|
49
|
+
"rpg.input.error.step": string;
|
|
50
|
+
"rpg.input.error.min-length": string;
|
|
51
|
+
"rpg.input.error.max-length": string;
|
|
52
|
+
"rpg.input.error.email": string;
|
|
53
|
+
"rpg.transition.loading": string;
|
|
42
54
|
"rpg.shop.default-message": string;
|
|
43
55
|
"rpg.shop.choose-action": string;
|
|
44
56
|
"rpg.shop.buy": string;
|
package/dist/i18n.js
CHANGED
|
@@ -39,6 +39,18 @@ var RpgClientBuiltinI18n = { en: {
|
|
|
39
39
|
"rpg.gameover.title": "Game Over",
|
|
40
40
|
"rpg.gameover.title-screen": "Title Screen",
|
|
41
41
|
"rpg.gameover.load-game": "Load Game",
|
|
42
|
+
"rpg.input.confirm": "Confirm",
|
|
43
|
+
"rpg.input.cancel": "Cancel",
|
|
44
|
+
"rpg.input.error.invalid": "Invalid value.",
|
|
45
|
+
"rpg.input.error.required": "A value is required.",
|
|
46
|
+
"rpg.input.error.number": "Enter a valid number.",
|
|
47
|
+
"rpg.input.error.min": "The value must be at least {min}.",
|
|
48
|
+
"rpg.input.error.max": "The value must be at most {max}.",
|
|
49
|
+
"rpg.input.error.step": "The value must use increments of {step}.",
|
|
50
|
+
"rpg.input.error.min-length": "Enter at least {minLength} characters.",
|
|
51
|
+
"rpg.input.error.max-length": "Enter no more than {maxLength} characters.",
|
|
52
|
+
"rpg.input.error.email": "Enter a valid email address.",
|
|
53
|
+
"rpg.transition.loading": "Loading area…",
|
|
42
54
|
"rpg.shop.default-message": "Welcome to my shop!",
|
|
43
55
|
"rpg.shop.choose-action": "Choose an action",
|
|
44
56
|
"rpg.shop.buy": "Buy",
|
package/dist/i18n.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","names":[],"sources":["../src/i18n.ts"],"sourcesContent":["import { createI18nProvider, type I18nConfig } from \"@rpgjs/common\";\n\nexport const RpgClientBuiltinI18n = {\n en: {\n \"rpg.menu.title\": \"Menu\",\n \"rpg.menu.status\": \"Status\",\n \"rpg.menu.level\": \"Level\",\n \"rpg.menu.gold\": \"Gold\",\n \"rpg.menu.parameters\": \"Parameters\",\n \"rpg.menu.items\": \"Items\",\n \"rpg.menu.skills\": \"Skills\",\n \"rpg.menu.equip\": \"Equip\",\n \"rpg.menu.options\": \"Options\",\n \"rpg.menu.save\": \"Save\",\n \"rpg.menu.exit\": \"Exit\",\n \"rpg.menu.weapons\": \"Weapons\",\n \"rpg.menu.armor\": \"Armor\",\n \"rpg.menu.use\": \"Use\",\n \"rpg.menu.cancel\": \"Cancel\",\n \"rpg.menu.unequip\": \"Unequip\",\n \"rpg.menu.remove-equipment\": \"Remove the current equipment\",\n \"rpg.menu.empty\": \"Empty\",\n \"rpg.menu.leave-game\": \"Leave the game?\",\n \"rpg.menu.exit-help\": \"Press Action to confirm or Escape to go back.\",\n \"rpg.menu.options-help\": \"Configure your preferences here.\",\n \"rpg.save.title\": \"Save Game\",\n \"rpg.save.subtitle\": \"Choose a slot to overwrite or create.\",\n \"rpg.load.title\": \"Load Game\",\n \"rpg.load.subtitle\": \"Select a slot to load your progress.\",\n \"rpg.save.auto\": \"Auto Save\",\n \"rpg.save.slot\": \"Slot {index}\",\n \"rpg.save.empty-slot\": \"Empty Slot\",\n \"rpg.save.level\": \"Level\",\n \"rpg.save.exp\": \"Exp\",\n \"rpg.save.map\": \"Map\",\n \"rpg.save.date\": \"Date\",\n \"rpg.title.default\": \"RPG\",\n \"rpg.title.start\": \"Start\",\n \"rpg.title.load\": \"Load\",\n \"rpg.gameover.title\": \"Game Over\",\n \"rpg.gameover.title-screen\": \"Title Screen\",\n \"rpg.gameover.load-game\": \"Load Game\",\n \"rpg.shop.default-message\": \"Welcome to my shop!\",\n \"rpg.shop.choose-action\": \"Choose an action\",\n \"rpg.shop.buy\": \"Buy\",\n \"rpg.shop.sell\": \"Sell\",\n \"rpg.shop.back\": \"Back\",\n \"rpg.shop.equipped\": \"Equipped\",\n \"rpg.shop.already-equipped\": \"Already equipped\",\n \"rpg.shop.qty\": \"Qty\",\n \"rpg.shop.available\": \"Available\",\n \"rpg.shop.quantity\": \"Quantity\",\n \"rpg.shop.total\": \"Total\",\n },\n};\n\nexport function provideI18n(config: I18nConfig = {}) {\n return createI18nProvider(config);\n}\n"],"mappings":";;AAEA,IAAa,uBAAuB,EAClC,IAAI;CACF,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,iBAAiB;CACjB,uBAAuB;CACvB,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,oBAAoB;CACpB,iBAAiB;CACjB,iBAAiB;CACjB,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,mBAAmB;CACnB,oBAAoB;CACpB,6BAA6B;CAC7B,kBAAkB;CAClB,uBAAuB;CACvB,sBAAsB;CACtB,yBAAyB;CACzB,kBAAkB;CAClB,qBAAqB;CACrB,kBAAkB;CAClB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,uBAAuB;CACvB,kBAAkB;CAClB,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;CACjB,qBAAqB;CACrB,mBAAmB;CACnB,kBAAkB;CAClB,sBAAsB;CACtB,6BAA6B;CAC7B,0BAA0B;CAC1B,4BAA4B;CAC5B,0BAA0B;CAC1B,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,qBAAqB;CACrB,6BAA6B;CAC7B,gBAAgB;CAChB,sBAAsB;CACtB,qBAAqB;CACrB,kBAAkB;AACpB,EACF;AAEA,SAAgB,YAAY,SAAqB,CAAC,GAAG;CACnD,OAAO,mBAAmB,MAAM;AAClC"}
|
|
1
|
+
{"version":3,"file":"i18n.js","names":[],"sources":["../src/i18n.ts"],"sourcesContent":["import { createI18nProvider, type I18nConfig } from \"@rpgjs/common\";\n\nexport const RpgClientBuiltinI18n = {\n en: {\n \"rpg.menu.title\": \"Menu\",\n \"rpg.menu.status\": \"Status\",\n \"rpg.menu.level\": \"Level\",\n \"rpg.menu.gold\": \"Gold\",\n \"rpg.menu.parameters\": \"Parameters\",\n \"rpg.menu.items\": \"Items\",\n \"rpg.menu.skills\": \"Skills\",\n \"rpg.menu.equip\": \"Equip\",\n \"rpg.menu.options\": \"Options\",\n \"rpg.menu.save\": \"Save\",\n \"rpg.menu.exit\": \"Exit\",\n \"rpg.menu.weapons\": \"Weapons\",\n \"rpg.menu.armor\": \"Armor\",\n \"rpg.menu.use\": \"Use\",\n \"rpg.menu.cancel\": \"Cancel\",\n \"rpg.menu.unequip\": \"Unequip\",\n \"rpg.menu.remove-equipment\": \"Remove the current equipment\",\n \"rpg.menu.empty\": \"Empty\",\n \"rpg.menu.leave-game\": \"Leave the game?\",\n \"rpg.menu.exit-help\": \"Press Action to confirm or Escape to go back.\",\n \"rpg.menu.options-help\": \"Configure your preferences here.\",\n \"rpg.save.title\": \"Save Game\",\n \"rpg.save.subtitle\": \"Choose a slot to overwrite or create.\",\n \"rpg.load.title\": \"Load Game\",\n \"rpg.load.subtitle\": \"Select a slot to load your progress.\",\n \"rpg.save.auto\": \"Auto Save\",\n \"rpg.save.slot\": \"Slot {index}\",\n \"rpg.save.empty-slot\": \"Empty Slot\",\n \"rpg.save.level\": \"Level\",\n \"rpg.save.exp\": \"Exp\",\n \"rpg.save.map\": \"Map\",\n \"rpg.save.date\": \"Date\",\n \"rpg.title.default\": \"RPG\",\n \"rpg.title.start\": \"Start\",\n \"rpg.title.load\": \"Load\",\n \"rpg.gameover.title\": \"Game Over\",\n \"rpg.gameover.title-screen\": \"Title Screen\",\n \"rpg.gameover.load-game\": \"Load Game\",\n \"rpg.input.confirm\": \"Confirm\",\n \"rpg.input.cancel\": \"Cancel\",\n \"rpg.input.error.invalid\": \"Invalid value.\",\n \"rpg.input.error.required\": \"A value is required.\",\n \"rpg.input.error.number\": \"Enter a valid number.\",\n \"rpg.input.error.min\": \"The value must be at least {min}.\",\n \"rpg.input.error.max\": \"The value must be at most {max}.\",\n \"rpg.input.error.step\": \"The value must use increments of {step}.\",\n \"rpg.input.error.min-length\": \"Enter at least {minLength} characters.\",\n \"rpg.input.error.max-length\": \"Enter no more than {maxLength} characters.\",\n \"rpg.input.error.email\": \"Enter a valid email address.\",\n \"rpg.transition.loading\": \"Loading area…\",\n \"rpg.shop.default-message\": \"Welcome to my shop!\",\n \"rpg.shop.choose-action\": \"Choose an action\",\n \"rpg.shop.buy\": \"Buy\",\n \"rpg.shop.sell\": \"Sell\",\n \"rpg.shop.back\": \"Back\",\n \"rpg.shop.equipped\": \"Equipped\",\n \"rpg.shop.already-equipped\": \"Already equipped\",\n \"rpg.shop.qty\": \"Qty\",\n \"rpg.shop.available\": \"Available\",\n \"rpg.shop.quantity\": \"Quantity\",\n \"rpg.shop.total\": \"Total\",\n },\n};\n\nexport function provideI18n(config: I18nConfig = {}) {\n return createI18nProvider(config);\n}\n"],"mappings":";;AAEA,IAAa,uBAAuB,EAClC,IAAI;CACF,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,iBAAiB;CACjB,uBAAuB;CACvB,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,oBAAoB;CACpB,iBAAiB;CACjB,iBAAiB;CACjB,oBAAoB;CACpB,kBAAkB;CAClB,gBAAgB;CAChB,mBAAmB;CACnB,oBAAoB;CACpB,6BAA6B;CAC7B,kBAAkB;CAClB,uBAAuB;CACvB,sBAAsB;CACtB,yBAAyB;CACzB,kBAAkB;CAClB,qBAAqB;CACrB,kBAAkB;CAClB,qBAAqB;CACrB,iBAAiB;CACjB,iBAAiB;CACjB,uBAAuB;CACvB,kBAAkB;CAClB,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;CACjB,qBAAqB;CACrB,mBAAmB;CACnB,kBAAkB;CAClB,sBAAsB;CACtB,6BAA6B;CAC7B,0BAA0B;CAC1B,qBAAqB;CACrB,oBAAoB;CACpB,2BAA2B;CAC3B,4BAA4B;CAC5B,0BAA0B;CAC1B,uBAAuB;CACvB,uBAAuB;CACvB,wBAAwB;CACxB,8BAA8B;CAC9B,8BAA8B;CAC9B,yBAAyB;CACzB,0BAA0B;CAC1B,4BAA4B;CAC5B,0BAA0B;CAC1B,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,qBAAqB;CACrB,6BAA6B;CAC7B,gBAAgB;CAChB,sBAAsB;CACtB,qBAAqB;CACrB,kBAAkB;AACpB,EACF;AAEA,SAAgB,YAAY,SAAqB,CAAC,GAAG;CACnD,OAAO,mBAAmB,MAAM;AAClC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './core/setup';
|
|
|
7
7
|
export * from './core/inject';
|
|
8
8
|
export * from './services/loadMap';
|
|
9
9
|
export * from './services/actionInput';
|
|
10
|
+
export * from './services/mapStreaming';
|
|
10
11
|
export * from './services/pointerContext';
|
|
11
12
|
export * from './services/interactions';
|
|
12
13
|
export * from './module';
|
|
@@ -24,6 +25,7 @@ export * from './utils/getEntityProp';
|
|
|
24
25
|
export { Context } from '@signe/di';
|
|
25
26
|
export { KeyboardControls, Input } from 'canvasengine';
|
|
26
27
|
export { Control } from './services/keyboardControls';
|
|
28
|
+
export { defineModule } from '@rpgjs/common';
|
|
27
29
|
export { RpgClientObject } from './Game/Object';
|
|
28
30
|
export { RpgClientPlayer } from './Game/Player';
|
|
29
31
|
export { RpgClientEvent } from './Game/Event';
|