@rpgjs/client 5.0.0-beta.6 → 5.0.0-beta.8

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/Game/AnimationManager.d.ts +2 -2
  3. package/dist/Game/AnimationManager.js +18 -9
  4. package/dist/Game/AnimationManager.js.map +1 -1
  5. package/dist/Game/AnimationManager.spec.d.ts +1 -0
  6. package/dist/Game/Map.d.ts +7 -9
  7. package/dist/Game/Map.js +5 -4
  8. package/dist/Game/Map.js.map +1 -1
  9. package/dist/Game/Object.d.ts +44 -20
  10. package/dist/Game/Object.js +28 -14
  11. package/dist/Game/Object.js.map +1 -1
  12. package/dist/Gui/Gui.d.ts +19 -6
  13. package/dist/Gui/Gui.js +64 -34
  14. package/dist/Gui/Gui.js.map +1 -1
  15. package/dist/Gui/Gui.spec.d.ts +1 -0
  16. package/dist/Gui/NotificationManager.d.ts +1 -1
  17. package/dist/Gui/NotificationManager.js.map +1 -1
  18. package/dist/Resource.js +1 -1
  19. package/dist/Resource.js.map +1 -1
  20. package/dist/RpgClient.d.ts +57 -2
  21. package/dist/RpgClientEngine.d.ts +55 -16
  22. package/dist/RpgClientEngine.js +60 -5
  23. package/dist/RpgClientEngine.js.map +1 -1
  24. package/dist/Sound.js.map +1 -1
  25. package/dist/_virtual/{_@oxc-project_runtime@0.127.0 → _@oxc-project_runtime@0.128.0}/helpers/decorate.js +1 -1
  26. package/dist/_virtual/{_@oxc-project_runtime@0.127.0 → _@oxc-project_runtime@0.128.0}/helpers/decorateMetadata.js +1 -1
  27. package/dist/components/animations/animation.ce.js.map +1 -1
  28. package/dist/components/animations/hit.ce.js.map +1 -1
  29. package/dist/components/character.ce.js +280 -3
  30. package/dist/components/character.ce.js.map +1 -1
  31. package/dist/components/dynamics/bar.ce.js +96 -0
  32. package/dist/components/dynamics/bar.ce.js.map +1 -0
  33. package/dist/components/dynamics/image.ce.js +23 -0
  34. package/dist/components/dynamics/image.ce.js.map +1 -0
  35. package/dist/components/dynamics/parse-value.d.ts +4 -1
  36. package/dist/components/dynamics/parse-value.js +51 -35
  37. package/dist/components/dynamics/parse-value.js.map +1 -1
  38. package/dist/components/dynamics/parse-value.spec.d.ts +1 -0
  39. package/dist/components/dynamics/shape-utils.d.ts +16 -0
  40. package/dist/components/dynamics/shape-utils.js +73 -0
  41. package/dist/components/dynamics/shape-utils.js.map +1 -0
  42. package/dist/components/dynamics/shape-utils.spec.d.ts +1 -0
  43. package/dist/components/dynamics/shape.ce.js +83 -0
  44. package/dist/components/dynamics/shape.ce.js.map +1 -0
  45. package/dist/components/dynamics/text.ce.js +28 -41
  46. package/dist/components/dynamics/text.ce.js.map +1 -1
  47. package/dist/components/gui/box.ce.js.map +1 -1
  48. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  49. package/dist/components/gui/gameover.ce.js.map +1 -1
  50. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  51. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
  52. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
  53. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  54. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  55. package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
  56. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
  57. package/dist/components/gui/mobile/index.d.ts +1 -1
  58. package/dist/components/gui/mobile/index.js.map +1 -1
  59. package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
  60. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  61. package/dist/components/gui/save-load.ce.js.map +1 -1
  62. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  63. package/dist/components/gui/title-screen.ce.js.map +1 -1
  64. package/dist/components/player-components-utils.d.ts +67 -0
  65. package/dist/components/player-components-utils.js +162 -0
  66. package/dist/components/player-components-utils.js.map +1 -0
  67. package/dist/components/player-components-utils.spec.d.ts +1 -0
  68. package/dist/components/player-components.ce.js +188 -0
  69. package/dist/components/player-components.ce.js.map +1 -0
  70. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
  71. package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
  72. package/dist/components/scenes/canvas.ce.js.map +1 -1
  73. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  74. package/dist/components/scenes/event-layer.ce.js.map +1 -1
  75. package/dist/core/inject.js +1 -1
  76. package/dist/core/inject.js.map +1 -1
  77. package/dist/core/setup.js +1 -1
  78. package/dist/core/setup.js.map +1 -1
  79. package/dist/index.js +1 -1
  80. package/dist/module.js +4 -1
  81. package/dist/module.js.map +1 -1
  82. package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@2.10.0}/node_modules/@signe/di/dist/index.js +7 -117
  83. package/dist/node_modules/.pnpm/@signe_di@2.10.0/node_modules/@signe/di/dist/index.js.map +1 -0
  84. package/dist/node_modules/.pnpm/@signe_reactive@2.10.0/node_modules/@signe/reactive/dist/index.js +239 -0
  85. package/dist/node_modules/.pnpm/@signe_reactive@2.10.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
  86. package/dist/node_modules/.pnpm/@signe_room@2.10.0/node_modules/@signe/room/dist/index.js +611 -0
  87. package/dist/node_modules/.pnpm/@signe_room@2.10.0/node_modules/@signe/room/dist/index.js.map +1 -0
  88. package/dist/node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/client/index.js +44 -0
  89. package/dist/node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  90. package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@2.10.0}/node_modules/@signe/sync/dist/index.js +29 -136
  91. package/dist/node_modules/.pnpm/@signe_sync@2.10.0/node_modules/@signe/sync/dist/index.js.map +1 -0
  92. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -1
  93. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -1
  94. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -1
  95. package/dist/presets/animation.js.map +1 -1
  96. package/dist/presets/faceset.js.map +1 -1
  97. package/dist/presets/icon.js.map +1 -1
  98. package/dist/presets/lpc.js.map +1 -1
  99. package/dist/presets/rmspritesheet.js.map +1 -1
  100. package/dist/services/AbstractSocket.js.map +1 -1
  101. package/dist/services/keyboardControls.js.map +1 -1
  102. package/dist/services/loadMap.d.ts +6 -0
  103. package/dist/services/loadMap.js +1 -1
  104. package/dist/services/loadMap.js.map +1 -1
  105. package/dist/services/mmorpg.js +1 -1
  106. package/dist/services/mmorpg.js.map +1 -1
  107. package/dist/services/save.js.map +1 -1
  108. package/dist/services/standalone.js +1 -1
  109. package/dist/services/standalone.js.map +1 -1
  110. package/dist/utils/getEntityProp.js.map +1 -1
  111. package/package.json +8 -8
  112. package/src/Game/AnimationManager.spec.ts +30 -0
  113. package/src/Game/AnimationManager.ts +22 -10
  114. package/src/Game/Map.ts +12 -2
  115. package/src/Game/Object.ts +68 -43
  116. package/src/Gui/Gui.spec.ts +273 -0
  117. package/src/Gui/Gui.ts +105 -50
  118. package/src/Resource.ts +1 -2
  119. package/src/RpgClient.ts +63 -2
  120. package/src/RpgClientEngine.ts +82 -12
  121. package/src/components/character.ce +353 -1
  122. package/src/components/dynamics/bar.ce +87 -0
  123. package/src/components/dynamics/image.ce +20 -0
  124. package/src/components/dynamics/parse-value.spec.ts +41 -0
  125. package/src/components/dynamics/parse-value.ts +102 -37
  126. package/src/components/dynamics/shape-utils.spec.ts +46 -0
  127. package/src/components/dynamics/shape-utils.ts +61 -0
  128. package/src/components/dynamics/shape.ce +89 -0
  129. package/src/components/dynamics/text.ce +34 -149
  130. package/src/components/player-components-utils.spec.ts +109 -0
  131. package/src/components/player-components-utils.ts +205 -0
  132. package/src/components/player-components.ce +221 -0
  133. package/src/core/setup.ts +2 -2
  134. package/src/module.ts +5 -1
  135. package/src/services/loadMap.ts +2 -0
  136. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
  137. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
  138. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
  139. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
  140. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
  141. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
  142. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
  143. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
  144. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
  145. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
  146. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
  147. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
@@ -0,0 +1,205 @@
1
+ export const DEFAULT_HP_BAR_STYLE = { fillColor: '#ef4444' };
2
+ export const DEFAULT_SP_BAR_STYLE = { fillColor: '#3b82f6' };
3
+
4
+ const DEFAULT_CELL_HEIGHT = 16;
5
+ const DEFAULT_CELL_WIDTH = 32;
6
+
7
+ type NumberResolver = (value: any, fallback?: number) => number;
8
+
9
+ const defaultToNumber: NumberResolver = (value, fallback = 0) => {
10
+ const num = typeof value === 'number' ? value : parseFloat(value);
11
+ return Number.isFinite(num) ? num : fallback;
12
+ };
13
+
14
+ export function getPointBounds(points: any[] = [], toNumber: NumberResolver = defaultToNumber) {
15
+ if (!Array.isArray(points) || points.length < 2) {
16
+ return { width: 1, height: 1 };
17
+ }
18
+
19
+ let minX = Infinity;
20
+ let minY = Infinity;
21
+ let maxX = -Infinity;
22
+ let maxY = -Infinity;
23
+
24
+ for (let i = 0; i < points.length; i += 2) {
25
+ const x = toNumber(points[i], 0);
26
+ const y = toNumber(points[i + 1], 0);
27
+ minX = Math.min(minX, x);
28
+ minY = Math.min(minY, y);
29
+ maxX = Math.max(maxX, x);
30
+ maxY = Math.max(maxY, y);
31
+ }
32
+
33
+ return {
34
+ width: Math.max(1, maxX - minX),
35
+ height: Math.max(1, maxY - minY)
36
+ };
37
+ }
38
+
39
+ export function getComponentId(definition: any) {
40
+ if (!definition) return undefined;
41
+ if (definition.id) return definition.id;
42
+ if (definition.type === 'text') return 'rpg:text';
43
+ if (definition.type === 'hpBar') return 'rpg:hpBar';
44
+ if (definition.type === 'spBar') return 'rpg:spBar';
45
+ if (definition.type === 'bar') return 'rpg:bar';
46
+ if (definition.type === 'shape') return 'rpg:shape';
47
+ if (definition.type === 'image') return 'rpg:image';
48
+ if (definition.type === 'tile') return 'rpg:tile';
49
+ return definition.type;
50
+ }
51
+
52
+ export function getComponentProps(definition: any) {
53
+ if (definition.props) return definition.props;
54
+
55
+ if (definition.type === 'text') {
56
+ return { value: definition.value, style: definition.style };
57
+ }
58
+ if (definition.type === 'hpBar') {
59
+ return { current: '{hp}', max: '{param.maxHp}', style: { ...DEFAULT_HP_BAR_STYLE, ...definition.style }, text: definition.text };
60
+ }
61
+ if (definition.type === 'spBar') {
62
+ return { current: '{sp}', max: '{param.maxSp}', style: { ...DEFAULT_SP_BAR_STYLE, ...definition.style }, text: definition.text };
63
+ }
64
+ if (definition.type === 'bar') {
65
+ return { current: `{${definition.current}}`, max: `{${definition.max}}`, style: definition.style, text: definition.text };
66
+ }
67
+ if (definition.type === 'shape') {
68
+ return definition.value;
69
+ }
70
+ if (definition.type === 'image' || definition.type === 'tile') {
71
+ return { value: definition.value };
72
+ }
73
+
74
+ return {};
75
+ }
76
+
77
+ export function estimateComponentSize(
78
+ definition: any,
79
+ {
80
+ toNumber = defaultToNumber,
81
+ estimateTextWidth = (value: any) => String(value ?? '').length * 8
82
+ }: {
83
+ toNumber?: NumberResolver;
84
+ estimateTextWidth?: (value: any, style?: any) => number;
85
+ } = {}
86
+ ) {
87
+ const props = getComponentProps(definition);
88
+ const style = props?.style ?? definition?.style ?? {};
89
+
90
+ if (definition?.type === 'text' || definition?.id === 'rpg:text') {
91
+ return {
92
+ width: estimateTextWidth(props.value ?? definition.value, style),
93
+ height: toNumber(style.fontSize, 12)
94
+ };
95
+ }
96
+
97
+ if (definition?.type === 'hpBar' || definition?.type === 'spBar' || definition?.type === 'bar' || definition?.id === 'rpg:hpBar' || definition?.id === 'rpg:spBar' || definition?.id === 'rpg:bar') {
98
+ const barHeight = toNumber(style.height, 8);
99
+ const labelHeight = props.text != null && props.text !== '' ? toNumber(style.fontSize, 10) + 2 : 0;
100
+ return {
101
+ width: toNumber(style.width, 50),
102
+ height: barHeight + labelHeight
103
+ };
104
+ }
105
+
106
+ if (definition?.type === 'shape' || definition?.id === 'rpg:shape') {
107
+ const shape = props ?? {};
108
+ if (shape.type === 'circle') {
109
+ const radius = toNumber(shape.radius, 8);
110
+ return { width: radius * 2, height: radius * 2 };
111
+ }
112
+ if (shape.type === 'line') {
113
+ return {
114
+ width: Math.max(1, Math.abs(toNumber(shape.x2, 16) - toNumber(shape.x1, 0))),
115
+ height: Math.max(1, Math.abs(toNumber(shape.y2, 0) - toNumber(shape.y1, 0)))
116
+ };
117
+ }
118
+ if (shape.type === 'polygon') {
119
+ return getPointBounds(shape.points, toNumber);
120
+ }
121
+ return {
122
+ width: toNumber(shape.width, 16),
123
+ height: toNumber(shape.height, 16)
124
+ };
125
+ }
126
+
127
+ return {
128
+ width: toNumber(definition?.props?.width, DEFAULT_CELL_WIDTH),
129
+ height: toNumber(definition?.props?.height, DEFAULT_CELL_HEIGHT)
130
+ };
131
+ }
132
+
133
+ export function computeBlockSize({
134
+ position,
135
+ layout = {},
136
+ rowMetrics,
137
+ gap = { row: 0, column: 0 },
138
+ graphic,
139
+ hitbox
140
+ }: {
141
+ position: string;
142
+ layout?: any;
143
+ rowMetrics: Array<{ width: number; height: number; cells: any[] }>;
144
+ gap?: { row: number; column: number };
145
+ graphic: { width: number; height: number };
146
+ hitbox: { w: number; h: number };
147
+ }) {
148
+ const rowGapTotal = Math.max(0, rowMetrics.length - 1) * gap.row;
149
+ const maxColumns = rowMetrics.reduce((max, row) => Math.max(max, row.cells.length), 0);
150
+ const columnGapTotal = Math.max(0, maxColumns - 1) * gap.column;
151
+ const contentWidth = rowMetrics.reduce((max, row) => Math.max(max, row.width), 0) + columnGapTotal;
152
+ const contentHeight = rowMetrics.reduce((sum, row) => sum + row.height, 0) + rowGapTotal;
153
+ const width = layout.width ?? Math.max(contentWidth, position === 'bottom' ? hitbox.w : position === 'top' || position === 'center' ? graphic.width : contentWidth);
154
+ const height = layout.height ?? Math.max(contentHeight, position === 'bottom' ? hitbox.h : position === 'left' || position === 'right' || position === 'center' ? graphic.height : contentHeight);
155
+
156
+ return { width, height };
157
+ }
158
+
159
+ export function computeBlockPosition({
160
+ position,
161
+ size,
162
+ layout = {},
163
+ graphic,
164
+ hitbox
165
+ }: {
166
+ position: string;
167
+ size: { width: number; height: number };
168
+ layout?: any;
169
+ graphic: { left: number; top: number; right: number; centerX: number; centerY: number };
170
+ hitbox: { w: number; h: number };
171
+ }) {
172
+ const marginLeft = layout.marginLeft ?? 0;
173
+ const marginRight = layout.marginRight ?? 0;
174
+ const marginTop = layout.marginTop ?? 0;
175
+ const marginBottom = layout.marginBottom ?? 0;
176
+
177
+ switch (position) {
178
+ case 'bottom':
179
+ return {
180
+ x: (hitbox.w / 2) - (size.width / 2) + marginLeft - marginRight,
181
+ y: (hitbox.h / 2) - (size.height / 2) + marginBottom - marginTop
182
+ };
183
+ case 'center':
184
+ return {
185
+ x: graphic.centerX - (size.width / 2) + marginLeft - marginRight,
186
+ y: graphic.centerY - (size.height / 2) + marginTop - marginBottom
187
+ };
188
+ case 'left':
189
+ return {
190
+ x: graphic.left - size.width + marginLeft - marginRight,
191
+ y: graphic.centerY - (size.height / 2) + marginTop - marginBottom
192
+ };
193
+ case 'right':
194
+ return {
195
+ x: graphic.right + marginLeft - marginRight,
196
+ y: graphic.centerY - (size.height / 2) + marginTop - marginBottom
197
+ };
198
+ case 'top':
199
+ default:
200
+ return {
201
+ x: graphic.centerX - (size.width / 2) + marginLeft - marginRight,
202
+ y: graphic.top - size.height + marginTop - marginBottom
203
+ };
204
+ }
205
+ }
@@ -0,0 +1,221 @@
1
+ <Container
2
+ x={blockPosition().x}
3
+ y={blockPosition().y}
4
+ width={blockSize().width}
5
+ height={blockSize().height}
6
+ minWidth={blockSize().width}
7
+ minHeight={blockSize().height}
8
+ display="flex"
9
+ flexDirection="column"
10
+ justifyContent="center"
11
+ alignItems="center"
12
+ rowGap={gap().row}
13
+ >
14
+ @for (row of renderedRows) {
15
+ <Container
16
+ width="100%"
17
+ height={row.height}
18
+ display="flex"
19
+ flexDirection="row"
20
+ justifyContent="center"
21
+ alignItems="center"
22
+ columnGap={gap().column}
23
+ >
24
+ @for (entry of row.entries) {
25
+ <Container
26
+ width={entry.width}
27
+ height={entry.height}
28
+ display="flex"
29
+ justifyContent="center"
30
+ alignItems="center"
31
+ >
32
+ <entry.component object ...entry.props />
33
+ </Container>
34
+ }
35
+ </Container>
36
+ }
37
+ </Container>
38
+
39
+ <script>
40
+ import { computed } from "canvasengine";
41
+ import { RpgClientEngine } from "../RpgClientEngine";
42
+ import { inject } from "../core/inject";
43
+ import { resolveDynamicProps, resolveDynamicValue } from "./dynamics/parse-value";
44
+ import {
45
+ computeBlockPosition,
46
+ computeBlockSize,
47
+ estimateComponentSize,
48
+ getComponentId,
49
+ getComponentProps
50
+ } from "./player-components-utils";
51
+
52
+ const { object, position, graphicBounds } = defineProps({
53
+ position: {
54
+ default: 'top'
55
+ }
56
+ });
57
+
58
+ const client = inject(RpgClientEngine);
59
+ const warnedComponents = new Set();
60
+
61
+ const readPosition = computed(() => position?.() ?? 'top');
62
+
63
+ const componentSource = computed(() => {
64
+ switch (readPosition()) {
65
+ case 'bottom':
66
+ return object.componentsBottom?.();
67
+ case 'center':
68
+ return object.componentsCenter?.();
69
+ case 'left':
70
+ return object.componentsLeft?.();
71
+ case 'right':
72
+ return object.componentsRight?.();
73
+ case 'top':
74
+ default:
75
+ return object.componentsTop?.();
76
+ }
77
+ });
78
+
79
+ const componentData = computed(() => {
80
+ const value = componentSource();
81
+ if (!value) {
82
+ return { components: [], layout: {} };
83
+ }
84
+
85
+ if (typeof value !== 'string') {
86
+ return value;
87
+ }
88
+
89
+ try {
90
+ return JSON.parse(value);
91
+ } catch (error) {
92
+ if (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') {
93
+ console.warn('[RPGJS] Invalid server sprite component payload', error);
94
+ }
95
+ return { components: [], layout: {} };
96
+ }
97
+ });
98
+
99
+ const layout = computed(() => componentData()?.layout ?? {});
100
+ const rows = computed(() => componentData()?.components ?? []);
101
+ const hitbox = object.hitbox;
102
+
103
+ const toNumber = (value, fallback = 0) => {
104
+ const resolved = resolveDynamicValue(value, object);
105
+ const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
106
+ return Number.isFinite(num) ? num : fallback;
107
+ };
108
+
109
+ const estimateTextWidth = (value, style = {}) => {
110
+ const text = String(resolveDynamicValue(value ?? '', object) ?? '');
111
+ const fontSize = toNumber(style.fontSize, 12);
112
+ return Math.max(1, Math.ceil(text.length * fontSize * 0.6));
113
+ };
114
+
115
+ const rowMetrics = computed(() => {
116
+ return rows().map((row) => {
117
+ const cells = row.map((definition) => {
118
+ const intrinsic = estimateComponentSize(definition, { toNumber, estimateTextWidth });
119
+ return {
120
+ definition,
121
+ width: intrinsic.width,
122
+ height: intrinsic.height
123
+ };
124
+ });
125
+
126
+ return {
127
+ cells,
128
+ width: cells.reduce((sum, cell) => sum + cell.width, 0),
129
+ height: cells.reduce((max, cell) => Math.max(max, cell.height), 0)
130
+ };
131
+ });
132
+ });
133
+
134
+ const gap = computed(() => ({
135
+ row: toNumber(layout().rowGap ?? layout().gap, 0),
136
+ column: toNumber(layout().columnGap ?? layout().gap, 0)
137
+ }));
138
+
139
+ const fallbackBounds = computed(() => {
140
+ const box = hitbox();
141
+ const width = box?.w ?? 0;
142
+ const height = box?.h ?? 0;
143
+
144
+ return {
145
+ left: 0,
146
+ top: 0,
147
+ right: width,
148
+ bottom: height,
149
+ width,
150
+ height,
151
+ centerX: width / 2,
152
+ centerY: height / 2
153
+ };
154
+ });
155
+
156
+ const bounds = computed(() => {
157
+ const resolvedBounds = typeof graphicBounds === 'function' ? graphicBounds() : undefined;
158
+ return resolvedBounds ?? fallbackBounds();
159
+ });
160
+
161
+ const blockSize = computed(() => {
162
+ const box = hitbox() ?? { w: 0, h: 0 };
163
+ const graphic = bounds();
164
+ return computeBlockSize({
165
+ position: readPosition(),
166
+ layout: layout(),
167
+ rowMetrics: rowMetrics(),
168
+ gap: gap(),
169
+ graphic,
170
+ hitbox: box
171
+ });
172
+ });
173
+
174
+ const blockPosition = computed(() => {
175
+ const box = hitbox() ?? { w: 0, h: 0 };
176
+ const graphic = bounds();
177
+ return computeBlockPosition({
178
+ position: readPosition(),
179
+ size: blockSize(),
180
+ layout: layout(),
181
+ graphic,
182
+ hitbox: box
183
+ });
184
+ });
185
+
186
+ const warnMissingComponent = (id) => {
187
+ if (!id || warnedComponents.has(id)) return;
188
+ if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;
189
+ warnedComponents.add(id);
190
+ console.warn(`[RPGJS] Server sprite component "${id}" is not registered on the client.`);
191
+ };
192
+
193
+ const renderedRows = computed(() => {
194
+ return rowMetrics().map((row) => {
195
+ const entries = [];
196
+
197
+ row.cells.forEach((cell) => {
198
+ const definition = cell.definition;
199
+ const id = getComponentId(definition);
200
+ const component = client.getSpriteComponent(id);
201
+
202
+ if (!component) {
203
+ warnMissingComponent(id);
204
+ return;
205
+ }
206
+
207
+ entries.push({
208
+ component,
209
+ props: resolveDynamicProps(getComponentProps(definition), object),
210
+ width: cell.width,
211
+ height: cell.height
212
+ });
213
+ });
214
+
215
+ return {
216
+ height: row.height,
217
+ entries
218
+ };
219
+ });
220
+ });
221
+ </script>
package/src/core/setup.ts CHANGED
@@ -14,7 +14,7 @@ export async function startGame(options: SetupOptions) {
14
14
 
15
15
  await injector(context, options.providers);
16
16
 
17
- const engine = inject(context, RpgClientEngine);
17
+ const engine = inject<RpgClientEngine>(context, RpgClientEngine);
18
18
  await engine.start();
19
19
  return context;
20
- }
20
+ }
package/src/module.ts CHANGED
@@ -195,6 +195,11 @@ export function provideClientModules(modules: RpgClientModule[]): FactoryProvide
195
195
  engine.addSpriteComponentInFront(component);
196
196
  });
197
197
  }
198
+ if (sprite.components) {
199
+ Object.entries(sprite.components).forEach(([id, component]) => {
200
+ engine.registerSpriteComponent(id, component);
201
+ });
202
+ }
198
203
  },
199
204
  };
200
205
  }
@@ -226,4 +231,3 @@ export function provideClientGlobalConfig(config: any = {}) {
226
231
  }
227
232
  return provideGlobalConfig(config)
228
233
  }
229
-
@@ -20,6 +20,8 @@ type MapData = {
20
20
  height?: number;
21
21
  /** Optional map events data (NPCs, interactive objects, etc.) */
22
22
  events?: any;
23
+ /** Optional named positions, for example Tiled point objects used by changeMap("map", "name") */
24
+ positions?: Record<string, { x: number; y: number; z?: number }>;
23
25
  /** Optional map identifier, defaults to the mapId parameter if not provided */
24
26
  id?: string;
25
27
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../../../../../../node_modules/.pnpm/@signe+di@2.9.0/node_modules/@signe/di/dist/index.js"],"sourcesContent":["var __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/inject.ts\nvar DEFAULT_INSTANCE_KEY = \"__default__\";\nfunction toTokenName(token) {\n return typeof token === \"function\" ? token.name : token;\n}\n__name(toTokenName, \"toTokenName\");\nfunction toInstanceKey(name) {\n return name ?? DEFAULT_INSTANCE_KEY;\n}\n__name(toInstanceKey, \"toInstanceKey\");\nfunction getRecord(context, token) {\n return context.get(\"inject:\" + toTokenName(token));\n}\n__name(getRecord, \"getRecord\");\nfunction ensureRecord(context, token) {\n const key = \"inject:\" + toTokenName(token);\n let record = context.get(key);\n if (!record) {\n record = {\n multi: false,\n values: /* @__PURE__ */ new Map(),\n injected: /* @__PURE__ */ new Set()\n };\n }\n context.set(key, record);\n return record;\n}\n__name(ensureRecord, \"ensureRecord\");\nfunction provide(context, token, value, options = {}) {\n const record = ensureRecord(context, token);\n const instanceKey = toInstanceKey(options.name);\n if (options.multi) {\n record.multi = true;\n }\n if (!record.multi && instanceKey !== DEFAULT_INSTANCE_KEY) {\n record.multi = true;\n }\n record.values.set(instanceKey, value);\n return value;\n}\n__name(provide, \"provide\");\nfunction isInjected(context, token, options = {}) {\n const record = getRecord(context, token);\n if (!record) {\n return false;\n }\n if (options.name) {\n return record.injected.has(toInstanceKey(options.name));\n }\n if (record.multi) {\n return record.injected.size > 0;\n }\n return record.injected.has(DEFAULT_INSTANCE_KEY);\n}\n__name(isInjected, \"isInjected\");\nfunction isProvided(context, token, options = {}) {\n const record = getRecord(context, token);\n if (!record) {\n return false;\n }\n if (options.name) {\n return record.values.has(toInstanceKey(options.name));\n }\n if (record.multi) {\n return record.values.size > 0;\n }\n return record.values.has(DEFAULT_INSTANCE_KEY);\n}\n__name(isProvided, \"isProvided\");\nfunction hasInstance(context, token, options = {}) {\n return isProvided(context, token, options);\n}\n__name(hasInstance, \"hasInstance\");\nfunction handleMissingInjection(token, options) {\n const name = toTokenName(token);\n if (options.name) {\n throw new Error(`Injection provider ${name} with name ${options.name} not found`);\n }\n throw new Error(`Injection provider ${name} not found`);\n}\n__name(handleMissingInjection, \"handleMissingInjection\");\nfunction markInjected(record, key) {\n record.injected.add(key);\n}\n__name(markInjected, \"markInjected\");\nfunction markAllInjected(record) {\n for (const key of record.values.keys()) {\n record.injected.add(key);\n }\n}\n__name(markAllInjected, \"markAllInjected\");\nfunction inject(context, token, options = {}) {\n const record = getRecord(context, token);\n if (!record) {\n if (options.optional) {\n return options.multi ? [] : void 0;\n }\n return handleMissingInjection(token, options);\n }\n if (options.name) {\n const instanceKey = toInstanceKey(options.name);\n if (!record.values.has(instanceKey)) {\n if (options.optional) {\n return void 0;\n }\n return handleMissingInjection(token, options);\n }\n const value2 = record.values.get(instanceKey);\n markInjected(record, instanceKey);\n return value2;\n }\n if (options.multi || record.multi) {\n if (record.values.size === 0) {\n if (options.optional) {\n return [];\n }\n return handleMissingInjection(token, options);\n }\n markAllInjected(record);\n return Array.from(record.values.values());\n }\n const value = record.values.get(DEFAULT_INSTANCE_KEY);\n if (value === void 0) {\n if (options.optional) {\n return void 0;\n }\n return handleMissingInjection(token, options);\n }\n markInjected(record, DEFAULT_INSTANCE_KEY);\n return value;\n}\n__name(inject, \"inject\");\nfunction override(providers, newProvider, options) {\n let { upsert = false, key } = options ?? {};\n if (!key) {\n key = typeof newProvider === \"function\" ? newProvider.name : newProvider.provide;\n }\n const flatProviders = providers.flat();\n const exists = flatProviders.some((provider) => {\n if (typeof provider === \"function\") {\n return provider.name === key;\n } else if (typeof provider === \"object\") {\n return provider.provide === key;\n }\n return false;\n });\n const mappedProviders = flatProviders.map((provider) => {\n if (typeof provider === \"function\" && provider.name === key) {\n return newProvider;\n } else if (typeof provider === \"object\" && provider.provide === key) {\n return newProvider;\n }\n return provider;\n });\n if (upsert && !exists) {\n mappedProviders.push(newProvider);\n }\n return mappedProviders;\n}\n__name(override, \"override\");\nfunction findProviders(providers, name) {\n const results = [];\n for (const provider of providers) {\n if (Array.isArray(provider)) {\n results.push(...findProviders(provider, name));\n } else if (findProvider(provider, name)) {\n results.push(provider);\n }\n }\n return results;\n}\n__name(findProviders, \"findProviders\");\nfunction findProvider(providers, name) {\n if (!Array.isArray(providers)) {\n if (typeof providers === \"object\" && \"provide\" in providers) {\n const provider = providers;\n const providerName = typeof provider.provide === \"function\" ? provider.provide.name : provider.provide;\n if (name instanceof RegExp) {\n if (name.test(providerName)) return providers;\n } else {\n if (providerName === name) return providers;\n }\n }\n return null;\n }\n for (const provider of providers) {\n if (Array.isArray(provider)) {\n const found = findProvider(provider, name);\n if (found) return found;\n continue;\n }\n if (typeof provider === \"object\" && \"provide\" in provider) {\n const providerName = typeof provider.provide === \"function\" ? provider.provide.name : provider.provide;\n if (name instanceof RegExp) {\n if (name.test(providerName)) return provider;\n } else {\n if (providerName === name) return provider;\n }\n }\n }\n return null;\n}\n__name(findProvider, \"findProvider\");\n\n// src/merge-config.ts\nfunction processProvider(mergedConfig, baseConfig, provider) {\n if (Array.isArray(provider)) {\n for (const nestedProvider of provider) {\n processProvider(mergedConfig, baseConfig, nestedProvider);\n }\n return;\n }\n const existingProvider = findProvider(baseConfig.providers, provider.provide);\n if (existingProvider) {\n mergedConfig.providers = override(mergedConfig.providers, provider);\n } else {\n mergedConfig.providers.push(provider);\n }\n}\n__name(processProvider, \"processProvider\");\nfunction mergeConfig(baseConfig, config) {\n const mergedConfig = {\n ...baseConfig,\n ...config,\n providers: [\n ...baseConfig.providers\n ]\n // Start with a copy of base providers\n };\n for (const provider of config.providers) {\n processProvider(mergedConfig, baseConfig, provider);\n }\n return mergedConfig;\n}\n__name(mergeConfig, \"mergeConfig\");\n\n// src/provider.ts\nfunction extractProvideOptions(source) {\n if (!source) {\n return void 0;\n }\n const { multi, name } = source;\n if (multi === void 0 && name === void 0) {\n return void 0;\n }\n return {\n multi,\n name\n };\n}\n__name(extractProvideOptions, \"extractProvideOptions\");\nfunction getDeps(provider) {\n if (typeof provider === \"function\") {\n return provider.deps ?? [];\n }\n return provider.deps ?? [];\n}\n__name(getDeps, \"getDeps\");\nfunction sortProviders(providers) {\n const tokenName = /* @__PURE__ */ __name((t) => typeof t === \"function\" ? t.name : t, \"tokenName\");\n const map = /* @__PURE__ */ new Map();\n for (const p of providers) {\n const token = tokenName(typeof p === \"function\" ? p : p.provide);\n const list = map.get(token);\n if (list) {\n list.push(p);\n } else {\n map.set(token, [\n p\n ]);\n }\n }\n const result = [];\n const visited = /* @__PURE__ */ new Set();\n const stack = /* @__PURE__ */ new Set();\n const visit = /* @__PURE__ */ __name((token) => {\n const name = tokenName(token);\n if (visited.has(name)) return;\n if (stack.has(name)) {\n throw new Error(`Circular dependency detected for provider ${name}`);\n }\n stack.add(name);\n const providersForToken = map.get(name);\n if (providersForToken) {\n for (const provider of providersForToken) {\n for (const dep of getDeps(provider)) {\n visit(dep);\n }\n result.push(provider);\n }\n visited.add(name);\n }\n stack.delete(name);\n }, \"visit\");\n for (const p of providers) {\n const token = typeof p === \"function\" ? p : p.provide;\n visit(token);\n }\n return result;\n}\n__name(sortProviders, \"sortProviders\");\nasync function injector(context, providers) {\n providers = providers.flat();\n providers = sortProviders(providers);\n for (const provider of providers) {\n let token;\n let instance;\n let options;\n if (typeof provider === \"function\") {\n token = provider;\n instance = new provider(context);\n const diOptions = extractProvideOptions(provider.diOptions ?? provider.di);\n options = diOptions;\n } else {\n token = provider.provide;\n options = extractProvideOptions(provider);\n const provideUserClass = provider.useClass;\n const isClass = typeof provideUserClass === \"function\";\n if (isClass) {\n instance = new provideUserClass(context);\n } else if (\"useValue\" in provider) {\n instance = provider.useValue;\n } else if (\"useFactory\" in provider) {\n instance = provider.useFactory?.(context);\n if (instance instanceof Promise) {\n instance = await instance;\n }\n } else if (\"useExisting\" in provider) {\n instance = inject(context, provider.useExisting);\n }\n }\n provide(context, token, instance, options);\n }\n}\n__name(injector, \"injector\");\n\n// src/context.ts\nvar Context = class {\n static {\n __name(this, \"Context\");\n }\n /** Internal storage for injected values */\n values = {};\n /**\n * Sets a value in the context\n * @param key - Unique identifier for the value\n * @param value - Value to store\n */\n set(key, value) {\n this.values[key] = value;\n }\n /**\n * Retrieves a value from the context\n * @param key - Unique identifier for the value\n * @returns The stored value or undefined if not found\n */\n get(key) {\n return this.values[key];\n }\n};\nexport {\n Context,\n findProvider,\n findProviders,\n hasInstance,\n inject,\n injector,\n isInjected,\n isProvided,\n mergeConfig,\n override,\n provide\n};\n//# sourceMappingURL=index.js.map"],"x_google_ignoreList":[0],"mappings":"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"}