@rpgjs/server 5.0.0-alpha.10 → 5.0.0-alpha.12

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/dist/index.js CHANGED
@@ -6095,6 +6095,19 @@ function computed$2(computeFunction, disposableFn) {
6095
6095
  return fn;
6096
6096
  }
6097
6097
  __name$5(computed$2, "computed");
6098
+ function untracked(fn) {
6099
+ const prevDepTracker = reactiveStore$2.currentDependencyTracker;
6100
+ const prevSubTracker = reactiveStore$2.currentSubscriptionsTracker;
6101
+ reactiveStore$2.currentDependencyTracker = null;
6102
+ reactiveStore$2.currentSubscriptionsTracker = null;
6103
+ try {
6104
+ return fn();
6105
+ } finally {
6106
+ reactiveStore$2.currentDependencyTracker = prevDepTracker;
6107
+ reactiveStore$2.currentSubscriptionsTracker = prevSubTracker;
6108
+ }
6109
+ }
6110
+ __name$5(untracked, "untracked");
6098
6111
 
6099
6112
  // src/effect.ts
6100
6113
  function effect$2(fn) {
@@ -6443,6 +6456,8 @@ function loadValue$1(rootInstance, parts, value) {
6443
6456
  Reflect.deleteProperty(current, part);
6444
6457
  } else if (current[part]?._subject) {
6445
6458
  current[part].set(value);
6459
+ } else if (isSignal$2(current) && Array.isArray(current()) && !isNaN(Number(part))) {
6460
+ current()[Number(part)] = value;
6446
6461
  } else {
6447
6462
  current[part] = value;
6448
6463
  }
@@ -7404,6 +7419,101 @@ var Server = class {
7404
7419
  instance.$broadcast = (obj) => {
7405
7420
  return this.broadcast(obj, instance);
7406
7421
  };
7422
+ instance.$sessionTransfer = async (userOrPublicId, targetRoomId) => {
7423
+ let user;
7424
+ let publicId = null;
7425
+ const signal2 = this.getUsersProperty(instance);
7426
+ if (!signal2) {
7427
+ console.error("[sessionTransfer] `users` property not defined in the room.");
7428
+ return null;
7429
+ }
7430
+ if (typeof userOrPublicId === "string") {
7431
+ publicId = userOrPublicId;
7432
+ user = signal2()[publicId];
7433
+ if (!user) {
7434
+ console.error(`[sessionTransfer] User with publicId ${publicId} not found.`);
7435
+ return null;
7436
+ }
7437
+ } else {
7438
+ user = userOrPublicId;
7439
+ const users = signal2();
7440
+ for (const [id2, u] of Object.entries(users)) {
7441
+ if (u === user) {
7442
+ publicId = id2;
7443
+ break;
7444
+ }
7445
+ }
7446
+ if (!publicId && user && typeof user === "object") {
7447
+ for (const [id2, u] of Object.entries(users)) {
7448
+ if (u && typeof u === "object") {
7449
+ if (u.constructor === user.constructor) {
7450
+ publicId = id2;
7451
+ break;
7452
+ }
7453
+ }
7454
+ }
7455
+ }
7456
+ if (!publicId) {
7457
+ console.error("[sessionTransfer] User not found in users collection.", {
7458
+ userType: user?.constructor?.name,
7459
+ userKeys: user ? Object.keys(user) : "null",
7460
+ usersCount: Object.keys(users).length,
7461
+ userIds: Object.keys(users)
7462
+ });
7463
+ return null;
7464
+ }
7465
+ }
7466
+ const sessions = await this.room.storage.list();
7467
+ let userSession = null;
7468
+ let privateId = null;
7469
+ for (const [key, session] of sessions) {
7470
+ if (key.startsWith("session:") && session.publicId === publicId) {
7471
+ userSession = session;
7472
+ privateId = key.replace("session:", "");
7473
+ break;
7474
+ }
7475
+ }
7476
+ if (!userSession || !privateId) {
7477
+ console.error(`[sessionTransfer] Session for publicId ${publicId} not found.`);
7478
+ return null;
7479
+ }
7480
+ const usersPropName = this.getUsersPropName(instance);
7481
+ if (!usersPropName) {
7482
+ console.error("[sessionTransfer] `users` property not defined in the room.");
7483
+ return null;
7484
+ }
7485
+ const userSnapshot = createStatesSnapshot$1(user);
7486
+ const transferData = {
7487
+ privateId,
7488
+ userSnapshot,
7489
+ sessionState: userSession.state,
7490
+ publicId
7491
+ };
7492
+ try {
7493
+ const targetRoomParty = this.room.context.parties.main.get(targetRoomId);
7494
+ const response2 = await targetRoomParty.fetch("/session-transfer", {
7495
+ method: "POST",
7496
+ body: JSON.stringify(transferData),
7497
+ headers: {
7498
+ "Content-Type": "application/json"
7499
+ }
7500
+ });
7501
+ if (!response2.ok) {
7502
+ throw new Error(`Transfer request failed: ${await response2.text()}`);
7503
+ }
7504
+ const { transferToken } = await response2.json();
7505
+ await this.deleteSession(privateId);
7506
+ await this.room.storage.delete(`${usersPropName}.${publicId}`);
7507
+ const currentUsers = signal2();
7508
+ if (currentUsers[publicId]) {
7509
+ delete currentUsers[publicId];
7510
+ }
7511
+ return transferToken;
7512
+ } catch (error) {
7513
+ console.error(`[sessionTransfer] Failed to transfer session to room ${targetRoomId}:`, error);
7514
+ return null;
7515
+ }
7516
+ };
7407
7517
  const syncCb = /* @__PURE__ */ __name$3((values) => {
7408
7518
  if (options.getMemoryAll) {
7409
7519
  buildObject(values, instance.$memoryAll);
@@ -7594,29 +7704,46 @@ var Server = class {
7594
7704
  });
7595
7705
  const roomGuards = subRoom.constructor["_roomGuards"] || [];
7596
7706
  for (const guard of roomGuards) {
7597
- const isAuthorized = await guard(conn, ctx);
7707
+ const isAuthorized = await guard(conn, ctx, this.room);
7598
7708
  if (!isAuthorized) {
7599
7709
  conn.close();
7600
7710
  return;
7601
7711
  }
7602
7712
  }
7713
+ let transferToken = null;
7714
+ if (ctx.request?.url) {
7715
+ const url = new URL(ctx.request.url);
7716
+ transferToken = url.searchParams.get("transferToken");
7717
+ }
7718
+ let transferData = null;
7719
+ if (transferToken) {
7720
+ transferData = await this.room.storage.get(`transfer:${transferToken}`);
7721
+ if (transferData) {
7722
+ await this.room.storage.delete(`transfer:${transferToken}`);
7723
+ }
7724
+ }
7603
7725
  const existingSession = await this.getSession(conn.id);
7604
- const publicId = existingSession?.publicId || generateShortUUID$2();
7726
+ const publicId = existingSession?.publicId || transferData?.publicId || generateShortUUID$2();
7605
7727
  let user = null;
7606
7728
  const signal2 = this.getUsersProperty(subRoom);
7607
7729
  const usersPropName = this.getUsersPropName(subRoom);
7608
7730
  if (signal2) {
7609
7731
  const { classType } = signal2.options;
7610
7732
  if (!existingSession?.publicId) {
7611
- user = isClass(classType) ? new classType() : classType(conn, ctx);
7612
- signal2()[publicId] = user;
7613
- const snapshot = createStatesSnapshot$1(user);
7614
- this.room.storage.put(`${usersPropName}.${publicId}`, snapshot);
7733
+ if (transferData?.restored && signal2()[publicId]) {
7734
+ user = signal2()[publicId];
7735
+ } else {
7736
+ user = isClass(classType) ? new classType() : classType(conn, ctx);
7737
+ signal2()[publicId] = user;
7738
+ const snapshot = createStatesSnapshot$1(user);
7739
+ this.room.storage.put(`${usersPropName}.${publicId}`, snapshot);
7740
+ }
7615
7741
  } else {
7616
7742
  user = signal2()[existingSession.publicId];
7617
7743
  }
7618
7744
  if (!existingSession) {
7619
- await this.saveSession(conn.id, {
7745
+ const sessionPrivateId = transferData?.privateId || conn.id;
7746
+ await this.saveSession(sessionPrivateId, {
7620
7747
  publicId
7621
7748
  });
7622
7749
  } else {
@@ -7904,7 +8031,7 @@ var Server = class {
7904
8031
  * @method onClose
7905
8032
  * @async
7906
8033
  * @param {Party.Connection} conn - The connection object of the disconnecting user.
7907
- * @description Handles user disconnection, removing them from the room and triggering the onLeave event.
8034
+ * @description Handles user disconnection, removing them from the room and triggering the onLeave event..
7908
8035
  * @returns {Promise<void>}
7909
8036
  *
7910
8037
  * @example
@@ -7970,6 +8097,58 @@ var Server = class {
7970
8097
  return this.handleDirectRequest(req, res);
7971
8098
  }
7972
8099
  /**
8100
+ * @method handleSessionRestore
8101
+ * @private
8102
+ * @async
8103
+ * @param {Party.Request} req - The HTTP request for session restore
8104
+ * @param {ServerResponse} res - The response object
8105
+ * @description Handles session restoration from transfer data, creates session from privateId
8106
+ * @returns {Promise<Response>} The response to return to the client
8107
+ */
8108
+ async handleSessionRestore(req, res) {
8109
+ try {
8110
+ const transferData = await req.json();
8111
+ const { privateId, userSnapshot, sessionState, publicId } = transferData;
8112
+ if (!privateId || !publicId) {
8113
+ return res.badRequest("Missing privateId or publicId in transfer data");
8114
+ }
8115
+ const subRoom = await this.getSubRoom();
8116
+ if (!subRoom) {
8117
+ return res.serverError("Room not available");
8118
+ }
8119
+ await this.saveSession(privateId, {
8120
+ publicId,
8121
+ state: sessionState,
8122
+ created: Date.now(),
8123
+ connected: false
8124
+ // Will be set to true when user connects
8125
+ });
8126
+ if (userSnapshot) {
8127
+ const signal2 = this.getUsersProperty(subRoom);
8128
+ const usersPropName = this.getUsersPropName(subRoom);
8129
+ if (signal2 && usersPropName) {
8130
+ const { classType } = signal2.options;
8131
+ const user = isClass(classType) ? new classType() : classType();
8132
+ load$1(user, userSnapshot, true);
8133
+ signal2()[publicId] = user;
8134
+ await this.room.storage.put(`${usersPropName}.${publicId}`, userSnapshot);
8135
+ }
8136
+ }
8137
+ const transferToken = generateShortUUID$2();
8138
+ await this.room.storage.put(`transfer:${transferToken}`, {
8139
+ privateId,
8140
+ publicId,
8141
+ restored: true
8142
+ });
8143
+ return res.success({
8144
+ transferToken
8145
+ });
8146
+ } catch (error) {
8147
+ console.error("Error restoring session:", error);
8148
+ return res.serverError("Failed to restore session");
8149
+ }
8150
+ }
8151
+ /**
7973
8152
  * @method handleDirectRequest
7974
8153
  * @private
7975
8154
  * @async
@@ -7982,6 +8161,10 @@ var Server = class {
7982
8161
  if (!subRoom) {
7983
8162
  return res.notFound();
7984
8163
  }
8164
+ const url = new URL(req.url);
8165
+ if (url.pathname.endsWith("/session-transfer") && req.method === "POST") {
8166
+ return this.handleSessionRestore(req, res);
8167
+ }
7985
8168
  const response2 = await this.tryMatchRequestHandler(req, res, subRoom);
7986
8169
  if (response2) {
7987
8170
  return response2;
@@ -8080,7 +8263,7 @@ var Server = class {
8080
8263
  */
8081
8264
  pathMatches(requestPath, handlerPath) {
8082
8265
  const pathRegexString = handlerPath.replace(/\//g, "\\/").replace(/:([^\/]+)/g, "([^/]+)");
8083
- const pathRegex = new RegExp(`^${pathRegexString}$`);
8266
+ const pathRegex = new RegExp(`^${pathRegexString}`);
8084
8267
  return pathRegex.test(requestPath);
8085
8268
  }
8086
8269
  /**
@@ -8100,7 +8283,7 @@ var Server = class {
8100
8283
  }
8101
8284
  });
8102
8285
  const pathRegexString = handlerPath.replace(/\//g, "\\/").replace(/:([^\/]+)/g, "([^/]+)");
8103
- const pathRegex = new RegExp(`^${pathRegexString}$`);
8286
+ const pathRegex = new RegExp(`^${pathRegexString}`);
8104
8287
  const matches = requestPath.match(pathRegex);
8105
8288
  if (matches && matches.length > 1) {
8106
8289
  for (let i = 0; i < paramNames.length; i++) {
@@ -9208,6 +9391,30 @@ WorldRoom = _ts_decorate([
9208
9391
  ])
9209
9392
  ], WorldRoom);
9210
9393
 
9394
+ // src/session.guard.ts
9395
+ function createRequireSessionGuard(storage) {
9396
+ return async (sender, value) => {
9397
+ if (!sender || !sender.id) {
9398
+ return false;
9399
+ }
9400
+ try {
9401
+ const session = await storage.get(`session:${sender.id}`);
9402
+ if (!session) {
9403
+ return false;
9404
+ }
9405
+ const typedSession = session;
9406
+ if (!typedSession.publicId) {
9407
+ return false;
9408
+ }
9409
+ return true;
9410
+ } catch (error) {
9411
+ console.error("Error checking session in requireSession guard:", error);
9412
+ return false;
9413
+ }
9414
+ };
9415
+ }
9416
+ __name$3(createRequireSessionGuard, "createRequireSessionGuard");
9417
+
9211
9418
  function _mergeNamespaces(n, m) {
9212
9419
  for (var i = 0; i < m.length; i++) {
9213
9420
  const e = m[i];
@@ -11477,6 +11684,8 @@ var Direction = /* @__PURE__ */ ((Direction2) => {
11477
11684
  })(Direction || {});
11478
11685
  class RpgCommonPlayer {
11479
11686
  constructor() {
11687
+ this.name = signal("");
11688
+ this.type = signal("");
11480
11689
  this.x = signal(0);
11481
11690
  this.y = signal(0);
11482
11691
  this.z = signal(0);
@@ -11491,8 +11700,8 @@ class RpgCommonPlayer {
11491
11700
  });
11492
11701
  this._gold = signal(0);
11493
11702
  this.animationName = signal("stand");
11494
- this._hp = signal(0);
11495
- this._sp = signal(0);
11703
+ this.hpSignal = signal(0);
11704
+ this.spSignal = signal(0);
11496
11705
  this._exp = signal(0);
11497
11706
  this._level = signal(0);
11498
11707
  this._class = signal({});
@@ -11510,14 +11719,14 @@ class RpgCommonPlayer {
11510
11719
  }
11511
11720
  /**
11512
11721
  * Change the player's facing direction
11513
- *
11722
+ *
11514
11723
  * Updates the direction the player is facing, which affects animations
11515
11724
  * and directional abilities. This should be called when the player
11516
11725
  * intends to move in a specific direction, not when they are pushed
11517
11726
  * by physics or sliding.
11518
- *
11727
+ *
11519
11728
  * @param direction - The new direction to face
11520
- *
11729
+ *
11521
11730
  * @example
11522
11731
  * ```ts
11523
11732
  * // Player presses right arrow key
@@ -11529,9 +11738,9 @@ class RpgCommonPlayer {
11529
11738
  }
11530
11739
  /**
11531
11740
  * Get the current facing direction
11532
- *
11741
+ *
11533
11742
  * @returns Current direction the player is facing
11534
- *
11743
+ *
11535
11744
  * @example
11536
11745
  * ```ts
11537
11746
  * const currentDirection = player.getDirection();
@@ -11545,18 +11754,18 @@ class RpgCommonPlayer {
11545
11754
  }
11546
11755
  /**
11547
11756
  * Set the intended movement direction
11548
- *
11757
+ *
11549
11758
  * This should be called when the player intends to move in a direction,
11550
11759
  * typically from input handling. This direction will be used to update
11551
11760
  * the player's facing direction regardless of physics interactions.
11552
- *
11761
+ *
11553
11762
  * @param direction - The intended movement direction, or null if not moving
11554
- *
11763
+ *
11555
11764
  * @example
11556
11765
  * ```ts
11557
11766
  * // Player presses down arrow key
11558
11767
  * player.setIntendedDirection(Direction.Down);
11559
- *
11768
+ *
11560
11769
  * // Player releases all movement keys
11561
11770
  * player.setIntendedDirection(null);
11562
11771
  * ```
@@ -11569,9 +11778,9 @@ class RpgCommonPlayer {
11569
11778
  }
11570
11779
  /**
11571
11780
  * Get the intended movement direction
11572
- *
11781
+ *
11573
11782
  * @returns The direction the player intends to move, or null if not moving
11574
- *
11783
+ *
11575
11784
  * @example
11576
11785
  * ```ts
11577
11786
  * const intended = player.getIntendedDirection();
@@ -11585,14 +11794,14 @@ class RpgCommonPlayer {
11585
11794
  }
11586
11795
  /**
11587
11796
  * Apply physics body position to player coordinates
11588
- *
11797
+ *
11589
11798
  * Synchronizes the player's position with their physics body after
11590
11799
  * physics calculations. This method no longer automatically changes
11591
11800
  * the player's direction based on position changes, as direction
11592
11801
  * should be controlled by intended movement instead.
11593
- *
11802
+ *
11594
11803
  * @param body - The Matter.js physics body
11595
- *
11804
+ *
11596
11805
  * @example
11597
11806
  * ```ts
11598
11807
  * // Called automatically by physics system
@@ -11610,6 +11819,43 @@ class RpgCommonPlayer {
11610
11819
  this.y.set(topLeftY);
11611
11820
  }
11612
11821
  }
11822
+ /**
11823
+ * Display a spritesheet animation on the player
11824
+ *
11825
+ * This method displays a temporary visual animation using a spritesheet.
11826
+ * The animation can either be displayed as an overlay on the player or replace
11827
+ * the player's current graphic temporarily. This is useful for spell effects,
11828
+ * transformations, or other visual feedback that uses predefined spritesheets.
11829
+ *
11830
+ * @param graphic - The ID of the spritesheet to use for the animation
11831
+ * @param animationName - The name of the animation within the spritesheet (default: 'default')
11832
+ * @param replaceGraphic - Whether to replace the player's sprite with the animation (default: false)
11833
+ *
11834
+ * @example
11835
+ * ```ts
11836
+ * // Show explosion animation as overlay on player
11837
+ * player.showAnimation("explosion");
11838
+ *
11839
+ * // Show specific spell effect animation
11840
+ * player.showAnimation("spell-effects", "fireball");
11841
+ *
11842
+ * // Transform player graphic temporarily with animation
11843
+ * player.showAnimation("transformation", "werewolf", true);
11844
+ *
11845
+ * // Show healing effect on player
11846
+ * player.showAnimation("healing-effects", "holy-light");
11847
+ * ```
11848
+ */
11849
+ showAnimation(graphic, animationName = "default", replaceGraphic = false) {
11850
+ if (replaceGraphic) {
11851
+ this.setAnimation(animationName, 1);
11852
+ return;
11853
+ }
11854
+ this.showComponentAnimation("animation", {
11855
+ graphic,
11856
+ animationName
11857
+ });
11858
+ }
11613
11859
  _showAnimation(params) {
11614
11860
  const { graphic, animationName, loop } = params;
11615
11861
  if (graphic) {
@@ -11622,20 +11868,20 @@ class RpgCommonPlayer {
11622
11868
  }
11623
11869
  /**
11624
11870
  * Create a temporary and moving hitbox relative to the player's position
11625
- *
11871
+ *
11626
11872
  * Creates a temporary hitbox that moves through multiple positions sequentially,
11627
11873
  * with all coordinates being relative to the player's current position.
11628
11874
  * For example, you can use it for player attacks, spells, or area effects
11629
11875
  * that should follow the player's position.
11630
- *
11876
+ *
11631
11877
  * The method creates a zone sensor that moves through the specified hitbox positions
11632
11878
  * at the given speed, detecting collisions with other players and events at each step.
11633
- *
11879
+ *
11634
11880
  * @param hitboxes - Array of hitbox positions relative to player position
11635
11881
  * @param options - Configuration options for the movement
11636
11882
  * @param map - Reference to the map instance for physics access
11637
11883
  * @returns Observable that emits arrays of hit entities and completes when movement is finished
11638
- *
11884
+ *
11639
11885
  * @example
11640
11886
  * ```ts
11641
11887
  * // Create a forward attack relative to player position
@@ -11665,10 +11911,22 @@ class RpgCommonPlayer {
11665
11911
  getCurrentMap() {
11666
11912
  return this["map"];
11667
11913
  }
11914
+ get hp() {
11915
+ return this.hpSignal();
11916
+ }
11917
+ get sp() {
11918
+ return this.spSignal();
11919
+ }
11668
11920
  }
11669
11921
  __decorateClass$3([
11670
11922
  id()
11671
11923
  ], RpgCommonPlayer.prototype, "id");
11924
+ __decorateClass$3([
11925
+ sync()
11926
+ ], RpgCommonPlayer.prototype, "name");
11927
+ __decorateClass$3([
11928
+ sync()
11929
+ ], RpgCommonPlayer.prototype, "type");
11672
11930
  __decorateClass$3([
11673
11931
  sync()
11674
11932
  ], RpgCommonPlayer.prototype, "x");
@@ -11704,10 +11962,10 @@ __decorateClass$3([
11704
11962
  ], RpgCommonPlayer.prototype, "animationName");
11705
11963
  __decorateClass$3([
11706
11964
  sync()
11707
- ], RpgCommonPlayer.prototype, "_hp");
11965
+ ], RpgCommonPlayer.prototype, "hpSignal");
11708
11966
  __decorateClass$3([
11709
11967
  sync()
11710
- ], RpgCommonPlayer.prototype, "_sp");
11968
+ ], RpgCommonPlayer.prototype, "spSignal");
11711
11969
  __decorateClass$3([
11712
11970
  sync()
11713
11971
  ], RpgCommonPlayer.prototype, "_exp");
@@ -23281,32 +23539,61 @@ class RpgCommonPhysic {
23281
23539
  return dy > 0 ? Direction.Down : Direction.Up;
23282
23540
  }
23283
23541
  }
23284
- /**
23285
- * Add a static hitbox (immovable objects like walls, obstacles)
23286
- *
23287
- * @param id - Unique identifier for the hitbox
23288
- * @param x - X position
23289
- * @param y - Y position
23290
- * @param width - Width of hitbox
23291
- * @param height - Height of hitbox
23292
- * @returns The id of the created hitbox
23293
- *
23294
- * @example
23295
- * ```ts
23296
- * // Add a wall
23297
- * physic.addStaticHitbox('wall1', 100, 50, 32, 128);
23298
- * ```
23299
- */
23300
- addStaticHitbox(id, x, y, width, height) {
23542
+ addStaticHitbox(id, xOrPoints, y, width, height) {
23301
23543
  if (this.hitboxes.has(id)) {
23302
23544
  throw new Error(`Hitbox with id ${id} already exists`);
23303
23545
  }
23304
- const centerX = x + width / 2;
23305
- const centerY = y + height / 2;
23306
- const body = matterExports.Bodies.rectangle(centerX, centerY, width, height, {
23307
- isStatic: true,
23308
- label: id
23309
- });
23546
+ let body;
23547
+ if (Array.isArray(xOrPoints)) {
23548
+ const points = xOrPoints;
23549
+ if (points.length < 3) {
23550
+ throw new Error(`Polygon must have at least 3 points, got ${points.length}`);
23551
+ }
23552
+ for (let i = 0; i < points.length; i++) {
23553
+ const point = points[i];
23554
+ if (!Array.isArray(point) || point.length !== 2 || typeof point[0] !== "number" || typeof point[1] !== "number") {
23555
+ throw new Error(`Invalid point at index ${i}: ${JSON.stringify(point)}. Expected [x, y] with numbers.`);
23556
+ }
23557
+ }
23558
+ let centerX = 0, centerY = 0;
23559
+ for (const point of points) {
23560
+ centerX += point[0];
23561
+ centerY += point[1];
23562
+ }
23563
+ centerX /= points.length;
23564
+ centerY /= points.length;
23565
+ const vertices = points.map((point) => ({
23566
+ x: point[0] - centerX,
23567
+ y: point[1] - centerY
23568
+ }));
23569
+ try {
23570
+ body = matterExports.Bodies.fromVertices(0, 0, [vertices], {
23571
+ isStatic: true,
23572
+ label: id
23573
+ });
23574
+ if (!body) {
23575
+ throw new Error(`Matter.Bodies.fromVertices returned null/undefined`);
23576
+ }
23577
+ if (!body.vertices || body.vertices.length === 0) {
23578
+ throw new Error(`Created body has no vertices`);
23579
+ }
23580
+ matterExports.Body.setPosition(body, { x: centerX, y: centerY });
23581
+ } catch (error) {
23582
+ const errorMessage = error instanceof Error ? error.message : String(error);
23583
+ throw new Error(`Failed to create polygon body from points ${JSON.stringify(points)}: ${errorMessage}`);
23584
+ }
23585
+ } else {
23586
+ const x = xOrPoints;
23587
+ if (y === void 0 || width === void 0 || height === void 0) {
23588
+ throw new Error("Rectangle hitbox requires x, y, width, and height parameters");
23589
+ }
23590
+ const centerX = x + width / 2;
23591
+ const centerY = y + height / 2;
23592
+ body = matterExports.Bodies.rectangle(centerX, centerY, width, height, {
23593
+ isStatic: true,
23594
+ label: id
23595
+ });
23596
+ }
23310
23597
  matterExports.Composite.add(this.world, body);
23311
23598
  this.hitboxes.set(id, {
23312
23599
  id,
@@ -23890,6 +24177,39 @@ class RpgCommonPhysic {
23890
24177
  getWorld() {
23891
24178
  return this.world;
23892
24179
  }
24180
+ /**
24181
+ * Get debug information about all hitboxes
24182
+ *
24183
+ * Useful for debugging collision issues
24184
+ *
24185
+ * @returns Array of hitbox debug information
24186
+ *
24187
+ * @example
24188
+ * ```ts
24189
+ * // Debug all hitboxes
24190
+ * const info = physic.getDebugInfo();
24191
+ * console.log('All hitboxes:', info);
24192
+ * ```
24193
+ */
24194
+ getDebugInfo() {
24195
+ const info = [];
24196
+ for (const [id, hitboxData] of this.hitboxes.entries()) {
24197
+ const body = hitboxData.body;
24198
+ info.push({
24199
+ id,
24200
+ type: hitboxData.type,
24201
+ position: { x: body.position.x, y: body.position.y },
24202
+ bounds: {
24203
+ min: { x: body.bounds.min.x, y: body.bounds.min.y },
24204
+ max: { x: body.bounds.max.x, y: body.bounds.max.y }
24205
+ },
24206
+ verticesCount: body.vertices.length,
24207
+ isPolygon: body.vertices.length > 4
24208
+ // Rectangles have 4 vertices
24209
+ });
24210
+ }
24211
+ return info;
24212
+ }
23893
24213
  /* ----------------------------------------------------------------------- */
23894
24214
  /* ZONES */
23895
24215
  /* ----------------------------------------------------------------------- */
@@ -25321,7 +25641,11 @@ class RpgCommonMap {
25321
25641
  this.physic.addStaticHitbox("map-height-top", 0, -100, this.data().width, gap);
25322
25642
  this.physic.addStaticHitbox("map-height-bottom", 0, this.data().height, this.data().width, gap);
25323
25643
  for (let staticHitbox of hitboxes) {
25324
- this.physic.addStaticHitbox(staticHitbox.id ?? generateShortUUID(), staticHitbox.x, staticHitbox.y, staticHitbox.width, staticHitbox.height);
25644
+ if ("x" in staticHitbox) {
25645
+ this.physic.addStaticHitbox(staticHitbox.id ?? generateShortUUID(), staticHitbox.x, staticHitbox.y, staticHitbox.width, staticHitbox.height);
25646
+ } else if ("points" in staticHitbox) {
25647
+ this.physic.addStaticHitbox(staticHitbox.id ?? generateShortUUID(), staticHitbox.points);
25648
+ }
25325
25649
  }
25326
25650
  this.events.observable.subscribe(({ value: event, type }) => {
25327
25651
  if (type == "add") {
@@ -25794,8 +26118,50 @@ function mergeConfig(baseConfig, config) {
25794
26118
  __name(mergeConfig, "mergeConfig");
25795
26119
 
25796
26120
  // src/provider.ts
26121
+ function getDeps(provider) {
26122
+ if (typeof provider === "function") {
26123
+ return provider.deps ?? [];
26124
+ }
26125
+ return provider.deps ?? [];
26126
+ }
26127
+ __name(getDeps, "getDeps");
26128
+ function sortProviders(providers) {
26129
+ const tokenName = /* @__PURE__ */ __name((t) => typeof t === "function" ? t.name : t, "tokenName");
26130
+ const map = /* @__PURE__ */ new Map();
26131
+ for (const p of providers) {
26132
+ const token = tokenName(typeof p === "function" ? p : p.provide);
26133
+ map.set(token, p);
26134
+ }
26135
+ const result = [];
26136
+ const visited = /* @__PURE__ */ new Set();
26137
+ const stack = /* @__PURE__ */ new Set();
26138
+ const visit = /* @__PURE__ */ __name((token) => {
26139
+ const name = tokenName(token);
26140
+ if (visited.has(name)) return;
26141
+ if (stack.has(name)) {
26142
+ throw new Error(`Circular dependency detected for provider ${name}`);
26143
+ }
26144
+ stack.add(name);
26145
+ const provider = map.get(name);
26146
+ if (provider) {
26147
+ for (const dep of getDeps(provider)) {
26148
+ visit(dep);
26149
+ }
26150
+ visited.add(name);
26151
+ result.push(provider);
26152
+ }
26153
+ stack.delete(name);
26154
+ }, "visit");
26155
+ for (const p of providers) {
26156
+ const token = typeof p === "function" ? p : p.provide;
26157
+ visit(token);
26158
+ }
26159
+ return result;
26160
+ }
26161
+ __name(sortProviders, "sortProviders");
25797
26162
  async function injector(context, providers) {
25798
26163
  providers = providers.flat();
26164
+ providers = sortProviders(providers);
25799
26165
  for (const provider of providers) {
25800
26166
  let token;
25801
26167
  let instance;
@@ -26856,6 +27222,12 @@ function WithMoveManager(Base) {
26856
27222
  };
26857
27223
  }
26858
27224
 
27225
+ var DialogPosition = /* @__PURE__ */ ((DialogPosition2) => {
27226
+ DialogPosition2["Top"] = "top";
27227
+ DialogPosition2["Bottom"] = "bottom";
27228
+ DialogPosition2["Middle"] = "middle";
27229
+ return DialogPosition2;
27230
+ })(DialogPosition || {});
26859
27231
  class DialogGui extends Gui {
26860
27232
  constructor(player) {
26861
27233
  super(PrebuiltGui.Dialog, player);
@@ -26881,7 +27253,8 @@ class DialogGui extends Gui {
26881
27253
  // remove value property. It is not useful to know this on the client side.
26882
27254
  choices: options.choices.map((choice) => ({
26883
27255
  text: choice.text
26884
- }))
27256
+ })),
27257
+ face: options.face
26885
27258
  };
26886
27259
  return super.open({
26887
27260
  message,
@@ -27380,8 +27753,63 @@ function WithParameterManager(Base) {
27380
27753
  return class extends Base {
27381
27754
  constructor() {
27382
27755
  super(...arguments);
27383
- this._paramsModifier = {};
27384
- this._parameters = /* @__PURE__ */ new Map();
27756
+ /**
27757
+ * Signal for parameter modifiers - allows reactive updates when modifiers change
27758
+ *
27759
+ * This signal tracks temporary parameter modifications from equipment, states, etc.
27760
+ * When updated, it automatically triggers recalculation of all computed parameters.
27761
+ *
27762
+ * @example
27763
+ * ```ts
27764
+ * // Set modifier that adds 100 to MaxHP
27765
+ * player.paramsModifier = {
27766
+ * [MAXHP]: { value: 100 }
27767
+ * };
27768
+ *
27769
+ * // Parameters automatically recalculate
27770
+ * console.log(player.param[MAXHP]); // Updated value
27771
+ * ```
27772
+ */
27773
+ this._paramsModifierSignal = signal$2({});
27774
+ /**
27775
+ * Signal for base parameters configuration
27776
+ *
27777
+ * Stores the start and end values for each parameter's level curve.
27778
+ * Changes to this signal trigger recalculation of all parameter values.
27779
+ */
27780
+ this._parametersSignal = signal$2({});
27781
+ /**
27782
+ * Computed signal for all parameter values
27783
+ *
27784
+ * Automatically recalculates all parameter values when level or modifiers change.
27785
+ * This provides reactive parameter updates throughout the system.
27786
+ *
27787
+ * @example
27788
+ * ```ts
27789
+ * // Access reactive parameters
27790
+ * const maxHp = player.param[MAXHP]; // Always current value
27791
+ *
27792
+ * // Parameters update automatically when level changes
27793
+ * player.level = 10;
27794
+ * console.log(player.param[MAXHP]); // New calculated value
27795
+ * ```
27796
+ */
27797
+ this._param = type$1(computed$2(() => {
27798
+ const obj = {};
27799
+ const parameters = this._parametersSignal();
27800
+ const level = this._level();
27801
+ for (const [name, paramConfig] of Object.entries(parameters)) {
27802
+ let curveVal = Math.floor((paramConfig.end - paramConfig.start) * ((level - 1) / (this.finalLevel - this.initialLevel))) + paramConfig.start;
27803
+ const allModifiers = this._getAggregatedModifiers();
27804
+ const modifier = allModifiers[name];
27805
+ if (modifier) {
27806
+ if (modifier.rate) curveVal *= modifier.rate;
27807
+ if (modifier.value) curveVal += modifier.value;
27808
+ }
27809
+ obj[name] = curveVal;
27810
+ }
27811
+ return obj;
27812
+ }), "_param", {}, this);
27385
27813
  /**
27386
27814
  * ```ts
27387
27815
  * player.initialLevel = 5
@@ -27405,6 +27833,52 @@ function WithParameterManager(Base) {
27405
27833
  * */
27406
27834
  this.finalLevel = 99;
27407
27835
  }
27836
+ /**
27837
+ * Aggregates parameter modifiers from all sources (direct modifiers, states, equipment)
27838
+ *
27839
+ * This method combines modifiers from multiple sources and calculates the final
27840
+ * modifier values for each parameter. It handles both value and rate modifiers.
27841
+ *
27842
+ * @returns Aggregated parameter modifiers
27843
+ *
27844
+ * @example
27845
+ * ```ts
27846
+ * // Internal usage - gets modifiers from all sources
27847
+ * const modifiers = this._getAggregatedModifiers();
27848
+ * console.log(modifiers[MAXHP]); // { value: 100, rate: 1.2 }
27849
+ * ```
27850
+ */
27851
+ _getAggregatedModifiers() {
27852
+ const params = {};
27853
+ const paramsAvg = {};
27854
+ const changeParam = (paramsModifier) => {
27855
+ for (let key in paramsModifier) {
27856
+ const { rate, value } = paramsModifier[key];
27857
+ if (!params[key]) params[key] = { rate: 0, value: 0 };
27858
+ if (!paramsAvg[key]) paramsAvg[key] = 0;
27859
+ if (value) params[key].value += value;
27860
+ if (rate !== void 0) params[key].rate += rate;
27861
+ paramsAvg[key]++;
27862
+ }
27863
+ };
27864
+ const getModifier = (prop) => {
27865
+ if (!isString(prop)) {
27866
+ changeParam(prop);
27867
+ return;
27868
+ }
27869
+ for (let el of this[prop]()) {
27870
+ if (!el.paramsModifier) continue;
27871
+ changeParam(el.paramsModifier);
27872
+ }
27873
+ };
27874
+ getModifier(this._paramsModifierSignal());
27875
+ getModifier("states");
27876
+ getModifier("equipments");
27877
+ for (let key in params) {
27878
+ params[key].rate /= paramsAvg[key];
27879
+ }
27880
+ return params;
27881
+ }
27408
27882
  /**
27409
27883
  * Changes the health points
27410
27884
  * - Cannot exceed the MaxHP parameter
@@ -27426,10 +27900,7 @@ function WithParameterManager(Base) {
27426
27900
  this["execMethod"]("onDead");
27427
27901
  val = 0;
27428
27902
  }
27429
- this._hp.set(val);
27430
- }
27431
- get hp() {
27432
- return this._hp();
27903
+ this.hpSignal.set(val);
27433
27904
  }
27434
27905
  /**
27435
27906
  * Changes the skill points
@@ -27448,10 +27919,7 @@ function WithParameterManager(Base) {
27448
27919
  if (val > this.param[MAXSP]) {
27449
27920
  val = this.param[MAXSP];
27450
27921
  }
27451
- this._sp.set(val);
27452
- }
27453
- get sp() {
27454
- return this._sp();
27922
+ this.spSignal.set(val);
27455
27923
  }
27456
27924
  /**
27457
27925
  * Changing the player's experience.
@@ -27557,42 +28025,10 @@ function WithParameterManager(Base) {
27557
28025
  * @memberof ParameterManager
27558
28026
  * */
27559
28027
  get param() {
27560
- const obj = {};
27561
- this._parameters.forEach((val, name) => {
27562
- obj[name] = this.getParamValue(name);
27563
- });
27564
- return obj;
28028
+ return this._param();
27565
28029
  }
27566
28030
  get paramsModifier() {
27567
- const params = {};
27568
- const paramsAvg = {};
27569
- const changeParam = (paramsModifier) => {
27570
- for (let key in paramsModifier) {
27571
- const { rate, value } = paramsModifier[key];
27572
- if (!params[key]) params[key] = { rate: 0, value: 0 };
27573
- if (!paramsAvg[key]) paramsAvg[key] = 0;
27574
- if (value) params[key].value += value;
27575
- if (rate !== void 0) params[key].rate += rate;
27576
- paramsAvg[key]++;
27577
- }
27578
- };
27579
- const getModifier = (prop) => {
27580
- if (!isString(prop)) {
27581
- changeParam(prop);
27582
- return;
27583
- }
27584
- for (let el of this[prop]()) {
27585
- if (!el.paramsModifier) continue;
27586
- changeParam(el.paramsModifier);
27587
- }
27588
- };
27589
- getModifier(this._paramsModifier);
27590
- getModifier("states");
27591
- getModifier("equipments");
27592
- for (let key in params) {
27593
- params[key].rate /= paramsAvg[key];
27594
- }
27595
- return params;
28031
+ return this._paramsModifierSignal();
27596
28032
  }
27597
28033
  /**
27598
28034
  * Changes the values of some parameters
@@ -27652,13 +28088,13 @@ function WithParameterManager(Base) {
27652
28088
  * @memberof ParameterManager
27653
28089
  * */
27654
28090
  set paramsModifier(val) {
27655
- this._paramsModifier = val;
28091
+ this._paramsModifierSignal.set(val);
27656
28092
  }
27657
28093
  get parameters() {
27658
- return this._parameters;
28094
+ return this._parametersSignal();
27659
28095
  }
27660
28096
  set parameters(val) {
27661
- this._parameters = val;
28097
+ this._parametersSignal.set(val);
27662
28098
  }
27663
28099
  _expForLevel(level) {
27664
28100
  const {
@@ -27669,22 +28105,8 @@ function WithParameterManager(Base) {
27669
28105
  } = this.expCurve;
27670
28106
  return Math.round(basis * Math.pow(level - 1, 0.9 + accelerationA / 250) * level * (level + 1) / (6 + Math.pow(level, 2) / 50 / accelerationB) + (level - 1) * extra);
27671
28107
  }
27672
- getParam(name) {
27673
- const features = this._parameters.get(name);
27674
- if (!features) {
27675
- throw `Parameter ${name} not exists. Please use addParameter() before`;
27676
- }
27677
- return features;
27678
- }
27679
28108
  getParamValue(name) {
27680
- const features = this.getParam(name);
27681
- let curveVal = Math.floor((features.end - features.start) * ((this.level - 1) / (this.finalLevel - this.initialLevel))) + features.start;
27682
- const modifier = this.paramsModifier[name];
27683
- if (modifier) {
27684
- if (modifier.rate) curveVal *= modifier.rate;
27685
- if (modifier.value) curveVal += modifier.value;
27686
- }
27687
- return curveVal;
28109
+ return this.param[name];
27688
28110
  }
27689
28111
  /**
27690
28112
  * Give a new parameter. Give a start value and an end value.
@@ -27705,15 +28127,17 @@ function WithParameterManager(Base) {
27705
28127
  *
27706
28128
  * @title Add custom parameters
27707
28129
  * @method player.addParameter(name,curve)
27708
- * @param {name} name
27709
- * @param {object} curve Scheme of the object: { start: number, end: number }
28130
+ * @param {string} name - The name of the parameter
28131
+ * @param {object} curve - Scheme of the object: { start: number, end: number }
27710
28132
  * @returns {void}
27711
28133
  * @memberof ParameterManager
27712
28134
  * */
27713
28135
  addParameter(name, { start, end }) {
27714
- this._parameters.set(name, {
27715
- start,
27716
- end
28136
+ this._parametersSignal.mutate((parameters) => {
28137
+ parameters[name] = {
28138
+ start,
28139
+ end
28140
+ };
27717
28141
  });
27718
28142
  const maxHp = this.param[MAXHP];
27719
28143
  const maxSp = this.param[MAXSP];
@@ -27739,7 +28163,7 @@ function WithParameterManager(Base) {
27739
28163
  *
27740
28164
  * @title Recovery HP and/or SP
27741
28165
  * @method player.recovery(params)
27742
- * @param {object} params Scheme of the object: { hp: number, sp: number }. The values of the numbers must be in 0 and 1
28166
+ * @param {object} params - Scheme of the object: { hp: number, sp: number }. The values of the numbers must be in 0 and 1
27743
28167
  * @returns {void}
27744
28168
  * @memberof ParameterManager
27745
28169
  * */
@@ -29476,13 +29900,18 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29476
29900
  this.addParameter(AGI, AGI_CURVE);
29477
29901
  this.allRecovery();
29478
29902
  }
29903
+ _onInit() {
29904
+ this.hooks.callHooks("server-playerProps-load", this).subscribe();
29905
+ }
29906
+ get hooks() {
29907
+ return inject$1(this.context, ModulesToken);
29908
+ }
29479
29909
  async execMethod(method, methodData = [], target) {
29480
29910
  let ret;
29481
29911
  if (target) {
29482
29912
  ret = await target[method](...methodData);
29483
29913
  } else {
29484
- const hooks = inject$1(this.context, ModulesToken);
29485
- ret = await lastValueFrom(hooks.callHooks(`server-player-${method}`, target ?? this, ...methodData));
29914
+ ret = await lastValueFrom(this.hooks.callHooks(`server-player-${method}`, target ?? this, ...methodData));
29486
29915
  }
29487
29916
  this.syncChanges();
29488
29917
  return ret;
@@ -29504,6 +29933,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29504
29933
  * ```
29505
29934
  */
29506
29935
  async changeMap(mapId, positions) {
29936
+ this.getCurrentMap();
29507
29937
  this.emit("changeMap", {
29508
29938
  mapId: "map-" + mapId,
29509
29939
  positions
@@ -29517,14 +29947,25 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29517
29947
  getCurrentMap() {
29518
29948
  return this.map;
29519
29949
  }
29520
- emit(type, value) {
29950
+ emit(type2, value) {
29521
29951
  const map = this.getCurrentMap();
29522
29952
  if (!map || !this.conn) return;
29523
29953
  map.$send(this.conn, {
29524
- type,
29954
+ type: type2,
29525
29955
  value
29526
29956
  });
29527
29957
  }
29958
+ async save() {
29959
+ const snapshot = createStatesSnapshot$1(this);
29960
+ await lastValueFrom(this.hooks.callHooks("server-player-onSave", this, snapshot));
29961
+ return JSON.stringify(snapshot);
29962
+ }
29963
+ async load(snapshot) {
29964
+ const data = JSON.parse(snapshot);
29965
+ const dataLoaded = load$1(this, data);
29966
+ await lastValueFrom(this.hooks.callHooks("server-player-onLoad", this, dataLoaded));
29967
+ return dataLoaded;
29968
+ }
29528
29969
  /**
29529
29970
  * Set the current animation of the player's sprite
29530
29971
  *
@@ -29659,7 +30100,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29659
30100
  * });
29660
30101
  * ```
29661
30102
  */
29662
- showComponentAnimation(id, params) {
30103
+ showComponentAnimation(id, params = {}) {
29663
30104
  const map = this.getCurrentMap();
29664
30105
  if (!map) return;
29665
30106
  map.$broadcast({
@@ -29671,49 +30112,24 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
29671
30112
  }
29672
30113
  });
29673
30114
  }
29674
- /**
29675
- * Display a spritesheet animation on the player
29676
- *
29677
- * This method displays a temporary visual animation using a spritesheet.
29678
- * The animation can either be displayed as an overlay on the player or replace
29679
- * the player's current graphic temporarily. This is useful for spell effects,
29680
- * transformations, or other visual feedback that uses predefined spritesheets.
29681
- *
29682
- * @param graphic - The ID of the spritesheet to use for the animation
29683
- * @param animationName - The name of the animation within the spritesheet (default: 'default')
29684
- * @param replaceGraphic - Whether to replace the player's sprite with the animation (default: false)
29685
- *
29686
- * @example
29687
- * ```ts
29688
- * // Show explosion animation as overlay on player
29689
- * player.showAnimation("explosion");
29690
- *
29691
- * // Show specific spell effect animation
29692
- * player.showAnimation("spell-effects", "fireball");
29693
- *
29694
- * // Transform player graphic temporarily with animation
29695
- * player.showAnimation("transformation", "werewolf", true);
29696
- *
29697
- * // Show healing effect on player
29698
- * player.showAnimation("healing-effects", "holy-light");
29699
- * ```
29700
- */
29701
- showAnimation(graphic, animationName = "default", replaceGraphic = false) {
29702
- if (replaceGraphic) {
29703
- this.setAnimation(animationName, 1);
29704
- return;
29705
- }
29706
- this.showComponentAnimation("animation", {
29707
- graphic,
29708
- animationName
29709
- });
29710
- }
29711
30115
  showHit(text) {
29712
30116
  this.showComponentAnimation("hit", {
29713
30117
  text,
29714
30118
  direction: this.direction()
29715
30119
  });
29716
30120
  }
30121
+ /**
30122
+ * Set the sync schema for the map
30123
+ * @param schema - The schema to set
30124
+ */
30125
+ setSync(schema) {
30126
+ for (let key in schema) {
30127
+ this[key] = type$1(signal$2(null), key, {
30128
+ syncWithClient: schema[key]?.$syncWithClient,
30129
+ persist: schema[key]?.$permanent
30130
+ }, this);
30131
+ }
30132
+ }
29717
30133
  };
29718
30134
  __decorateClass$2([
29719
30135
  sync$1(_RpgPlayer)
@@ -29721,8 +30137,7 @@ __decorateClass$2([
29721
30137
  let RpgPlayer = _RpgPlayer;
29722
30138
  class RpgEvent extends RpgPlayer {
29723
30139
  async execMethod(methodName, methodData = [], instance = this) {
29724
- const hooks = inject$1(this.context, ModulesToken);
29725
- await lastValueFrom(hooks.callHooks(`server-event-${methodName}`, instance, ...methodData));
30140
+ await lastValueFrom(this.hooks.callHooks(`server-event-${methodName}`, instance, ...methodData));
29726
30141
  if (!instance[methodName]) {
29727
30142
  return;
29728
30143
  }
@@ -29774,6 +30189,7 @@ let RpgMap = class extends RpgCommonMap {
29774
30189
  }, () => {
29775
30190
  player.animationName.set("stand");
29776
30191
  });
30192
+ player._onInit();
29777
30193
  this.dataIsReady$.pipe(
29778
30194
  finalize$1(() => {
29779
30195
  this.hooks.callHooks("server-player-onJoinMap", player, this).subscribe();
@@ -29913,6 +30329,7 @@ let RpgMap = class extends RpgCommonMap {
29913
30329
  eventInstance.context = context$1;
29914
30330
  eventInstance.x.set(x);
29915
30331
  eventInstance.y.set(y);
30332
+ if (event.name) eventInstance.name.set(event.name);
29916
30333
  this.events()[id] = eventInstance;
29917
30334
  await eventInstance.execMethod("onInit");
29918
30335
  }
@@ -29925,6 +30342,12 @@ let RpgMap = class extends RpgCommonMap {
29925
30342
  getEvents() {
29926
30343
  return Object.values(this.events());
29927
30344
  }
30345
+ getEventBy(cb) {
30346
+ return this.getEventsBy(cb)[0];
30347
+ }
30348
+ getEventsBy(cb) {
30349
+ return this.getEvents().filter(cb);
30350
+ }
29928
30351
  removeEvent(eventId) {
29929
30352
  delete this.events()[eventId];
29930
30353
  }
@@ -30006,6 +30429,18 @@ let RpgMap = class extends RpgCommonMap {
30006
30429
  animationName
30007
30430
  });
30008
30431
  }
30432
+ /**
30433
+ * Set the sync schema for the map
30434
+ * @param schema - The schema to set
30435
+ */
30436
+ setSync(schema) {
30437
+ for (let key in schema) {
30438
+ this[key] = type$1(signal$2(null), key, {
30439
+ syncWithClient: schema[key]?.$syncWithClient,
30440
+ persist: schema[key]?.$permanent
30441
+ }, this);
30442
+ }
30443
+ }
30009
30444
  };
30010
30445
  __decorateClass$1([
30011
30446
  users$1(RpgPlayer)
@@ -30111,6 +30546,16 @@ function provideServerModules(modules) {
30111
30546
  if ("server" in module) {
30112
30547
  module = module.server;
30113
30548
  }
30549
+ if (module.player?.props) {
30550
+ module = {
30551
+ ...module,
30552
+ playerProps: {
30553
+ load: (player) => {
30554
+ player.setSync(module.player.props);
30555
+ }
30556
+ }
30557
+ };
30558
+ }
30114
30559
  if (module.maps && Array.isArray(module.maps)) {
30115
30560
  const maps = [...module.maps];
30116
30561
  module = {
@@ -30130,5 +30575,5 @@ function provideServerModules(modules) {
30130
30575
  });
30131
30576
  }
30132
30577
 
30133
- export { AGI, AGI_CURVE, ATK, COEFFICIENT_ELEMENTS, DAMAGE_CRITICAL, DAMAGE_GUARD, DAMAGE_PHYSIC, DAMAGE_SKILL, DEX, DEX_CURVE, Frequency, INT, INT_CURVE, MAXHP, MAXHP_CURVE, MAXSP, MAXSP_CURVE, Move, PDEF, RpgEvent, RpgMap, RpgPlayer, RpgServerEngine, SDEF, STR, STR_CURVE, Speed, WithMoveManager, clearInject, context, createServer, inject, provideServerModules, setInject };
30578
+ export { AGI, AGI_CURVE, ATK, ArraySubject$2 as ArraySubject, COEFFICIENT_ELEMENTS, DAMAGE_CRITICAL, DAMAGE_GUARD, DAMAGE_PHYSIC, DAMAGE_SKILL, DEX, DEX_CURVE, DialogGui, DialogPosition, Frequency, Gui, INT, INT_CURVE, MAXHP, MAXHP_CURVE, MAXSP, MAXSP_CURVE, MenuGui, Move, NotificationGui, ObjectSubject$2 as ObjectSubject, PDEF, RpgEvent, RpgMap, RpgPlayer, RpgServerEngine, SDEF, STR, STR_CURVE, ShopGui, Speed, WithMoveManager, clearInject, computed$2 as computed, context, createServer, effect$2 as effect, inject, isArraySubject$1 as isArraySubject, isComputed$2 as isComputed, isObjectSubject$1 as isObjectSubject, isSignal$2 as isSignal, provideServerModules, setInject, signal$2 as signal, untracked };
30134
30579
  //# sourceMappingURL=index.js.map