@rpgjs/client 5.0.0-beta.7 → 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 (73) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/Game/Map.js +2 -1
  3. package/dist/Game/Map.js.map +1 -1
  4. package/dist/Game/Object.d.ts +17 -9
  5. package/dist/Game/Object.js +1 -12
  6. package/dist/Game/Object.js.map +1 -1
  7. package/dist/Gui/Gui.d.ts +17 -4
  8. package/dist/Gui/Gui.js +63 -33
  9. package/dist/Gui/Gui.js.map +1 -1
  10. package/dist/Gui/Gui.spec.d.ts +1 -0
  11. package/dist/Resource.js +1 -1
  12. package/dist/Resource.js.map +1 -1
  13. package/dist/RpgClient.d.ts +35 -2
  14. package/dist/RpgClientEngine.d.ts +41 -5
  15. package/dist/RpgClientEngine.js +43 -3
  16. package/dist/RpgClientEngine.js.map +1 -1
  17. package/dist/components/character.ce.js +225 -2
  18. package/dist/components/character.ce.js.map +1 -1
  19. package/dist/components/dynamics/bar.ce.js +96 -0
  20. package/dist/components/dynamics/bar.ce.js.map +1 -0
  21. package/dist/components/dynamics/image.ce.js +23 -0
  22. package/dist/components/dynamics/image.ce.js.map +1 -0
  23. package/dist/components/dynamics/parse-value.d.ts +3 -0
  24. package/dist/components/dynamics/parse-value.js +51 -35
  25. package/dist/components/dynamics/parse-value.js.map +1 -1
  26. package/dist/components/dynamics/parse-value.spec.d.ts +1 -0
  27. package/dist/components/dynamics/shape-utils.d.ts +16 -0
  28. package/dist/components/dynamics/shape-utils.js +73 -0
  29. package/dist/components/dynamics/shape-utils.js.map +1 -0
  30. package/dist/components/dynamics/shape-utils.spec.d.ts +1 -0
  31. package/dist/components/dynamics/shape.ce.js +83 -0
  32. package/dist/components/dynamics/shape.ce.js.map +1 -0
  33. package/dist/components/dynamics/text.ce.js +28 -41
  34. package/dist/components/dynamics/text.ce.js.map +1 -1
  35. package/dist/components/player-components-utils.d.ts +67 -0
  36. package/dist/components/player-components-utils.js +162 -0
  37. package/dist/components/player-components-utils.js.map +1 -0
  38. package/dist/components/player-components-utils.spec.d.ts +1 -0
  39. package/dist/components/player-components.ce.js +188 -0
  40. package/dist/components/player-components.ce.js.map +1 -0
  41. package/dist/core/setup.js.map +1 -1
  42. package/dist/module.js +3 -0
  43. package/dist/module.js.map +1 -1
  44. package/dist/node_modules/.pnpm/@signe_reactive@2.10.0/node_modules/@signe/reactive/dist/index.js +197 -3
  45. package/dist/node_modules/.pnpm/@signe_reactive@2.10.0/node_modules/@signe/reactive/dist/index.js.map +1 -1
  46. package/dist/node_modules/.pnpm/@signe_room@2.10.0/node_modules/@signe/room/dist/index.js +1 -1
  47. package/dist/services/loadMap.d.ts +6 -0
  48. package/dist/services/loadMap.js.map +1 -1
  49. package/package.json +4 -4
  50. package/src/Game/Map.ts +12 -2
  51. package/src/Game/Object.ts +22 -35
  52. package/src/Gui/Gui.spec.ts +273 -0
  53. package/src/Gui/Gui.ts +105 -50
  54. package/src/Resource.ts +1 -2
  55. package/src/RpgClient.ts +36 -2
  56. package/src/RpgClientEngine.ts +64 -10
  57. package/src/components/character.ce +281 -1
  58. package/src/components/dynamics/bar.ce +87 -0
  59. package/src/components/dynamics/image.ce +20 -0
  60. package/src/components/dynamics/parse-value.spec.ts +41 -0
  61. package/src/components/dynamics/parse-value.ts +102 -37
  62. package/src/components/dynamics/shape-utils.spec.ts +46 -0
  63. package/src/components/dynamics/shape-utils.ts +61 -0
  64. package/src/components/dynamics/shape.ce +89 -0
  65. package/src/components/dynamics/text.ce +34 -149
  66. package/src/components/player-components-utils.spec.ts +109 -0
  67. package/src/components/player-components-utils.ts +205 -0
  68. package/src/components/player-components.ce +221 -0
  69. package/src/core/setup.ts +2 -2
  70. package/src/module.ts +5 -1
  71. package/src/services/loadMap.ts +2 -0
  72. package/dist/node_modules/.pnpm/@signe_reactive@2.9.2/node_modules/@signe/reactive/dist/index.js +0 -227
  73. package/dist/node_modules/.pnpm/@signe_reactive@2.9.2/node_modules/@signe/reactive/dist/index.js.map +0 -1
@@ -0,0 +1,162 @@
1
+ //#region src/components/player-components-utils.ts
2
+ var DEFAULT_HP_BAR_STYLE = { fillColor: "#ef4444" };
3
+ var DEFAULT_SP_BAR_STYLE = { fillColor: "#3b82f6" };
4
+ var DEFAULT_CELL_HEIGHT = 16;
5
+ var DEFAULT_CELL_WIDTH = 32;
6
+ var defaultToNumber = (value, fallback = 0) => {
7
+ const num = typeof value === "number" ? value : parseFloat(value);
8
+ return Number.isFinite(num) ? num : fallback;
9
+ };
10
+ function getPointBounds(points = [], toNumber = defaultToNumber) {
11
+ if (!Array.isArray(points) || points.length < 2) return {
12
+ width: 1,
13
+ height: 1
14
+ };
15
+ let minX = Infinity;
16
+ let minY = Infinity;
17
+ let maxX = -Infinity;
18
+ let maxY = -Infinity;
19
+ for (let i = 0; i < points.length; i += 2) {
20
+ const x = toNumber(points[i], 0);
21
+ const y = toNumber(points[i + 1], 0);
22
+ minX = Math.min(minX, x);
23
+ minY = Math.min(minY, y);
24
+ maxX = Math.max(maxX, x);
25
+ maxY = Math.max(maxY, y);
26
+ }
27
+ return {
28
+ width: Math.max(1, maxX - minX),
29
+ height: Math.max(1, maxY - minY)
30
+ };
31
+ }
32
+ function getComponentId(definition) {
33
+ if (!definition) return void 0;
34
+ if (definition.id) return definition.id;
35
+ if (definition.type === "text") return "rpg:text";
36
+ if (definition.type === "hpBar") return "rpg:hpBar";
37
+ if (definition.type === "spBar") return "rpg:spBar";
38
+ if (definition.type === "bar") return "rpg:bar";
39
+ if (definition.type === "shape") return "rpg:shape";
40
+ if (definition.type === "image") return "rpg:image";
41
+ if (definition.type === "tile") return "rpg:tile";
42
+ return definition.type;
43
+ }
44
+ function getComponentProps(definition) {
45
+ if (definition.props) return definition.props;
46
+ if (definition.type === "text") return {
47
+ value: definition.value,
48
+ style: definition.style
49
+ };
50
+ if (definition.type === "hpBar") return {
51
+ current: "{hp}",
52
+ max: "{param.maxHp}",
53
+ style: {
54
+ ...DEFAULT_HP_BAR_STYLE,
55
+ ...definition.style
56
+ },
57
+ text: definition.text
58
+ };
59
+ if (definition.type === "spBar") return {
60
+ current: "{sp}",
61
+ max: "{param.maxSp}",
62
+ style: {
63
+ ...DEFAULT_SP_BAR_STYLE,
64
+ ...definition.style
65
+ },
66
+ text: definition.text
67
+ };
68
+ if (definition.type === "bar") return {
69
+ current: `{${definition.current}}`,
70
+ max: `{${definition.max}}`,
71
+ style: definition.style,
72
+ text: definition.text
73
+ };
74
+ if (definition.type === "shape") return definition.value;
75
+ if (definition.type === "image" || definition.type === "tile") return { value: definition.value };
76
+ return {};
77
+ }
78
+ function estimateComponentSize(definition, { toNumber = defaultToNumber, estimateTextWidth = (value) => String(value ?? "").length * 8 } = {}) {
79
+ const props = getComponentProps(definition);
80
+ const style = props?.style ?? definition?.style ?? {};
81
+ if (definition?.type === "text" || definition?.id === "rpg:text") return {
82
+ width: estimateTextWidth(props.value ?? definition.value, style),
83
+ height: toNumber(style.fontSize, 12)
84
+ };
85
+ if (definition?.type === "hpBar" || definition?.type === "spBar" || definition?.type === "bar" || definition?.id === "rpg:hpBar" || definition?.id === "rpg:spBar" || definition?.id === "rpg:bar") {
86
+ const barHeight = toNumber(style.height, 8);
87
+ const labelHeight = props.text != null && props.text !== "" ? toNumber(style.fontSize, 10) + 2 : 0;
88
+ return {
89
+ width: toNumber(style.width, 50),
90
+ height: barHeight + labelHeight
91
+ };
92
+ }
93
+ if (definition?.type === "shape" || definition?.id === "rpg:shape") {
94
+ const shape = props ?? {};
95
+ if (shape.type === "circle") {
96
+ const radius = toNumber(shape.radius, 8);
97
+ return {
98
+ width: radius * 2,
99
+ height: radius * 2
100
+ };
101
+ }
102
+ if (shape.type === "line") return {
103
+ width: Math.max(1, Math.abs(toNumber(shape.x2, 16) - toNumber(shape.x1, 0))),
104
+ height: Math.max(1, Math.abs(toNumber(shape.y2, 0) - toNumber(shape.y1, 0)))
105
+ };
106
+ if (shape.type === "polygon") return getPointBounds(shape.points, toNumber);
107
+ return {
108
+ width: toNumber(shape.width, 16),
109
+ height: toNumber(shape.height, 16)
110
+ };
111
+ }
112
+ return {
113
+ width: toNumber(definition?.props?.width, DEFAULT_CELL_WIDTH),
114
+ height: toNumber(definition?.props?.height, DEFAULT_CELL_HEIGHT)
115
+ };
116
+ }
117
+ function computeBlockSize({ position, layout = {}, rowMetrics, gap = {
118
+ row: 0,
119
+ column: 0
120
+ }, graphic, hitbox }) {
121
+ const rowGapTotal = Math.max(0, rowMetrics.length - 1) * gap.row;
122
+ const maxColumns = rowMetrics.reduce((max, row) => Math.max(max, row.cells.length), 0);
123
+ const columnGapTotal = Math.max(0, maxColumns - 1) * gap.column;
124
+ const contentWidth = rowMetrics.reduce((max, row) => Math.max(max, row.width), 0) + columnGapTotal;
125
+ const contentHeight = rowMetrics.reduce((sum, row) => sum + row.height, 0) + rowGapTotal;
126
+ return {
127
+ width: layout.width ?? Math.max(contentWidth, position === "bottom" ? hitbox.w : position === "top" || position === "center" ? graphic.width : contentWidth),
128
+ height: layout.height ?? Math.max(contentHeight, position === "bottom" ? hitbox.h : position === "left" || position === "right" || position === "center" ? graphic.height : contentHeight)
129
+ };
130
+ }
131
+ function computeBlockPosition({ position, size, layout = {}, graphic, hitbox }) {
132
+ const marginLeft = layout.marginLeft ?? 0;
133
+ const marginRight = layout.marginRight ?? 0;
134
+ const marginTop = layout.marginTop ?? 0;
135
+ const marginBottom = layout.marginBottom ?? 0;
136
+ switch (position) {
137
+ case "bottom": return {
138
+ x: hitbox.w / 2 - size.width / 2 + marginLeft - marginRight,
139
+ y: hitbox.h / 2 - size.height / 2 + marginBottom - marginTop
140
+ };
141
+ case "center": return {
142
+ x: graphic.centerX - size.width / 2 + marginLeft - marginRight,
143
+ y: graphic.centerY - size.height / 2 + marginTop - marginBottom
144
+ };
145
+ case "left": return {
146
+ x: graphic.left - size.width + marginLeft - marginRight,
147
+ y: graphic.centerY - size.height / 2 + marginTop - marginBottom
148
+ };
149
+ case "right": return {
150
+ x: graphic.right + marginLeft - marginRight,
151
+ y: graphic.centerY - size.height / 2 + marginTop - marginBottom
152
+ };
153
+ default: return {
154
+ x: graphic.centerX - size.width / 2 + marginLeft - marginRight,
155
+ y: graphic.top - size.height + marginTop - marginBottom
156
+ };
157
+ }
158
+ }
159
+ //#endregion
160
+ export { computeBlockPosition, computeBlockSize, estimateComponentSize, getComponentId, getComponentProps };
161
+
162
+ //# sourceMappingURL=player-components-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-components-utils.js","names":[],"sources":["../../src/components/player-components-utils.ts"],"sourcesContent":["export const DEFAULT_HP_BAR_STYLE = { fillColor: '#ef4444' };\nexport const DEFAULT_SP_BAR_STYLE = { fillColor: '#3b82f6' };\n\nconst DEFAULT_CELL_HEIGHT = 16;\nconst DEFAULT_CELL_WIDTH = 32;\n\ntype NumberResolver = (value: any, fallback?: number) => number;\n\nconst defaultToNumber: NumberResolver = (value, fallback = 0) => {\n const num = typeof value === 'number' ? value : parseFloat(value);\n return Number.isFinite(num) ? num : fallback;\n};\n\nexport function getPointBounds(points: any[] = [], toNumber: NumberResolver = defaultToNumber) {\n if (!Array.isArray(points) || points.length < 2) {\n return { width: 1, height: 1 };\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (let i = 0; i < points.length; i += 2) {\n const x = toNumber(points[i], 0);\n const y = toNumber(points[i + 1], 0);\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n\n return {\n width: Math.max(1, maxX - minX),\n height: Math.max(1, maxY - minY)\n };\n}\n\nexport function getComponentId(definition: any) {\n if (!definition) return undefined;\n if (definition.id) return definition.id;\n if (definition.type === 'text') return 'rpg:text';\n if (definition.type === 'hpBar') return 'rpg:hpBar';\n if (definition.type === 'spBar') return 'rpg:spBar';\n if (definition.type === 'bar') return 'rpg:bar';\n if (definition.type === 'shape') return 'rpg:shape';\n if (definition.type === 'image') return 'rpg:image';\n if (definition.type === 'tile') return 'rpg:tile';\n return definition.type;\n}\n\nexport function getComponentProps(definition: any) {\n if (definition.props) return definition.props;\n\n if (definition.type === 'text') {\n return { value: definition.value, style: definition.style };\n }\n if (definition.type === 'hpBar') {\n return { current: '{hp}', max: '{param.maxHp}', style: { ...DEFAULT_HP_BAR_STYLE, ...definition.style }, text: definition.text };\n }\n if (definition.type === 'spBar') {\n return { current: '{sp}', max: '{param.maxSp}', style: { ...DEFAULT_SP_BAR_STYLE, ...definition.style }, text: definition.text };\n }\n if (definition.type === 'bar') {\n return { current: `{${definition.current}}`, max: `{${definition.max}}`, style: definition.style, text: definition.text };\n }\n if (definition.type === 'shape') {\n return definition.value;\n }\n if (definition.type === 'image' || definition.type === 'tile') {\n return { value: definition.value };\n }\n\n return {};\n}\n\nexport function estimateComponentSize(\n definition: any,\n {\n toNumber = defaultToNumber,\n estimateTextWidth = (value: any) => String(value ?? '').length * 8\n }: {\n toNumber?: NumberResolver;\n estimateTextWidth?: (value: any, style?: any) => number;\n } = {}\n) {\n const props = getComponentProps(definition);\n const style = props?.style ?? definition?.style ?? {};\n\n if (definition?.type === 'text' || definition?.id === 'rpg:text') {\n return {\n width: estimateTextWidth(props.value ?? definition.value, style),\n height: toNumber(style.fontSize, 12)\n };\n }\n\n if (definition?.type === 'hpBar' || definition?.type === 'spBar' || definition?.type === 'bar' || definition?.id === 'rpg:hpBar' || definition?.id === 'rpg:spBar' || definition?.id === 'rpg:bar') {\n const barHeight = toNumber(style.height, 8);\n const labelHeight = props.text != null && props.text !== '' ? toNumber(style.fontSize, 10) + 2 : 0;\n return {\n width: toNumber(style.width, 50),\n height: barHeight + labelHeight\n };\n }\n\n if (definition?.type === 'shape' || definition?.id === 'rpg:shape') {\n const shape = props ?? {};\n if (shape.type === 'circle') {\n const radius = toNumber(shape.radius, 8);\n return { width: radius * 2, height: radius * 2 };\n }\n if (shape.type === 'line') {\n return {\n width: Math.max(1, Math.abs(toNumber(shape.x2, 16) - toNumber(shape.x1, 0))),\n height: Math.max(1, Math.abs(toNumber(shape.y2, 0) - toNumber(shape.y1, 0)))\n };\n }\n if (shape.type === 'polygon') {\n return getPointBounds(shape.points, toNumber);\n }\n return {\n width: toNumber(shape.width, 16),\n height: toNumber(shape.height, 16)\n };\n }\n\n return {\n width: toNumber(definition?.props?.width, DEFAULT_CELL_WIDTH),\n height: toNumber(definition?.props?.height, DEFAULT_CELL_HEIGHT)\n };\n}\n\nexport function computeBlockSize({\n position,\n layout = {},\n rowMetrics,\n gap = { row: 0, column: 0 },\n graphic,\n hitbox\n}: {\n position: string;\n layout?: any;\n rowMetrics: Array<{ width: number; height: number; cells: any[] }>;\n gap?: { row: number; column: number };\n graphic: { width: number; height: number };\n hitbox: { w: number; h: number };\n}) {\n const rowGapTotal = Math.max(0, rowMetrics.length - 1) * gap.row;\n const maxColumns = rowMetrics.reduce((max, row) => Math.max(max, row.cells.length), 0);\n const columnGapTotal = Math.max(0, maxColumns - 1) * gap.column;\n const contentWidth = rowMetrics.reduce((max, row) => Math.max(max, row.width), 0) + columnGapTotal;\n const contentHeight = rowMetrics.reduce((sum, row) => sum + row.height, 0) + rowGapTotal;\n const width = layout.width ?? Math.max(contentWidth, position === 'bottom' ? hitbox.w : position === 'top' || position === 'center' ? graphic.width : contentWidth);\n const height = layout.height ?? Math.max(contentHeight, position === 'bottom' ? hitbox.h : position === 'left' || position === 'right' || position === 'center' ? graphic.height : contentHeight);\n\n return { width, height };\n}\n\nexport function computeBlockPosition({\n position,\n size,\n layout = {},\n graphic,\n hitbox\n}: {\n position: string;\n size: { width: number; height: number };\n layout?: any;\n graphic: { left: number; top: number; right: number; centerX: number; centerY: number };\n hitbox: { w: number; h: number };\n}) {\n const marginLeft = layout.marginLeft ?? 0;\n const marginRight = layout.marginRight ?? 0;\n const marginTop = layout.marginTop ?? 0;\n const marginBottom = layout.marginBottom ?? 0;\n\n switch (position) {\n case 'bottom':\n return {\n x: (hitbox.w / 2) - (size.width / 2) + marginLeft - marginRight,\n y: (hitbox.h / 2) - (size.height / 2) + marginBottom - marginTop\n };\n case 'center':\n return {\n x: graphic.centerX - (size.width / 2) + marginLeft - marginRight,\n y: graphic.centerY - (size.height / 2) + marginTop - marginBottom\n };\n case 'left':\n return {\n x: graphic.left - size.width + marginLeft - marginRight,\n y: graphic.centerY - (size.height / 2) + marginTop - marginBottom\n };\n case 'right':\n return {\n x: graphic.right + marginLeft - marginRight,\n y: graphic.centerY - (size.height / 2) + marginTop - marginBottom\n };\n case 'top':\n default:\n return {\n x: graphic.centerX - (size.width / 2) + marginLeft - marginRight,\n y: graphic.top - size.height + marginTop - marginBottom\n };\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,188 @@
1
+ import { inject } from "../core/inject.js";
2
+ import { resolveDynamicProps, resolveDynamicValue } from "./dynamics/parse-value.js";
3
+ import { RpgClientEngine } from "../RpgClientEngine.js";
4
+ import { computeBlockPosition, computeBlockSize, estimateComponentSize, getComponentId, getComponentProps } from "./player-components-utils.js";
5
+ import { Container, computed, h, loop, useDefineProps, useProps } from "canvasengine";
6
+ //#region src/components/player-components.ce
7
+ function component($$props) {
8
+ useProps($$props);
9
+ const { object, position, graphicBounds } = useDefineProps($$props)({ position: { default: "top" } });
10
+ const client = inject(RpgClientEngine);
11
+ const warnedComponents = /* @__PURE__ */ new Set();
12
+ const readPosition = computed(() => position?.() ?? "top");
13
+ const componentSource = computed(() => {
14
+ switch (readPosition()) {
15
+ case "bottom": return object.componentsBottom?.();
16
+ case "center": return object.componentsCenter?.();
17
+ case "left": return object.componentsLeft?.();
18
+ case "right": return object.componentsRight?.();
19
+ default: return object.componentsTop?.();
20
+ }
21
+ });
22
+ const componentData = computed(() => {
23
+ const value = componentSource();
24
+ if (!value) return {
25
+ components: [],
26
+ layout: {}
27
+ };
28
+ if (typeof value !== "string") return value;
29
+ try {
30
+ return JSON.parse(value);
31
+ } catch (error) {
32
+ if (typeof process === "undefined" || process.env.NODE_ENV !== "production") console.warn("[RPGJS] Invalid server sprite component payload", error);
33
+ return {
34
+ components: [],
35
+ layout: {}
36
+ };
37
+ }
38
+ });
39
+ const layout = computed(() => componentData()?.layout ?? {});
40
+ const rows = computed(() => componentData()?.components ?? []);
41
+ const hitbox = object.hitbox;
42
+ const toNumber = (value, fallback = 0) => {
43
+ const resolved = resolveDynamicValue(value, object);
44
+ const num = typeof resolved === "number" ? resolved : parseFloat(resolved);
45
+ return Number.isFinite(num) ? num : fallback;
46
+ };
47
+ const estimateTextWidth = (value, style = {}) => {
48
+ const text = String(resolveDynamicValue(value ?? "", object) ?? "");
49
+ const fontSize = toNumber(style.fontSize, 12);
50
+ return Math.max(1, Math.ceil(text.length * fontSize * .6));
51
+ };
52
+ const rowMetrics = computed(() => {
53
+ return rows().map((row) => {
54
+ const cells = row.map((definition) => {
55
+ const intrinsic = estimateComponentSize(definition, {
56
+ toNumber,
57
+ estimateTextWidth
58
+ });
59
+ return {
60
+ definition,
61
+ width: intrinsic.width,
62
+ height: intrinsic.height
63
+ };
64
+ });
65
+ return {
66
+ cells,
67
+ width: cells.reduce((sum, cell) => sum + cell.width, 0),
68
+ height: cells.reduce((max, cell) => Math.max(max, cell.height), 0)
69
+ };
70
+ });
71
+ });
72
+ const gap = computed(() => ({
73
+ row: toNumber(layout().rowGap ?? layout().gap, 0),
74
+ column: toNumber(layout().columnGap ?? layout().gap, 0)
75
+ }));
76
+ const fallbackBounds = computed(() => {
77
+ const box = hitbox();
78
+ const width = box?.w ?? 0;
79
+ const height = box?.h ?? 0;
80
+ return {
81
+ left: 0,
82
+ top: 0,
83
+ right: width,
84
+ bottom: height,
85
+ width,
86
+ height,
87
+ centerX: width / 2,
88
+ centerY: height / 2
89
+ };
90
+ });
91
+ const bounds = computed(() => {
92
+ return (typeof graphicBounds === "function" ? graphicBounds() : void 0) ?? fallbackBounds();
93
+ });
94
+ const blockSize = computed(() => {
95
+ const box = hitbox() ?? {
96
+ w: 0,
97
+ h: 0
98
+ };
99
+ const graphic = bounds();
100
+ return computeBlockSize({
101
+ position: readPosition(),
102
+ layout: layout(),
103
+ rowMetrics: rowMetrics(),
104
+ gap: gap(),
105
+ graphic,
106
+ hitbox: box
107
+ });
108
+ });
109
+ const blockPosition = computed(() => {
110
+ const box = hitbox() ?? {
111
+ w: 0,
112
+ h: 0
113
+ };
114
+ const graphic = bounds();
115
+ return computeBlockPosition({
116
+ position: readPosition(),
117
+ size: blockSize(),
118
+ layout: layout(),
119
+ graphic,
120
+ hitbox: box
121
+ });
122
+ });
123
+ const warnMissingComponent = (id) => {
124
+ if (!id || warnedComponents.has(id)) return;
125
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") return;
126
+ warnedComponents.add(id);
127
+ console.warn(`[RPGJS] Server sprite component "${id}" is not registered on the client.`);
128
+ };
129
+ const renderedRows = computed(() => {
130
+ return rowMetrics().map((row) => {
131
+ const entries = [];
132
+ row.cells.forEach((cell) => {
133
+ const definition = cell.definition;
134
+ const id = getComponentId(definition);
135
+ const component = client.getSpriteComponent(id);
136
+ if (!component) {
137
+ warnMissingComponent(id);
138
+ return;
139
+ }
140
+ entries.push({
141
+ component,
142
+ props: resolveDynamicProps(getComponentProps(definition), object),
143
+ width: cell.width,
144
+ height: cell.height
145
+ });
146
+ });
147
+ return {
148
+ height: row.height,
149
+ entries
150
+ };
151
+ });
152
+ });
153
+ return h(Container, {
154
+ x: computed(() => blockPosition().x),
155
+ y: computed(() => blockPosition().y),
156
+ width: computed(() => blockSize().width),
157
+ height: computed(() => blockSize().height),
158
+ minWidth: computed(() => blockSize().width),
159
+ minHeight: computed(() => blockSize().height),
160
+ display: "flex",
161
+ flexDirection: "column",
162
+ justifyContent: "center",
163
+ alignItems: "center",
164
+ rowGap: computed(() => gap().row)
165
+ }, loop(renderedRows, (row) => h(Container, {
166
+ width: "100%",
167
+ height: row.height,
168
+ display: "flex",
169
+ flexDirection: "row",
170
+ justifyContent: "center",
171
+ alignItems: "center",
172
+ columnGap: computed(() => gap().column)
173
+ }, loop(row.entries, (entry) => h(Container, {
174
+ width: entry.width,
175
+ height: entry.height,
176
+ display: "flex",
177
+ justifyContent: "center",
178
+ alignItems: "center"
179
+ }, h(entry.component, {
180
+ object,
181
+ ...entry.props
182
+ }))))));
183
+ }
184
+ var __ce_component = component;
185
+ //#endregion
186
+ export { __ce_component as default };
187
+
188
+ //# sourceMappingURL=player-components.ce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-components.ce.js","names":[],"sources":["../../src/components/player-components.ce"],"sourcesContent":["<Container\n x={blockPosition().x}\n y={blockPosition().y}\n width={blockSize().width}\n height={blockSize().height}\n minWidth={blockSize().width}\n minHeight={blockSize().height}\n display=\"flex\"\n flexDirection=\"column\"\n justifyContent=\"center\"\n alignItems=\"center\"\n rowGap={gap().row}\n>\n @for (row of renderedRows) {\n <Container\n width=\"100%\"\n height={row.height}\n display=\"flex\"\n flexDirection=\"row\"\n justifyContent=\"center\"\n alignItems=\"center\"\n columnGap={gap().column}\n >\n @for (entry of row.entries) {\n <Container\n width={entry.width}\n height={entry.height}\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <entry.component object ...entry.props />\n </Container>\n }\n </Container>\n }\n</Container>\n\n<script>\nimport { computed } from \"canvasengine\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { inject } from \"../core/inject\";\nimport { resolveDynamicProps, resolveDynamicValue } from \"./dynamics/parse-value\";\nimport {\n computeBlockPosition,\n computeBlockSize,\n estimateComponentSize,\n getComponentId,\n getComponentProps\n} from \"./player-components-utils\";\n\nconst { object, position, graphicBounds } = defineProps({\n position: {\n default: 'top'\n }\n});\n\nconst client = inject(RpgClientEngine);\nconst warnedComponents = new Set();\n\nconst readPosition = computed(() => position?.() ?? 'top');\n\nconst componentSource = computed(() => {\n switch (readPosition()) {\n case 'bottom':\n return object.componentsBottom?.();\n case 'center':\n return object.componentsCenter?.();\n case 'left':\n return object.componentsLeft?.();\n case 'right':\n return object.componentsRight?.();\n case 'top':\n default:\n return object.componentsTop?.();\n }\n});\n\nconst componentData = computed(() => {\n const value = componentSource();\n if (!value) {\n return { components: [], layout: {} };\n }\n\n if (typeof value !== 'string') {\n return value;\n }\n\n try {\n return JSON.parse(value);\n } catch (error) {\n if (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') {\n console.warn('[RPGJS] Invalid server sprite component payload', error);\n }\n return { components: [], layout: {} };\n }\n});\n\nconst layout = computed(() => componentData()?.layout ?? {});\nconst rows = computed(() => componentData()?.components ?? []);\nconst hitbox = object.hitbox;\n\nconst toNumber = (value, fallback = 0) => {\n const resolved = resolveDynamicValue(value, object);\n const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);\n return Number.isFinite(num) ? num : fallback;\n};\n\nconst estimateTextWidth = (value, style = {}) => {\n const text = String(resolveDynamicValue(value ?? '', object) ?? '');\n const fontSize = toNumber(style.fontSize, 12);\n return Math.max(1, Math.ceil(text.length * fontSize * 0.6));\n};\n\nconst rowMetrics = computed(() => {\n return rows().map((row) => {\n const cells = row.map((definition) => {\n const intrinsic = estimateComponentSize(definition, { toNumber, estimateTextWidth });\n return {\n definition,\n width: intrinsic.width,\n height: intrinsic.height\n };\n });\n\n return {\n cells,\n width: cells.reduce((sum, cell) => sum + cell.width, 0),\n height: cells.reduce((max, cell) => Math.max(max, cell.height), 0)\n };\n });\n});\n\nconst gap = computed(() => ({\n row: toNumber(layout().rowGap ?? layout().gap, 0),\n column: toNumber(layout().columnGap ?? layout().gap, 0)\n}));\n\nconst fallbackBounds = computed(() => {\n const box = hitbox();\n const width = box?.w ?? 0;\n const height = box?.h ?? 0;\n\n return {\n left: 0,\n top: 0,\n right: width,\n bottom: height,\n width,\n height,\n centerX: width / 2,\n centerY: height / 2\n };\n});\n\nconst bounds = computed(() => {\n const resolvedBounds = typeof graphicBounds === 'function' ? graphicBounds() : undefined;\n return resolvedBounds ?? fallbackBounds();\n});\n\nconst blockSize = computed(() => {\n const box = hitbox() ?? { w: 0, h: 0 };\n const graphic = bounds();\n return computeBlockSize({\n position: readPosition(),\n layout: layout(),\n rowMetrics: rowMetrics(),\n gap: gap(),\n graphic,\n hitbox: box\n });\n});\n\nconst blockPosition = computed(() => {\n const box = hitbox() ?? { w: 0, h: 0 };\n const graphic = bounds();\n return computeBlockPosition({\n position: readPosition(),\n size: blockSize(),\n layout: layout(),\n graphic,\n hitbox: box\n });\n});\n\nconst warnMissingComponent = (id) => {\n if (!id || warnedComponents.has(id)) return;\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') return;\n warnedComponents.add(id);\n console.warn(`[RPGJS] Server sprite component \"${id}\" is not registered on the client.`);\n};\n\nconst renderedRows = computed(() => {\n return rowMetrics().map((row) => {\n const entries = [];\n\n row.cells.forEach((cell) => {\n const definition = cell.definition;\n const id = getComponentId(definition);\n const component = client.getSpriteComponent(id);\n\n if (!component) {\n warnMissingComponent(id);\n return;\n }\n\n entries.push({\n component,\n props: resolveDynamicProps(getComponentProps(definition), object),\n width: cell.width,\n height: cell.height\n });\n });\n\n return {\n height: row.height,\n entries\n };\n });\n});\n</script>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","names":[],"sources":["../../src/core/setup.ts"],"sourcesContent":["import { Context, FactoryProvider, findProvider, findProviders, inject, injector, Providers } from \"@signe/di\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { setInject } from \"./inject\";\n\ninterface SetupOptions {\n providers: Providers;\n}\n\n\nexport async function startGame(options: SetupOptions) {\n const context = new Context();\n context['side'] = 'client'\n setInject(context);\n\n await injector(context, options.providers);\n\n const engine = inject(context, RpgClientEngine);\n await engine.start();\n return context;\n}"],"mappings":";;;;AASA,eAAsB,UAAU,SAAuB;CACrD,MAAM,UAAU,IAAI,SAAS;CAC7B,QAAQ,UAAU;CAClB,UAAU,QAAQ;CAElB,MAAM,SAAS,SAAS,QAAQ,UAAU;CAG1C,MADe,OAAO,SAAS,gBACzB,CAAO,OAAO;CACpB,OAAO"}
1
+ {"version":3,"file":"setup.js","names":[],"sources":["../../src/core/setup.ts"],"sourcesContent":["import { Context, FactoryProvider, findProvider, findProviders, inject, injector, Providers } from \"@signe/di\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { setInject } from \"./inject\";\n\ninterface SetupOptions {\n providers: Providers;\n}\n\n\nexport async function startGame(options: SetupOptions) {\n const context = new Context();\n context['side'] = 'client'\n setInject(context);\n\n await injector(context, options.providers);\n\n const engine = inject<RpgClientEngine>(context, RpgClientEngine);\n await engine.start();\n return context;\n}\n"],"mappings":";;;;AASA,eAAsB,UAAU,SAAuB;CACrD,MAAM,UAAU,IAAI,SAAS;CAC7B,QAAQ,UAAU;CAClB,UAAU,QAAQ;CAElB,MAAM,SAAS,SAAS,QAAQ,UAAU;CAG1C,MADe,OAAwB,SAAS,gBAC1C,CAAO,OAAO;CACpB,OAAO"}
package/dist/module.js CHANGED
@@ -144,6 +144,9 @@ function provideClientModules(modules) {
144
144
  if (sprite.componentsInFront) sprite.componentsInFront.forEach((component) => {
145
145
  engine.addSpriteComponentInFront(component);
146
146
  });
147
+ if (sprite.components) Object.entries(sprite.components).forEach(([id, component]) => {
148
+ engine.registerSpriteComponent(id, component);
149
+ });
147
150
  }
148
151
  };
149
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","names":[],"sources":["../src/module.ts"],"sourcesContent":["import { findModules, provideModules } from \"@rpgjs/common\";\nimport { FactoryProvider } from \"@signe/di\";\nimport { RpgClientEngine } from \"./RpgClientEngine\";\nimport { RpgClient } from \"./RpgClient\";\nimport { inject } from \"@signe/di\";\nimport { RpgGui } from \"./Gui/Gui\";\nimport { getSoundMetadata } from \"./Sound\";\n\n/**\n * Type for client modules that can be either:\n * - An object implementing RpgClient interface\n * - A class decorated with @RpgModule decorator\n */\nexport type RpgClientModule = RpgClient | (new () => any);\n\n/**\n * Provides client modules configuration to Dependency Injection\n * \n * This function accepts an array of client modules that can be either:\n * - Objects implementing the RpgClient interface\n * - Classes decorated with the @RpgModule decorator (which will be instantiated)\n * \n * @param modules - Array of client modules (objects or classes)\n * @returns FactoryProvider configuration for DI\n * @example\n * ```ts\n * // Using an object\n * provideClientModules([\n * {\n * engine: {\n * onConnected(engine) {\n * console.log('Client connected')\n * }\n * }\n * }\n * ])\n * \n * // Using a decorated class\n * @RpgModule<RpgClient>({\n * engine: {\n * onStart(engine) {\n * console.log('Client started')\n * }\n * }\n * })\n * class MyClientModule {}\n * \n * provideClientModules([MyClientModule])\n * ```\n */\nexport function provideClientModules(modules: RpgClientModule[]): FactoryProvider {\n return provideModules(modules, \"client\", (modules, context) => {\n const mainModuleClient = findModules(context, 'Client')\n modules = [...mainModuleClient, ...modules]\n modules = modules.map((module) => {\n // If module is a class (constructor function), instantiate it\n // The RpgModule decorator adds properties to the prototype, which will be accessible via the instance\n if (typeof module === 'function') {\n const instance = new module() as any;\n // Copy all enumerable properties (including from prototype) to a plain object\n const moduleObj: any = {};\n for (const key in instance) {\n moduleObj[key] = instance[key];\n }\n module = moduleObj;\n }\n if ('client' in module) {\n module = module.client as any;\n }\n if (module.spritesheets) {\n const spritesheets = [...module.spritesheets];\n module.spritesheets = {\n load: (engine: RpgClientEngine) => {\n spritesheets.forEach((spritesheet) => {\n engine.addSpriteSheet(spritesheet);\n });\n },\n };\n }\n if (module.spritesheetResolver) {\n const resolver = module.spritesheetResolver;\n module.spritesheetResolver = {\n load: (engine: RpgClientEngine) => {\n engine.setSpritesheetResolver(resolver);\n },\n };\n }\n if (module.sounds) {\n const sounds = [...module.sounds];\n module.sounds = {\n load: (engine: RpgClientEngine) => {\n sounds.forEach((sound) => {\n // Check if it's a class decorated with @Sound\n if (typeof sound === 'function' || (sound && sound.constructor && sound.constructor !== Object)) {\n const metadata = getSoundMetadata(sound);\n if (metadata) {\n // Handle single sound\n if (metadata.id && metadata.sound) {\n engine.addSound({\n id: metadata.id,\n src: metadata.sound,\n loop: metadata.loop,\n volume: metadata.volume,\n });\n }\n // Handle multiple sounds\n if (metadata.sounds) {\n Object.entries(metadata.sounds).forEach(([soundId, soundSrc]) => {\n engine.addSound({\n id: soundId,\n src: soundSrc,\n loop: metadata.loop,\n volume: metadata.volume,\n });\n });\n }\n } else {\n // Not a decorated class, treat as regular sound object\n engine.addSound(sound);\n }\n } else {\n // Regular sound object\n engine.addSound(sound);\n }\n });\n },\n };\n }\n if (module.soundResolver) {\n const resolver = module.soundResolver;\n module.soundResolver = {\n load: (engine: RpgClientEngine) => {\n engine.setSoundResolver(resolver);\n },\n };\n }\n if (module.gui) {\n const gui = [...module.gui];\n module.gui = {\n load: (engine: RpgClientEngine) => {\n const guiService = inject(engine.context, RpgGui) as RpgGui;\n gui.forEach((gui) => {\n guiService.add(gui);\n });\n },\n };\n }\n if (module.componentAnimations) {\n const componentAnimations = [...module.componentAnimations];\n module.componentAnimations = {\n load: (engine: RpgClientEngine) => {\n componentAnimations.forEach((componentAnimation) => {\n engine.addComponentAnimation(componentAnimation);\n });\n },\n };\n }\n if (module.transitions) {\n const transitions = [...module.transitions];\n module.transitions = {\n load: (engine: RpgClientEngine) => {\n const guiService = inject(engine.context, RpgGui) as RpgGui;\n transitions.forEach((transition) => {\n guiService.add({\n name: transition.id,\n component: transition.component,\n data: transition.props || {}\n });\n });\n },\n };\n }\n if (module.particles) {\n const particles = [...module.particles];\n module.particles = {\n load: (engine: RpgClientEngine) => {\n particles.forEach((particle) => {\n engine.addParticle(particle);\n });\n },\n };\n }\n if (module.sprite) {\n const sprite = {...module.sprite};\n module.sprite = {\n ...sprite,\n load: (engine: RpgClientEngine) => {\n if (sprite.componentsBehind) {\n sprite.componentsBehind.forEach((component) => {\n engine.addSpriteComponentBehind(component);\n });\n }\n if (sprite.componentsInFront) {\n sprite.componentsInFront.forEach((component) => {\n engine.addSpriteComponentInFront(component);\n });\n }\n },\n };\n }\n return module;\n });\n return modules\n });\n}\n\nexport const GlobalConfigToken = \"GlobalConfigToken\";\n\nexport function provideGlobalConfig(config: any) {\n return {\n provide: GlobalConfigToken,\n useValue: config ?? {},\n };\n}\n\nexport function provideClientGlobalConfig(config: any = {}) {\n if (!config.keyboardControls) {\n config.keyboardControls = {\n up: 'up',\n down: 'down',\n left: 'left',\n right: 'right',\n action: 'space',\n escape: 'escape'\n }\n }\n return provideGlobalConfig(config)\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"module.js","names":[],"sources":["../src/module.ts"],"sourcesContent":["import { findModules, provideModules } from \"@rpgjs/common\";\nimport { FactoryProvider } from \"@signe/di\";\nimport { RpgClientEngine } from \"./RpgClientEngine\";\nimport { RpgClient } from \"./RpgClient\";\nimport { inject } from \"@signe/di\";\nimport { RpgGui } from \"./Gui/Gui\";\nimport { getSoundMetadata } from \"./Sound\";\n\n/**\n * Type for client modules that can be either:\n * - An object implementing RpgClient interface\n * - A class decorated with @RpgModule decorator\n */\nexport type RpgClientModule = RpgClient | (new () => any);\n\n/**\n * Provides client modules configuration to Dependency Injection\n * \n * This function accepts an array of client modules that can be either:\n * - Objects implementing the RpgClient interface\n * - Classes decorated with the @RpgModule decorator (which will be instantiated)\n * \n * @param modules - Array of client modules (objects or classes)\n * @returns FactoryProvider configuration for DI\n * @example\n * ```ts\n * // Using an object\n * provideClientModules([\n * {\n * engine: {\n * onConnected(engine) {\n * console.log('Client connected')\n * }\n * }\n * }\n * ])\n * \n * // Using a decorated class\n * @RpgModule<RpgClient>({\n * engine: {\n * onStart(engine) {\n * console.log('Client started')\n * }\n * }\n * })\n * class MyClientModule {}\n * \n * provideClientModules([MyClientModule])\n * ```\n */\nexport function provideClientModules(modules: RpgClientModule[]): FactoryProvider {\n return provideModules(modules, \"client\", (modules, context) => {\n const mainModuleClient = findModules(context, 'Client')\n modules = [...mainModuleClient, ...modules]\n modules = modules.map((module) => {\n // If module is a class (constructor function), instantiate it\n // The RpgModule decorator adds properties to the prototype, which will be accessible via the instance\n if (typeof module === 'function') {\n const instance = new module() as any;\n // Copy all enumerable properties (including from prototype) to a plain object\n const moduleObj: any = {};\n for (const key in instance) {\n moduleObj[key] = instance[key];\n }\n module = moduleObj;\n }\n if ('client' in module) {\n module = module.client as any;\n }\n if (module.spritesheets) {\n const spritesheets = [...module.spritesheets];\n module.spritesheets = {\n load: (engine: RpgClientEngine) => {\n spritesheets.forEach((spritesheet) => {\n engine.addSpriteSheet(spritesheet);\n });\n },\n };\n }\n if (module.spritesheetResolver) {\n const resolver = module.spritesheetResolver;\n module.spritesheetResolver = {\n load: (engine: RpgClientEngine) => {\n engine.setSpritesheetResolver(resolver);\n },\n };\n }\n if (module.sounds) {\n const sounds = [...module.sounds];\n module.sounds = {\n load: (engine: RpgClientEngine) => {\n sounds.forEach((sound) => {\n // Check if it's a class decorated with @Sound\n if (typeof sound === 'function' || (sound && sound.constructor && sound.constructor !== Object)) {\n const metadata = getSoundMetadata(sound);\n if (metadata) {\n // Handle single sound\n if (metadata.id && metadata.sound) {\n engine.addSound({\n id: metadata.id,\n src: metadata.sound,\n loop: metadata.loop,\n volume: metadata.volume,\n });\n }\n // Handle multiple sounds\n if (metadata.sounds) {\n Object.entries(metadata.sounds).forEach(([soundId, soundSrc]) => {\n engine.addSound({\n id: soundId,\n src: soundSrc,\n loop: metadata.loop,\n volume: metadata.volume,\n });\n });\n }\n } else {\n // Not a decorated class, treat as regular sound object\n engine.addSound(sound);\n }\n } else {\n // Regular sound object\n engine.addSound(sound);\n }\n });\n },\n };\n }\n if (module.soundResolver) {\n const resolver = module.soundResolver;\n module.soundResolver = {\n load: (engine: RpgClientEngine) => {\n engine.setSoundResolver(resolver);\n },\n };\n }\n if (module.gui) {\n const gui = [...module.gui];\n module.gui = {\n load: (engine: RpgClientEngine) => {\n const guiService = inject(engine.context, RpgGui) as RpgGui;\n gui.forEach((gui) => {\n guiService.add(gui);\n });\n },\n };\n }\n if (module.componentAnimations) {\n const componentAnimations = [...module.componentAnimations];\n module.componentAnimations = {\n load: (engine: RpgClientEngine) => {\n componentAnimations.forEach((componentAnimation) => {\n engine.addComponentAnimation(componentAnimation);\n });\n },\n };\n }\n if (module.transitions) {\n const transitions = [...module.transitions];\n module.transitions = {\n load: (engine: RpgClientEngine) => {\n const guiService = inject(engine.context, RpgGui) as RpgGui;\n transitions.forEach((transition) => {\n guiService.add({\n name: transition.id,\n component: transition.component,\n data: transition.props || {}\n });\n });\n },\n };\n }\n if (module.particles) {\n const particles = [...module.particles];\n module.particles = {\n load: (engine: RpgClientEngine) => {\n particles.forEach((particle) => {\n engine.addParticle(particle);\n });\n },\n };\n }\n if (module.sprite) {\n const sprite = {...module.sprite};\n module.sprite = {\n ...sprite,\n load: (engine: RpgClientEngine) => {\n if (sprite.componentsBehind) {\n sprite.componentsBehind.forEach((component) => {\n engine.addSpriteComponentBehind(component);\n });\n }\n if (sprite.componentsInFront) {\n sprite.componentsInFront.forEach((component) => {\n engine.addSpriteComponentInFront(component);\n });\n }\n if (sprite.components) {\n Object.entries(sprite.components).forEach(([id, component]) => {\n engine.registerSpriteComponent(id, component);\n });\n }\n },\n };\n }\n return module;\n });\n return modules\n });\n}\n\nexport const GlobalConfigToken = \"GlobalConfigToken\";\n\nexport function provideGlobalConfig(config: any) {\n return {\n provide: GlobalConfigToken,\n useValue: config ?? {},\n };\n}\n\nexport function provideClientGlobalConfig(config: any = {}) {\n if (!config.keyboardControls) {\n config.keyboardControls = {\n up: 'up',\n down: 'down',\n left: 'left',\n right: 'right',\n action: 'space',\n escape: 'escape'\n }\n }\n return provideGlobalConfig(config)\n}\n"],"mappings":"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"}