@rpgjs/server 5.0.0-alpha.31 → 5.0.0-alpha.33

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.
@@ -4,8 +4,12 @@ export type ShopSellList = Record<string, number> | Array<{
4
4
  id: string;
5
5
  multiplier: number;
6
6
  }>;
7
+ export type ShopItemInput = string | {
8
+ id?: string;
9
+ [key: string]: any;
10
+ };
7
11
  export interface ShopGuiOptions {
8
- items: any[];
12
+ items: ShopItemInput[];
9
13
  sell?: ShopSellList;
10
14
  sellMultiplier?: number;
11
15
  message?: string;
@@ -386,12 +386,13 @@ export interface IItemManager {
386
386
  /**
387
387
  * Equips a weapon or armor on a player
388
388
  *
389
- * Think first to add the item in the inventory with the `addItem()` method before equipping the item.
389
+ * Think first to add the item in the inventory with the `addItem()` method before equipping the item,
390
+ * or pass `"auto"` to add the item if it is missing and equip it.
390
391
  *
391
392
  * The `onEquip()` method is called on the ItemClass when the item is equipped or unequipped.
392
393
  *
393
- * @param itemClass - Item class or string identifier. If string, it's the item ID
394
- * @param equip - Equip the item if `true`, unequip if `false` (default: `true`)
394
+ * @param itemId - Item identifier to resolve from the database
395
+ * @param equip - Equip the item if `true`, unequip if `false`, or `"auto"` to add then equip (default: `true`)
395
396
  * @throws {Object} ItemLog.notInInventory - If the item is not in the inventory
396
397
  * - `id`: `ITEM_NOT_INVENTORY`
397
398
  * - `msg`: Error message
@@ -404,19 +405,17 @@ export interface IItemManager {
404
405
  *
405
406
  * @example
406
407
  * ```ts
407
- * import Sword from 'your-database/sword'
408
- *
409
408
  * try {
410
- * player.addItem(Sword)
411
- * player.equip(Sword)
409
+ * player.addItem('sword')
410
+ * player.equip('sword')
412
411
  * // Later, unequip it
413
- * player.equip(Sword, false)
412
+ * player.equip('sword', false)
414
413
  * } catch (err) {
415
414
  * console.log(err)
416
415
  * }
417
416
  * ```
418
417
  */
419
- equip(itemClass: ItemClass | string, equip?: boolean): void;
418
+ equip(itemId: string, equip?: boolean | 'auto'): void;
420
419
  /**
421
420
  * Get the player's attack (sum of items equipped)
422
421
  *
@@ -659,10 +659,10 @@ export interface RpgServer {
659
659
  * })
660
660
  * ```
661
661
  *
662
- * @prop { { [dataName]: data } } [database]
662
+ * @prop { { [dataName]: data } | (engine: RpgMap) => { [dataName]: data } | Promise<{ [dataName]: data }> } [database]
663
663
  * @memberof RpgServer
664
664
  * */
665
- database?: object | any[];
665
+ database?: object | any[] | ((engine: RpgMap) => object | any[] | Promise<object | any[]>);
666
666
  /**
667
667
  * Array of all maps. Each element can be either a class (decorated with `@MapData` or not) or a `MapOptions` object
668
668
  *
package/dist/index.js CHANGED
@@ -8543,9 +8543,9 @@ var Server = class {
8543
8543
  sessionState,
8544
8544
  room: this.room
8545
8545
  })) ?? userSnapshot;
8546
- load(user, hydratedSnapshot, true);
8547
8546
  signal2()[publicId] = user;
8548
- await this.room.storage.put(`${usersPropName}.${publicId}`, hydratedSnapshot);
8547
+ load(user, hydratedSnapshot, true);
8548
+ await this.room.storage.put(`${usersPropName}.${publicId}`, userSnapshot);
8549
8549
  }
8550
8550
  }
8551
8551
  const transferToken = generateShortUUID$1();
@@ -19476,6 +19476,9 @@ function WithMoveManager(Base) {
19476
19476
  this.waitingForPromise = false;
19477
19477
  this.promiseStartTime = 0;
19478
19478
  this.promiseDuration = 0;
19479
+ this.remainingDistance = 0;
19480
+ this.segmentDirection = null;
19481
+ this.segmentStep = 0;
19479
19482
  // Frequency wait state
19480
19483
  this.waitingForFrequency = false;
19481
19484
  this.frequencyWaitStartTime = 0;
@@ -19502,6 +19505,9 @@ function WithMoveManager(Base) {
19502
19505
  processNextRoute() {
19503
19506
  this.waitingForFrequency = false;
19504
19507
  this.frequencyWaitStartTime = 0;
19508
+ this.remainingDistance = 0;
19509
+ this.segmentDirection = null;
19510
+ this.segmentStep = 0;
19505
19511
  if (this.routeIndex >= this.routes.length) {
19506
19512
  this.debugLog("COMPLETE all routes finished");
19507
19513
  this.finished = true;
@@ -19578,41 +19584,13 @@ function WithMoveManager(Base) {
19578
19584
  break;
19579
19585
  }
19580
19586
  }
19581
- let targetTopLeftX = currentTopLeftX;
19582
- let targetTopLeftY = currentTopLeftY;
19583
- switch (moveDirection) {
19584
- case Direction.Right:
19585
- case "right":
19586
- targetTopLeftX = currentTopLeftX + distance;
19587
- break;
19588
- case Direction.Left:
19589
- case "left":
19590
- targetTopLeftX = currentTopLeftX - distance;
19591
- break;
19592
- case Direction.Down:
19593
- case "down":
19594
- targetTopLeftY = currentTopLeftY + distance;
19595
- break;
19596
- case Direction.Up:
19597
- case "up":
19598
- targetTopLeftY = currentTopLeftY - distance;
19599
- break;
19587
+ this.remainingDistance = distance;
19588
+ this.segmentDirection = moveDirection;
19589
+ this.segmentStep = this.getTileStepDistance(playerSpeed);
19590
+ this.setNextSegmentTarget(currentTopLeftX, currentTopLeftY);
19591
+ if (this.currentTargetTopLeft) {
19592
+ this.debugLog(`MOVE direction=${moveDirection} from=(${currentTopLeftX.toFixed(1)}, ${currentTopLeftY.toFixed(1)}) to=(${this.currentTargetTopLeft.x.toFixed(1)}, ${this.currentTargetTopLeft.y.toFixed(1)}) dist=${distance.toFixed(1)}`);
19600
19593
  }
19601
- const entity = map.physic.getEntityByUUID(this.player.id);
19602
- if (!entity) {
19603
- this.finished = true;
19604
- this.onComplete(false);
19605
- return;
19606
- }
19607
- const hitbox = this.player.hitbox();
19608
- const hitboxWidth = hitbox?.w ?? 32;
19609
- const hitboxHeight = hitbox?.h ?? 32;
19610
- const targetX = targetTopLeftX + hitboxWidth / 2;
19611
- const targetY = targetTopLeftY + hitboxHeight / 2;
19612
- this.currentTarget = { x: targetX, y: targetY };
19613
- this.currentTargetTopLeft = { x: targetTopLeftX, y: targetTopLeftY };
19614
- this.currentDirection = { x: 0, y: 0 };
19615
- this.debugLog(`MOVE direction=${moveDirection} from=(${currentTopLeftX.toFixed(1)}, ${currentTopLeftY.toFixed(1)}) to=(${targetTopLeftX.toFixed(1)}, ${targetTopLeftY.toFixed(1)}) dist=${distance.toFixed(1)}`);
19616
19594
  this.lastPosition = null;
19617
19595
  this.isCurrentlyStuck = false;
19618
19596
  this.stuckCheckStartTime = 0;
@@ -19648,7 +19626,13 @@ function WithMoveManager(Base) {
19648
19626
  const frequencyMs = playerFrequency || 0;
19649
19627
  if (frequencyMs > 0 && Date.now() - this.frequencyWaitStartTime >= frequencyMs * this.ratioFrequency) {
19650
19628
  this.waitingForFrequency = false;
19651
- this.processNextRoute();
19629
+ if (this.remainingDistance > 0) {
19630
+ const currentTopLeftX2 = this.player.x();
19631
+ const currentTopLeftY2 = this.player.y();
19632
+ this.setNextSegmentTarget(currentTopLeftX2, currentTopLeftY2);
19633
+ } else {
19634
+ this.processNextRoute();
19635
+ }
19652
19636
  }
19653
19637
  return;
19654
19638
  }
@@ -19696,6 +19680,10 @@ function WithMoveManager(Base) {
19696
19680
  if (playerFrequency && playerFrequency > 0) {
19697
19681
  this.waitingForFrequency = true;
19698
19682
  this.frequencyWaitStartTime = Date.now();
19683
+ } else if (this.remainingDistance > 0) {
19684
+ const nextTopLeftX = this.player.x();
19685
+ const nextTopLeftY = this.player.y();
19686
+ this.setNextSegmentTarget(nextTopLeftX, nextTopLeftY);
19699
19687
  } else {
19700
19688
  this.processNextRoute();
19701
19689
  }
@@ -19720,6 +19708,10 @@ function WithMoveManager(Base) {
19720
19708
  if (playerFrequency && playerFrequency > 0) {
19721
19709
  this.waitingForFrequency = true;
19722
19710
  this.frequencyWaitStartTime = Date.now();
19711
+ } else if (this.remainingDistance > 0) {
19712
+ const nextTopLeftX = this.player.x();
19713
+ const nextTopLeftY = this.player.y();
19714
+ this.setNextSegmentTarget(nextTopLeftX, nextTopLeftY);
19723
19715
  } else {
19724
19716
  this.processNextRoute();
19725
19717
  }
@@ -19794,6 +19786,10 @@ function WithMoveManager(Base) {
19794
19786
  if (playerFrequency && playerFrequency > 0) {
19795
19787
  this.waitingForFrequency = true;
19796
19788
  this.frequencyWaitStartTime = Date.now();
19789
+ } else if (this.remainingDistance > 0) {
19790
+ const nextTopLeftX = this.player.x();
19791
+ const nextTopLeftY = this.player.y();
19792
+ this.setNextSegmentTarget(nextTopLeftX, nextTopLeftY);
19797
19793
  } else {
19798
19794
  this.processNextRoute();
19799
19795
  }
@@ -19816,6 +19812,60 @@ function WithMoveManager(Base) {
19816
19812
  onFinished() {
19817
19813
  this.onComplete(true);
19818
19814
  }
19815
+ getTileStepDistance(playerSpeed) {
19816
+ if (!Number.isFinite(playerSpeed) || playerSpeed <= 0) {
19817
+ return this.tileSize;
19818
+ }
19819
+ const stepsPerTile = Math.max(1, Math.floor(this.tileSize / playerSpeed));
19820
+ return stepsPerTile * playerSpeed;
19821
+ }
19822
+ setNextSegmentTarget(currentTopLeftX, currentTopLeftY) {
19823
+ if (!this.segmentDirection || this.remainingDistance <= 0) {
19824
+ return;
19825
+ }
19826
+ const map = this.player.getCurrentMap();
19827
+ if (!map) {
19828
+ this.finished = true;
19829
+ this.onComplete(false);
19830
+ return;
19831
+ }
19832
+ const entity = map.physic.getEntityByUUID(this.player.id);
19833
+ if (!entity) {
19834
+ this.finished = true;
19835
+ this.onComplete(false);
19836
+ return;
19837
+ }
19838
+ const segmentDistance = Math.min(this.segmentStep || this.remainingDistance, this.remainingDistance);
19839
+ let targetTopLeftX = currentTopLeftX;
19840
+ let targetTopLeftY = currentTopLeftY;
19841
+ switch (this.segmentDirection) {
19842
+ case Direction.Right:
19843
+ case "right":
19844
+ targetTopLeftX = currentTopLeftX + segmentDistance;
19845
+ break;
19846
+ case Direction.Left:
19847
+ case "left":
19848
+ targetTopLeftX = currentTopLeftX - segmentDistance;
19849
+ break;
19850
+ case Direction.Down:
19851
+ case "down":
19852
+ targetTopLeftY = currentTopLeftY + segmentDistance;
19853
+ break;
19854
+ case Direction.Up:
19855
+ case "up":
19856
+ targetTopLeftY = currentTopLeftY - segmentDistance;
19857
+ break;
19858
+ }
19859
+ const hitbox = this.player.hitbox();
19860
+ const hitboxWidth = hitbox?.w ?? 32;
19861
+ const hitboxHeight = hitbox?.h ?? 32;
19862
+ const targetX = targetTopLeftX + hitboxWidth / 2;
19863
+ const targetY = targetTopLeftY + hitboxHeight / 2;
19864
+ this.currentTarget = { x: targetX, y: targetY };
19865
+ this.currentTargetTopLeft = { x: targetTopLeftX, y: targetTopLeftY };
19866
+ this.currentDirection = { x: 0, y: 0 };
19867
+ this.remainingDistance -= segmentDistance;
19868
+ }
19819
19869
  }
19820
19870
  const routeStrategy = new RouteMovementStrategy(
19821
19871
  finalRoutes,
@@ -20178,7 +20228,7 @@ class MenuGui extends Gui {
20178
20228
  spCost: skill?.spCost() ?? 0
20179
20229
  }));
20180
20230
  const saveLoad = this.buildSaveLoad(options);
20181
- return { menus, items, equips: menuEquips, skills, saveLoad, playerStats: buildStats() };
20231
+ return { menus, items, equips: menuEquips, skills, saveLoad, playerStats: buildStats(), expForNextlevel: player2.expForNextlevel };
20182
20232
  }
20183
20233
  refreshMenu(clientActionId) {
20184
20234
  const data = this.buildMenuData(this.menuOptions);
@@ -20667,10 +20717,10 @@ function WithParameterManager(Base) {
20667
20717
  this._param = type(computed(() => {
20668
20718
  const obj = {};
20669
20719
  const parameters = this._parametersSignal();
20720
+ const allModifiers = this._getAggregatedModifiers();
20670
20721
  const level = this._level();
20671
20722
  for (const [name, paramConfig] of Object.entries(parameters)) {
20672
20723
  let curveVal = Math.floor((paramConfig.end - paramConfig.start) * ((level - 1) / (this.finalLevel - this.initialLevel))) + paramConfig.start;
20673
- const allModifiers = this._getAggregatedModifiers();
20674
20724
  const modifier = allModifiers[name];
20675
20725
  if (modifier) {
20676
20726
  if (modifier.rate) curveVal *= modifier.rate;
@@ -21499,13 +21549,17 @@ function WithItemManager(Base) {
21499
21549
  this.removeItem(itemClass);
21500
21550
  return inventory;
21501
21551
  }
21502
- equip(itemClass, equip = true) {
21503
- const itemId = isString(itemClass) ? itemClass : itemClass.name;
21504
- const inventory = this.getItem(itemClass);
21552
+ equip(itemId, equip = true) {
21553
+ const autoAdd = equip === "auto";
21554
+ const equipState = equip === "auto" ? true : equip;
21555
+ const data = this.databaseById(itemId);
21556
+ let inventory = this.getItem(itemId);
21557
+ if (!inventory && autoAdd) {
21558
+ inventory = this.addItem(itemId, 1);
21559
+ }
21505
21560
  if (!inventory) {
21506
21561
  throw ItemLog.notInInventory(itemId);
21507
21562
  }
21508
- const data = this.databaseById(itemId);
21509
21563
  if (data._type == "item") {
21510
21564
  throw ItemLog.invalidToEquiped(itemId);
21511
21565
  }
@@ -21520,18 +21574,18 @@ function WithItemManager(Base) {
21520
21574
  }
21521
21575
  }
21522
21576
  const item = inventory;
21523
- if (item.equipped && equip) {
21577
+ if (item.equipped && equipState) {
21524
21578
  throw ItemLog.isAlreadyEquiped(itemId);
21525
21579
  }
21526
- item.equipped = equip;
21527
- if (!equip) {
21580
+ item.equipped = equipState;
21581
+ if (!equipState) {
21528
21582
  const index = this.equipments().findIndex((it) => it.id() == item.id());
21529
21583
  this.equipments().splice(index, 1);
21530
21584
  } else {
21531
21585
  this.equipments().push(item);
21532
21586
  }
21533
21587
  const hookTarget = item._itemInstance || item;
21534
- this["execMethod"]("onEquip", [this, equip], hookTarget);
21588
+ this["execMethod"]("onEquip", [this, equipState], hookTarget);
21535
21589
  }
21536
21590
  };
21537
21591
  }
@@ -22130,8 +22184,11 @@ function WithClassManager(Base) {
22130
22184
  this.addParameter(param, actor.parameters[param]);
22131
22185
  }
22132
22186
  for (let item of actor.startingEquipment) {
22133
- this.addItem(item);
22134
- this.equip(item, true);
22187
+ const inventory = this.addItem(item);
22188
+ const itemId = inventory?.id?.();
22189
+ if (itemId) {
22190
+ this.equip(itemId, true);
22191
+ }
22135
22192
  }
22136
22193
  if (actor.class) this.setClass(actor.class);
22137
22194
  this["execMethod"]("onSet", [this], actor);
@@ -29874,14 +29931,18 @@ function provideServerModules(modules) {
29874
29931
  }
29875
29932
  };
29876
29933
  }
29877
- if (module.database && typeof module.database === "object") {
29878
- const database = { ...module.database };
29934
+ if (module.database) {
29935
+ const database = module.database;
29879
29936
  module = {
29880
29937
  ...module,
29881
29938
  databaseHooks: {
29882
- load: (engine) => {
29883
- for (const key in database) {
29884
- engine.addInDatabase(key, database[key]);
29939
+ load: async (engine) => {
29940
+ const data = typeof database === "function" ? await database(engine) : database;
29941
+ if (!data || typeof data !== "object") {
29942
+ return;
29943
+ }
29944
+ for (const key in data) {
29945
+ engine.addInDatabase(key, data[key]);
29885
29946
  }
29886
29947
  }
29887
29948
  }