@rpgjs/tiledmap 5.0.0-beta.7 → 5.0.0-beta.9

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 ADDED
@@ -0,0 +1,29 @@
1
+ # @rpgjs/tiledmap
2
+
3
+ ## 5.0.0-beta.9
4
+
5
+ ### Major Changes
6
+
7
+ - c456d25: beta.9
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [c456d25]
12
+ - @rpgjs/client@5.0.0-beta.9
13
+ - @rpgjs/common@5.0.0-beta.9
14
+ - @rpgjs/server@5.0.0-beta.9
15
+ - @rpgjs/vite@5.0.0-beta.9
16
+
17
+ ## 5.0.0-beta.8
18
+
19
+ ### Major Changes
20
+
21
+ - 35e7fa4: beta.8
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [35e7fa4]
26
+ - @rpgjs/client@5.0.0-beta.8
27
+ - @rpgjs/common@5.0.0-beta.8
28
+ - @rpgjs/server@5.0.0-beta.8
29
+ - @rpgjs/vite@5.0.0-beta.8
@@ -1,7 +1,7 @@
1
1
  import { TiledParser } from "./index2.js";
2
2
  import { prepareTiledPhysicsData } from "./index3.js";
3
3
  import client_default from "./index4.js";
4
- import component from "./index5.js";
4
+ import __ce_component from "./index5.js";
5
5
  import { createModule } from "@rpgjs/common";
6
6
  import { provideLoadMap } from "@rpgjs/client";
7
7
  //#region src/index.ts
@@ -25,7 +25,7 @@ function provideTiledMap(options) {
25
25
  parsedMap.tilesets = tilesets;
26
26
  const obj = {
27
27
  data: mapData,
28
- component,
28
+ component: __ce_component,
29
29
  parsedMap,
30
30
  id: map,
31
31
  params: { basePath: options.basePath }
@@ -1,6 +1,7 @@
1
1
  import { MapClass } from "./index2.js";
2
2
  //#region src/physics.ts
3
3
  var TILED_HITBOX_ID_PREFIX = "__tiled_collision__:";
4
+ var START_POSITION_NAME = "start";
4
5
  function prepareTiledPhysicsData(mapData, map) {
5
6
  if (!mapData?.parsedMap) return;
6
7
  const tiledMap = new MapClass(mapData.parsedMap);
@@ -9,6 +10,29 @@ function prepareTiledPhysicsData(mapData, map) {
9
10
  mapData.hitboxes = mergeTiledHitboxes(mapData.hitboxes, tiledHitboxes);
10
11
  mapData.width = tiledMap.widthPx;
11
12
  mapData.height = tiledMap.heightPx;
13
+ mapData.positions = mergeTiledPositions(mapData.positions, collectTiledPointPositions(mapData.parsedMap.objects));
14
+ }
15
+ function collectTiledPointPositions(objects) {
16
+ if (!Array.isArray(objects)) return {};
17
+ const positions = {};
18
+ for (const obj of objects) {
19
+ if (!obj?.point || typeof obj.x !== "number" || typeof obj.y !== "number") continue;
20
+ if (typeof obj.name === "string" && obj.name.length > 0) positions[obj.name] = {
21
+ x: obj.x,
22
+ y: obj.y
23
+ };
24
+ if (!positions[START_POSITION_NAME] && (obj.class === START_POSITION_NAME || obj.type === START_POSITION_NAME)) positions[START_POSITION_NAME] = {
25
+ x: obj.x,
26
+ y: obj.y
27
+ };
28
+ }
29
+ return positions;
30
+ }
31
+ function mergeTiledPositions(existingPositions, tiledPositions) {
32
+ return {
33
+ ...existingPositions && typeof existingPositions === "object" ? existingPositions : {},
34
+ ...tiledPositions
35
+ };
12
36
  }
13
37
  function collectBlockedTileHitboxes(tiledMap) {
14
38
  const hitboxes = [];
@@ -17,5 +17,6 @@ function component($$props) {
17
17
  objectLayer: () => h(EventLayerComponent)
18
18
  }));
19
19
  }
20
+ var __ce_component = component;
20
21
  //#endregion
21
- export { component as default };
22
+ export { __ce_component as default };
@@ -0,0 +1,4 @@
1
+ export declare function provideTiledMap(options: {
2
+ basePath: string;
3
+ onLoadMap?: (map: string) => Promise<void>;
4
+ }): any[];
@@ -1,6 +1,7 @@
1
1
  import { MapClass } from "./index2.js";
2
2
  //#region src/physics.ts
3
3
  var TILED_HITBOX_ID_PREFIX = "__tiled_collision__:";
4
+ var START_POSITION_NAME = "start";
4
5
  function prepareTiledPhysicsData(mapData, map) {
5
6
  if (!mapData?.parsedMap) return;
6
7
  const tiledMap = new MapClass(mapData.parsedMap);
@@ -9,6 +10,7 @@ function prepareTiledPhysicsData(mapData, map) {
9
10
  mapData.hitboxes = mergeTiledHitboxes(mapData.hitboxes, tiledHitboxes);
10
11
  mapData.width = tiledMap.widthPx;
11
12
  mapData.height = tiledMap.heightPx;
13
+ mapData.positions = mergeTiledPositions(mapData.positions, collectTiledPointPositions(mapData.parsedMap.objects));
12
14
  }
13
15
  function applyTiledPointEvents(mapData) {
14
16
  const objects = mapData?.parsedMap?.objects;
@@ -16,8 +18,8 @@ function applyTiledPointEvents(mapData) {
16
18
  for (const obj of objects) {
17
19
  if (!obj?.point) continue;
18
20
  mapData.events = mapData.events.map((eventEntry) => {
19
- if (eventEntry?.name === obj.name) return {
20
- event: eventEntry,
21
+ if (obj.name && eventEntry?.x === void 0 && eventEntry?.y === void 0 && getEventName(eventEntry) === obj.name) return {
22
+ ...eventEntry && typeof eventEntry === "object" && "event" in eventEntry ? eventEntry : { event: eventEntry },
21
23
  x: obj.x,
22
24
  y: obj.y
23
25
  };
@@ -25,6 +27,42 @@ function applyTiledPointEvents(mapData) {
25
27
  }).filter((eventEntry) => eventEntry !== null);
26
28
  }
27
29
  }
30
+ function collectTiledPointPositions(objects) {
31
+ if (!Array.isArray(objects)) return {};
32
+ const positions = {};
33
+ for (const obj of objects) {
34
+ if (!obj?.point || typeof obj.x !== "number" || typeof obj.y !== "number") continue;
35
+ if (typeof obj.name === "string" && obj.name.length > 0) positions[obj.name] = {
36
+ x: obj.x,
37
+ y: obj.y
38
+ };
39
+ if (!positions[START_POSITION_NAME] && (obj.class === START_POSITION_NAME || obj.type === START_POSITION_NAME)) positions[START_POSITION_NAME] = {
40
+ x: obj.x,
41
+ y: obj.y
42
+ };
43
+ }
44
+ return positions;
45
+ }
46
+ function mergeTiledPositions(existingPositions, tiledPositions) {
47
+ return {
48
+ ...existingPositions && typeof existingPositions === "object" ? existingPositions : {},
49
+ ...tiledPositions
50
+ };
51
+ }
52
+ function getEventName(eventEntry) {
53
+ const event = eventEntry?.event ?? eventEntry;
54
+ if (typeof event === "function") {
55
+ const staticEventName = event._name;
56
+ const prototypeEventName = event.prototype?._name;
57
+ const staticName = event.name;
58
+ const prototypeName = event.prototype?.name;
59
+ if (typeof prototypeEventName === "string") return prototypeEventName;
60
+ if (typeof staticEventName === "string") return staticEventName;
61
+ if (typeof prototypeName === "string") return prototypeName;
62
+ if (typeof staticName === "string") return staticName;
63
+ }
64
+ if (typeof event?.name === "string") return event.name;
65
+ }
28
66
  function collectBlockedTileHitboxes(tiledMap) {
29
67
  const hitboxes = [];
30
68
  const mapWidth = tiledMap.width;
@@ -0,0 +1,7 @@
1
+ import { MapClass } from '@canvasengine/tiled';
2
+ type AnyMap = {
3
+ tiled?: MapClass;
4
+ };
5
+ export declare function prepareTiledPhysicsData(mapData: any, map: AnyMap): void;
6
+ export declare function applyTiledPointEvents(mapData: any): void;
7
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgjs/tiledmap",
3
- "version": "5.0.0-beta.7",
3
+ "version": "5.0.0-beta.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -23,10 +23,10 @@
23
23
  "description": "RPGJS is a framework for creating RPG/MMORPG games",
24
24
  "peerDependencies": {
25
25
  "@canvasengine/presets": "*",
26
- "@rpgjs/client": "5.0.0-beta.7",
27
- "@rpgjs/common": "5.0.0-beta.7",
28
- "@rpgjs/server": "5.0.0-beta.7",
29
- "@rpgjs/vite": "5.0.0-beta.7",
26
+ "@rpgjs/client": "5.0.0-beta.9",
27
+ "@rpgjs/common": "5.0.0-beta.9",
28
+ "@rpgjs/server": "5.0.0-beta.9",
29
+ "@rpgjs/vite": "5.0.0-beta.9",
30
30
  "canvasengine": "*"
31
31
  },
32
32
  "publishConfig": {
@@ -32,7 +32,7 @@ vi.mock("@canvasengine/tiled", () => {
32
32
  return { MapClass };
33
33
  });
34
34
 
35
- import { prepareTiledPhysicsData } from "./physics";
35
+ import { applyTiledPointEvents, prepareTiledPhysicsData } from "./physics";
36
36
 
37
37
  describe("prepareTiledPhysicsData", () => {
38
38
  it("adds tiled collision hitboxes without duplicating them on repeated preparation", () => {
@@ -88,3 +88,158 @@ describe("prepareTiledPhysicsData", () => {
88
88
  expect(mapData.hitboxes).toEqual([]);
89
89
  });
90
90
  });
91
+
92
+ describe("tiled point positions", () => {
93
+ it("extracts named point objects as map positions", () => {
94
+ const mapData = {
95
+ parsedMap: {
96
+ width: 1,
97
+ height: 1,
98
+ objects: [
99
+ { point: true, name: "start", x: 10, y: 20 },
100
+ { point: true, name: "entrance", x: 30, y: 40 },
101
+ ],
102
+ },
103
+ };
104
+
105
+ prepareTiledPhysicsData(mapData, {});
106
+
107
+ expect(mapData.positions).toEqual({
108
+ start: { x: 10, y: 20 },
109
+ entrance: { x: 30, y: 40 },
110
+ });
111
+ });
112
+
113
+ it("uses class or type as a fallback for the special start position", () => {
114
+ const mapData = {
115
+ parsedMap: {
116
+ width: 1,
117
+ height: 1,
118
+ objects: [
119
+ { point: true, class: "start", x: 10, y: 20 },
120
+ { point: true, type: "start", x: 30, y: 40 },
121
+ ],
122
+ },
123
+ };
124
+
125
+ prepareTiledPhysicsData(mapData, {});
126
+
127
+ expect(mapData.positions).toEqual({
128
+ start: { x: 10, y: 20 },
129
+ });
130
+ });
131
+
132
+ it("keeps explicitly named start before class or type fallback", () => {
133
+ const mapData = {
134
+ parsedMap: {
135
+ width: 1,
136
+ height: 1,
137
+ objects: [
138
+ { point: true, name: "start", x: 10, y: 20 },
139
+ { point: true, class: "start", x: 30, y: 40 },
140
+ ],
141
+ },
142
+ };
143
+
144
+ prepareTiledPhysicsData(mapData, {});
145
+
146
+ expect(mapData.positions).toEqual({
147
+ start: { x: 10, y: 20 },
148
+ });
149
+ });
150
+ });
151
+
152
+ describe("applyTiledPointEvents", () => {
153
+ it("places direct object events by matching their name with a tiled point", () => {
154
+ const mapData = {
155
+ parsedMap: {
156
+ objects: [
157
+ { point: true, name: "EV-1", x: 10, y: 20 },
158
+ ],
159
+ },
160
+ events: [
161
+ { name: "EV-1", onInit() {} },
162
+ ],
163
+ };
164
+
165
+ applyTiledPointEvents(mapData);
166
+
167
+ expect(mapData.events).toEqual([
168
+ {
169
+ event: { name: "EV-1", onInit: expect.any(Function) },
170
+ x: 10,
171
+ y: 20,
172
+ },
173
+ ]);
174
+ });
175
+
176
+ it("places wrapped object events by matching the wrapped event name", () => {
177
+ const mapData = {
178
+ parsedMap: {
179
+ objects: [
180
+ { point: true, name: "EV-1", x: 10, y: 20 },
181
+ ],
182
+ },
183
+ events: [
184
+ { id: "event-id", event: { name: "EV-1", onInit() {} } },
185
+ ],
186
+ };
187
+
188
+ applyTiledPointEvents(mapData);
189
+
190
+ expect(mapData.events).toEqual([
191
+ {
192
+ id: "event-id",
193
+ event: { name: "EV-1", onInit: expect.any(Function) },
194
+ x: 10,
195
+ y: 20,
196
+ },
197
+ ]);
198
+ });
199
+
200
+ it("places class events decorated with EventData metadata", () => {
201
+ class NpcEvent {}
202
+ (NpcEvent as any)._name = "EV-1";
203
+ (NpcEvent as any).prototype._name = "EV-1";
204
+
205
+ const mapData = {
206
+ parsedMap: {
207
+ objects: [
208
+ { point: true, name: "EV-1", x: 10, y: 20 },
209
+ ],
210
+ },
211
+ events: [
212
+ { event: NpcEvent },
213
+ ],
214
+ };
215
+
216
+ applyTiledPointEvents(mapData);
217
+
218
+ expect(mapData.events).toEqual([
219
+ {
220
+ event: NpcEvent,
221
+ x: 10,
222
+ y: 20,
223
+ },
224
+ ]);
225
+ });
226
+
227
+ it("does not override explicit event coordinates", () => {
228
+ const mapData = {
229
+ parsedMap: {
230
+ objects: [
231
+ { point: true, name: "EV-1", x: 10, y: 20 },
232
+ ],
233
+ },
234
+ events: [
235
+ { x: 50, y: 60, event: { name: "EV-1" } },
236
+ ],
237
+ };
238
+
239
+ applyTiledPointEvents(mapData);
240
+
241
+ expect(mapData.events).toEqual([
242
+ { x: 50, y: 60, event: { name: "EV-1" } },
243
+ ]);
244
+ });
245
+ });
package/src/physics.ts CHANGED
@@ -13,6 +13,7 @@ type RectHitbox = {
13
13
  };
14
14
 
15
15
  const TILED_HITBOX_ID_PREFIX = "__tiled_collision__:";
16
+ const START_POSITION_NAME = "start";
16
17
 
17
18
  export function prepareTiledPhysicsData(mapData: any, map: AnyMap): void {
18
19
  if (!mapData?.parsedMap) {
@@ -26,6 +27,7 @@ export function prepareTiledPhysicsData(mapData: any, map: AnyMap): void {
26
27
  mapData.hitboxes = mergeTiledHitboxes(mapData.hitboxes, tiledHitboxes);
27
28
  mapData.width = tiledMap.widthPx;
28
29
  mapData.height = tiledMap.heightPx;
30
+ mapData.positions = mergeTiledPositions(mapData.positions, collectTiledPointPositions(mapData.parsedMap.objects));
29
31
  }
30
32
 
31
33
  export function applyTiledPointEvents(mapData: any): void {
@@ -41,9 +43,15 @@ export function applyTiledPointEvents(mapData: any): void {
41
43
 
42
44
  mapData.events = mapData.events
43
45
  .map((eventEntry: any) => {
44
- if (eventEntry?.name === obj.name) {
46
+ if (
47
+ obj.name &&
48
+ eventEntry?.x === undefined &&
49
+ eventEntry?.y === undefined &&
50
+ getEventName(eventEntry) === obj.name
51
+ ) {
52
+ const isWrappedEvent = eventEntry && typeof eventEntry === "object" && "event" in eventEntry;
45
53
  return {
46
- event: eventEntry,
54
+ ...(isWrappedEvent ? eventEntry : { event: eventEntry }),
47
55
  x: obj.x,
48
56
  y: obj.y,
49
57
  };
@@ -54,6 +62,69 @@ export function applyTiledPointEvents(mapData: any): void {
54
62
  }
55
63
  }
56
64
 
65
+ function collectTiledPointPositions(objects: any): Record<string, { x: number; y: number }> {
66
+ if (!Array.isArray(objects)) {
67
+ return {};
68
+ }
69
+
70
+ const positions: Record<string, { x: number; y: number }> = {};
71
+
72
+ for (const obj of objects) {
73
+ if (!obj?.point || typeof obj.x !== "number" || typeof obj.y !== "number") {
74
+ continue;
75
+ }
76
+
77
+ if (typeof obj.name === "string" && obj.name.length > 0) {
78
+ positions[obj.name] = { x: obj.x, y: obj.y };
79
+ }
80
+
81
+ if (
82
+ !positions[START_POSITION_NAME] &&
83
+ (obj.class === START_POSITION_NAME || obj.type === START_POSITION_NAME)
84
+ ) {
85
+ positions[START_POSITION_NAME] = { x: obj.x, y: obj.y };
86
+ }
87
+ }
88
+
89
+ return positions;
90
+ }
91
+
92
+ function mergeTiledPositions(existingPositions: any, tiledPositions: Record<string, { x: number; y: number }>) {
93
+ return {
94
+ ...(existingPositions && typeof existingPositions === "object" ? existingPositions : {}),
95
+ ...tiledPositions,
96
+ };
97
+ }
98
+
99
+ function getEventName(eventEntry: any): string | undefined {
100
+ const event = eventEntry?.event ?? eventEntry;
101
+
102
+ if (typeof event === "function") {
103
+ const staticEventName = (event as any)._name;
104
+ const prototypeEventName = (event as any).prototype?._name;
105
+ const staticName = (event as any).name;
106
+ const prototypeName = (event as any).prototype?.name;
107
+ if (typeof prototypeEventName === "string") {
108
+ return prototypeEventName;
109
+ }
110
+ if (typeof staticEventName === "string") {
111
+ return staticEventName;
112
+ }
113
+ if (typeof prototypeName === "string") {
114
+ return prototypeName;
115
+ }
116
+ if (typeof staticName === "string") {
117
+ return staticName;
118
+ }
119
+ }
120
+
121
+ if (typeof event?.name === "string") {
122
+ return event.name;
123
+ }
124
+
125
+ return undefined;
126
+ }
127
+
57
128
  function collectBlockedTileHitboxes(tiledMap: MapClass): RectHitbox[] {
58
129
  const hitboxes: RectHitbox[] = [];
59
130
  const mapWidth = tiledMap.width;
File without changes
File without changes
File without changes
File without changes