@rpgjs/server 5.0.0-alpha.25 → 5.0.0-alpha.26
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/Player/Player.d.ts +31 -22
- package/dist/index.js +412 -196
- package/dist/index.js.map +1 -1
- package/dist/rooms/BaseRoom.d.ts +95 -0
- package/dist/rooms/lobby.d.ts +4 -1
- package/dist/rooms/map.d.ts +17 -75
- package/package.json +8 -8
- package/src/Player/ItemManager.ts +50 -15
- package/src/Player/Player.ts +161 -135
- package/src/module.ts +13 -0
- package/src/rooms/BaseRoom.ts +120 -0
- package/src/rooms/lobby.ts +11 -1
- package/src/rooms/map.ts +68 -144
- package/tests/item.spec.ts +455 -441
- package/tests/world-maps.spec.ts +43 -81
package/dist/index.js
CHANGED
|
@@ -7743,12 +7743,30 @@ var Server = class {
|
|
|
7743
7743
|
load(instance, tmpObject, true);
|
|
7744
7744
|
}, "loadMemory");
|
|
7745
7745
|
instance.$memoryAll = {};
|
|
7746
|
+
instance.$autoSync = instance["autoSync"] !== false;
|
|
7747
|
+
instance.$pendingSync = /* @__PURE__ */ new Map();
|
|
7746
7748
|
instance.$send = (conn, obj) => {
|
|
7747
7749
|
return this.send(conn, obj, instance);
|
|
7748
7750
|
};
|
|
7749
7751
|
instance.$broadcast = (obj) => {
|
|
7750
7752
|
return this.broadcast(obj, instance);
|
|
7751
7753
|
};
|
|
7754
|
+
instance.$applySync = () => {
|
|
7755
|
+
let packet;
|
|
7756
|
+
if (instance.$pendingSync.size > 0) {
|
|
7757
|
+
if (options.getMemoryAll) {
|
|
7758
|
+
buildObject(instance.$pendingSync, instance.$memoryAll);
|
|
7759
|
+
}
|
|
7760
|
+
packet = buildObject(instance.$pendingSync, instance.$memoryAll);
|
|
7761
|
+
instance.$pendingSync.clear();
|
|
7762
|
+
} else {
|
|
7763
|
+
packet = instance.$memoryAll;
|
|
7764
|
+
}
|
|
7765
|
+
this.broadcast({
|
|
7766
|
+
type: "sync",
|
|
7767
|
+
value: packet
|
|
7768
|
+
}, instance);
|
|
7769
|
+
};
|
|
7752
7770
|
instance.$sessionTransfer = async (conn, targetRoomId) => {
|
|
7753
7771
|
let user;
|
|
7754
7772
|
const signal2 = this.getUsersProperty(instance);
|
|
@@ -7815,6 +7833,13 @@ var Server = class {
|
|
|
7815
7833
|
init = false;
|
|
7816
7834
|
return;
|
|
7817
7835
|
}
|
|
7836
|
+
if (!instance.$autoSync) {
|
|
7837
|
+
for (const [path, value] of values) {
|
|
7838
|
+
instance.$pendingSync.set(path, value);
|
|
7839
|
+
}
|
|
7840
|
+
values.clear();
|
|
7841
|
+
return;
|
|
7842
|
+
}
|
|
7818
7843
|
const packet = buildObject(values, instance.$memoryAll);
|
|
7819
7844
|
this.broadcast({
|
|
7820
7845
|
type: "sync",
|
|
@@ -7839,11 +7864,12 @@ var Server = class {
|
|
|
7839
7864
|
values.clear();
|
|
7840
7865
|
}, "persistCb");
|
|
7841
7866
|
syncClass(instance, {
|
|
7842
|
-
onSync: throttle(syncCb, instance["throttleSync"]
|
|
7843
|
-
onPersist: throttle(persistCb, instance["throttleStorage"]
|
|
7867
|
+
onSync: instance["throttleSync"] ? throttle(syncCb, instance["throttleSync"]) : syncCb,
|
|
7868
|
+
onPersist: instance["throttleStorage"] ? throttle(persistCb, instance["throttleStorage"]) : persistCb
|
|
7844
7869
|
});
|
|
7845
7870
|
await loadMemory();
|
|
7846
7871
|
initPersist = false;
|
|
7872
|
+
init = false;
|
|
7847
7873
|
return instance;
|
|
7848
7874
|
}
|
|
7849
7875
|
/**
|
|
@@ -8049,13 +8075,15 @@ var Server = class {
|
|
|
8049
8075
|
publicId
|
|
8050
8076
|
});
|
|
8051
8077
|
await awaitReturn(subRoom["onJoin"]?.(user, conn, ctx));
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8078
|
+
if (subRoom.$autoSync) {
|
|
8079
|
+
this.send(conn, {
|
|
8080
|
+
type: "sync",
|
|
8081
|
+
value: {
|
|
8082
|
+
pId: publicId,
|
|
8083
|
+
...subRoom.$memoryAll
|
|
8084
|
+
}
|
|
8085
|
+
}, subRoom);
|
|
8086
|
+
}
|
|
8059
8087
|
}
|
|
8060
8088
|
/**
|
|
8061
8089
|
* @method onConnect
|
|
@@ -9777,10 +9805,10 @@ class Item {
|
|
|
9777
9805
|
this.quantity = signal(1);
|
|
9778
9806
|
this.onAdd = () => {
|
|
9779
9807
|
};
|
|
9780
|
-
this.description.set(data
|
|
9781
|
-
this.price.set(data
|
|
9782
|
-
this.name.set(data
|
|
9783
|
-
this.onAdd = data
|
|
9808
|
+
this.description.set(data?.description ?? "");
|
|
9809
|
+
this.price.set(data?.price ?? 0);
|
|
9810
|
+
this.name.set(data?.name ?? "");
|
|
9811
|
+
this.onAdd = data?.onAdd?.bind(this) ?? (() => {
|
|
9784
9812
|
});
|
|
9785
9813
|
}
|
|
9786
9814
|
}
|
|
@@ -15777,6 +15805,10 @@ class RpgCommonMap {
|
|
|
15777
15805
|
});
|
|
15778
15806
|
this.moveManager = new MovementManager(() => this.physic);
|
|
15779
15807
|
this.speedScalar = 50;
|
|
15808
|
+
// Default speed scalar for movement
|
|
15809
|
+
// World Maps properties
|
|
15810
|
+
this.tileWidth = 32;
|
|
15811
|
+
this.tileHeight = 32;
|
|
15780
15812
|
this.physicsAccumulatorMs = 0;
|
|
15781
15813
|
this.physicsSyncDepth = 0;
|
|
15782
15814
|
/**
|
|
@@ -15831,6 +15863,88 @@ class RpgCommonMap {
|
|
|
15831
15863
|
get isStandalone() {
|
|
15832
15864
|
return typeof window !== "undefined";
|
|
15833
15865
|
}
|
|
15866
|
+
/**
|
|
15867
|
+
* Get the width of the map in pixels
|
|
15868
|
+
*
|
|
15869
|
+
* @returns The width of the map in pixels, or 0 if not loaded
|
|
15870
|
+
*
|
|
15871
|
+
* @example
|
|
15872
|
+
* ```ts
|
|
15873
|
+
* const width = map.widthPx;
|
|
15874
|
+
* console.log(`Map width: ${width}px`);
|
|
15875
|
+
* ```
|
|
15876
|
+
*/
|
|
15877
|
+
get widthPx() {
|
|
15878
|
+
return this.data()?.width ?? 0;
|
|
15879
|
+
}
|
|
15880
|
+
/**
|
|
15881
|
+
* Get the height of the map in pixels
|
|
15882
|
+
*
|
|
15883
|
+
* @returns The height of the map in pixels, or 0 if not loaded
|
|
15884
|
+
*
|
|
15885
|
+
* @example
|
|
15886
|
+
* ```ts
|
|
15887
|
+
* const height = map.heightPx;
|
|
15888
|
+
* console.log(`Map height: ${height}px`);
|
|
15889
|
+
* ```
|
|
15890
|
+
*/
|
|
15891
|
+
get heightPx() {
|
|
15892
|
+
return this.data()?.height ?? 0;
|
|
15893
|
+
}
|
|
15894
|
+
/**
|
|
15895
|
+
* Get the unique identifier of the map
|
|
15896
|
+
*
|
|
15897
|
+
* @returns The map ID, or empty string if not loaded
|
|
15898
|
+
*
|
|
15899
|
+
* @example
|
|
15900
|
+
* ```ts
|
|
15901
|
+
* const mapId = map.id;
|
|
15902
|
+
* console.log(`Current map: ${mapId}`);
|
|
15903
|
+
* ```
|
|
15904
|
+
*/
|
|
15905
|
+
get id() {
|
|
15906
|
+
return this.data()?.id ?? "";
|
|
15907
|
+
}
|
|
15908
|
+
/**
|
|
15909
|
+
* Get the X position of this map in the world coordinate system
|
|
15910
|
+
*
|
|
15911
|
+
* This is used when maps are part of a larger world map. The world position
|
|
15912
|
+
* indicates where this map is located relative to other maps.
|
|
15913
|
+
*
|
|
15914
|
+
* @returns The X position in world coordinates, or 0 if not in a world
|
|
15915
|
+
*
|
|
15916
|
+
* @example
|
|
15917
|
+
* ```ts
|
|
15918
|
+
* const worldX = map.worldX;
|
|
15919
|
+
* console.log(`Map is at world position (${worldX}, ${map.worldY})`);
|
|
15920
|
+
* ```
|
|
15921
|
+
*/
|
|
15922
|
+
get worldX() {
|
|
15923
|
+
const worldMaps = this.getWorldMapsManager?.();
|
|
15924
|
+
if (!worldMaps) return 0;
|
|
15925
|
+
const mapId = this.id.startsWith("map-") ? this.id.slice(4) : this.id;
|
|
15926
|
+
return worldMaps.getMapInfo(mapId)?.worldX ?? 0;
|
|
15927
|
+
}
|
|
15928
|
+
/**
|
|
15929
|
+
* Get the Y position of this map in the world coordinate system
|
|
15930
|
+
*
|
|
15931
|
+
* This is used when maps are part of a larger world map. The world position
|
|
15932
|
+
* indicates where this map is located relative to other maps.
|
|
15933
|
+
*
|
|
15934
|
+
* @returns The Y position in world coordinates, or 0 if not in a world
|
|
15935
|
+
*
|
|
15936
|
+
* @example
|
|
15937
|
+
* ```ts
|
|
15938
|
+
* const worldY = map.worldY;
|
|
15939
|
+
* console.log(`Map is at world position (${map.worldX}, ${worldY})`);
|
|
15940
|
+
* ```
|
|
15941
|
+
*/
|
|
15942
|
+
get worldY() {
|
|
15943
|
+
const worldMaps = this.getWorldMapsManager?.();
|
|
15944
|
+
if (!worldMaps) return 0;
|
|
15945
|
+
const mapId = this.id.startsWith("map-") ? this.id.slice(4) : this.id;
|
|
15946
|
+
return worldMaps.getMapInfo(mapId)?.worldY ?? 0;
|
|
15947
|
+
}
|
|
15834
15948
|
/**
|
|
15835
15949
|
* Clear all physics content and reset to initial state
|
|
15836
15950
|
*
|
|
@@ -16922,17 +17036,19 @@ class WorldMapsManager {
|
|
|
16922
17036
|
if (typeof search === "number") {
|
|
16923
17037
|
const src = map;
|
|
16924
17038
|
return maps.filter((m) => {
|
|
16925
|
-
const
|
|
16926
|
-
const
|
|
17039
|
+
const horizontallyOverlapsOrTouches = Math.max(src.worldX, m.worldX) <= Math.min(src.worldX + src.widthPx, m.worldX + m.widthPx);
|
|
17040
|
+
const verticallyOverlapsOrTouches = Math.max(src.worldY, m.worldY) <= Math.min(src.worldY + src.heightPx, m.worldY + m.heightPx);
|
|
17041
|
+
const marginLeftRight = src.tileWidth / 2;
|
|
17042
|
+
const marginTopDown = src.tileHeight / 2;
|
|
16927
17043
|
switch (search) {
|
|
16928
17044
|
case 0:
|
|
16929
|
-
return
|
|
17045
|
+
return verticallyOverlapsOrTouches && m.worldY + m.heightPx - marginTopDown === src.worldY;
|
|
16930
17046
|
case 1:
|
|
16931
|
-
return
|
|
17047
|
+
return verticallyOverlapsOrTouches && m.worldY + marginTopDown === src.worldY + src.heightPx;
|
|
16932
17048
|
case 2:
|
|
16933
|
-
return
|
|
17049
|
+
return horizontallyOverlapsOrTouches && m.worldX + m.widthPx - marginLeftRight === src.worldX;
|
|
16934
17050
|
case 3:
|
|
16935
|
-
return
|
|
17051
|
+
return horizontallyOverlapsOrTouches && m.worldX + marginLeftRight === src.worldX + src.widthPx;
|
|
16936
17052
|
default:
|
|
16937
17053
|
return false;
|
|
16938
17054
|
}
|
|
@@ -16940,7 +17056,7 @@ class WorldMapsManager {
|
|
|
16940
17056
|
}
|
|
16941
17057
|
if ("x" in search && "y" in search) {
|
|
16942
17058
|
const found = maps.find(
|
|
16943
|
-
(m) => search.x >= m.worldX && search.x < m.worldX + m.
|
|
17059
|
+
(m) => search.x >= m.worldX && search.x < m.worldX + m.widthPx && search.y >= m.worldY && search.y < m.worldY + m.heightPx
|
|
16944
17060
|
);
|
|
16945
17061
|
return found ? [found] : [];
|
|
16946
17062
|
}
|
|
@@ -16948,9 +17064,9 @@ class WorldMapsManager {
|
|
|
16948
17064
|
const { minX, minY, maxX, maxY } = search;
|
|
16949
17065
|
return maps.filter((m) => {
|
|
16950
17066
|
const aLeft = m.worldX;
|
|
16951
|
-
const aRight = m.worldX + m.
|
|
17067
|
+
const aRight = m.worldX + m.widthPx;
|
|
16952
17068
|
const aTop = m.worldY;
|
|
16953
|
-
const aBottom = m.worldY + m.
|
|
17069
|
+
const aBottom = m.worldY + m.heightPx;
|
|
16954
17070
|
const bLeft = minX;
|
|
16955
17071
|
const bRight = maxX;
|
|
16956
17072
|
const bTop = minY;
|
|
@@ -19361,8 +19477,8 @@ function WithItemManager(Base) {
|
|
|
19361
19477
|
});
|
|
19362
19478
|
}
|
|
19363
19479
|
addItem(item, nb = 1) {
|
|
19364
|
-
const map = this.getCurrentMap();
|
|
19365
|
-
if (!map) {
|
|
19480
|
+
const map = this.getCurrentMap() || this.map;
|
|
19481
|
+
if (!map || !map.database) {
|
|
19366
19482
|
throw new Error("Player must be on a map to add items");
|
|
19367
19483
|
}
|
|
19368
19484
|
let itemId;
|
|
@@ -19371,11 +19487,6 @@ function WithItemManager(Base) {
|
|
|
19371
19487
|
if (isString(item)) {
|
|
19372
19488
|
itemId = item;
|
|
19373
19489
|
data = this.databaseById(itemId);
|
|
19374
|
-
if (!data) {
|
|
19375
|
-
throw new Error(
|
|
19376
|
-
`The ID=${itemId} data is not found in the database. Add the data in the property "database"`
|
|
19377
|
-
);
|
|
19378
|
-
}
|
|
19379
19490
|
} else if (typeof item === "function" || item.prototype) {
|
|
19380
19491
|
itemId = item.name;
|
|
19381
19492
|
const existingData = map.database()[itemId];
|
|
@@ -19404,6 +19515,21 @@ function WithItemManager(Base) {
|
|
|
19404
19515
|
if (existingItem) {
|
|
19405
19516
|
instance = existingItem;
|
|
19406
19517
|
instance.quantity.update((it) => it + nb);
|
|
19518
|
+
if (data.name !== void 0) {
|
|
19519
|
+
instance.name.set(data.name);
|
|
19520
|
+
}
|
|
19521
|
+
if (data.description !== void 0) {
|
|
19522
|
+
instance.description.set(data.description);
|
|
19523
|
+
}
|
|
19524
|
+
if (data.price !== void 0) {
|
|
19525
|
+
instance.price.set(data.price);
|
|
19526
|
+
}
|
|
19527
|
+
if (itemInstance && typeof itemInstance === "object" && !(itemInstance instanceof Function)) {
|
|
19528
|
+
instance._itemInstance = itemInstance;
|
|
19529
|
+
if (itemInstance.onAdd) {
|
|
19530
|
+
instance.onAdd = itemInstance.onAdd.bind(itemInstance);
|
|
19531
|
+
}
|
|
19532
|
+
}
|
|
19407
19533
|
} else {
|
|
19408
19534
|
instance = new Item(data);
|
|
19409
19535
|
instance.id.set(itemId);
|
|
@@ -19488,7 +19614,11 @@ function WithItemManager(Base) {
|
|
|
19488
19614
|
getParamItem(name) {
|
|
19489
19615
|
let nb = 0;
|
|
19490
19616
|
for (let item of this.equipments()) {
|
|
19491
|
-
|
|
19617
|
+
try {
|
|
19618
|
+
const itemData = this.databaseById(item.id());
|
|
19619
|
+
nb += itemData[name] || 0;
|
|
19620
|
+
} catch {
|
|
19621
|
+
}
|
|
19492
19622
|
}
|
|
19493
19623
|
const modifier = this.paramsModifier?.[name];
|
|
19494
19624
|
if (modifier) {
|
|
@@ -19515,19 +19645,23 @@ function WithItemManager(Base) {
|
|
|
19515
19645
|
if (!inventory) {
|
|
19516
19646
|
throw ItemLog.notInInventory(itemId);
|
|
19517
19647
|
}
|
|
19518
|
-
const
|
|
19519
|
-
|
|
19648
|
+
const itemData = this.databaseById(itemId);
|
|
19649
|
+
const consumable = itemData?.consumable;
|
|
19650
|
+
if (consumable === false) {
|
|
19520
19651
|
throw ItemLog.notUseItem(itemId);
|
|
19521
19652
|
}
|
|
19522
|
-
|
|
19523
|
-
|
|
19653
|
+
if (consumable === void 0 && itemData?._type && itemData._type !== "item") {
|
|
19654
|
+
throw ItemLog.notUseItem(itemId);
|
|
19655
|
+
}
|
|
19656
|
+
const hitRate = itemData?.hitRate ?? 1;
|
|
19657
|
+
const hookTarget = inventory._itemInstance || inventory;
|
|
19524
19658
|
if (Math.random() > hitRate) {
|
|
19525
19659
|
this.removeItem(itemClass);
|
|
19526
19660
|
this["execMethod"]("onUseFailed", [this], hookTarget);
|
|
19527
19661
|
throw ItemLog.chanceToUseFailed(itemId);
|
|
19528
19662
|
}
|
|
19529
|
-
this.applyEffect?.(
|
|
19530
|
-
this.applyStates?.(this,
|
|
19663
|
+
this.applyEffect?.(itemData);
|
|
19664
|
+
this.applyStates?.(this, itemData);
|
|
19531
19665
|
this["execMethod"]("onUse", [this], hookTarget);
|
|
19532
19666
|
this.removeItem(itemClass);
|
|
19533
19667
|
return inventory;
|
|
@@ -19972,7 +20106,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
19972
20106
|
this.map = null;
|
|
19973
20107
|
this.conn = null;
|
|
19974
20108
|
this.touchSide = false;
|
|
19975
|
-
|
|
20109
|
+
this._worldPositionSignals = /* @__PURE__ */ new WeakMap();
|
|
19976
20110
|
/** Internal: Shapes attached to this player */
|
|
19977
20111
|
this._attachedShapes = /* @__PURE__ */ new Map();
|
|
19978
20112
|
/** Internal: Shapes where this player is currently located */
|
|
@@ -20021,6 +20155,56 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20021
20155
|
}
|
|
20022
20156
|
});
|
|
20023
20157
|
}
|
|
20158
|
+
// Protection against map change loops
|
|
20159
|
+
/**
|
|
20160
|
+
* Computed signal for world X position
|
|
20161
|
+
*
|
|
20162
|
+
* Calculates the absolute world X position from the map's world position
|
|
20163
|
+
* plus the player's local X position. Returns 0 if no map is assigned.
|
|
20164
|
+
*
|
|
20165
|
+
* @example
|
|
20166
|
+
* ```ts
|
|
20167
|
+
* const worldX = player.worldX();
|
|
20168
|
+
* console.log(`Player is at world X: ${worldX}`);
|
|
20169
|
+
* ```
|
|
20170
|
+
*/
|
|
20171
|
+
get worldPositionX() {
|
|
20172
|
+
return this._getComputedWorldPosition("x");
|
|
20173
|
+
}
|
|
20174
|
+
/**
|
|
20175
|
+
* Computed signal for world Y position
|
|
20176
|
+
*
|
|
20177
|
+
* Calculates the absolute world Y position from the map's world position
|
|
20178
|
+
* plus the player's local Y position. Returns 0 if no map is assigned.
|
|
20179
|
+
*
|
|
20180
|
+
* @example
|
|
20181
|
+
* ```ts
|
|
20182
|
+
* const worldY = player.worldY();
|
|
20183
|
+
* console.log(`Player is at world Y: ${worldY}`);
|
|
20184
|
+
* ```
|
|
20185
|
+
*/
|
|
20186
|
+
get worldPositionY() {
|
|
20187
|
+
return this._getComputedWorldPosition("y");
|
|
20188
|
+
}
|
|
20189
|
+
_getComputedWorldPosition(axis) {
|
|
20190
|
+
if (!this._worldPositionSignals) {
|
|
20191
|
+
this._worldPositionSignals = /* @__PURE__ */ new WeakMap();
|
|
20192
|
+
}
|
|
20193
|
+
const key = axis;
|
|
20194
|
+
let signals = this._worldPositionSignals.get(this);
|
|
20195
|
+
if (!signals) {
|
|
20196
|
+
signals = {};
|
|
20197
|
+
this._worldPositionSignals.set(this, signals);
|
|
20198
|
+
}
|
|
20199
|
+
if (!signals[key]) {
|
|
20200
|
+
signals[key] = computed(() => {
|
|
20201
|
+
const map2 = this.map;
|
|
20202
|
+
const mapWorldPos = map2 ? map2[axis === "x" ? "worldX" : "worldY"] ?? 0 : 0;
|
|
20203
|
+
return mapWorldPos + this[axis]();
|
|
20204
|
+
});
|
|
20205
|
+
}
|
|
20206
|
+
return signals[key];
|
|
20207
|
+
}
|
|
20024
20208
|
_onInit() {
|
|
20025
20209
|
this.hooks.callHooks("server-playerProps-load", this).subscribe();
|
|
20026
20210
|
}
|
|
@@ -20031,6 +20215,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20031
20215
|
get server() {
|
|
20032
20216
|
return this.map;
|
|
20033
20217
|
}
|
|
20218
|
+
setMap(map2) {
|
|
20219
|
+
this.map = map2;
|
|
20220
|
+
}
|
|
20034
20221
|
applyFrames() {
|
|
20035
20222
|
this._frames.set(this.frames);
|
|
20036
20223
|
this.frames = [];
|
|
@@ -20080,76 +20267,55 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20080
20267
|
});
|
|
20081
20268
|
return true;
|
|
20082
20269
|
}
|
|
20083
|
-
|
|
20084
|
-
* Auto change map when player touches map borders
|
|
20085
|
-
*
|
|
20086
|
-
* This method checks if the player touches the current map borders
|
|
20087
|
-
* and automatically performs a change to the adjacent map if it exists.
|
|
20088
|
-
*
|
|
20089
|
-
* @param nextPosition - The next position of the player
|
|
20090
|
-
* @returns Promise<boolean> - true if a map change occurred
|
|
20091
|
-
*
|
|
20092
|
-
* @example
|
|
20093
|
-
* ```ts
|
|
20094
|
-
* // Called automatically by the movement system
|
|
20095
|
-
* const changed = await player.autoChangeMap({ x: newX, y: newY });
|
|
20096
|
-
* if (changed) {
|
|
20097
|
-
* console.log('Player changed map automatically');
|
|
20098
|
-
* }
|
|
20099
|
-
* ```
|
|
20100
|
-
*/
|
|
20101
|
-
async autoChangeMap(nextPosition, forcedDirection) {
|
|
20270
|
+
async autoChangeMap(nextPosition) {
|
|
20102
20271
|
const map2 = this.getCurrentMap();
|
|
20103
|
-
|
|
20104
|
-
const worldMaps = map2.getWorldMapsManager?.();
|
|
20272
|
+
const worldMaps = map2?.getInWorldMaps();
|
|
20105
20273
|
let ret = false;
|
|
20106
20274
|
if (worldMaps && map2) {
|
|
20107
|
-
const direction =
|
|
20108
|
-
const marginLeftRight =
|
|
20109
|
-
const marginTopDown =
|
|
20110
|
-
|
|
20111
|
-
(map2.worldY ?? 0) + this.y();
|
|
20112
|
-
const changeMap = async (directionNumber, positionCalculator) => {
|
|
20275
|
+
const direction = this.getDirection();
|
|
20276
|
+
const marginLeftRight = map2.tileWidth / 2;
|
|
20277
|
+
const marginTopDown = map2.tileHeight / 2;
|
|
20278
|
+
const changeMap = async (adjacent, to) => {
|
|
20113
20279
|
if (this.touchSide) {
|
|
20114
20280
|
return false;
|
|
20115
20281
|
}
|
|
20116
20282
|
this.touchSide = true;
|
|
20117
|
-
const [nextMap] = worldMaps.getAdjacentMaps(map2,
|
|
20118
|
-
if (!nextMap)
|
|
20119
|
-
this.touchSide = false;
|
|
20120
|
-
return false;
|
|
20121
|
-
}
|
|
20283
|
+
const [nextMap] = worldMaps.getAdjacentMaps(map2, adjacent);
|
|
20284
|
+
if (!nextMap) return false;
|
|
20122
20285
|
const id = nextMap.id;
|
|
20123
20286
|
const nextMapInfo = worldMaps.getMapInfo(id);
|
|
20124
|
-
|
|
20125
|
-
this.touchSide = false;
|
|
20126
|
-
return false;
|
|
20127
|
-
}
|
|
20128
|
-
const newPosition = positionCalculator(nextMapInfo);
|
|
20129
|
-
const success = await this.changeMap(id, newPosition);
|
|
20130
|
-
setTimeout(() => {
|
|
20131
|
-
this.touchSide = false;
|
|
20132
|
-
}, 100);
|
|
20133
|
-
return !!success;
|
|
20287
|
+
return !!await this.changeMap(id, to(nextMapInfo));
|
|
20134
20288
|
};
|
|
20135
|
-
if (nextPosition.x < marginLeftRight && direction
|
|
20136
|
-
ret = await changeMap(
|
|
20289
|
+
if (nextPosition.x < marginLeftRight && direction == Direction.Left) {
|
|
20290
|
+
ret = await changeMap({
|
|
20291
|
+
x: map2.worldX - 1,
|
|
20292
|
+
y: this.worldPositionY() + 1
|
|
20293
|
+
}, (nextMapInfo) => ({
|
|
20137
20294
|
x: nextMapInfo.width - this.hitbox().w - marginLeftRight,
|
|
20138
|
-
y:
|
|
20295
|
+
y: map2.worldY - nextMapInfo.y + nextPosition.y
|
|
20139
20296
|
}));
|
|
20140
|
-
} else if (nextPosition.x > map2.widthPx - this.hitbox().w - marginLeftRight && direction
|
|
20141
|
-
ret = await changeMap(
|
|
20297
|
+
} else if (nextPosition.x > map2.widthPx - this.hitbox().w - marginLeftRight && direction == Direction.Right) {
|
|
20298
|
+
ret = await changeMap({
|
|
20299
|
+
x: map2.worldX + map2.widthPx + 1,
|
|
20300
|
+
y: this.worldPositionY() + 1
|
|
20301
|
+
}, (nextMapInfo) => ({
|
|
20142
20302
|
x: marginLeftRight,
|
|
20143
|
-
y:
|
|
20303
|
+
y: map2.worldY - nextMapInfo.y + nextPosition.y
|
|
20144
20304
|
}));
|
|
20145
|
-
} else if (nextPosition.y < marginTopDown && direction
|
|
20146
|
-
ret = await changeMap(
|
|
20147
|
-
x:
|
|
20305
|
+
} else if (nextPosition.y < marginTopDown && direction == Direction.Up) {
|
|
20306
|
+
ret = await changeMap({
|
|
20307
|
+
x: this.worldPositionX() + 1,
|
|
20308
|
+
y: map2.worldY - 1
|
|
20309
|
+
}, (nextMapInfo) => ({
|
|
20310
|
+
x: map2.worldX - nextMapInfo.x + nextPosition.x,
|
|
20148
20311
|
y: nextMapInfo.height - this.hitbox().h - marginTopDown
|
|
20149
20312
|
}));
|
|
20150
|
-
} else if (nextPosition.y > map2.heightPx - this.hitbox().h - marginTopDown && direction
|
|
20151
|
-
ret = await changeMap(
|
|
20152
|
-
x:
|
|
20313
|
+
} else if (nextPosition.y > map2.heightPx - this.hitbox().h - marginTopDown && direction == Direction.Down) {
|
|
20314
|
+
ret = await changeMap({
|
|
20315
|
+
x: this.worldPositionX() + 1,
|
|
20316
|
+
y: map2.worldY + map2.heightPx + 1
|
|
20317
|
+
}, (nextMapInfo) => ({
|
|
20318
|
+
x: map2.worldX - nextMapInfo.x + nextPosition.x,
|
|
20153
20319
|
y: marginTopDown
|
|
20154
20320
|
}));
|
|
20155
20321
|
} else {
|
|
@@ -20160,15 +20326,14 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20160
20326
|
}
|
|
20161
20327
|
async teleport(positions) {
|
|
20162
20328
|
if (!this.map) return false;
|
|
20163
|
-
if (this.map.physic) {
|
|
20329
|
+
if (this.map && this.map.physic) {
|
|
20164
20330
|
const entity = this.map.physic.getEntityByUUID(this.id);
|
|
20165
20331
|
if (entity) {
|
|
20166
20332
|
this.map.physic.teleport(entity, { x: positions.x, y: positions.y });
|
|
20167
20333
|
}
|
|
20168
|
-
} else {
|
|
20169
|
-
this.x.set(positions.x);
|
|
20170
|
-
this.y.set(positions.y);
|
|
20171
20334
|
}
|
|
20335
|
+
this.x.set(positions.x);
|
|
20336
|
+
this.y.set(positions.y);
|
|
20172
20337
|
queueMicrotask(() => {
|
|
20173
20338
|
this.applyFrames();
|
|
20174
20339
|
});
|
|
@@ -20250,8 +20415,8 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20250
20415
|
this._eventChanges();
|
|
20251
20416
|
}
|
|
20252
20417
|
databaseById(id) {
|
|
20253
|
-
const map2 = this.
|
|
20254
|
-
if (!map2) return;
|
|
20418
|
+
const map2 = this.map;
|
|
20419
|
+
if (!map2 || !map2.database) return;
|
|
20255
20420
|
const data = map2.database()[id];
|
|
20256
20421
|
if (!data)
|
|
20257
20422
|
throw new Error(
|
|
@@ -24318,6 +24483,99 @@ function superRefine(fn) {
|
|
|
24318
24483
|
return _superRefine(fn);
|
|
24319
24484
|
}
|
|
24320
24485
|
|
|
24486
|
+
class BaseRoom {
|
|
24487
|
+
constructor() {
|
|
24488
|
+
/**
|
|
24489
|
+
* Signal containing the room's database of items, classes, and other game data
|
|
24490
|
+
*
|
|
24491
|
+
* This database can be dynamically populated using `addInDatabase()` and
|
|
24492
|
+
* `removeInDatabase()` methods. It's used to store game entities like items,
|
|
24493
|
+
* classes, skills, etc. that are available in this room.
|
|
24494
|
+
*
|
|
24495
|
+
* @example
|
|
24496
|
+
* ```ts
|
|
24497
|
+
* // Add data to database
|
|
24498
|
+
* room.addInDatabase('Potion', PotionClass);
|
|
24499
|
+
*
|
|
24500
|
+
* // Access database
|
|
24501
|
+
* const potion = room.database()['Potion'];
|
|
24502
|
+
* ```
|
|
24503
|
+
*/
|
|
24504
|
+
this.database = signal({});
|
|
24505
|
+
}
|
|
24506
|
+
/**
|
|
24507
|
+
* Add data to the room's database
|
|
24508
|
+
*
|
|
24509
|
+
* Adds an item, class, or other game entity to the room's database.
|
|
24510
|
+
* If the ID already exists and `force` is not enabled, the addition is ignored.
|
|
24511
|
+
*
|
|
24512
|
+
* ## Architecture
|
|
24513
|
+
*
|
|
24514
|
+
* This method is used by the item management system to store item definitions
|
|
24515
|
+
* in the room's database. When a player adds an item, the system first checks
|
|
24516
|
+
* if the item exists in the database, and if not, adds it using this method.
|
|
24517
|
+
*
|
|
24518
|
+
* @param id - Unique identifier for the data
|
|
24519
|
+
* @param data - The data to add (can be a class, object, etc.)
|
|
24520
|
+
* @param options - Optional configuration
|
|
24521
|
+
* @param options.force - If true, overwrites existing data with the same ID
|
|
24522
|
+
* @returns `true` if data was added, `false` if it was ignored (ID already exists)
|
|
24523
|
+
*
|
|
24524
|
+
* @example
|
|
24525
|
+
* ```ts
|
|
24526
|
+
* // Add a class to the database
|
|
24527
|
+
* room.addInDatabase('Potion', PotionClass);
|
|
24528
|
+
*
|
|
24529
|
+
* // Add an item object to the database
|
|
24530
|
+
* room.addInDatabase('custom-item', {
|
|
24531
|
+
* name: 'Custom Item',
|
|
24532
|
+
* price: 100
|
|
24533
|
+
* });
|
|
24534
|
+
*
|
|
24535
|
+
* // Force overwrite existing data
|
|
24536
|
+
* room.addInDatabase('Potion', UpdatedPotionClass, { force: true });
|
|
24537
|
+
* ```
|
|
24538
|
+
*/
|
|
24539
|
+
addInDatabase(id, data, options) {
|
|
24540
|
+
const database = this.database();
|
|
24541
|
+
if (database[id] !== void 0 && !options?.force) {
|
|
24542
|
+
return false;
|
|
24543
|
+
}
|
|
24544
|
+
database[id] = data;
|
|
24545
|
+
this.database.set(database);
|
|
24546
|
+
return true;
|
|
24547
|
+
}
|
|
24548
|
+
/**
|
|
24549
|
+
* Remove data from the room's database
|
|
24550
|
+
*
|
|
24551
|
+
* This method allows you to remove items or data from the room's database.
|
|
24552
|
+
*
|
|
24553
|
+
* @param id - Unique identifier of the data to remove
|
|
24554
|
+
* @returns `true` if data was removed, `false` if ID didn't exist
|
|
24555
|
+
*
|
|
24556
|
+
* @example
|
|
24557
|
+
* ```ts
|
|
24558
|
+
* // Remove an item from the database
|
|
24559
|
+
* room.removeInDatabase('Potion');
|
|
24560
|
+
*
|
|
24561
|
+
* // Check if removal was successful
|
|
24562
|
+
* const removed = room.removeInDatabase('custom-item');
|
|
24563
|
+
* if (removed) {
|
|
24564
|
+
* console.log('Item removed successfully');
|
|
24565
|
+
* }
|
|
24566
|
+
* ```
|
|
24567
|
+
*/
|
|
24568
|
+
removeInDatabase(id) {
|
|
24569
|
+
const database = this.database();
|
|
24570
|
+
if (database[id] === void 0) {
|
|
24571
|
+
return false;
|
|
24572
|
+
}
|
|
24573
|
+
delete database[id];
|
|
24574
|
+
this.database.set(database);
|
|
24575
|
+
return true;
|
|
24576
|
+
}
|
|
24577
|
+
}
|
|
24578
|
+
|
|
24321
24579
|
var __defProp$1 = Object.defineProperty;
|
|
24322
24580
|
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
24323
24581
|
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
@@ -24341,7 +24599,7 @@ const MapUpdateSchema = object({
|
|
|
24341
24599
|
height: number()
|
|
24342
24600
|
});
|
|
24343
24601
|
let RpgMap = class extends RpgCommonMap {
|
|
24344
|
-
constructor() {
|
|
24602
|
+
constructor(room) {
|
|
24345
24603
|
super();
|
|
24346
24604
|
this.players = signal({});
|
|
24347
24605
|
this.events = signal({});
|
|
@@ -24418,9 +24676,18 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24418
24676
|
this._shapeEntities = /* @__PURE__ */ new Map();
|
|
24419
24677
|
/** Enable/disable automatic tick processing (useful for unit tests) */
|
|
24420
24678
|
this._autoTickEnabled = true;
|
|
24679
|
+
this.autoSync = true;
|
|
24421
24680
|
this.hooks.callHooks("server-map-onStart", this).subscribe();
|
|
24422
|
-
|
|
24423
|
-
|
|
24681
|
+
const isTest = room.env.TEST === "true" ? true : false;
|
|
24682
|
+
if (isTest) {
|
|
24683
|
+
this.autoSync = false;
|
|
24684
|
+
this.setAutoTick(false);
|
|
24685
|
+
this.throttleSync = 0;
|
|
24686
|
+
this.throttleStorage = 0;
|
|
24687
|
+
} else {
|
|
24688
|
+
this.throttleSync = this.isStandalone ? 1 : 50;
|
|
24689
|
+
this.throttleStorage = this.isStandalone ? 1 : 50;
|
|
24690
|
+
}
|
|
24424
24691
|
this.sessionExpiryTime = 1e3 * 60 * 5;
|
|
24425
24692
|
this.setupCollisionDetection();
|
|
24426
24693
|
if (this._autoTickEnabled) {
|
|
@@ -24617,7 +24884,11 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24617
24884
|
* ```
|
|
24618
24885
|
*/
|
|
24619
24886
|
onJoin(player, conn) {
|
|
24620
|
-
player.
|
|
24887
|
+
if (player.setMap) {
|
|
24888
|
+
player.setMap(this);
|
|
24889
|
+
} else {
|
|
24890
|
+
player.map = this;
|
|
24891
|
+
}
|
|
24621
24892
|
player.context = context$1;
|
|
24622
24893
|
player.conn = conn;
|
|
24623
24894
|
player._onInit();
|
|
@@ -24683,85 +24954,8 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24683
24954
|
get hooks() {
|
|
24684
24955
|
return inject$1(context$1, ModulesToken);
|
|
24685
24956
|
}
|
|
24686
|
-
/**
|
|
24687
|
-
* Get the width of the map in pixels
|
|
24688
|
-
*
|
|
24689
|
-
* @returns The width of the map in pixels, or 0 if not loaded
|
|
24690
|
-
*
|
|
24691
|
-
* @example
|
|
24692
|
-
* ```ts
|
|
24693
|
-
* const width = map.widthPx;
|
|
24694
|
-
* console.log(`Map width: ${width}px`);
|
|
24695
|
-
* ```
|
|
24696
|
-
*/
|
|
24697
|
-
get widthPx() {
|
|
24698
|
-
return this.data()?.width ?? 0;
|
|
24699
|
-
}
|
|
24700
|
-
/**
|
|
24701
|
-
* Get the height of the map in pixels
|
|
24702
|
-
*
|
|
24703
|
-
* @returns The height of the map in pixels, or 0 if not loaded
|
|
24704
|
-
*
|
|
24705
|
-
* @example
|
|
24706
|
-
* ```ts
|
|
24707
|
-
* const height = map.heightPx;
|
|
24708
|
-
* console.log(`Map height: ${height}px`);
|
|
24709
|
-
* ```
|
|
24710
|
-
*/
|
|
24711
|
-
get heightPx() {
|
|
24712
|
-
return this.data()?.height ?? 0;
|
|
24713
|
-
}
|
|
24714
|
-
/**
|
|
24715
|
-
* Get the unique identifier of the map
|
|
24716
|
-
*
|
|
24717
|
-
* @returns The map ID, or empty string if not loaded
|
|
24718
|
-
*
|
|
24719
|
-
* @example
|
|
24720
|
-
* ```ts
|
|
24721
|
-
* const mapId = map.id;
|
|
24722
|
-
* console.log(`Current map: ${mapId}`);
|
|
24723
|
-
* ```
|
|
24724
|
-
*/
|
|
24725
|
-
get id() {
|
|
24726
|
-
return this.data()?.id ?? "";
|
|
24727
|
-
}
|
|
24728
|
-
/**
|
|
24729
|
-
* Get the X position of this map in the world coordinate system
|
|
24730
|
-
*
|
|
24731
|
-
* This is used when maps are part of a larger world map. The world position
|
|
24732
|
-
* indicates where this map is located relative to other maps.
|
|
24733
|
-
*
|
|
24734
|
-
* @returns The X position in world coordinates, or 0 if not in a world
|
|
24735
|
-
*
|
|
24736
|
-
* @example
|
|
24737
|
-
* ```ts
|
|
24738
|
-
* const worldX = map.worldX;
|
|
24739
|
-
* console.log(`Map is at world position (${worldX}, ${map.worldY})`);
|
|
24740
|
-
* ```
|
|
24741
|
-
*/
|
|
24742
|
-
get worldX() {
|
|
24743
|
-
const worldMaps = this.getWorldMapsManager?.();
|
|
24744
|
-
return worldMaps?.getMapInfo(this.id)?.worldX ?? 0;
|
|
24745
|
-
}
|
|
24746
|
-
/**
|
|
24747
|
-
* Get the Y position of this map in the world coordinate system
|
|
24748
|
-
*
|
|
24749
|
-
* This is used when maps are part of a larger world map. The world position
|
|
24750
|
-
* indicates where this map is located relative to other maps.
|
|
24751
|
-
*
|
|
24752
|
-
* @returns The Y position in world coordinates, or 0 if not in a world
|
|
24753
|
-
*
|
|
24754
|
-
* @example
|
|
24755
|
-
* ```ts
|
|
24756
|
-
* const worldY = map.worldY;
|
|
24757
|
-
* console.log(`Map is at world position (${map.worldX}, ${worldY})`);
|
|
24758
|
-
* ```
|
|
24759
|
-
*/
|
|
24760
|
-
get worldY() {
|
|
24761
|
-
const worldMaps = this.getWorldMapsManager?.();
|
|
24762
|
-
return worldMaps?.getMapInfo(this.id)?.worldY ?? 0;
|
|
24763
|
-
}
|
|
24764
24957
|
guiInteraction(player, value) {
|
|
24958
|
+
this.hooks.callHooks("server-player-guiInteraction", player, value);
|
|
24765
24959
|
player.syncChanges();
|
|
24766
24960
|
}
|
|
24767
24961
|
guiExit(player, { guiId, data }) {
|
|
@@ -24804,6 +24998,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24804
24998
|
};
|
|
24805
24999
|
await lastValueFrom(this.hooks.callHooks("server-maps-load", this));
|
|
24806
25000
|
await lastValueFrom(this.hooks.callHooks("server-worldMaps-load", this));
|
|
25001
|
+
await lastValueFrom(this.hooks.callHooks("server-databaseHooks-load", this));
|
|
24807
25002
|
map.events = map.events ?? [];
|
|
24808
25003
|
if (map.id) {
|
|
24809
25004
|
const mapFound = this.maps.find((m) => m.id === map.id);
|
|
@@ -25151,8 +25346,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25151
25346
|
/**
|
|
25152
25347
|
* Add data to the map's database
|
|
25153
25348
|
*
|
|
25154
|
-
* This method
|
|
25155
|
-
* By default, if an ID already exists, the operation is ignored to prevent overwriting existing data.
|
|
25349
|
+
* This method delegates to BaseRoom's implementation to avoid code duplication.
|
|
25156
25350
|
*
|
|
25157
25351
|
* @param id - Unique identifier for the data
|
|
25158
25352
|
* @param data - The data to store (can be a class, object, or any value)
|
|
@@ -25176,17 +25370,12 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25176
25370
|
* ```
|
|
25177
25371
|
*/
|
|
25178
25372
|
addInDatabase(id, data, options) {
|
|
25179
|
-
|
|
25180
|
-
if (database[id] !== void 0 && !options?.force) {
|
|
25181
|
-
return false;
|
|
25182
|
-
}
|
|
25183
|
-
database[id] = data;
|
|
25184
|
-
return true;
|
|
25373
|
+
return BaseRoom.prototype.addInDatabase.call(this, id, data, options);
|
|
25185
25374
|
}
|
|
25186
25375
|
/**
|
|
25187
25376
|
* Remove data from the map's database
|
|
25188
25377
|
*
|
|
25189
|
-
* This method
|
|
25378
|
+
* This method delegates to BaseRoom's implementation to avoid code duplication.
|
|
25190
25379
|
*
|
|
25191
25380
|
* @param id - Unique identifier of the data to remove
|
|
25192
25381
|
* @returns true if data was removed, false if ID didn't exist
|
|
@@ -25204,12 +25393,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25204
25393
|
* ```
|
|
25205
25394
|
*/
|
|
25206
25395
|
removeInDatabase(id) {
|
|
25207
|
-
|
|
25208
|
-
if (database[id] === void 0) {
|
|
25209
|
-
return false;
|
|
25210
|
-
}
|
|
25211
|
-
delete database[id];
|
|
25212
|
-
return true;
|
|
25396
|
+
return BaseRoom.prototype.removeInDatabase.call(this, id);
|
|
25213
25397
|
}
|
|
25214
25398
|
/**
|
|
25215
25399
|
* Creates a dynamic event on the map
|
|
@@ -25577,6 +25761,19 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25577
25761
|
}, holder);
|
|
25578
25762
|
}
|
|
25579
25763
|
}
|
|
25764
|
+
/**
|
|
25765
|
+
* Apply sync to the client
|
|
25766
|
+
*
|
|
25767
|
+
* This method applies sync to the client by calling the `$applySync()` method.
|
|
25768
|
+
*
|
|
25769
|
+
* @example
|
|
25770
|
+
* ```ts
|
|
25771
|
+
* map.applySyncToClient();
|
|
25772
|
+
* ```
|
|
25773
|
+
*/
|
|
25774
|
+
applySyncToClient() {
|
|
25775
|
+
this.$applySync();
|
|
25776
|
+
}
|
|
25580
25777
|
/**
|
|
25581
25778
|
* Create a shape dynamically on the map
|
|
25582
25779
|
*
|
|
@@ -25983,9 +26180,15 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
25983
26180
|
if (kind && result) __defProp(target, key, result);
|
|
25984
26181
|
return result;
|
|
25985
26182
|
};
|
|
25986
|
-
let LobbyRoom = class {
|
|
25987
|
-
constructor() {
|
|
26183
|
+
let LobbyRoom = class extends BaseRoom {
|
|
26184
|
+
constructor(room) {
|
|
26185
|
+
super();
|
|
25988
26186
|
this.players = signal({});
|
|
26187
|
+
this.autoSync = true;
|
|
26188
|
+
const isTest = room.env.TEST === "true" ? true : false;
|
|
26189
|
+
if (isTest) {
|
|
26190
|
+
this.autoSync = false;
|
|
26191
|
+
}
|
|
25989
26192
|
}
|
|
25990
26193
|
onJoin(player, conn) {
|
|
25991
26194
|
player.map = this;
|
|
@@ -26338,6 +26541,19 @@ function provideServerModules(modules) {
|
|
|
26338
26541
|
}
|
|
26339
26542
|
};
|
|
26340
26543
|
}
|
|
26544
|
+
if (module.database && typeof module.database === "object") {
|
|
26545
|
+
const database = { ...module.database };
|
|
26546
|
+
module = {
|
|
26547
|
+
...module,
|
|
26548
|
+
databaseHooks: {
|
|
26549
|
+
load: (engine) => {
|
|
26550
|
+
for (const key in database) {
|
|
26551
|
+
engine.addInDatabase(key, database[key]);
|
|
26552
|
+
}
|
|
26553
|
+
}
|
|
26554
|
+
}
|
|
26555
|
+
};
|
|
26556
|
+
}
|
|
26341
26557
|
return module;
|
|
26342
26558
|
});
|
|
26343
26559
|
return modules2;
|