@rpgjs/server 5.0.0-alpha.25 → 5.0.0-alpha.27
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/MoveManager.d.ts +62 -1
- package/dist/Player/Player.d.ts +33 -22
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1827 -365
- 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 +10 -10
- package/src/Player/ItemManager.ts +50 -15
- package/src/Player/MoveManager.ts +654 -112
- package/src/Player/Player.ts +179 -136
- package/src/index.ts +2 -1
- 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 +70 -146
- package/tests/change-map.spec.ts +2 -2
- package/tests/event.spec.ts +80 -0
- package/tests/item.spec.ts +455 -441
- package/tests/move.spec.ts +601 -0
- package/tests/random-move.spec.ts +65 -0
- package/tests/world-maps.spec.ts +43 -81
package/dist/index.js
CHANGED
|
@@ -5608,13 +5608,13 @@ function fromIterable(iterable) {
|
|
|
5608
5608
|
}
|
|
5609
5609
|
function fromAsyncIterable(asyncIterable) {
|
|
5610
5610
|
return new Observable(function (subscriber) {
|
|
5611
|
-
process$
|
|
5611
|
+
process$2(asyncIterable, subscriber).catch(function (err) { return subscriber.error(err); });
|
|
5612
5612
|
});
|
|
5613
5613
|
}
|
|
5614
5614
|
function fromReadableStreamLike(readableStream) {
|
|
5615
5615
|
return fromAsyncIterable(readableStreamLikeToAsyncGenerator(readableStream));
|
|
5616
5616
|
}
|
|
5617
|
-
function process$
|
|
5617
|
+
function process$2(asyncIterable, subscriber) {
|
|
5618
5618
|
var asyncIterable_1, asyncIterable_1_1;
|
|
5619
5619
|
var e_2, _a;
|
|
5620
5620
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -6065,7 +6065,7 @@ function toArray() {
|
|
|
6065
6065
|
});
|
|
6066
6066
|
}
|
|
6067
6067
|
|
|
6068
|
-
function finalize(callback) {
|
|
6068
|
+
function finalize$1(callback) {
|
|
6069
6069
|
return operate(function (source, subscriber) {
|
|
6070
6070
|
try {
|
|
6071
6071
|
source.subscribe(subscriber);
|
|
@@ -6517,7 +6517,7 @@ function computed(computeFunction, disposableFn) {
|
|
|
6517
6517
|
}
|
|
6518
6518
|
return dep.observable;
|
|
6519
6519
|
});
|
|
6520
|
-
const computedObservable = combineLatest(observables).pipe(filter(() => !init), map(() => computeFunction()), finalize(() => disposableFn?.()));
|
|
6520
|
+
const computedObservable = combineLatest(observables).pipe(filter(() => !init), map(() => computeFunction()), finalize$1(() => disposableFn?.()));
|
|
6521
6521
|
const fn = /* @__PURE__ */ __name$2(function() {
|
|
6522
6522
|
trackDependency(fn);
|
|
6523
6523
|
return lastComputedValue;
|
|
@@ -7743,12 +7743,46 @@ 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();
|
|
7748
|
+
instance.$pendingInitialSync = /* @__PURE__ */ new Map();
|
|
7746
7749
|
instance.$send = (conn, obj) => {
|
|
7747
7750
|
return this.send(conn, obj, instance);
|
|
7748
7751
|
};
|
|
7749
7752
|
instance.$broadcast = (obj) => {
|
|
7750
7753
|
return this.broadcast(obj, instance);
|
|
7751
7754
|
};
|
|
7755
|
+
instance.$applySync = () => {
|
|
7756
|
+
let packet;
|
|
7757
|
+
if (instance.$pendingSync.size > 0) {
|
|
7758
|
+
if (options.getMemoryAll) {
|
|
7759
|
+
buildObject(instance.$pendingSync, instance.$memoryAll);
|
|
7760
|
+
}
|
|
7761
|
+
packet = buildObject(instance.$pendingSync, instance.$memoryAll);
|
|
7762
|
+
instance.$pendingSync.clear();
|
|
7763
|
+
} else {
|
|
7764
|
+
packet = instance.$memoryAll;
|
|
7765
|
+
}
|
|
7766
|
+
const pendingConnections = new Set(instance.$pendingInitialSync.keys());
|
|
7767
|
+
for (const [conn, publicId] of instance.$pendingInitialSync) {
|
|
7768
|
+
this.send(conn, {
|
|
7769
|
+
type: "sync",
|
|
7770
|
+
value: {
|
|
7771
|
+
pId: publicId,
|
|
7772
|
+
...packet
|
|
7773
|
+
}
|
|
7774
|
+
}, instance);
|
|
7775
|
+
}
|
|
7776
|
+
instance.$pendingInitialSync.clear();
|
|
7777
|
+
for (const conn of this.room.getConnections()) {
|
|
7778
|
+
if (!pendingConnections.has(conn)) {
|
|
7779
|
+
this.send(conn, {
|
|
7780
|
+
type: "sync",
|
|
7781
|
+
value: packet
|
|
7782
|
+
}, instance);
|
|
7783
|
+
}
|
|
7784
|
+
}
|
|
7785
|
+
};
|
|
7752
7786
|
instance.$sessionTransfer = async (conn, targetRoomId) => {
|
|
7753
7787
|
let user;
|
|
7754
7788
|
const signal2 = this.getUsersProperty(instance);
|
|
@@ -7815,6 +7849,13 @@ var Server = class {
|
|
|
7815
7849
|
init = false;
|
|
7816
7850
|
return;
|
|
7817
7851
|
}
|
|
7852
|
+
if (!instance.$autoSync) {
|
|
7853
|
+
for (const [path, value] of values) {
|
|
7854
|
+
instance.$pendingSync.set(path, value);
|
|
7855
|
+
}
|
|
7856
|
+
values.clear();
|
|
7857
|
+
return;
|
|
7858
|
+
}
|
|
7818
7859
|
const packet = buildObject(values, instance.$memoryAll);
|
|
7819
7860
|
this.broadcast({
|
|
7820
7861
|
type: "sync",
|
|
@@ -7839,11 +7880,12 @@ var Server = class {
|
|
|
7839
7880
|
values.clear();
|
|
7840
7881
|
}, "persistCb");
|
|
7841
7882
|
syncClass(instance, {
|
|
7842
|
-
onSync: throttle(syncCb, instance["throttleSync"]
|
|
7843
|
-
onPersist: throttle(persistCb, instance["throttleStorage"]
|
|
7883
|
+
onSync: instance["throttleSync"] ? throttle(syncCb, instance["throttleSync"]) : syncCb,
|
|
7884
|
+
onPersist: instance["throttleStorage"] ? throttle(persistCb, instance["throttleStorage"]) : persistCb
|
|
7844
7885
|
});
|
|
7845
7886
|
await loadMemory();
|
|
7846
7887
|
initPersist = false;
|
|
7888
|
+
init = false;
|
|
7847
7889
|
return instance;
|
|
7848
7890
|
}
|
|
7849
7891
|
/**
|
|
@@ -8049,13 +8091,17 @@ var Server = class {
|
|
|
8049
8091
|
publicId
|
|
8050
8092
|
});
|
|
8051
8093
|
await awaitReturn(subRoom["onJoin"]?.(user, conn, ctx));
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8094
|
+
if (subRoom.$autoSync) {
|
|
8095
|
+
this.send(conn, {
|
|
8096
|
+
type: "sync",
|
|
8097
|
+
value: {
|
|
8098
|
+
pId: publicId,
|
|
8099
|
+
...subRoom.$memoryAll
|
|
8100
|
+
}
|
|
8101
|
+
}, subRoom);
|
|
8102
|
+
} else {
|
|
8103
|
+
subRoom.$pendingInitialSync.set(conn, publicId);
|
|
8104
|
+
}
|
|
8059
8105
|
}
|
|
8060
8106
|
/**
|
|
8061
8107
|
* @method onConnect
|
|
@@ -8340,6 +8386,9 @@ var Server = class {
|
|
|
8340
8386
|
if (!subRoom) {
|
|
8341
8387
|
return;
|
|
8342
8388
|
}
|
|
8389
|
+
if (subRoom.$pendingInitialSync) {
|
|
8390
|
+
subRoom.$pendingInitialSync.delete(conn);
|
|
8391
|
+
}
|
|
8343
8392
|
const signal2 = this.getUsersProperty(subRoom);
|
|
8344
8393
|
if (!conn.state) {
|
|
8345
8394
|
return;
|
|
@@ -9777,10 +9826,10 @@ class Item {
|
|
|
9777
9826
|
this.quantity = signal(1);
|
|
9778
9827
|
this.onAdd = () => {
|
|
9779
9828
|
};
|
|
9780
|
-
this.description.set(data
|
|
9781
|
-
this.price.set(data
|
|
9782
|
-
this.name.set(data
|
|
9783
|
-
this.onAdd = data
|
|
9829
|
+
this.description.set(data?.description ?? "");
|
|
9830
|
+
this.price.set(data?.price ?? 0);
|
|
9831
|
+
this.name.set(data?.name ?? "");
|
|
9832
|
+
this.onAdd = data?.onAdd?.bind(this) ?? (() => {
|
|
9784
9833
|
});
|
|
9785
9834
|
}
|
|
9786
9835
|
}
|
|
@@ -9934,6 +9983,9 @@ __decorateClass$3([
|
|
|
9934
9983
|
__decorateClass$3([
|
|
9935
9984
|
sync()
|
|
9936
9985
|
], RpgCommonPlayer.prototype, "_gold");
|
|
9986
|
+
__decorateClass$3([
|
|
9987
|
+
sync()
|
|
9988
|
+
], RpgCommonPlayer.prototype, "animationName");
|
|
9937
9989
|
__decorateClass$3([
|
|
9938
9990
|
sync()
|
|
9939
9991
|
], RpgCommonPlayer.prototype, "hpSignal");
|
|
@@ -15236,29 +15288,6 @@ class Knockback {
|
|
|
15236
15288
|
}
|
|
15237
15289
|
}
|
|
15238
15290
|
|
|
15239
|
-
class LinearMove {
|
|
15240
|
-
/**
|
|
15241
|
-
* Creates a linear movement strategy.
|
|
15242
|
-
*
|
|
15243
|
-
* @param velocity - Velocity to apply (units per second)
|
|
15244
|
-
* @param duration - Optional duration in seconds (undefined for infinite)
|
|
15245
|
-
*/
|
|
15246
|
-
constructor(velocity, duration) {
|
|
15247
|
-
this.velocity = velocity;
|
|
15248
|
-
this.duration = duration;
|
|
15249
|
-
this.elapsed = 0;
|
|
15250
|
-
}
|
|
15251
|
-
update(body, dt) {
|
|
15252
|
-
if (this.duration !== void 0) {
|
|
15253
|
-
this.elapsed += dt;
|
|
15254
|
-
}
|
|
15255
|
-
body.setVelocity(this.velocity);
|
|
15256
|
-
}
|
|
15257
|
-
isFinished() {
|
|
15258
|
-
return this.duration !== void 0 && this.elapsed >= this.duration;
|
|
15259
|
-
}
|
|
15260
|
-
}
|
|
15261
|
-
|
|
15262
15291
|
class LinearRepulsion {
|
|
15263
15292
|
/**
|
|
15264
15293
|
* @param engine - Physics engine used for spatial queries
|
|
@@ -15777,8 +15806,17 @@ class RpgCommonMap {
|
|
|
15777
15806
|
});
|
|
15778
15807
|
this.moveManager = new MovementManager(() => this.physic);
|
|
15779
15808
|
this.speedScalar = 50;
|
|
15809
|
+
// Default speed scalar for movement
|
|
15810
|
+
// World Maps properties
|
|
15811
|
+
this.tileWidth = 32;
|
|
15812
|
+
this.tileHeight = 32;
|
|
15780
15813
|
this.physicsAccumulatorMs = 0;
|
|
15781
15814
|
this.physicsSyncDepth = 0;
|
|
15815
|
+
/**
|
|
15816
|
+
* Whether to automatically subscribe to tick$ for physics updates
|
|
15817
|
+
* Set to false in test environments for manual control with nextTick()
|
|
15818
|
+
*/
|
|
15819
|
+
this.autoTickEnabled = true;
|
|
15782
15820
|
/**
|
|
15783
15821
|
* Observable representing the game loop tick
|
|
15784
15822
|
*
|
|
@@ -15831,6 +15869,88 @@ class RpgCommonMap {
|
|
|
15831
15869
|
get isStandalone() {
|
|
15832
15870
|
return typeof window !== "undefined";
|
|
15833
15871
|
}
|
|
15872
|
+
/**
|
|
15873
|
+
* Get the width of the map in pixels
|
|
15874
|
+
*
|
|
15875
|
+
* @returns The width of the map in pixels, or 0 if not loaded
|
|
15876
|
+
*
|
|
15877
|
+
* @example
|
|
15878
|
+
* ```ts
|
|
15879
|
+
* const width = map.widthPx;
|
|
15880
|
+
* console.log(`Map width: ${width}px`);
|
|
15881
|
+
* ```
|
|
15882
|
+
*/
|
|
15883
|
+
get widthPx() {
|
|
15884
|
+
return this.data()?.width ?? 0;
|
|
15885
|
+
}
|
|
15886
|
+
/**
|
|
15887
|
+
* Get the height of the map in pixels
|
|
15888
|
+
*
|
|
15889
|
+
* @returns The height of the map in pixels, or 0 if not loaded
|
|
15890
|
+
*
|
|
15891
|
+
* @example
|
|
15892
|
+
* ```ts
|
|
15893
|
+
* const height = map.heightPx;
|
|
15894
|
+
* console.log(`Map height: ${height}px`);
|
|
15895
|
+
* ```
|
|
15896
|
+
*/
|
|
15897
|
+
get heightPx() {
|
|
15898
|
+
return this.data()?.height ?? 0;
|
|
15899
|
+
}
|
|
15900
|
+
/**
|
|
15901
|
+
* Get the unique identifier of the map
|
|
15902
|
+
*
|
|
15903
|
+
* @returns The map ID, or empty string if not loaded
|
|
15904
|
+
*
|
|
15905
|
+
* @example
|
|
15906
|
+
* ```ts
|
|
15907
|
+
* const mapId = map.id;
|
|
15908
|
+
* console.log(`Current map: ${mapId}`);
|
|
15909
|
+
* ```
|
|
15910
|
+
*/
|
|
15911
|
+
get id() {
|
|
15912
|
+
return this.data()?.id ?? "";
|
|
15913
|
+
}
|
|
15914
|
+
/**
|
|
15915
|
+
* Get the X position of this map in the world coordinate system
|
|
15916
|
+
*
|
|
15917
|
+
* This is used when maps are part of a larger world map. The world position
|
|
15918
|
+
* indicates where this map is located relative to other maps.
|
|
15919
|
+
*
|
|
15920
|
+
* @returns The X position in world coordinates, or 0 if not in a world
|
|
15921
|
+
*
|
|
15922
|
+
* @example
|
|
15923
|
+
* ```ts
|
|
15924
|
+
* const worldX = map.worldX;
|
|
15925
|
+
* console.log(`Map is at world position (${worldX}, ${map.worldY})`);
|
|
15926
|
+
* ```
|
|
15927
|
+
*/
|
|
15928
|
+
get worldX() {
|
|
15929
|
+
const worldMaps = this.getWorldMapsManager?.();
|
|
15930
|
+
if (!worldMaps) return 0;
|
|
15931
|
+
const mapId = this.id.startsWith("map-") ? this.id.slice(4) : this.id;
|
|
15932
|
+
return worldMaps.getMapInfo(mapId)?.worldX ?? 0;
|
|
15933
|
+
}
|
|
15934
|
+
/**
|
|
15935
|
+
* Get the Y position of this map in the world coordinate system
|
|
15936
|
+
*
|
|
15937
|
+
* This is used when maps are part of a larger world map. The world position
|
|
15938
|
+
* indicates where this map is located relative to other maps.
|
|
15939
|
+
*
|
|
15940
|
+
* @returns The Y position in world coordinates, or 0 if not in a world
|
|
15941
|
+
*
|
|
15942
|
+
* @example
|
|
15943
|
+
* ```ts
|
|
15944
|
+
* const worldY = map.worldY;
|
|
15945
|
+
* console.log(`Map is at world position (${map.worldX}, ${worldY})`);
|
|
15946
|
+
* ```
|
|
15947
|
+
*/
|
|
15948
|
+
get worldY() {
|
|
15949
|
+
const worldMaps = this.getWorldMapsManager?.();
|
|
15950
|
+
if (!worldMaps) return 0;
|
|
15951
|
+
const mapId = this.id.startsWith("map-") ? this.id.slice(4) : this.id;
|
|
15952
|
+
return worldMaps.getMapInfo(mapId)?.worldY ?? 0;
|
|
15953
|
+
}
|
|
15834
15954
|
/**
|
|
15835
15955
|
* Clear all physics content and reset to initial state
|
|
15836
15956
|
*
|
|
@@ -15930,9 +16050,11 @@ class RpgCommonMap {
|
|
|
15930
16050
|
this.updateCharacterHitbox(event);
|
|
15931
16051
|
}
|
|
15932
16052
|
});
|
|
15933
|
-
|
|
15934
|
-
this.
|
|
15935
|
-
|
|
16053
|
+
if (this.autoTickEnabled) {
|
|
16054
|
+
this.tickSubscription = this.tick$.subscribe(({ delta }) => {
|
|
16055
|
+
this.runFixedTicks(delta);
|
|
16056
|
+
});
|
|
16057
|
+
}
|
|
15936
16058
|
}
|
|
15937
16059
|
async movePlayer(player, direction) {
|
|
15938
16060
|
const currentX = player.x();
|
|
@@ -15954,12 +16076,8 @@ class RpgCommonMap {
|
|
|
15954
16076
|
nextY = currentY + speed;
|
|
15955
16077
|
break;
|
|
15956
16078
|
}
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
} else if (typeof player.changeDirection === "function") {
|
|
15960
|
-
player.changeDirection(direction);
|
|
15961
|
-
}
|
|
15962
|
-
if (typeof player.autoChangeMap === "function") {
|
|
16079
|
+
player.changeDirection(direction);
|
|
16080
|
+
if (typeof player.autoChangeMap === "function" && !player.isEvent()) {
|
|
15963
16081
|
const mapChanged = await player.autoChangeMap({ x: nextX, y: nextY }, direction);
|
|
15964
16082
|
if (mapChanged) {
|
|
15965
16083
|
this.stopMovement(player);
|
|
@@ -16043,6 +16161,46 @@ class RpgCommonMap {
|
|
|
16043
16161
|
}
|
|
16044
16162
|
return executed;
|
|
16045
16163
|
}
|
|
16164
|
+
/**
|
|
16165
|
+
* Manually trigger a single game tick
|
|
16166
|
+
*
|
|
16167
|
+
* This method allows you to manually advance the game by one tick (16ms at 60fps).
|
|
16168
|
+
* It's primarily useful for testing where you need precise control over when
|
|
16169
|
+
* physics updates occur, rather than relying on the automatic tick$ subscription.
|
|
16170
|
+
*
|
|
16171
|
+
* ## Use Cases
|
|
16172
|
+
*
|
|
16173
|
+
* - **Testing**: Control exactly when physics steps occur in unit tests
|
|
16174
|
+
* - **Manual control**: Step through game state manually for debugging
|
|
16175
|
+
* - **Deterministic testing**: Ensure consistent timing in test scenarios
|
|
16176
|
+
*
|
|
16177
|
+
* ## Important
|
|
16178
|
+
*
|
|
16179
|
+
* This method should NOT be used in production code alongside the automatic `tick$`
|
|
16180
|
+
* subscription, as it will cause double-stepping. Use either:
|
|
16181
|
+
* - Automatic ticks (via `loadPhysic()` which subscribes to `tick$`)
|
|
16182
|
+
* - Manual ticks (via `nextTick()` without `loadPhysic()` subscription)
|
|
16183
|
+
*
|
|
16184
|
+
* @param deltaMs - Optional delta time in milliseconds (default: 16ms for 60fps)
|
|
16185
|
+
* @returns Number of physics ticks executed
|
|
16186
|
+
*
|
|
16187
|
+
* @example
|
|
16188
|
+
* ```ts
|
|
16189
|
+
* // In tests: manually advance game by one tick
|
|
16190
|
+
* map.nextTick(); // Advances by 16ms (one frame at 60fps)
|
|
16191
|
+
*
|
|
16192
|
+
* // With custom delta
|
|
16193
|
+
* map.nextTick(32); // Advances by 32ms (two frames at 60fps)
|
|
16194
|
+
*
|
|
16195
|
+
* // In a test loop
|
|
16196
|
+
* for (let i = 0; i < 60; i++) {
|
|
16197
|
+
* map.nextTick(); // Simulate 1 second of game time
|
|
16198
|
+
* }
|
|
16199
|
+
* ```
|
|
16200
|
+
*/
|
|
16201
|
+
nextTick(deltaMs = 16) {
|
|
16202
|
+
return this.runFixedTicks(deltaMs);
|
|
16203
|
+
}
|
|
16046
16204
|
/**
|
|
16047
16205
|
* Force a single physics tick outside of the normal game loop
|
|
16048
16206
|
*
|
|
@@ -16092,19 +16250,12 @@ class RpgCommonMap {
|
|
|
16092
16250
|
const hitbox = typeof owner.hitbox === "function" ? owner.hitbox() : owner.hitbox;
|
|
16093
16251
|
const width = hitbox?.w ?? 32;
|
|
16094
16252
|
const height = hitbox?.h ?? 32;
|
|
16095
|
-
const topLeftX = this.resolveNumeric(owner.x);
|
|
16096
|
-
const topLeftY = this.resolveNumeric(owner.y);
|
|
16097
|
-
const centerX = topLeftX + width / 2;
|
|
16098
|
-
const centerY = topLeftY + height / 2;
|
|
16099
16253
|
const radius = Math.max(width, height) / 2;
|
|
16100
|
-
const speedValue = typeof owner.speed === "function" ? owner.speed() : typeof owner.speed === "number" ? owner.speed : void 0;
|
|
16101
16254
|
this.addCharacter({
|
|
16102
16255
|
owner,
|
|
16103
|
-
x: centerX,
|
|
16104
|
-
y: centerY,
|
|
16105
16256
|
radius,
|
|
16106
16257
|
kind,
|
|
16107
|
-
maxSpeed:
|
|
16258
|
+
maxSpeed: owner.speed(),
|
|
16108
16259
|
collidesWithCharacters: !this.shouldDisableCharacterCollisions(owner),
|
|
16109
16260
|
isStatic: options?.isStatic,
|
|
16110
16261
|
mass: options?.mass
|
|
@@ -16476,11 +16627,24 @@ class RpgCommonMap {
|
|
|
16476
16627
|
owner2.changeDirection(cardinalDirection);
|
|
16477
16628
|
});
|
|
16478
16629
|
entity.onMovementChange(({ isMoving, intensity }) => {
|
|
16630
|
+
const owner2 = entity.owner;
|
|
16631
|
+
if (!owner2) return;
|
|
16479
16632
|
const LOW_INTENSITY_THRESHOLD = 10;
|
|
16633
|
+
const hasSetAnimation = typeof owner2.setAnimation === "function";
|
|
16634
|
+
const animationNameSignal = owner2.animationName;
|
|
16635
|
+
const ownerHasAnimationName = animationNameSignal && typeof animationNameSignal === "object" && typeof animationNameSignal.set === "function";
|
|
16480
16636
|
if (isMoving && intensity > LOW_INTENSITY_THRESHOLD) {
|
|
16481
|
-
|
|
16637
|
+
if (hasSetAnimation) {
|
|
16638
|
+
owner2.setAnimation("walk");
|
|
16639
|
+
} else if (ownerHasAnimationName) {
|
|
16640
|
+
animationNameSignal.set("walk");
|
|
16641
|
+
}
|
|
16482
16642
|
} else if (!isMoving) {
|
|
16483
|
-
|
|
16643
|
+
if (hasSetAnimation) {
|
|
16644
|
+
owner2.setAnimation("stand");
|
|
16645
|
+
} else if (ownerHasAnimationName) {
|
|
16646
|
+
animationNameSignal.set("stand");
|
|
16647
|
+
}
|
|
16484
16648
|
}
|
|
16485
16649
|
});
|
|
16486
16650
|
const entityWidth = width;
|
|
@@ -16555,10 +16719,7 @@ class RpgCommonMap {
|
|
|
16555
16719
|
moveBody(player, direction) {
|
|
16556
16720
|
const entity = this.physic.getEntityByUUID(player.id);
|
|
16557
16721
|
if (!entity) return false;
|
|
16558
|
-
const speedValue =
|
|
16559
|
-
if (typeof player.setIntendedDirection === "function") {
|
|
16560
|
-
player.setIntendedDirection(direction);
|
|
16561
|
-
}
|
|
16722
|
+
const speedValue = player.speed();
|
|
16562
16723
|
let vx = 0, vy = 0;
|
|
16563
16724
|
switch (direction) {
|
|
16564
16725
|
case Direction.Left:
|
|
@@ -16610,9 +16771,6 @@ class RpgCommonMap {
|
|
|
16610
16771
|
const entity = this.physic.getEntityByUUID(player.id);
|
|
16611
16772
|
if (!entity) return false;
|
|
16612
16773
|
this.moveManager.stopMovement(player.id);
|
|
16613
|
-
if (typeof player.setIntendedDirection === "function") {
|
|
16614
|
-
player.setIntendedDirection(null);
|
|
16615
|
-
}
|
|
16616
16774
|
player.pendingInputs = [];
|
|
16617
16775
|
return true;
|
|
16618
16776
|
}
|
|
@@ -16922,17 +17080,19 @@ class WorldMapsManager {
|
|
|
16922
17080
|
if (typeof search === "number") {
|
|
16923
17081
|
const src = map;
|
|
16924
17082
|
return maps.filter((m) => {
|
|
16925
|
-
const
|
|
16926
|
-
const
|
|
17083
|
+
const horizontallyOverlapsOrTouches = Math.max(src.worldX, m.worldX) <= Math.min(src.worldX + src.widthPx, m.worldX + m.widthPx);
|
|
17084
|
+
const verticallyOverlapsOrTouches = Math.max(src.worldY, m.worldY) <= Math.min(src.worldY + src.heightPx, m.worldY + m.heightPx);
|
|
17085
|
+
const marginLeftRight = src.tileWidth / 2;
|
|
17086
|
+
const marginTopDown = src.tileHeight / 2;
|
|
16927
17087
|
switch (search) {
|
|
16928
17088
|
case 0:
|
|
16929
|
-
return
|
|
17089
|
+
return verticallyOverlapsOrTouches && m.worldY + m.heightPx - marginTopDown === src.worldY;
|
|
16930
17090
|
case 1:
|
|
16931
|
-
return
|
|
17091
|
+
return verticallyOverlapsOrTouches && m.worldY + marginTopDown === src.worldY + src.heightPx;
|
|
16932
17092
|
case 2:
|
|
16933
|
-
return
|
|
17093
|
+
return horizontallyOverlapsOrTouches && m.worldX + m.widthPx - marginLeftRight === src.worldX;
|
|
16934
17094
|
case 3:
|
|
16935
|
-
return
|
|
17095
|
+
return horizontallyOverlapsOrTouches && m.worldX + marginLeftRight === src.worldX + src.widthPx;
|
|
16936
17096
|
default:
|
|
16937
17097
|
return false;
|
|
16938
17098
|
}
|
|
@@ -16940,7 +17100,7 @@ class WorldMapsManager {
|
|
|
16940
17100
|
}
|
|
16941
17101
|
if ("x" in search && "y" in search) {
|
|
16942
17102
|
const found = maps.find(
|
|
16943
|
-
(m) => search.x >= m.worldX && search.x < m.worldX + m.
|
|
17103
|
+
(m) => search.x >= m.worldX && search.x < m.worldX + m.widthPx && search.y >= m.worldY && search.y < m.worldY + m.heightPx
|
|
16944
17104
|
);
|
|
16945
17105
|
return found ? [found] : [];
|
|
16946
17106
|
}
|
|
@@ -16948,9 +17108,9 @@ class WorldMapsManager {
|
|
|
16948
17108
|
const { minX, minY, maxX, maxY } = search;
|
|
16949
17109
|
return maps.filter((m) => {
|
|
16950
17110
|
const aLeft = m.worldX;
|
|
16951
|
-
const aRight = m.worldX + m.
|
|
17111
|
+
const aRight = m.worldX + m.widthPx;
|
|
16952
17112
|
const aTop = m.worldY;
|
|
16953
|
-
const aBottom = m.worldY + m.
|
|
17113
|
+
const aBottom = m.worldY + m.heightPx;
|
|
16954
17114
|
const bLeft = minX;
|
|
16955
17115
|
const bRight = maxX;
|
|
16956
17116
|
const bTop = minY;
|
|
@@ -17193,6 +17353,204 @@ var PrebuiltGui = /* @__PURE__ */ ((PrebuiltGui2) => {
|
|
|
17193
17353
|
return PrebuiltGui2;
|
|
17194
17354
|
})(PrebuiltGui || {});
|
|
17195
17355
|
|
|
17356
|
+
class PerlinNoise2D {
|
|
17357
|
+
/**
|
|
17358
|
+
* Creates a new Perlin noise generator
|
|
17359
|
+
*
|
|
17360
|
+
* @param seed - Optional seed for deterministic noise generation. If not provided, uses a default seed.
|
|
17361
|
+
*
|
|
17362
|
+
* @example
|
|
17363
|
+
* ```ts
|
|
17364
|
+
* const noise = new PerlinNoise2D(12345);
|
|
17365
|
+
* const value = noise.get(10, 20);
|
|
17366
|
+
* ```
|
|
17367
|
+
*/
|
|
17368
|
+
constructor(seed = 0) {
|
|
17369
|
+
this.permutation = this.generatePermutation(seed);
|
|
17370
|
+
this.p = [...this.permutation, ...this.permutation];
|
|
17371
|
+
}
|
|
17372
|
+
/**
|
|
17373
|
+
* Generates a permutation table based on seed
|
|
17374
|
+
*
|
|
17375
|
+
* @param seed - Seed value for permutation generation
|
|
17376
|
+
* @returns Array of 256 shuffled values
|
|
17377
|
+
*/
|
|
17378
|
+
generatePermutation(seed) {
|
|
17379
|
+
const p = [];
|
|
17380
|
+
for (let i = 0; i < 256; i++) {
|
|
17381
|
+
p[i] = i;
|
|
17382
|
+
}
|
|
17383
|
+
let state = seed;
|
|
17384
|
+
const lcg = () => {
|
|
17385
|
+
state = state * 1103515245 + 12345 & 2147483647;
|
|
17386
|
+
return state;
|
|
17387
|
+
};
|
|
17388
|
+
for (let i = 255; i > 0; i--) {
|
|
17389
|
+
const j = lcg() % (i + 1);
|
|
17390
|
+
[p[i], p[j]] = [p[j], p[i]];
|
|
17391
|
+
}
|
|
17392
|
+
return p;
|
|
17393
|
+
}
|
|
17394
|
+
/**
|
|
17395
|
+
* Fade function for smooth interpolation (ease curve)
|
|
17396
|
+
*
|
|
17397
|
+
* @param t - Value between 0 and 1
|
|
17398
|
+
* @returns Smoothed value between 0 and 1
|
|
17399
|
+
*/
|
|
17400
|
+
fade(t) {
|
|
17401
|
+
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
17402
|
+
}
|
|
17403
|
+
/**
|
|
17404
|
+
* Linear interpolation
|
|
17405
|
+
*
|
|
17406
|
+
* @param a - Start value
|
|
17407
|
+
* @param b - End value
|
|
17408
|
+
* @param t - Interpolation factor (0 to 1)
|
|
17409
|
+
* @returns Interpolated value
|
|
17410
|
+
*/
|
|
17411
|
+
lerp(a, b, t) {
|
|
17412
|
+
return a + t * (b - a);
|
|
17413
|
+
}
|
|
17414
|
+
/**
|
|
17415
|
+
* Gradient function - generates a pseudo-random gradient vector
|
|
17416
|
+
*
|
|
17417
|
+
* @param hash - Hash value from permutation table
|
|
17418
|
+
* @param x - X component
|
|
17419
|
+
* @param y - Y component
|
|
17420
|
+
* @returns Dot product of gradient and position
|
|
17421
|
+
*/
|
|
17422
|
+
grad(hash, x, y) {
|
|
17423
|
+
const h = hash & 3;
|
|
17424
|
+
switch (h) {
|
|
17425
|
+
case 0:
|
|
17426
|
+
return x + y;
|
|
17427
|
+
// (1, 1)
|
|
17428
|
+
case 1:
|
|
17429
|
+
return -x + y;
|
|
17430
|
+
// (-1, 1)
|
|
17431
|
+
case 2:
|
|
17432
|
+
return x - y;
|
|
17433
|
+
// (1, -1)
|
|
17434
|
+
case 3:
|
|
17435
|
+
return -x - y;
|
|
17436
|
+
// (-1, -1)
|
|
17437
|
+
default:
|
|
17438
|
+
return 0;
|
|
17439
|
+
}
|
|
17440
|
+
}
|
|
17441
|
+
/**
|
|
17442
|
+
* Gets the noise value at the specified 2D coordinates
|
|
17443
|
+
*
|
|
17444
|
+
* Returns a value between approximately -1 and 1, though values near the edges
|
|
17445
|
+
* are less common. For practical use, you may want to clamp or normalize the result.
|
|
17446
|
+
*
|
|
17447
|
+
* @param x - X coordinate
|
|
17448
|
+
* @param y - Y coordinate
|
|
17449
|
+
* @param scale - Optional scale factor (default: 0.1). Lower values create smoother, larger patterns.
|
|
17450
|
+
* @returns Noise value between approximately -1 and 1
|
|
17451
|
+
*
|
|
17452
|
+
* @example
|
|
17453
|
+
* ```ts
|
|
17454
|
+
* const noise = new PerlinNoise2D();
|
|
17455
|
+
* const value = noise.get(10, 20); // Basic usage
|
|
17456
|
+
* const scaled = noise.get(10, 20, 0.05); // Smoother pattern
|
|
17457
|
+
* ```
|
|
17458
|
+
*/
|
|
17459
|
+
get(x, y, scale = 0.1) {
|
|
17460
|
+
x *= scale;
|
|
17461
|
+
y *= scale;
|
|
17462
|
+
const X = Math.floor(x) & 255;
|
|
17463
|
+
const Y = Math.floor(y) & 255;
|
|
17464
|
+
x -= Math.floor(x);
|
|
17465
|
+
y -= Math.floor(y);
|
|
17466
|
+
const u = this.fade(x);
|
|
17467
|
+
const v = this.fade(y);
|
|
17468
|
+
const A = this.p[X] + Y;
|
|
17469
|
+
const AA = this.p[A];
|
|
17470
|
+
const AB = this.p[A + 1];
|
|
17471
|
+
const B = this.p[X + 1] + Y;
|
|
17472
|
+
const BA = this.p[B];
|
|
17473
|
+
const BB = this.p[B + 1];
|
|
17474
|
+
return this.lerp(
|
|
17475
|
+
this.lerp(
|
|
17476
|
+
this.grad(this.p[AA], x, y),
|
|
17477
|
+
this.grad(this.p[BA], x - 1, y),
|
|
17478
|
+
u
|
|
17479
|
+
),
|
|
17480
|
+
this.lerp(
|
|
17481
|
+
this.grad(this.p[AB], x, y - 1),
|
|
17482
|
+
this.grad(this.p[BB], x - 1, y - 1),
|
|
17483
|
+
u
|
|
17484
|
+
),
|
|
17485
|
+
v
|
|
17486
|
+
);
|
|
17487
|
+
}
|
|
17488
|
+
/**
|
|
17489
|
+
* Gets a normalized noise value between 0 and 1
|
|
17490
|
+
*
|
|
17491
|
+
* Convenience method that normalizes the noise output to a 0-1 range.
|
|
17492
|
+
*
|
|
17493
|
+
* @param x - X coordinate
|
|
17494
|
+
* @param y - Y coordinate
|
|
17495
|
+
* @param scale - Optional scale factor (default: 0.1)
|
|
17496
|
+
* @returns Noise value between 0 and 1
|
|
17497
|
+
*
|
|
17498
|
+
* @example
|
|
17499
|
+
* ```ts
|
|
17500
|
+
* const noise = new PerlinNoise2D();
|
|
17501
|
+
* const normalized = noise.getNormalized(10, 20);
|
|
17502
|
+
* // Returns value between 0 and 1
|
|
17503
|
+
* ```
|
|
17504
|
+
*/
|
|
17505
|
+
getNormalized(x, y, scale = 0.1) {
|
|
17506
|
+
return (this.get(x, y, scale) + 1) * 0.5;
|
|
17507
|
+
}
|
|
17508
|
+
/**
|
|
17509
|
+
* Gets a noise value mapped to a specific range
|
|
17510
|
+
*
|
|
17511
|
+
* Maps the noise output to a custom min-max range.
|
|
17512
|
+
*
|
|
17513
|
+
* @param x - X coordinate
|
|
17514
|
+
* @param y - Y coordinate
|
|
17515
|
+
* @param min - Minimum output value
|
|
17516
|
+
* @param max - Maximum output value
|
|
17517
|
+
* @param scale - Optional scale factor (default: 0.1)
|
|
17518
|
+
* @returns Noise value between min and max
|
|
17519
|
+
*
|
|
17520
|
+
* @example
|
|
17521
|
+
* ```ts
|
|
17522
|
+
* const noise = new PerlinNoise2D();
|
|
17523
|
+
* const direction = noise.getRange(10, 20, 0, 3); // Returns 0, 1, 2, or 3
|
|
17524
|
+
* ```
|
|
17525
|
+
*/
|
|
17526
|
+
getRange(x, y, min, max, scale = 0.1) {
|
|
17527
|
+
const normalized = this.getNormalized(x, y, scale);
|
|
17528
|
+
return min + normalized * (max - min);
|
|
17529
|
+
}
|
|
17530
|
+
/**
|
|
17531
|
+
* Gets an integer noise value in a specific range (inclusive)
|
|
17532
|
+
*
|
|
17533
|
+
* Useful for selecting discrete values like array indices or enum values.
|
|
17534
|
+
*
|
|
17535
|
+
* @param x - X coordinate
|
|
17536
|
+
* @param y - Y coordinate
|
|
17537
|
+
* @param min - Minimum integer value (inclusive)
|
|
17538
|
+
* @param max - Maximum integer value (inclusive)
|
|
17539
|
+
* @param scale - Optional scale factor (default: 0.1)
|
|
17540
|
+
* @returns Integer noise value between min and max (inclusive)
|
|
17541
|
+
*
|
|
17542
|
+
* @example
|
|
17543
|
+
* ```ts
|
|
17544
|
+
* const noise = new PerlinNoise2D();
|
|
17545
|
+
* const directionIndex = noise.getInt(10, 20, 0, 3); // Returns 0, 1, 2, or 3
|
|
17546
|
+
* ```
|
|
17547
|
+
*/
|
|
17548
|
+
getInt(x, y, min, max, scale = 0.1) {
|
|
17549
|
+
const value = this.getRange(x, y, min, max + 1, scale);
|
|
17550
|
+
return Math.floor(value);
|
|
17551
|
+
}
|
|
17552
|
+
}
|
|
17553
|
+
|
|
17196
17554
|
function WithComponentManager(Base) {
|
|
17197
17555
|
return class extends Base {
|
|
17198
17556
|
setGraphic(graphic) {
|
|
@@ -17900,6 +18258,63 @@ var Speed = /* @__PURE__ */ ((Speed2) => {
|
|
|
17900
18258
|
return Speed2;
|
|
17901
18259
|
})(Speed || {});
|
|
17902
18260
|
class MoveList {
|
|
18261
|
+
static {
|
|
18262
|
+
// Shared Perlin noise instance for smooth random movement
|
|
18263
|
+
this.perlinNoise = new PerlinNoise2D();
|
|
18264
|
+
}
|
|
18265
|
+
static {
|
|
18266
|
+
this.randomCounter = 0;
|
|
18267
|
+
}
|
|
18268
|
+
static {
|
|
18269
|
+
// Instance counter for each call to ensure variation
|
|
18270
|
+
this.callCounter = 0;
|
|
18271
|
+
}
|
|
18272
|
+
/**
|
|
18273
|
+
* Gets a random direction index (0-3) using a hybrid approach for balanced randomness
|
|
18274
|
+
*
|
|
18275
|
+
* Uses a combination of hash-based pseudo-randomness and Perlin noise to ensure
|
|
18276
|
+
* fair distribution of directions while maintaining smooth, natural-looking movement patterns.
|
|
18277
|
+
* The hash function guarantees uniform distribution, while Perlin noise adds spatial/temporal coherence.
|
|
18278
|
+
*
|
|
18279
|
+
* @param player - Optional player instance for coordinate-based noise
|
|
18280
|
+
* @param index - Optional index for array-based calls to ensure variation
|
|
18281
|
+
* @returns Direction index (0-3) corresponding to Right, Left, Up, Down
|
|
18282
|
+
*/
|
|
18283
|
+
getRandomDirectionIndex(player, index) {
|
|
18284
|
+
MoveList.callCounter++;
|
|
18285
|
+
let seed;
|
|
18286
|
+
const time = Date.now() * 1e-3;
|
|
18287
|
+
if (player) {
|
|
18288
|
+
const playerX = typeof player.x === "function" ? player.x() : player.x;
|
|
18289
|
+
const playerY = typeof player.y === "function" ? player.y() : player.y;
|
|
18290
|
+
seed = Math.floor(
|
|
18291
|
+
playerX * 0.1 + playerY * 0.1 + time * 1e3 + MoveList.callCounter * 17 + (index ?? 0) * 31
|
|
18292
|
+
);
|
|
18293
|
+
} else {
|
|
18294
|
+
MoveList.randomCounter++;
|
|
18295
|
+
seed = Math.floor(
|
|
18296
|
+
MoveList.randomCounter * 17 + time * 1e3 + MoveList.callCounter * 31 + (index ?? 0) * 47
|
|
18297
|
+
);
|
|
18298
|
+
}
|
|
18299
|
+
let hash1 = (seed * 1103515245 + 12345 & 2147483647) >>> 0;
|
|
18300
|
+
let hash2 = seed * 2654435761 >>> 0;
|
|
18301
|
+
let hash3 = seed ^ seed >>> 16;
|
|
18302
|
+
hash3 = hash3 * 2246822507 >>> 0;
|
|
18303
|
+
let combinedHash = (hash1 ^ hash2 ^ hash3) >>> 0;
|
|
18304
|
+
const hashValue = combinedHash % 1e6 / 1e6;
|
|
18305
|
+
const perlinX = seed * 1e-3;
|
|
18306
|
+
const perlinY = seed * 1.618 * 1e-3;
|
|
18307
|
+
const perlinValue = MoveList.perlinNoise.getNormalized(perlinX, perlinY, 0.3);
|
|
18308
|
+
const finalValue = hashValue * 0.9 + perlinValue * 0.1;
|
|
18309
|
+
const clampedValue = Math.max(0, Math.min(0.999999, finalValue));
|
|
18310
|
+
let directionIndex = Math.floor(clampedValue * 4);
|
|
18311
|
+
directionIndex = Math.max(0, Math.min(3, directionIndex));
|
|
18312
|
+
if (!Number.isFinite(directionIndex) || directionIndex < 0 || directionIndex > 3) {
|
|
18313
|
+
const fallbackIndex = Math.floor(hashValue * 4) % 4;
|
|
18314
|
+
return Math.max(0, Math.min(3, fallbackIndex));
|
|
18315
|
+
}
|
|
18316
|
+
return directionIndex;
|
|
18317
|
+
}
|
|
17903
18318
|
repeatMove(direction, repeat) {
|
|
17904
18319
|
if (!Number.isFinite(repeat) || repeat < 0 || repeat > 1e4) {
|
|
17905
18320
|
console.warn("Invalid repeat value:", repeat, "using default value 1");
|
|
@@ -17967,12 +18382,16 @@ class MoveList {
|
|
|
17967
18382
|
repeat = 1;
|
|
17968
18383
|
}
|
|
17969
18384
|
try {
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17974
|
-
|
|
17975
|
-
|
|
18385
|
+
MoveList.randomCounter += repeat;
|
|
18386
|
+
return new Array(repeat).fill(null).map((_, index) => {
|
|
18387
|
+
const directionIndex = this.getRandomDirectionIndex(void 0, index);
|
|
18388
|
+
return [
|
|
18389
|
+
Direction.Right,
|
|
18390
|
+
Direction.Left,
|
|
18391
|
+
Direction.Up,
|
|
18392
|
+
Direction.Down
|
|
18393
|
+
][directionIndex];
|
|
18394
|
+
});
|
|
17976
18395
|
} catch (error) {
|
|
17977
18396
|
console.error("Error creating random array with repeat:", repeat, error);
|
|
17978
18397
|
return [Direction.Down];
|
|
@@ -17998,13 +18417,23 @@ class MoveList {
|
|
|
17998
18417
|
}
|
|
17999
18418
|
repeat = Math.floor(repeat);
|
|
18000
18419
|
let directions = [];
|
|
18420
|
+
const directionFunctions = [
|
|
18421
|
+
this.tileRight(),
|
|
18422
|
+
this.tileLeft(),
|
|
18423
|
+
this.tileUp(),
|
|
18424
|
+
this.tileDown()
|
|
18425
|
+
];
|
|
18001
18426
|
for (let i = 0; i < repeat; i++) {
|
|
18002
|
-
|
|
18003
|
-
|
|
18004
|
-
|
|
18005
|
-
|
|
18006
|
-
|
|
18007
|
-
|
|
18427
|
+
let directionIndex = this.getRandomDirectionIndex(player, i);
|
|
18428
|
+
if (!Number.isInteger(directionIndex) || directionIndex < 0 || directionIndex > 3) {
|
|
18429
|
+
console.warn("Invalid directionIndex in tileRandom:", directionIndex, "using fallback");
|
|
18430
|
+
directionIndex = Math.floor(Math.random() * 4) % 4;
|
|
18431
|
+
}
|
|
18432
|
+
const randFn = directionFunctions[directionIndex];
|
|
18433
|
+
if (typeof randFn !== "function") {
|
|
18434
|
+
console.warn("randFn is not a function in tileRandom, skipping iteration");
|
|
18435
|
+
continue;
|
|
18436
|
+
}
|
|
18008
18437
|
try {
|
|
18009
18438
|
const newDirections = randFn(player, map);
|
|
18010
18439
|
if (Array.isArray(newDirections)) {
|
|
@@ -18114,12 +18543,13 @@ class MoveList {
|
|
|
18114
18543
|
return "turn-" + Direction.Down;
|
|
18115
18544
|
}
|
|
18116
18545
|
turnRandom() {
|
|
18546
|
+
const directionIndex = this.getRandomDirectionIndex();
|
|
18117
18547
|
return [
|
|
18118
18548
|
this.turnRight(),
|
|
18119
18549
|
this.turnLeft(),
|
|
18120
18550
|
this.turnUp(),
|
|
18121
18551
|
this.turnDown()
|
|
18122
|
-
][
|
|
18552
|
+
][directionIndex];
|
|
18123
18553
|
}
|
|
18124
18554
|
turnAwayFromPlayer(otherPlayer) {
|
|
18125
18555
|
return (player) => {
|
|
@@ -18263,115 +18693,369 @@ function WithMoveManager(Base) {
|
|
|
18263
18693
|
};
|
|
18264
18694
|
this.addMovement(new ProjectileMovement(type, config));
|
|
18265
18695
|
}
|
|
18266
|
-
moveRoutes(routes) {
|
|
18267
|
-
let count = 0;
|
|
18268
|
-
let frequence = 0;
|
|
18696
|
+
moveRoutes(routes, options) {
|
|
18269
18697
|
const player = this;
|
|
18270
18698
|
this.clearMovements();
|
|
18271
18699
|
return new Promise(async (resolve) => {
|
|
18272
18700
|
this._finishRoute = resolve;
|
|
18273
|
-
const processedRoutes =
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18701
|
+
const processedRoutes = await Promise.all(
|
|
18702
|
+
routes.map(async (route) => {
|
|
18703
|
+
if (typeof route === "function") {
|
|
18704
|
+
const map = player.getCurrentMap();
|
|
18705
|
+
if (!map) {
|
|
18706
|
+
return void 0;
|
|
18707
|
+
}
|
|
18708
|
+
return route.apply(route, [player, map]);
|
|
18278
18709
|
}
|
|
18279
|
-
return route
|
|
18280
|
-
}
|
|
18281
|
-
|
|
18282
|
-
|
|
18283
|
-
|
|
18284
|
-
|
|
18285
|
-
|
|
18286
|
-
|
|
18287
|
-
|
|
18288
|
-
|
|
18289
|
-
|
|
18710
|
+
return route;
|
|
18711
|
+
})
|
|
18712
|
+
);
|
|
18713
|
+
const finalRoutes = this.flattenRoutes(processedRoutes);
|
|
18714
|
+
class RouteMovementStrategy {
|
|
18715
|
+
constructor(routes2, player2, onComplete, options2) {
|
|
18716
|
+
this.routeIndex = 0;
|
|
18717
|
+
this.currentTarget = null;
|
|
18718
|
+
// Center position for physics
|
|
18719
|
+
this.currentTargetTopLeft = null;
|
|
18720
|
+
// Top-left position for player.x() comparison
|
|
18721
|
+
this.currentDirection = { x: 0, y: 0 };
|
|
18722
|
+
this.finished = false;
|
|
18723
|
+
this.waitingForPromise = false;
|
|
18724
|
+
this.promiseStartTime = 0;
|
|
18725
|
+
this.promiseDuration = 0;
|
|
18726
|
+
// Frequency wait state
|
|
18727
|
+
this.waitingForFrequency = false;
|
|
18728
|
+
this.frequencyWaitStartTime = 0;
|
|
18729
|
+
this.ratioFrequency = 15;
|
|
18730
|
+
// Stuck detection state
|
|
18731
|
+
this.lastPosition = null;
|
|
18732
|
+
this.lastPositionTime = 0;
|
|
18733
|
+
this.stuckCheckStartTime = 0;
|
|
18734
|
+
this.lastDistanceToTarget = null;
|
|
18735
|
+
this.isCurrentlyStuck = false;
|
|
18736
|
+
this.stuckCheckInitialized = false;
|
|
18737
|
+
this.routes = routes2;
|
|
18738
|
+
this.player = player2;
|
|
18739
|
+
this.onComplete = onComplete;
|
|
18740
|
+
this.tileSize = player2.nbPixelInTile || 32;
|
|
18741
|
+
this.tolerance = 0.5;
|
|
18742
|
+
this.onStuck = options2?.onStuck;
|
|
18743
|
+
this.stuckTimeout = options2?.stuckTimeout ?? 500;
|
|
18744
|
+
this.stuckThreshold = options2?.stuckThreshold ?? 1;
|
|
18745
|
+
this.processNextRoute();
|
|
18290
18746
|
}
|
|
18291
|
-
|
|
18292
|
-
|
|
18293
|
-
|
|
18294
|
-
|
|
18747
|
+
processNextRoute() {
|
|
18748
|
+
this.waitingForFrequency = false;
|
|
18749
|
+
this.frequencyWaitStartTime = 0;
|
|
18750
|
+
if (this.routeIndex >= this.routes.length) {
|
|
18751
|
+
this.finished = true;
|
|
18752
|
+
this.onComplete(true);
|
|
18295
18753
|
return;
|
|
18296
18754
|
}
|
|
18297
|
-
|
|
18298
|
-
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18310
|
-
|
|
18311
|
-
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18315
|
-
|
|
18316
|
-
|
|
18317
|
-
|
|
18318
|
-
|
|
18319
|
-
|
|
18320
|
-
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
|
|
18345
|
-
|
|
18346
|
-
|
|
18755
|
+
const currentRoute = this.routes[this.routeIndex];
|
|
18756
|
+
this.routeIndex++;
|
|
18757
|
+
if (currentRoute === void 0) {
|
|
18758
|
+
this.processNextRoute();
|
|
18759
|
+
return;
|
|
18760
|
+
}
|
|
18761
|
+
try {
|
|
18762
|
+
if (typeof currentRoute === "object" && "then" in currentRoute) {
|
|
18763
|
+
this.waitingForPromise = true;
|
|
18764
|
+
this.promiseStartTime = Date.now();
|
|
18765
|
+
this.promiseDuration = 1e3;
|
|
18766
|
+
currentRoute.then(() => {
|
|
18767
|
+
this.waitingForPromise = false;
|
|
18768
|
+
this.processNextRoute();
|
|
18769
|
+
}).catch(() => {
|
|
18770
|
+
this.waitingForPromise = false;
|
|
18771
|
+
this.processNextRoute();
|
|
18772
|
+
});
|
|
18773
|
+
} else if (typeof currentRoute === "string" && currentRoute.startsWith("turn-")) {
|
|
18774
|
+
const directionStr = currentRoute.replace("turn-", "");
|
|
18775
|
+
let direction = Direction.Down;
|
|
18776
|
+
switch (directionStr) {
|
|
18777
|
+
case "up":
|
|
18778
|
+
case Direction.Up:
|
|
18779
|
+
direction = Direction.Up;
|
|
18780
|
+
break;
|
|
18781
|
+
case "down":
|
|
18782
|
+
case Direction.Down:
|
|
18783
|
+
direction = Direction.Down;
|
|
18784
|
+
break;
|
|
18785
|
+
case "left":
|
|
18786
|
+
case Direction.Left:
|
|
18787
|
+
direction = Direction.Left;
|
|
18788
|
+
break;
|
|
18789
|
+
case "right":
|
|
18790
|
+
case Direction.Right:
|
|
18791
|
+
direction = Direction.Right;
|
|
18792
|
+
break;
|
|
18793
|
+
}
|
|
18794
|
+
if (this.player.changeDirection) {
|
|
18795
|
+
this.player.changeDirection(direction);
|
|
18796
|
+
}
|
|
18797
|
+
this.processNextRoute();
|
|
18798
|
+
} else if (typeof currentRoute === "number" || typeof currentRoute === "string") {
|
|
18799
|
+
const moveDirection = currentRoute;
|
|
18800
|
+
const map = this.player.getCurrentMap();
|
|
18801
|
+
if (!map) {
|
|
18802
|
+
this.finished = true;
|
|
18803
|
+
this.onComplete(false);
|
|
18804
|
+
return;
|
|
18805
|
+
}
|
|
18806
|
+
const currentTopLeftX = typeof this.player.x === "function" ? this.player.x() : this.player.x;
|
|
18807
|
+
const currentTopLeftY = typeof this.player.y === "function" ? this.player.y() : this.player.y;
|
|
18808
|
+
let playerSpeed = this.player.speed();
|
|
18809
|
+
let distance = playerSpeed;
|
|
18810
|
+
const initialDistance = distance;
|
|
18811
|
+
const initialRouteIndex = this.routeIndex;
|
|
18812
|
+
while (this.routeIndex < this.routes.length) {
|
|
18813
|
+
const nextRoute = this.routes[this.routeIndex];
|
|
18814
|
+
if (nextRoute === currentRoute) {
|
|
18815
|
+
distance += playerSpeed;
|
|
18816
|
+
this.routeIndex++;
|
|
18817
|
+
} else {
|
|
18818
|
+
break;
|
|
18819
|
+
}
|
|
18820
|
+
}
|
|
18821
|
+
let targetTopLeftX = currentTopLeftX;
|
|
18822
|
+
let targetTopLeftY = currentTopLeftY;
|
|
18823
|
+
switch (moveDirection) {
|
|
18347
18824
|
case Direction.Right:
|
|
18348
|
-
|
|
18825
|
+
case "right":
|
|
18826
|
+
targetTopLeftX = currentTopLeftX + distance;
|
|
18349
18827
|
break;
|
|
18350
18828
|
case Direction.Left:
|
|
18351
|
-
|
|
18829
|
+
case "left":
|
|
18830
|
+
targetTopLeftX = currentTopLeftX - distance;
|
|
18352
18831
|
break;
|
|
18353
18832
|
case Direction.Down:
|
|
18354
|
-
|
|
18833
|
+
case "down":
|
|
18834
|
+
targetTopLeftY = currentTopLeftY + distance;
|
|
18355
18835
|
break;
|
|
18356
18836
|
case Direction.Up:
|
|
18357
|
-
|
|
18837
|
+
case "up":
|
|
18838
|
+
targetTopLeftY = currentTopLeftY - distance;
|
|
18358
18839
|
break;
|
|
18359
18840
|
}
|
|
18360
|
-
const
|
|
18361
|
-
|
|
18362
|
-
|
|
18841
|
+
const entity = map.physic.getEntityByUUID(this.player.id);
|
|
18842
|
+
if (!entity) {
|
|
18843
|
+
this.finished = true;
|
|
18844
|
+
this.onComplete(false);
|
|
18845
|
+
return;
|
|
18846
|
+
}
|
|
18847
|
+
const hitbox = this.player.hitbox();
|
|
18848
|
+
const hitboxWidth = hitbox?.w ?? 32;
|
|
18849
|
+
const hitboxHeight = hitbox?.h ?? 32;
|
|
18850
|
+
const targetX = targetTopLeftX + hitboxWidth / 2;
|
|
18851
|
+
const targetY = targetTopLeftY + hitboxHeight / 2;
|
|
18852
|
+
this.currentTarget = { x: targetX, y: targetY };
|
|
18853
|
+
this.currentTargetTopLeft = { x: targetTopLeftX, y: targetTopLeftY };
|
|
18854
|
+
this.currentDirection = { x: 0, y: 0 };
|
|
18855
|
+
this.lastPosition = null;
|
|
18856
|
+
this.isCurrentlyStuck = false;
|
|
18857
|
+
this.stuckCheckStartTime = 0;
|
|
18858
|
+
this.lastDistanceToTarget = null;
|
|
18859
|
+
this.stuckCheckInitialized = false;
|
|
18860
|
+
this.waitingForFrequency = false;
|
|
18861
|
+
this.frequencyWaitStartTime = 0;
|
|
18862
|
+
} else if (Array.isArray(currentRoute)) {
|
|
18863
|
+
for (let i = currentRoute.length - 1; i >= 0; i--) {
|
|
18864
|
+
this.routes.splice(this.routeIndex, 0, currentRoute[i]);
|
|
18865
|
+
}
|
|
18866
|
+
this.processNextRoute();
|
|
18867
|
+
} else {
|
|
18868
|
+
this.processNextRoute();
|
|
18869
|
+
}
|
|
18870
|
+
} catch (error) {
|
|
18871
|
+
console.warn("Error processing route:", error);
|
|
18872
|
+
this.processNextRoute();
|
|
18873
|
+
}
|
|
18874
|
+
}
|
|
18875
|
+
update(body, dt) {
|
|
18876
|
+
if (this.waitingForPromise) {
|
|
18877
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
18878
|
+
if (Date.now() - this.promiseStartTime > this.promiseDuration) {
|
|
18879
|
+
this.waitingForPromise = false;
|
|
18880
|
+
this.processNextRoute();
|
|
18881
|
+
}
|
|
18882
|
+
return;
|
|
18883
|
+
}
|
|
18884
|
+
if (this.waitingForFrequency) {
|
|
18885
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
18886
|
+
const playerFrequency = this.player.frequency;
|
|
18887
|
+
const frequencyMs = playerFrequency || 0;
|
|
18888
|
+
if (frequencyMs > 0 && Date.now() - this.frequencyWaitStartTime >= frequencyMs * this.ratioFrequency) {
|
|
18889
|
+
this.waitingForFrequency = false;
|
|
18890
|
+
this.processNextRoute();
|
|
18891
|
+
}
|
|
18892
|
+
return;
|
|
18893
|
+
}
|
|
18894
|
+
if (!this.currentTarget) {
|
|
18895
|
+
if (!this.finished) {
|
|
18896
|
+
this.processNextRoute();
|
|
18897
|
+
}
|
|
18898
|
+
if (!this.currentTarget) {
|
|
18899
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
18900
|
+
this.lastPosition = null;
|
|
18901
|
+
this.isCurrentlyStuck = false;
|
|
18902
|
+
this.lastDistanceToTarget = null;
|
|
18903
|
+
this.stuckCheckInitialized = false;
|
|
18904
|
+
this.currentTargetTopLeft = null;
|
|
18905
|
+
return;
|
|
18906
|
+
}
|
|
18907
|
+
}
|
|
18908
|
+
const entity = body.getEntity?.();
|
|
18909
|
+
if (!entity) {
|
|
18910
|
+
this.finished = true;
|
|
18911
|
+
this.onComplete(false);
|
|
18912
|
+
return;
|
|
18913
|
+
}
|
|
18914
|
+
const currentPosition = { x: entity.position.x, y: entity.position.y };
|
|
18915
|
+
const currentTime = Date.now();
|
|
18916
|
+
const currentTopLeftX = this.player.x();
|
|
18917
|
+
const currentTopLeftY = this.player.y();
|
|
18918
|
+
let dx, dy, distance;
|
|
18919
|
+
if (this.currentTargetTopLeft) {
|
|
18920
|
+
dx = this.currentTargetTopLeft.x - currentTopLeftX;
|
|
18921
|
+
dy = this.currentTargetTopLeft.y - currentTopLeftY;
|
|
18922
|
+
distance = Math.hypot(dx, dy);
|
|
18923
|
+
if (distance <= this.tolerance) {
|
|
18924
|
+
this.currentTarget = null;
|
|
18925
|
+
this.currentTargetTopLeft = null;
|
|
18926
|
+
this.currentDirection = { x: 0, y: 0 };
|
|
18927
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
18928
|
+
this.lastPosition = null;
|
|
18929
|
+
this.isCurrentlyStuck = false;
|
|
18930
|
+
this.lastDistanceToTarget = null;
|
|
18931
|
+
this.stuckCheckInitialized = false;
|
|
18932
|
+
if (!this.finished) {
|
|
18933
|
+
const playerFrequency = this.player.frequency;
|
|
18934
|
+
if (playerFrequency && playerFrequency > 0) {
|
|
18935
|
+
this.waitingForFrequency = true;
|
|
18936
|
+
this.frequencyWaitStartTime = Date.now();
|
|
18937
|
+
} else {
|
|
18938
|
+
this.processNextRoute();
|
|
18939
|
+
}
|
|
18940
|
+
}
|
|
18941
|
+
return;
|
|
18942
|
+
}
|
|
18943
|
+
} else {
|
|
18944
|
+
dx = this.currentTarget.x - currentPosition.x;
|
|
18945
|
+
dy = this.currentTarget.y - currentPosition.y;
|
|
18946
|
+
distance = Math.hypot(dx, dy);
|
|
18947
|
+
if (distance <= this.tolerance) {
|
|
18948
|
+
this.currentTarget = null;
|
|
18949
|
+
this.currentTargetTopLeft = null;
|
|
18950
|
+
this.currentDirection = { x: 0, y: 0 };
|
|
18951
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
18952
|
+
this.lastPosition = null;
|
|
18953
|
+
this.isCurrentlyStuck = false;
|
|
18954
|
+
this.lastDistanceToTarget = null;
|
|
18955
|
+
this.stuckCheckInitialized = false;
|
|
18956
|
+
if (!this.finished) {
|
|
18957
|
+
const playerFrequency = player.frequency;
|
|
18958
|
+
if (playerFrequency && playerFrequency > 0) {
|
|
18959
|
+
this.waitingForFrequency = true;
|
|
18960
|
+
this.frequencyWaitStartTime = Date.now();
|
|
18961
|
+
} else {
|
|
18962
|
+
this.processNextRoute();
|
|
18963
|
+
}
|
|
18964
|
+
}
|
|
18363
18965
|
return;
|
|
18364
18966
|
}
|
|
18365
|
-
|
|
18967
|
+
}
|
|
18968
|
+
if (this.onStuck && this.currentTarget) {
|
|
18969
|
+
if (!this.stuckCheckInitialized) {
|
|
18970
|
+
this.lastPosition = { ...currentPosition };
|
|
18971
|
+
this.lastDistanceToTarget = distance;
|
|
18972
|
+
this.stuckCheckInitialized = true;
|
|
18973
|
+
this.lastPositionTime = currentTime;
|
|
18974
|
+
} else if (this.lastPosition && this.lastDistanceToTarget !== null) {
|
|
18975
|
+
const positionChanged = Math.hypot(
|
|
18976
|
+
currentPosition.x - this.lastPosition.x,
|
|
18977
|
+
currentPosition.y - this.lastPosition.y
|
|
18978
|
+
) > this.stuckThreshold;
|
|
18979
|
+
const distanceImproved = distance < this.lastDistanceToTarget - this.stuckThreshold;
|
|
18980
|
+
if (!positionChanged && !distanceImproved) {
|
|
18981
|
+
if (!this.isCurrentlyStuck) {
|
|
18982
|
+
this.stuckCheckStartTime = currentTime;
|
|
18983
|
+
this.isCurrentlyStuck = true;
|
|
18984
|
+
} else {
|
|
18985
|
+
if (currentTime - this.stuckCheckStartTime >= this.stuckTimeout) {
|
|
18986
|
+
const shouldContinue = this.onStuck(
|
|
18987
|
+
this.player,
|
|
18988
|
+
this.currentTarget,
|
|
18989
|
+
currentPosition
|
|
18990
|
+
);
|
|
18991
|
+
if (shouldContinue === false) {
|
|
18992
|
+
this.finished = true;
|
|
18993
|
+
this.onComplete(false);
|
|
18994
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
18995
|
+
return;
|
|
18996
|
+
}
|
|
18997
|
+
this.isCurrentlyStuck = false;
|
|
18998
|
+
this.stuckCheckStartTime = 0;
|
|
18999
|
+
this.lastPosition = { ...currentPosition };
|
|
19000
|
+
this.lastDistanceToTarget = distance;
|
|
19001
|
+
}
|
|
19002
|
+
}
|
|
19003
|
+
} else {
|
|
19004
|
+
this.isCurrentlyStuck = false;
|
|
19005
|
+
this.stuckCheckStartTime = 0;
|
|
19006
|
+
}
|
|
19007
|
+
this.lastPosition = { ...currentPosition };
|
|
19008
|
+
this.lastPositionTime = currentTime;
|
|
19009
|
+
this.lastDistanceToTarget = distance;
|
|
19010
|
+
}
|
|
19011
|
+
}
|
|
19012
|
+
const map = this.player.getCurrentMap();
|
|
19013
|
+
map?.speedScalar ?? 50;
|
|
19014
|
+
if (distance > 0) {
|
|
19015
|
+
this.currentDirection = { x: dx / distance, y: dy / distance };
|
|
18366
19016
|
} else {
|
|
18367
|
-
|
|
19017
|
+
this.currentTarget = null;
|
|
19018
|
+
this.currentTargetTopLeft = null;
|
|
19019
|
+
this.currentDirection = { x: 0, y: 0 };
|
|
19020
|
+
body.setVelocity({ x: 0, y: 0 });
|
|
19021
|
+
if (!this.finished) {
|
|
19022
|
+
const playerFrequency = typeof this.player.frequency === "function" ? this.player.frequency() : this.player.frequency;
|
|
19023
|
+
if (playerFrequency && playerFrequency > 0) {
|
|
19024
|
+
this.waitingForFrequency = true;
|
|
19025
|
+
this.frequencyWaitStartTime = Date.now();
|
|
19026
|
+
} else {
|
|
19027
|
+
this.processNextRoute();
|
|
19028
|
+
}
|
|
19029
|
+
}
|
|
19030
|
+
return;
|
|
18368
19031
|
}
|
|
18369
|
-
|
|
18370
|
-
|
|
18371
|
-
|
|
19032
|
+
const absX = Math.abs(this.currentDirection.x);
|
|
19033
|
+
const absY = Math.abs(this.currentDirection.y);
|
|
19034
|
+
let cardinalDirection;
|
|
19035
|
+
if (absX >= absY) {
|
|
19036
|
+
cardinalDirection = this.currentDirection.x >= 0 ? Direction.Right : Direction.Left;
|
|
19037
|
+
} else {
|
|
19038
|
+
cardinalDirection = this.currentDirection.y >= 0 ? Direction.Down : Direction.Up;
|
|
19039
|
+
}
|
|
19040
|
+
map.movePlayer(this.player, cardinalDirection);
|
|
18372
19041
|
}
|
|
18373
|
-
|
|
18374
|
-
|
|
19042
|
+
isFinished() {
|
|
19043
|
+
return this.finished;
|
|
19044
|
+
}
|
|
19045
|
+
onFinished() {
|
|
19046
|
+
this.onComplete(true);
|
|
19047
|
+
}
|
|
19048
|
+
}
|
|
19049
|
+
const routeStrategy = new RouteMovementStrategy(
|
|
19050
|
+
finalRoutes,
|
|
19051
|
+
player,
|
|
19052
|
+
(success) => {
|
|
19053
|
+
this._finishRoute = null;
|
|
19054
|
+
resolve(success);
|
|
19055
|
+
},
|
|
19056
|
+
options
|
|
19057
|
+
);
|
|
19058
|
+
this.addMovement(routeStrategy);
|
|
18375
19059
|
});
|
|
18376
19060
|
}
|
|
18377
19061
|
flattenRoutes(routes) {
|
|
@@ -19361,8 +20045,8 @@ function WithItemManager(Base) {
|
|
|
19361
20045
|
});
|
|
19362
20046
|
}
|
|
19363
20047
|
addItem(item, nb = 1) {
|
|
19364
|
-
const map = this.getCurrentMap();
|
|
19365
|
-
if (!map) {
|
|
20048
|
+
const map = this.getCurrentMap() || this.map;
|
|
20049
|
+
if (!map || !map.database) {
|
|
19366
20050
|
throw new Error("Player must be on a map to add items");
|
|
19367
20051
|
}
|
|
19368
20052
|
let itemId;
|
|
@@ -19371,11 +20055,6 @@ function WithItemManager(Base) {
|
|
|
19371
20055
|
if (isString(item)) {
|
|
19372
20056
|
itemId = item;
|
|
19373
20057
|
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
20058
|
} else if (typeof item === "function" || item.prototype) {
|
|
19380
20059
|
itemId = item.name;
|
|
19381
20060
|
const existingData = map.database()[itemId];
|
|
@@ -19404,6 +20083,21 @@ function WithItemManager(Base) {
|
|
|
19404
20083
|
if (existingItem) {
|
|
19405
20084
|
instance = existingItem;
|
|
19406
20085
|
instance.quantity.update((it) => it + nb);
|
|
20086
|
+
if (data.name !== void 0) {
|
|
20087
|
+
instance.name.set(data.name);
|
|
20088
|
+
}
|
|
20089
|
+
if (data.description !== void 0) {
|
|
20090
|
+
instance.description.set(data.description);
|
|
20091
|
+
}
|
|
20092
|
+
if (data.price !== void 0) {
|
|
20093
|
+
instance.price.set(data.price);
|
|
20094
|
+
}
|
|
20095
|
+
if (itemInstance && typeof itemInstance === "object" && !(itemInstance instanceof Function)) {
|
|
20096
|
+
instance._itemInstance = itemInstance;
|
|
20097
|
+
if (itemInstance.onAdd) {
|
|
20098
|
+
instance.onAdd = itemInstance.onAdd.bind(itemInstance);
|
|
20099
|
+
}
|
|
20100
|
+
}
|
|
19407
20101
|
} else {
|
|
19408
20102
|
instance = new Item(data);
|
|
19409
20103
|
instance.id.set(itemId);
|
|
@@ -19488,7 +20182,11 @@ function WithItemManager(Base) {
|
|
|
19488
20182
|
getParamItem(name) {
|
|
19489
20183
|
let nb = 0;
|
|
19490
20184
|
for (let item of this.equipments()) {
|
|
19491
|
-
|
|
20185
|
+
try {
|
|
20186
|
+
const itemData = this.databaseById(item.id());
|
|
20187
|
+
nb += itemData[name] || 0;
|
|
20188
|
+
} catch {
|
|
20189
|
+
}
|
|
19492
20190
|
}
|
|
19493
20191
|
const modifier = this.paramsModifier?.[name];
|
|
19494
20192
|
if (modifier) {
|
|
@@ -19515,19 +20213,23 @@ function WithItemManager(Base) {
|
|
|
19515
20213
|
if (!inventory) {
|
|
19516
20214
|
throw ItemLog.notInInventory(itemId);
|
|
19517
20215
|
}
|
|
19518
|
-
const
|
|
19519
|
-
|
|
20216
|
+
const itemData = this.databaseById(itemId);
|
|
20217
|
+
const consumable = itemData?.consumable;
|
|
20218
|
+
if (consumable === false) {
|
|
19520
20219
|
throw ItemLog.notUseItem(itemId);
|
|
19521
20220
|
}
|
|
19522
|
-
|
|
19523
|
-
|
|
20221
|
+
if (consumable === void 0 && itemData?._type && itemData._type !== "item") {
|
|
20222
|
+
throw ItemLog.notUseItem(itemId);
|
|
20223
|
+
}
|
|
20224
|
+
const hitRate = itemData?.hitRate ?? 1;
|
|
20225
|
+
const hookTarget = inventory._itemInstance || inventory;
|
|
19524
20226
|
if (Math.random() > hitRate) {
|
|
19525
20227
|
this.removeItem(itemClass);
|
|
19526
20228
|
this["execMethod"]("onUseFailed", [this], hookTarget);
|
|
19527
20229
|
throw ItemLog.chanceToUseFailed(itemId);
|
|
19528
20230
|
}
|
|
19529
|
-
this.applyEffect?.(
|
|
19530
|
-
this.applyStates?.(this,
|
|
20231
|
+
this.applyEffect?.(itemData);
|
|
20232
|
+
this.applyStates?.(this, itemData);
|
|
19531
20233
|
this["execMethod"]("onUse", [this], hookTarget);
|
|
19532
20234
|
this.removeItem(itemClass);
|
|
19533
20235
|
return inventory;
|
|
@@ -19972,7 +20674,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
19972
20674
|
this.map = null;
|
|
19973
20675
|
this.conn = null;
|
|
19974
20676
|
this.touchSide = false;
|
|
19975
|
-
|
|
20677
|
+
this._worldPositionSignals = /* @__PURE__ */ new WeakMap();
|
|
19976
20678
|
/** Internal: Shapes attached to this player */
|
|
19977
20679
|
this._attachedShapes = /* @__PURE__ */ new Map();
|
|
19978
20680
|
/** Internal: Shapes where this player is currently located */
|
|
@@ -20021,6 +20723,56 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20021
20723
|
}
|
|
20022
20724
|
});
|
|
20023
20725
|
}
|
|
20726
|
+
// Protection against map change loops
|
|
20727
|
+
/**
|
|
20728
|
+
* Computed signal for world X position
|
|
20729
|
+
*
|
|
20730
|
+
* Calculates the absolute world X position from the map's world position
|
|
20731
|
+
* plus the player's local X position. Returns 0 if no map is assigned.
|
|
20732
|
+
*
|
|
20733
|
+
* @example
|
|
20734
|
+
* ```ts
|
|
20735
|
+
* const worldX = player.worldX();
|
|
20736
|
+
* console.log(`Player is at world X: ${worldX}`);
|
|
20737
|
+
* ```
|
|
20738
|
+
*/
|
|
20739
|
+
get worldPositionX() {
|
|
20740
|
+
return this._getComputedWorldPosition("x");
|
|
20741
|
+
}
|
|
20742
|
+
/**
|
|
20743
|
+
* Computed signal for world Y position
|
|
20744
|
+
*
|
|
20745
|
+
* Calculates the absolute world Y position from the map's world position
|
|
20746
|
+
* plus the player's local Y position. Returns 0 if no map is assigned.
|
|
20747
|
+
*
|
|
20748
|
+
* @example
|
|
20749
|
+
* ```ts
|
|
20750
|
+
* const worldY = player.worldY();
|
|
20751
|
+
* console.log(`Player is at world Y: ${worldY}`);
|
|
20752
|
+
* ```
|
|
20753
|
+
*/
|
|
20754
|
+
get worldPositionY() {
|
|
20755
|
+
return this._getComputedWorldPosition("y");
|
|
20756
|
+
}
|
|
20757
|
+
_getComputedWorldPosition(axis) {
|
|
20758
|
+
if (!this._worldPositionSignals) {
|
|
20759
|
+
this._worldPositionSignals = /* @__PURE__ */ new WeakMap();
|
|
20760
|
+
}
|
|
20761
|
+
const key = axis;
|
|
20762
|
+
let signals = this._worldPositionSignals.get(this);
|
|
20763
|
+
if (!signals) {
|
|
20764
|
+
signals = {};
|
|
20765
|
+
this._worldPositionSignals.set(this, signals);
|
|
20766
|
+
}
|
|
20767
|
+
if (!signals[key]) {
|
|
20768
|
+
signals[key] = computed(() => {
|
|
20769
|
+
const map2 = this.map;
|
|
20770
|
+
const mapWorldPos = map2 ? map2[axis === "x" ? "worldX" : "worldY"] ?? 0 : 0;
|
|
20771
|
+
return mapWorldPos + this[axis]();
|
|
20772
|
+
});
|
|
20773
|
+
}
|
|
20774
|
+
return signals[key];
|
|
20775
|
+
}
|
|
20024
20776
|
_onInit() {
|
|
20025
20777
|
this.hooks.callHooks("server-playerProps-load", this).subscribe();
|
|
20026
20778
|
}
|
|
@@ -20031,6 +20783,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20031
20783
|
get server() {
|
|
20032
20784
|
return this.map;
|
|
20033
20785
|
}
|
|
20786
|
+
setMap(map2) {
|
|
20787
|
+
this.map = map2;
|
|
20788
|
+
}
|
|
20034
20789
|
applyFrames() {
|
|
20035
20790
|
this._frames.set(this.frames);
|
|
20036
20791
|
this.frames = [];
|
|
@@ -20080,76 +20835,55 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20080
20835
|
});
|
|
20081
20836
|
return true;
|
|
20082
20837
|
}
|
|
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) {
|
|
20838
|
+
async autoChangeMap(nextPosition) {
|
|
20102
20839
|
const map2 = this.getCurrentMap();
|
|
20103
|
-
|
|
20104
|
-
const worldMaps = map2.getWorldMapsManager?.();
|
|
20840
|
+
const worldMaps = map2?.getInWorldMaps();
|
|
20105
20841
|
let ret = false;
|
|
20106
20842
|
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) => {
|
|
20843
|
+
const direction = this.getDirection();
|
|
20844
|
+
const marginLeftRight = map2.tileWidth / 2;
|
|
20845
|
+
const marginTopDown = map2.tileHeight / 2;
|
|
20846
|
+
const changeMap = async (adjacent, to) => {
|
|
20113
20847
|
if (this.touchSide) {
|
|
20114
20848
|
return false;
|
|
20115
20849
|
}
|
|
20116
20850
|
this.touchSide = true;
|
|
20117
|
-
const [nextMap] = worldMaps.getAdjacentMaps(map2,
|
|
20118
|
-
if (!nextMap)
|
|
20119
|
-
this.touchSide = false;
|
|
20120
|
-
return false;
|
|
20121
|
-
}
|
|
20851
|
+
const [nextMap] = worldMaps.getAdjacentMaps(map2, adjacent);
|
|
20852
|
+
if (!nextMap) return false;
|
|
20122
20853
|
const id = nextMap.id;
|
|
20123
20854
|
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;
|
|
20855
|
+
return !!await this.changeMap(id, to(nextMapInfo));
|
|
20134
20856
|
};
|
|
20135
|
-
if (nextPosition.x < marginLeftRight && direction
|
|
20136
|
-
ret = await changeMap(
|
|
20857
|
+
if (nextPosition.x < marginLeftRight && direction == Direction.Left) {
|
|
20858
|
+
ret = await changeMap({
|
|
20859
|
+
x: map2.worldX - 1,
|
|
20860
|
+
y: this.worldPositionY() + 1
|
|
20861
|
+
}, (nextMapInfo) => ({
|
|
20137
20862
|
x: nextMapInfo.width - this.hitbox().w - marginLeftRight,
|
|
20138
|
-
y:
|
|
20863
|
+
y: map2.worldY - nextMapInfo.y + nextPosition.y
|
|
20139
20864
|
}));
|
|
20140
|
-
} else if (nextPosition.x > map2.widthPx - this.hitbox().w - marginLeftRight && direction
|
|
20141
|
-
ret = await changeMap(
|
|
20865
|
+
} else if (nextPosition.x > map2.widthPx - this.hitbox().w - marginLeftRight && direction == Direction.Right) {
|
|
20866
|
+
ret = await changeMap({
|
|
20867
|
+
x: map2.worldX + map2.widthPx + 1,
|
|
20868
|
+
y: this.worldPositionY() + 1
|
|
20869
|
+
}, (nextMapInfo) => ({
|
|
20142
20870
|
x: marginLeftRight,
|
|
20143
|
-
y:
|
|
20871
|
+
y: map2.worldY - nextMapInfo.y + nextPosition.y
|
|
20144
20872
|
}));
|
|
20145
|
-
} else if (nextPosition.y < marginTopDown && direction
|
|
20146
|
-
ret = await changeMap(
|
|
20147
|
-
x:
|
|
20873
|
+
} else if (nextPosition.y < marginTopDown && direction == Direction.Up) {
|
|
20874
|
+
ret = await changeMap({
|
|
20875
|
+
x: this.worldPositionX() + 1,
|
|
20876
|
+
y: map2.worldY - 1
|
|
20877
|
+
}, (nextMapInfo) => ({
|
|
20878
|
+
x: map2.worldX - nextMapInfo.x + nextPosition.x,
|
|
20148
20879
|
y: nextMapInfo.height - this.hitbox().h - marginTopDown
|
|
20149
20880
|
}));
|
|
20150
|
-
} else if (nextPosition.y > map2.heightPx - this.hitbox().h - marginTopDown && direction
|
|
20151
|
-
ret = await changeMap(
|
|
20152
|
-
x:
|
|
20881
|
+
} else if (nextPosition.y > map2.heightPx - this.hitbox().h - marginTopDown && direction == Direction.Down) {
|
|
20882
|
+
ret = await changeMap({
|
|
20883
|
+
x: this.worldPositionX() + 1,
|
|
20884
|
+
y: map2.worldY + map2.heightPx + 1
|
|
20885
|
+
}, (nextMapInfo) => ({
|
|
20886
|
+
x: map2.worldX - nextMapInfo.x + nextPosition.x,
|
|
20153
20887
|
y: marginTopDown
|
|
20154
20888
|
}));
|
|
20155
20889
|
} else {
|
|
@@ -20160,15 +20894,19 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20160
20894
|
}
|
|
20161
20895
|
async teleport(positions) {
|
|
20162
20896
|
if (!this.map) return false;
|
|
20163
|
-
if (this.map.physic) {
|
|
20897
|
+
if (this.map && this.map.physic) {
|
|
20164
20898
|
const entity = this.map.physic.getEntityByUUID(this.id);
|
|
20165
20899
|
if (entity) {
|
|
20166
|
-
this.
|
|
20900
|
+
const hitbox = typeof this.hitbox === "function" ? this.hitbox() : this.hitbox;
|
|
20901
|
+
const width = hitbox?.w ?? 32;
|
|
20902
|
+
const height = hitbox?.h ?? 32;
|
|
20903
|
+
const centerX = positions.x + width / 2;
|
|
20904
|
+
const centerY = positions.y + height / 2;
|
|
20905
|
+
this.map.physic.teleport(entity, { x: centerX, y: centerY });
|
|
20167
20906
|
}
|
|
20168
|
-
} else {
|
|
20169
|
-
this.x.set(positions.x);
|
|
20170
|
-
this.y.set(positions.y);
|
|
20171
20907
|
}
|
|
20908
|
+
this.x.set(positions.x);
|
|
20909
|
+
this.y.set(positions.y);
|
|
20172
20910
|
queueMicrotask(() => {
|
|
20173
20911
|
this.applyFrames();
|
|
20174
20912
|
});
|
|
@@ -20250,8 +20988,8 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20250
20988
|
this._eventChanges();
|
|
20251
20989
|
}
|
|
20252
20990
|
databaseById(id) {
|
|
20253
|
-
const map2 = this.
|
|
20254
|
-
if (!map2) return;
|
|
20991
|
+
const map2 = this.map;
|
|
20992
|
+
if (!map2 || !map2.database) return;
|
|
20255
20993
|
const data = map2.database()[id];
|
|
20256
20994
|
if (!data)
|
|
20257
20995
|
throw new Error(
|
|
@@ -20804,6 +21542,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
20804
21542
|
}, this);
|
|
20805
21543
|
}
|
|
20806
21544
|
}
|
|
21545
|
+
isEvent() {
|
|
21546
|
+
return false;
|
|
21547
|
+
}
|
|
20807
21548
|
};
|
|
20808
21549
|
__decorateClass$2([
|
|
20809
21550
|
sync(_RpgPlayer)
|
|
@@ -20823,6 +21564,9 @@ class RpgEvent extends RpgPlayer {
|
|
|
20823
21564
|
if (!map2) return;
|
|
20824
21565
|
map2.removeEvent(this.id);
|
|
20825
21566
|
}
|
|
21567
|
+
isEvent() {
|
|
21568
|
+
return true;
|
|
21569
|
+
}
|
|
20826
21570
|
}
|
|
20827
21571
|
|
|
20828
21572
|
const context$1 = new Context();
|
|
@@ -21975,8 +22719,8 @@ class Doc {
|
|
|
21975
22719
|
|
|
21976
22720
|
const version = {
|
|
21977
22721
|
major: 4,
|
|
21978
|
-
minor:
|
|
21979
|
-
patch:
|
|
22722
|
+
minor: 2,
|
|
22723
|
+
patch: 0,
|
|
21980
22724
|
};
|
|
21981
22725
|
|
|
21982
22726
|
const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
|
|
@@ -22046,16 +22790,6 @@ const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
|
|
|
22046
22790
|
}
|
|
22047
22791
|
return payload;
|
|
22048
22792
|
};
|
|
22049
|
-
// const handleChecksResult = (
|
|
22050
|
-
// checkResult: ParsePayload,
|
|
22051
|
-
// originalResult: ParsePayload,
|
|
22052
|
-
// ctx: ParseContextInternal
|
|
22053
|
-
// ): util.MaybeAsync<ParsePayload> => {
|
|
22054
|
-
// // if the checks mutated the value && there are no issues, re-parse the result
|
|
22055
|
-
// if (checkResult.value !== originalResult.value && !checkResult.issues.length)
|
|
22056
|
-
// return inst._zod.parse(checkResult, ctx);
|
|
22057
|
-
// return originalResult;
|
|
22058
|
-
// };
|
|
22059
22793
|
const handleCanaryResult = (canary, payload, ctx) => {
|
|
22060
22794
|
// abort if the canary is aborted
|
|
22061
22795
|
if (aborted(canary)) {
|
|
@@ -23666,6 +24400,656 @@ function _check(fn, params) {
|
|
|
23666
24400
|
return ch;
|
|
23667
24401
|
}
|
|
23668
24402
|
|
|
24403
|
+
// function initializeContext<T extends schemas.$ZodType>(inputs: JSONSchemaGeneratorParams<T>): ToJSONSchemaContext<T> {
|
|
24404
|
+
// return {
|
|
24405
|
+
// processor: inputs.processor,
|
|
24406
|
+
// metadataRegistry: inputs.metadata ?? globalRegistry,
|
|
24407
|
+
// target: inputs.target ?? "draft-2020-12",
|
|
24408
|
+
// unrepresentable: inputs.unrepresentable ?? "throw",
|
|
24409
|
+
// };
|
|
24410
|
+
// }
|
|
24411
|
+
function initializeContext(params) {
|
|
24412
|
+
// Normalize target: convert old non-hyphenated versions to hyphenated versions
|
|
24413
|
+
let target = params?.target ?? "draft-2020-12";
|
|
24414
|
+
if (target === "draft-4")
|
|
24415
|
+
target = "draft-04";
|
|
24416
|
+
if (target === "draft-7")
|
|
24417
|
+
target = "draft-07";
|
|
24418
|
+
return {
|
|
24419
|
+
processors: params.processors ?? {},
|
|
24420
|
+
metadataRegistry: params?.metadata ?? globalRegistry,
|
|
24421
|
+
target,
|
|
24422
|
+
unrepresentable: params?.unrepresentable ?? "throw",
|
|
24423
|
+
override: params?.override ?? (() => { }),
|
|
24424
|
+
io: params?.io ?? "output",
|
|
24425
|
+
counter: 0,
|
|
24426
|
+
seen: new Map(),
|
|
24427
|
+
cycles: params?.cycles ?? "ref",
|
|
24428
|
+
reused: params?.reused ?? "inline",
|
|
24429
|
+
external: params?.external ?? undefined,
|
|
24430
|
+
};
|
|
24431
|
+
}
|
|
24432
|
+
function process$1(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
24433
|
+
var _a;
|
|
24434
|
+
const def = schema._zod.def;
|
|
24435
|
+
// check for schema in seens
|
|
24436
|
+
const seen = ctx.seen.get(schema);
|
|
24437
|
+
if (seen) {
|
|
24438
|
+
seen.count++;
|
|
24439
|
+
// check if cycle
|
|
24440
|
+
const isCycle = _params.schemaPath.includes(schema);
|
|
24441
|
+
if (isCycle) {
|
|
24442
|
+
seen.cycle = _params.path;
|
|
24443
|
+
}
|
|
24444
|
+
return seen.schema;
|
|
24445
|
+
}
|
|
24446
|
+
// initialize
|
|
24447
|
+
const result = { schema: {}, count: 1, cycle: undefined, path: _params.path };
|
|
24448
|
+
ctx.seen.set(schema, result);
|
|
24449
|
+
// custom method overrides default behavior
|
|
24450
|
+
const overrideSchema = schema._zod.toJSONSchema?.();
|
|
24451
|
+
if (overrideSchema) {
|
|
24452
|
+
result.schema = overrideSchema;
|
|
24453
|
+
}
|
|
24454
|
+
else {
|
|
24455
|
+
const params = {
|
|
24456
|
+
..._params,
|
|
24457
|
+
schemaPath: [..._params.schemaPath, schema],
|
|
24458
|
+
path: _params.path,
|
|
24459
|
+
};
|
|
24460
|
+
const parent = schema._zod.parent;
|
|
24461
|
+
if (parent) {
|
|
24462
|
+
// schema was cloned from another schema
|
|
24463
|
+
result.ref = parent;
|
|
24464
|
+
process$1(parent, ctx, params);
|
|
24465
|
+
ctx.seen.get(parent).isParent = true;
|
|
24466
|
+
}
|
|
24467
|
+
else if (schema._zod.processJSONSchema) {
|
|
24468
|
+
schema._zod.processJSONSchema(ctx, result.schema, params);
|
|
24469
|
+
}
|
|
24470
|
+
else {
|
|
24471
|
+
const _json = result.schema;
|
|
24472
|
+
const processor = ctx.processors[def.type];
|
|
24473
|
+
if (!processor) {
|
|
24474
|
+
throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`);
|
|
24475
|
+
}
|
|
24476
|
+
processor(schema, ctx, _json, params);
|
|
24477
|
+
}
|
|
24478
|
+
}
|
|
24479
|
+
// metadata
|
|
24480
|
+
const meta = ctx.metadataRegistry.get(schema);
|
|
24481
|
+
if (meta)
|
|
24482
|
+
Object.assign(result.schema, meta);
|
|
24483
|
+
if (ctx.io === "input" && isTransforming(schema)) {
|
|
24484
|
+
// examples/defaults only apply to output type of pipe
|
|
24485
|
+
delete result.schema.examples;
|
|
24486
|
+
delete result.schema.default;
|
|
24487
|
+
}
|
|
24488
|
+
// set prefault as default
|
|
24489
|
+
if (ctx.io === "input" && result.schema._prefault)
|
|
24490
|
+
(_a = result.schema).default ?? (_a.default = result.schema._prefault);
|
|
24491
|
+
delete result.schema._prefault;
|
|
24492
|
+
// pulling fresh from ctx.seen in case it was overwritten
|
|
24493
|
+
const _result = ctx.seen.get(schema);
|
|
24494
|
+
return _result.schema;
|
|
24495
|
+
}
|
|
24496
|
+
function extractDefs(ctx, schema
|
|
24497
|
+
// params: EmitParams
|
|
24498
|
+
) {
|
|
24499
|
+
// iterate over seen map;
|
|
24500
|
+
const root = ctx.seen.get(schema);
|
|
24501
|
+
if (!root)
|
|
24502
|
+
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
24503
|
+
// returns a ref to the schema
|
|
24504
|
+
// defId will be empty if the ref points to an external schema (or #)
|
|
24505
|
+
const makeURI = (entry) => {
|
|
24506
|
+
// comparing the seen objects because sometimes
|
|
24507
|
+
// multiple schemas map to the same seen object.
|
|
24508
|
+
// e.g. lazy
|
|
24509
|
+
// external is configured
|
|
24510
|
+
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
24511
|
+
if (ctx.external) {
|
|
24512
|
+
const externalId = ctx.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${ctx.counter++}`;
|
|
24513
|
+
// check if schema is in the external registry
|
|
24514
|
+
const uriGenerator = ctx.external.uri ?? ((id) => id);
|
|
24515
|
+
if (externalId) {
|
|
24516
|
+
return { ref: uriGenerator(externalId) };
|
|
24517
|
+
}
|
|
24518
|
+
// otherwise, add to __shared
|
|
24519
|
+
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
|
|
24520
|
+
entry[1].defId = id; // set defId so it will be reused if needed
|
|
24521
|
+
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
|
24522
|
+
}
|
|
24523
|
+
if (entry[1] === root) {
|
|
24524
|
+
return { ref: "#" };
|
|
24525
|
+
}
|
|
24526
|
+
// self-contained schema
|
|
24527
|
+
const uriPrefix = `#`;
|
|
24528
|
+
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
|
24529
|
+
const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`;
|
|
24530
|
+
return { defId, ref: defUriPrefix + defId };
|
|
24531
|
+
};
|
|
24532
|
+
// stored cached version in `def` property
|
|
24533
|
+
// remove all properties, set $ref
|
|
24534
|
+
const extractToDef = (entry) => {
|
|
24535
|
+
// if the schema is already a reference, do not extract it
|
|
24536
|
+
if (entry[1].schema.$ref) {
|
|
24537
|
+
return;
|
|
24538
|
+
}
|
|
24539
|
+
const seen = entry[1];
|
|
24540
|
+
const { ref, defId } = makeURI(entry);
|
|
24541
|
+
seen.def = { ...seen.schema };
|
|
24542
|
+
// defId won't be set if the schema is a reference to an external schema
|
|
24543
|
+
// or if the schema is the root schema
|
|
24544
|
+
if (defId)
|
|
24545
|
+
seen.defId = defId;
|
|
24546
|
+
// wipe away all properties except $ref
|
|
24547
|
+
const schema = seen.schema;
|
|
24548
|
+
for (const key in schema) {
|
|
24549
|
+
delete schema[key];
|
|
24550
|
+
}
|
|
24551
|
+
schema.$ref = ref;
|
|
24552
|
+
};
|
|
24553
|
+
// throw on cycles
|
|
24554
|
+
// break cycles
|
|
24555
|
+
if (ctx.cycles === "throw") {
|
|
24556
|
+
for (const entry of ctx.seen.entries()) {
|
|
24557
|
+
const seen = entry[1];
|
|
24558
|
+
if (seen.cycle) {
|
|
24559
|
+
throw new Error("Cycle detected: " +
|
|
24560
|
+
`#/${seen.cycle?.join("/")}/<root>` +
|
|
24561
|
+
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
|
|
24562
|
+
}
|
|
24563
|
+
}
|
|
24564
|
+
}
|
|
24565
|
+
// extract schemas into $defs
|
|
24566
|
+
for (const entry of ctx.seen.entries()) {
|
|
24567
|
+
const seen = entry[1];
|
|
24568
|
+
// convert root schema to # $ref
|
|
24569
|
+
if (schema === entry[0]) {
|
|
24570
|
+
extractToDef(entry); // this has special handling for the root schema
|
|
24571
|
+
continue;
|
|
24572
|
+
}
|
|
24573
|
+
// extract schemas that are in the external registry
|
|
24574
|
+
if (ctx.external) {
|
|
24575
|
+
const ext = ctx.external.registry.get(entry[0])?.id;
|
|
24576
|
+
if (schema !== entry[0] && ext) {
|
|
24577
|
+
extractToDef(entry);
|
|
24578
|
+
continue;
|
|
24579
|
+
}
|
|
24580
|
+
}
|
|
24581
|
+
// extract schemas with `id` meta
|
|
24582
|
+
const id = ctx.metadataRegistry.get(entry[0])?.id;
|
|
24583
|
+
if (id) {
|
|
24584
|
+
extractToDef(entry);
|
|
24585
|
+
continue;
|
|
24586
|
+
}
|
|
24587
|
+
// break cycles
|
|
24588
|
+
if (seen.cycle) {
|
|
24589
|
+
// any
|
|
24590
|
+
extractToDef(entry);
|
|
24591
|
+
continue;
|
|
24592
|
+
}
|
|
24593
|
+
// extract reused schemas
|
|
24594
|
+
if (seen.count > 1) {
|
|
24595
|
+
if (ctx.reused === "ref") {
|
|
24596
|
+
extractToDef(entry);
|
|
24597
|
+
// biome-ignore lint:
|
|
24598
|
+
continue;
|
|
24599
|
+
}
|
|
24600
|
+
}
|
|
24601
|
+
}
|
|
24602
|
+
}
|
|
24603
|
+
function finalize(ctx, schema) {
|
|
24604
|
+
//
|
|
24605
|
+
// iterate over seen map;
|
|
24606
|
+
const root = ctx.seen.get(schema);
|
|
24607
|
+
if (!root)
|
|
24608
|
+
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
24609
|
+
// flatten _refs
|
|
24610
|
+
const flattenRef = (zodSchema) => {
|
|
24611
|
+
const seen = ctx.seen.get(zodSchema);
|
|
24612
|
+
const schema = seen.def ?? seen.schema;
|
|
24613
|
+
const _cached = { ...schema };
|
|
24614
|
+
// already seen
|
|
24615
|
+
if (seen.ref === null) {
|
|
24616
|
+
return;
|
|
24617
|
+
}
|
|
24618
|
+
// flatten ref if defined
|
|
24619
|
+
const ref = seen.ref;
|
|
24620
|
+
seen.ref = null; // prevent recursion
|
|
24621
|
+
if (ref) {
|
|
24622
|
+
flattenRef(ref);
|
|
24623
|
+
// merge referenced schema into current
|
|
24624
|
+
const refSchema = ctx.seen.get(ref).schema;
|
|
24625
|
+
if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) {
|
|
24626
|
+
schema.allOf = schema.allOf ?? [];
|
|
24627
|
+
schema.allOf.push(refSchema);
|
|
24628
|
+
}
|
|
24629
|
+
else {
|
|
24630
|
+
Object.assign(schema, refSchema);
|
|
24631
|
+
Object.assign(schema, _cached); // prevent overwriting any fields in the original schema
|
|
24632
|
+
}
|
|
24633
|
+
}
|
|
24634
|
+
// execute overrides
|
|
24635
|
+
if (!seen.isParent)
|
|
24636
|
+
ctx.override({
|
|
24637
|
+
zodSchema: zodSchema,
|
|
24638
|
+
jsonSchema: schema,
|
|
24639
|
+
path: seen.path ?? [],
|
|
24640
|
+
});
|
|
24641
|
+
};
|
|
24642
|
+
for (const entry of [...ctx.seen.entries()].reverse()) {
|
|
24643
|
+
flattenRef(entry[0]);
|
|
24644
|
+
}
|
|
24645
|
+
const result = {};
|
|
24646
|
+
if (ctx.target === "draft-2020-12") {
|
|
24647
|
+
result.$schema = "https://json-schema.org/draft/2020-12/schema";
|
|
24648
|
+
}
|
|
24649
|
+
else if (ctx.target === "draft-07") {
|
|
24650
|
+
result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
24651
|
+
}
|
|
24652
|
+
else if (ctx.target === "draft-04") {
|
|
24653
|
+
result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
24654
|
+
}
|
|
24655
|
+
else if (ctx.target === "openapi-3.0") ;
|
|
24656
|
+
else ;
|
|
24657
|
+
if (ctx.external?.uri) {
|
|
24658
|
+
const id = ctx.external.registry.get(schema)?.id;
|
|
24659
|
+
if (!id)
|
|
24660
|
+
throw new Error("Schema is missing an `id` property");
|
|
24661
|
+
result.$id = ctx.external.uri(id);
|
|
24662
|
+
}
|
|
24663
|
+
Object.assign(result, root.def ?? root.schema);
|
|
24664
|
+
// build defs object
|
|
24665
|
+
const defs = ctx.external?.defs ?? {};
|
|
24666
|
+
for (const entry of ctx.seen.entries()) {
|
|
24667
|
+
const seen = entry[1];
|
|
24668
|
+
if (seen.def && seen.defId) {
|
|
24669
|
+
defs[seen.defId] = seen.def;
|
|
24670
|
+
}
|
|
24671
|
+
}
|
|
24672
|
+
// set definitions in result
|
|
24673
|
+
if (ctx.external) ;
|
|
24674
|
+
else {
|
|
24675
|
+
if (Object.keys(defs).length > 0) {
|
|
24676
|
+
if (ctx.target === "draft-2020-12") {
|
|
24677
|
+
result.$defs = defs;
|
|
24678
|
+
}
|
|
24679
|
+
else {
|
|
24680
|
+
result.definitions = defs;
|
|
24681
|
+
}
|
|
24682
|
+
}
|
|
24683
|
+
}
|
|
24684
|
+
try {
|
|
24685
|
+
// this "finalizes" this schema and ensures all cycles are removed
|
|
24686
|
+
// each call to finalize() is functionally independent
|
|
24687
|
+
// though the seen map is shared
|
|
24688
|
+
const finalized = JSON.parse(JSON.stringify(result));
|
|
24689
|
+
Object.defineProperty(finalized, "~standard", {
|
|
24690
|
+
value: {
|
|
24691
|
+
...schema["~standard"],
|
|
24692
|
+
jsonSchema: {
|
|
24693
|
+
input: createStandardJSONSchemaMethod(schema, "input"),
|
|
24694
|
+
output: createStandardJSONSchemaMethod(schema, "output"),
|
|
24695
|
+
},
|
|
24696
|
+
},
|
|
24697
|
+
enumerable: false,
|
|
24698
|
+
writable: false,
|
|
24699
|
+
});
|
|
24700
|
+
return finalized;
|
|
24701
|
+
}
|
|
24702
|
+
catch (_err) {
|
|
24703
|
+
throw new Error("Error converting schema to JSON.");
|
|
24704
|
+
}
|
|
24705
|
+
}
|
|
24706
|
+
function isTransforming(_schema, _ctx) {
|
|
24707
|
+
const ctx = _ctx ?? { seen: new Set() };
|
|
24708
|
+
if (ctx.seen.has(_schema))
|
|
24709
|
+
return false;
|
|
24710
|
+
ctx.seen.add(_schema);
|
|
24711
|
+
const def = _schema._zod.def;
|
|
24712
|
+
if (def.type === "transform")
|
|
24713
|
+
return true;
|
|
24714
|
+
if (def.type === "array")
|
|
24715
|
+
return isTransforming(def.element, ctx);
|
|
24716
|
+
if (def.type === "set")
|
|
24717
|
+
return isTransforming(def.valueType, ctx);
|
|
24718
|
+
if (def.type === "lazy")
|
|
24719
|
+
return isTransforming(def.getter(), ctx);
|
|
24720
|
+
if (def.type === "promise" ||
|
|
24721
|
+
def.type === "optional" ||
|
|
24722
|
+
def.type === "nonoptional" ||
|
|
24723
|
+
def.type === "nullable" ||
|
|
24724
|
+
def.type === "readonly" ||
|
|
24725
|
+
def.type === "default" ||
|
|
24726
|
+
def.type === "prefault") {
|
|
24727
|
+
return isTransforming(def.innerType, ctx);
|
|
24728
|
+
}
|
|
24729
|
+
if (def.type === "intersection") {
|
|
24730
|
+
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
|
24731
|
+
}
|
|
24732
|
+
if (def.type === "record" || def.type === "map") {
|
|
24733
|
+
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
|
24734
|
+
}
|
|
24735
|
+
if (def.type === "pipe") {
|
|
24736
|
+
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
24737
|
+
}
|
|
24738
|
+
if (def.type === "object") {
|
|
24739
|
+
for (const key in def.shape) {
|
|
24740
|
+
if (isTransforming(def.shape[key], ctx))
|
|
24741
|
+
return true;
|
|
24742
|
+
}
|
|
24743
|
+
return false;
|
|
24744
|
+
}
|
|
24745
|
+
if (def.type === "union") {
|
|
24746
|
+
for (const option of def.options) {
|
|
24747
|
+
if (isTransforming(option, ctx))
|
|
24748
|
+
return true;
|
|
24749
|
+
}
|
|
24750
|
+
return false;
|
|
24751
|
+
}
|
|
24752
|
+
if (def.type === "tuple") {
|
|
24753
|
+
for (const item of def.items) {
|
|
24754
|
+
if (isTransforming(item, ctx))
|
|
24755
|
+
return true;
|
|
24756
|
+
}
|
|
24757
|
+
if (def.rest && isTransforming(def.rest, ctx))
|
|
24758
|
+
return true;
|
|
24759
|
+
return false;
|
|
24760
|
+
}
|
|
24761
|
+
return false;
|
|
24762
|
+
}
|
|
24763
|
+
/**
|
|
24764
|
+
* Creates a toJSONSchema method for a schema instance.
|
|
24765
|
+
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
|
24766
|
+
*/
|
|
24767
|
+
const createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
24768
|
+
const ctx = initializeContext({ ...params, processors });
|
|
24769
|
+
process$1(schema, ctx);
|
|
24770
|
+
extractDefs(ctx, schema);
|
|
24771
|
+
return finalize(ctx, schema);
|
|
24772
|
+
};
|
|
24773
|
+
const createStandardJSONSchemaMethod = (schema, io) => (params) => {
|
|
24774
|
+
const { libraryOptions, target } = params ?? {};
|
|
24775
|
+
const ctx = initializeContext({ ...(libraryOptions ?? {}), target, io, processors: {} });
|
|
24776
|
+
process$1(schema, ctx);
|
|
24777
|
+
extractDefs(ctx, schema);
|
|
24778
|
+
return finalize(ctx, schema);
|
|
24779
|
+
};
|
|
24780
|
+
|
|
24781
|
+
const formatMap = {
|
|
24782
|
+
guid: "uuid",
|
|
24783
|
+
url: "uri",
|
|
24784
|
+
datetime: "date-time",
|
|
24785
|
+
json_string: "json-string",
|
|
24786
|
+
regex: "", // do not set
|
|
24787
|
+
};
|
|
24788
|
+
// ==================== SIMPLE TYPE PROCESSORS ====================
|
|
24789
|
+
const stringProcessor = (schema, ctx, _json, _params) => {
|
|
24790
|
+
const json = _json;
|
|
24791
|
+
json.type = "string";
|
|
24792
|
+
const { minimum, maximum, format, patterns, contentEncoding } = schema._zod
|
|
24793
|
+
.bag;
|
|
24794
|
+
if (typeof minimum === "number")
|
|
24795
|
+
json.minLength = minimum;
|
|
24796
|
+
if (typeof maximum === "number")
|
|
24797
|
+
json.maxLength = maximum;
|
|
24798
|
+
// custom pattern overrides format
|
|
24799
|
+
if (format) {
|
|
24800
|
+
json.format = formatMap[format] ?? format;
|
|
24801
|
+
if (json.format === "")
|
|
24802
|
+
delete json.format; // empty format is not valid
|
|
24803
|
+
}
|
|
24804
|
+
if (contentEncoding)
|
|
24805
|
+
json.contentEncoding = contentEncoding;
|
|
24806
|
+
if (patterns && patterns.size > 0) {
|
|
24807
|
+
const regexes = [...patterns];
|
|
24808
|
+
if (regexes.length === 1)
|
|
24809
|
+
json.pattern = regexes[0].source;
|
|
24810
|
+
else if (regexes.length > 1) {
|
|
24811
|
+
json.allOf = [
|
|
24812
|
+
...regexes.map((regex) => ({
|
|
24813
|
+
...(ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0"
|
|
24814
|
+
? { type: "string" }
|
|
24815
|
+
: {}),
|
|
24816
|
+
pattern: regex.source,
|
|
24817
|
+
})),
|
|
24818
|
+
];
|
|
24819
|
+
}
|
|
24820
|
+
}
|
|
24821
|
+
};
|
|
24822
|
+
const numberProcessor = (schema, ctx, _json, _params) => {
|
|
24823
|
+
const json = _json;
|
|
24824
|
+
const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag;
|
|
24825
|
+
if (typeof format === "string" && format.includes("int"))
|
|
24826
|
+
json.type = "integer";
|
|
24827
|
+
else
|
|
24828
|
+
json.type = "number";
|
|
24829
|
+
if (typeof exclusiveMinimum === "number") {
|
|
24830
|
+
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
|
24831
|
+
json.minimum = exclusiveMinimum;
|
|
24832
|
+
json.exclusiveMinimum = true;
|
|
24833
|
+
}
|
|
24834
|
+
else {
|
|
24835
|
+
json.exclusiveMinimum = exclusiveMinimum;
|
|
24836
|
+
}
|
|
24837
|
+
}
|
|
24838
|
+
if (typeof minimum === "number") {
|
|
24839
|
+
json.minimum = minimum;
|
|
24840
|
+
if (typeof exclusiveMinimum === "number" && ctx.target !== "draft-04") {
|
|
24841
|
+
if (exclusiveMinimum >= minimum)
|
|
24842
|
+
delete json.minimum;
|
|
24843
|
+
else
|
|
24844
|
+
delete json.exclusiveMinimum;
|
|
24845
|
+
}
|
|
24846
|
+
}
|
|
24847
|
+
if (typeof exclusiveMaximum === "number") {
|
|
24848
|
+
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
|
24849
|
+
json.maximum = exclusiveMaximum;
|
|
24850
|
+
json.exclusiveMaximum = true;
|
|
24851
|
+
}
|
|
24852
|
+
else {
|
|
24853
|
+
json.exclusiveMaximum = exclusiveMaximum;
|
|
24854
|
+
}
|
|
24855
|
+
}
|
|
24856
|
+
if (typeof maximum === "number") {
|
|
24857
|
+
json.maximum = maximum;
|
|
24858
|
+
if (typeof exclusiveMaximum === "number" && ctx.target !== "draft-04") {
|
|
24859
|
+
if (exclusiveMaximum <= maximum)
|
|
24860
|
+
delete json.maximum;
|
|
24861
|
+
else
|
|
24862
|
+
delete json.exclusiveMaximum;
|
|
24863
|
+
}
|
|
24864
|
+
}
|
|
24865
|
+
if (typeof multipleOf === "number")
|
|
24866
|
+
json.multipleOf = multipleOf;
|
|
24867
|
+
};
|
|
24868
|
+
const neverProcessor = (_schema, _ctx, json, _params) => {
|
|
24869
|
+
json.not = {};
|
|
24870
|
+
};
|
|
24871
|
+
const anyProcessor = (_schema, _ctx, _json, _params) => {
|
|
24872
|
+
// empty schema accepts anything
|
|
24873
|
+
};
|
|
24874
|
+
const unknownProcessor = (_schema, _ctx, _json, _params) => {
|
|
24875
|
+
// empty schema accepts anything
|
|
24876
|
+
};
|
|
24877
|
+
const enumProcessor = (schema, _ctx, json, _params) => {
|
|
24878
|
+
const def = schema._zod.def;
|
|
24879
|
+
const values = getEnumValues(def.entries);
|
|
24880
|
+
// Number enums can have both string and number values
|
|
24881
|
+
if (values.every((v) => typeof v === "number"))
|
|
24882
|
+
json.type = "number";
|
|
24883
|
+
if (values.every((v) => typeof v === "string"))
|
|
24884
|
+
json.type = "string";
|
|
24885
|
+
json.enum = values;
|
|
24886
|
+
};
|
|
24887
|
+
const customProcessor = (_schema, ctx, _json, _params) => {
|
|
24888
|
+
if (ctx.unrepresentable === "throw") {
|
|
24889
|
+
throw new Error("Custom types cannot be represented in JSON Schema");
|
|
24890
|
+
}
|
|
24891
|
+
};
|
|
24892
|
+
const transformProcessor = (_schema, ctx, _json, _params) => {
|
|
24893
|
+
if (ctx.unrepresentable === "throw") {
|
|
24894
|
+
throw new Error("Transforms cannot be represented in JSON Schema");
|
|
24895
|
+
}
|
|
24896
|
+
};
|
|
24897
|
+
// ==================== COMPOSITE TYPE PROCESSORS ====================
|
|
24898
|
+
const arrayProcessor = (schema, ctx, _json, params) => {
|
|
24899
|
+
const json = _json;
|
|
24900
|
+
const def = schema._zod.def;
|
|
24901
|
+
const { minimum, maximum } = schema._zod.bag;
|
|
24902
|
+
if (typeof minimum === "number")
|
|
24903
|
+
json.minItems = minimum;
|
|
24904
|
+
if (typeof maximum === "number")
|
|
24905
|
+
json.maxItems = maximum;
|
|
24906
|
+
json.type = "array";
|
|
24907
|
+
json.items = process$1(def.element, ctx, { ...params, path: [...params.path, "items"] });
|
|
24908
|
+
};
|
|
24909
|
+
const objectProcessor = (schema, ctx, _json, params) => {
|
|
24910
|
+
const json = _json;
|
|
24911
|
+
const def = schema._zod.def;
|
|
24912
|
+
json.type = "object";
|
|
24913
|
+
json.properties = {};
|
|
24914
|
+
const shape = def.shape;
|
|
24915
|
+
for (const key in shape) {
|
|
24916
|
+
json.properties[key] = process$1(shape[key], ctx, {
|
|
24917
|
+
...params,
|
|
24918
|
+
path: [...params.path, "properties", key],
|
|
24919
|
+
});
|
|
24920
|
+
}
|
|
24921
|
+
// required keys
|
|
24922
|
+
const allKeys = new Set(Object.keys(shape));
|
|
24923
|
+
const requiredKeys = new Set([...allKeys].filter((key) => {
|
|
24924
|
+
const v = def.shape[key]._zod;
|
|
24925
|
+
if (ctx.io === "input") {
|
|
24926
|
+
return v.optin === undefined;
|
|
24927
|
+
}
|
|
24928
|
+
else {
|
|
24929
|
+
return v.optout === undefined;
|
|
24930
|
+
}
|
|
24931
|
+
}));
|
|
24932
|
+
if (requiredKeys.size > 0) {
|
|
24933
|
+
json.required = Array.from(requiredKeys);
|
|
24934
|
+
}
|
|
24935
|
+
// catchall
|
|
24936
|
+
if (def.catchall?._zod.def.type === "never") {
|
|
24937
|
+
// strict
|
|
24938
|
+
json.additionalProperties = false;
|
|
24939
|
+
}
|
|
24940
|
+
else if (!def.catchall) {
|
|
24941
|
+
// regular
|
|
24942
|
+
if (ctx.io === "output")
|
|
24943
|
+
json.additionalProperties = false;
|
|
24944
|
+
}
|
|
24945
|
+
else if (def.catchall) {
|
|
24946
|
+
json.additionalProperties = process$1(def.catchall, ctx, {
|
|
24947
|
+
...params,
|
|
24948
|
+
path: [...params.path, "additionalProperties"],
|
|
24949
|
+
});
|
|
24950
|
+
}
|
|
24951
|
+
};
|
|
24952
|
+
const unionProcessor = (schema, ctx, json, params) => {
|
|
24953
|
+
const def = schema._zod.def;
|
|
24954
|
+
// Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches)
|
|
24955
|
+
// This includes both z.xor() and discriminated unions
|
|
24956
|
+
const isExclusive = def.inclusive === false;
|
|
24957
|
+
const options = def.options.map((x, i) => process$1(x, ctx, {
|
|
24958
|
+
...params,
|
|
24959
|
+
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i],
|
|
24960
|
+
}));
|
|
24961
|
+
if (isExclusive) {
|
|
24962
|
+
json.oneOf = options;
|
|
24963
|
+
}
|
|
24964
|
+
else {
|
|
24965
|
+
json.anyOf = options;
|
|
24966
|
+
}
|
|
24967
|
+
};
|
|
24968
|
+
const intersectionProcessor = (schema, ctx, json, params) => {
|
|
24969
|
+
const def = schema._zod.def;
|
|
24970
|
+
const a = process$1(def.left, ctx, {
|
|
24971
|
+
...params,
|
|
24972
|
+
path: [...params.path, "allOf", 0],
|
|
24973
|
+
});
|
|
24974
|
+
const b = process$1(def.right, ctx, {
|
|
24975
|
+
...params,
|
|
24976
|
+
path: [...params.path, "allOf", 1],
|
|
24977
|
+
});
|
|
24978
|
+
const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1;
|
|
24979
|
+
const allOf = [
|
|
24980
|
+
...(isSimpleIntersection(a) ? a.allOf : [a]),
|
|
24981
|
+
...(isSimpleIntersection(b) ? b.allOf : [b]),
|
|
24982
|
+
];
|
|
24983
|
+
json.allOf = allOf;
|
|
24984
|
+
};
|
|
24985
|
+
const nullableProcessor = (schema, ctx, json, params) => {
|
|
24986
|
+
const def = schema._zod.def;
|
|
24987
|
+
const inner = process$1(def.innerType, ctx, params);
|
|
24988
|
+
const seen = ctx.seen.get(schema);
|
|
24989
|
+
if (ctx.target === "openapi-3.0") {
|
|
24990
|
+
seen.ref = def.innerType;
|
|
24991
|
+
json.nullable = true;
|
|
24992
|
+
}
|
|
24993
|
+
else {
|
|
24994
|
+
json.anyOf = [inner, { type: "null" }];
|
|
24995
|
+
}
|
|
24996
|
+
};
|
|
24997
|
+
const nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
24998
|
+
const def = schema._zod.def;
|
|
24999
|
+
process$1(def.innerType, ctx, params);
|
|
25000
|
+
const seen = ctx.seen.get(schema);
|
|
25001
|
+
seen.ref = def.innerType;
|
|
25002
|
+
};
|
|
25003
|
+
const defaultProcessor = (schema, ctx, json, params) => {
|
|
25004
|
+
const def = schema._zod.def;
|
|
25005
|
+
process$1(def.innerType, ctx, params);
|
|
25006
|
+
const seen = ctx.seen.get(schema);
|
|
25007
|
+
seen.ref = def.innerType;
|
|
25008
|
+
json.default = JSON.parse(JSON.stringify(def.defaultValue));
|
|
25009
|
+
};
|
|
25010
|
+
const prefaultProcessor = (schema, ctx, json, params) => {
|
|
25011
|
+
const def = schema._zod.def;
|
|
25012
|
+
process$1(def.innerType, ctx, params);
|
|
25013
|
+
const seen = ctx.seen.get(schema);
|
|
25014
|
+
seen.ref = def.innerType;
|
|
25015
|
+
if (ctx.io === "input")
|
|
25016
|
+
json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
|
25017
|
+
};
|
|
25018
|
+
const catchProcessor = (schema, ctx, json, params) => {
|
|
25019
|
+
const def = schema._zod.def;
|
|
25020
|
+
process$1(def.innerType, ctx, params);
|
|
25021
|
+
const seen = ctx.seen.get(schema);
|
|
25022
|
+
seen.ref = def.innerType;
|
|
25023
|
+
let catchValue;
|
|
25024
|
+
try {
|
|
25025
|
+
catchValue = def.catchValue(undefined);
|
|
25026
|
+
}
|
|
25027
|
+
catch {
|
|
25028
|
+
throw new Error("Dynamic catch values are not supported in JSON Schema");
|
|
25029
|
+
}
|
|
25030
|
+
json.default = catchValue;
|
|
25031
|
+
};
|
|
25032
|
+
const pipeProcessor = (schema, ctx, _json, params) => {
|
|
25033
|
+
const def = schema._zod.def;
|
|
25034
|
+
const innerType = ctx.io === "input" ? (def.in._zod.def.type === "transform" ? def.out : def.in) : def.out;
|
|
25035
|
+
process$1(innerType, ctx, params);
|
|
25036
|
+
const seen = ctx.seen.get(schema);
|
|
25037
|
+
seen.ref = innerType;
|
|
25038
|
+
};
|
|
25039
|
+
const readonlyProcessor = (schema, ctx, json, params) => {
|
|
25040
|
+
const def = schema._zod.def;
|
|
25041
|
+
process$1(def.innerType, ctx, params);
|
|
25042
|
+
const seen = ctx.seen.get(schema);
|
|
25043
|
+
seen.ref = def.innerType;
|
|
25044
|
+
json.readOnly = true;
|
|
25045
|
+
};
|
|
25046
|
+
const optionalProcessor = (schema, ctx, _json, params) => {
|
|
25047
|
+
const def = schema._zod.def;
|
|
25048
|
+
process$1(def.innerType, ctx, params);
|
|
25049
|
+
const seen = ctx.seen.get(schema);
|
|
25050
|
+
seen.ref = def.innerType;
|
|
25051
|
+
};
|
|
25052
|
+
|
|
23669
25053
|
const ZodISODateTime = /*@__PURE__*/ $constructor("ZodISODateTime", (inst, def) => {
|
|
23670
25054
|
$ZodISODateTime.init(inst, def);
|
|
23671
25055
|
ZodStringFormat.init(inst, def);
|
|
@@ -23756,6 +25140,13 @@ const safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
|
|
|
23756
25140
|
|
|
23757
25141
|
const ZodType = /*@__PURE__*/ $constructor("ZodType", (inst, def) => {
|
|
23758
25142
|
$ZodType.init(inst, def);
|
|
25143
|
+
Object.assign(inst["~standard"], {
|
|
25144
|
+
jsonSchema: {
|
|
25145
|
+
input: createStandardJSONSchemaMethod(inst, "input"),
|
|
25146
|
+
output: createStandardJSONSchemaMethod(inst, "output"),
|
|
25147
|
+
},
|
|
25148
|
+
});
|
|
25149
|
+
inst.toJSONSchema = createToJSONSchemaMethod(inst, {});
|
|
23759
25150
|
inst.def = def;
|
|
23760
25151
|
inst.type = def.type;
|
|
23761
25152
|
Object.defineProperty(inst, "_def", { value: def });
|
|
@@ -23837,6 +25228,7 @@ const ZodType = /*@__PURE__*/ $constructor("ZodType", (inst, def) => {
|
|
|
23837
25228
|
const _ZodString = /*@__PURE__*/ $constructor("_ZodString", (inst, def) => {
|
|
23838
25229
|
$ZodString.init(inst, def);
|
|
23839
25230
|
ZodType.init(inst, def);
|
|
25231
|
+
inst._zod.processJSONSchema = (ctx, json, params) => stringProcessor(inst, ctx, json);
|
|
23840
25232
|
const bag = inst._zod.bag;
|
|
23841
25233
|
inst.format = bag.format ?? null;
|
|
23842
25234
|
inst.minLength = bag.minimum ?? null;
|
|
@@ -23994,6 +25386,7 @@ const ZodJWT = /*@__PURE__*/ $constructor("ZodJWT", (inst, def) => {
|
|
|
23994
25386
|
const ZodNumber = /*@__PURE__*/ $constructor("ZodNumber", (inst, def) => {
|
|
23995
25387
|
$ZodNumber.init(inst, def);
|
|
23996
25388
|
ZodType.init(inst, def);
|
|
25389
|
+
inst._zod.processJSONSchema = (ctx, json, params) => numberProcessor(inst, ctx, json);
|
|
23997
25390
|
inst.gt = (value, params) => inst.check(_gt(value, params));
|
|
23998
25391
|
inst.gte = (value, params) => inst.check(_gte(value, params));
|
|
23999
25392
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
@@ -24032,6 +25425,7 @@ function int(params) {
|
|
|
24032
25425
|
const ZodAny = /*@__PURE__*/ $constructor("ZodAny", (inst, def) => {
|
|
24033
25426
|
$ZodAny.init(inst, def);
|
|
24034
25427
|
ZodType.init(inst, def);
|
|
25428
|
+
inst._zod.processJSONSchema = (ctx, json, params) => anyProcessor();
|
|
24035
25429
|
});
|
|
24036
25430
|
function any() {
|
|
24037
25431
|
return _any(ZodAny);
|
|
@@ -24039,6 +25433,7 @@ function any() {
|
|
|
24039
25433
|
const ZodUnknown = /*@__PURE__*/ $constructor("ZodUnknown", (inst, def) => {
|
|
24040
25434
|
$ZodUnknown.init(inst, def);
|
|
24041
25435
|
ZodType.init(inst, def);
|
|
25436
|
+
inst._zod.processJSONSchema = (ctx, json, params) => unknownProcessor();
|
|
24042
25437
|
});
|
|
24043
25438
|
function unknown() {
|
|
24044
25439
|
return _unknown(ZodUnknown);
|
|
@@ -24046,6 +25441,7 @@ function unknown() {
|
|
|
24046
25441
|
const ZodNever = /*@__PURE__*/ $constructor("ZodNever", (inst, def) => {
|
|
24047
25442
|
$ZodNever.init(inst, def);
|
|
24048
25443
|
ZodType.init(inst, def);
|
|
25444
|
+
inst._zod.processJSONSchema = (ctx, json, params) => neverProcessor(inst, ctx, json);
|
|
24049
25445
|
});
|
|
24050
25446
|
function never(params) {
|
|
24051
25447
|
return _never(ZodNever, params);
|
|
@@ -24053,6 +25449,7 @@ function never(params) {
|
|
|
24053
25449
|
const ZodArray = /*@__PURE__*/ $constructor("ZodArray", (inst, def) => {
|
|
24054
25450
|
$ZodArray.init(inst, def);
|
|
24055
25451
|
ZodType.init(inst, def);
|
|
25452
|
+
inst._zod.processJSONSchema = (ctx, json, params) => arrayProcessor(inst, ctx, json, params);
|
|
24056
25453
|
inst.element = def.element;
|
|
24057
25454
|
inst.min = (minLength, params) => inst.check(_minLength(minLength, params));
|
|
24058
25455
|
inst.nonempty = (params) => inst.check(_minLength(1, params));
|
|
@@ -24066,6 +25463,7 @@ function array(element, params) {
|
|
|
24066
25463
|
const ZodObject = /*@__PURE__*/ $constructor("ZodObject", (inst, def) => {
|
|
24067
25464
|
$ZodObjectJIT.init(inst, def);
|
|
24068
25465
|
ZodType.init(inst, def);
|
|
25466
|
+
inst._zod.processJSONSchema = (ctx, json, params) => objectProcessor(inst, ctx, json, params);
|
|
24069
25467
|
defineLazy(inst, "shape", () => {
|
|
24070
25468
|
return def.shape;
|
|
24071
25469
|
});
|
|
@@ -24098,6 +25496,7 @@ function object(shape, params) {
|
|
|
24098
25496
|
const ZodUnion = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => {
|
|
24099
25497
|
$ZodUnion.init(inst, def);
|
|
24100
25498
|
ZodType.init(inst, def);
|
|
25499
|
+
inst._zod.processJSONSchema = (ctx, json, params) => unionProcessor(inst, ctx, json, params);
|
|
24101
25500
|
inst.options = def.options;
|
|
24102
25501
|
});
|
|
24103
25502
|
function union(options, params) {
|
|
@@ -24110,6 +25509,7 @@ function union(options, params) {
|
|
|
24110
25509
|
const ZodIntersection = /*@__PURE__*/ $constructor("ZodIntersection", (inst, def) => {
|
|
24111
25510
|
$ZodIntersection.init(inst, def);
|
|
24112
25511
|
ZodType.init(inst, def);
|
|
25512
|
+
inst._zod.processJSONSchema = (ctx, json, params) => intersectionProcessor(inst, ctx, json, params);
|
|
24113
25513
|
});
|
|
24114
25514
|
function intersection(left, right) {
|
|
24115
25515
|
return new ZodIntersection({
|
|
@@ -24121,6 +25521,7 @@ function intersection(left, right) {
|
|
|
24121
25521
|
const ZodEnum = /*@__PURE__*/ $constructor("ZodEnum", (inst, def) => {
|
|
24122
25522
|
$ZodEnum.init(inst, def);
|
|
24123
25523
|
ZodType.init(inst, def);
|
|
25524
|
+
inst._zod.processJSONSchema = (ctx, json, params) => enumProcessor(inst, ctx, json);
|
|
24124
25525
|
inst.enum = def.entries;
|
|
24125
25526
|
inst.options = Object.values(def.entries);
|
|
24126
25527
|
const keys = new Set(Object.keys(def.entries));
|
|
@@ -24168,6 +25569,7 @@ function _enum(values, params) {
|
|
|
24168
25569
|
const ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => {
|
|
24169
25570
|
$ZodTransform.init(inst, def);
|
|
24170
25571
|
ZodType.init(inst, def);
|
|
25572
|
+
inst._zod.processJSONSchema = (ctx, json, params) => transformProcessor(inst, ctx);
|
|
24171
25573
|
inst._zod.parse = (payload, _ctx) => {
|
|
24172
25574
|
if (_ctx.direction === "backward") {
|
|
24173
25575
|
throw new $ZodEncodeError(inst.constructor.name);
|
|
@@ -24208,6 +25610,7 @@ function transform(fn) {
|
|
|
24208
25610
|
const ZodOptional = /*@__PURE__*/ $constructor("ZodOptional", (inst, def) => {
|
|
24209
25611
|
$ZodOptional.init(inst, def);
|
|
24210
25612
|
ZodType.init(inst, def);
|
|
25613
|
+
inst._zod.processJSONSchema = (ctx, json, params) => optionalProcessor(inst, ctx, json, params);
|
|
24211
25614
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24212
25615
|
});
|
|
24213
25616
|
function optional(innerType) {
|
|
@@ -24219,6 +25622,7 @@ function optional(innerType) {
|
|
|
24219
25622
|
const ZodNullable = /*@__PURE__*/ $constructor("ZodNullable", (inst, def) => {
|
|
24220
25623
|
$ZodNullable.init(inst, def);
|
|
24221
25624
|
ZodType.init(inst, def);
|
|
25625
|
+
inst._zod.processJSONSchema = (ctx, json, params) => nullableProcessor(inst, ctx, json, params);
|
|
24222
25626
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24223
25627
|
});
|
|
24224
25628
|
function nullable(innerType) {
|
|
@@ -24230,6 +25634,7 @@ function nullable(innerType) {
|
|
|
24230
25634
|
const ZodDefault = /*@__PURE__*/ $constructor("ZodDefault", (inst, def) => {
|
|
24231
25635
|
$ZodDefault.init(inst, def);
|
|
24232
25636
|
ZodType.init(inst, def);
|
|
25637
|
+
inst._zod.processJSONSchema = (ctx, json, params) => defaultProcessor(inst, ctx, json, params);
|
|
24233
25638
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24234
25639
|
inst.removeDefault = inst.unwrap;
|
|
24235
25640
|
});
|
|
@@ -24245,6 +25650,7 @@ function _default(innerType, defaultValue) {
|
|
|
24245
25650
|
const ZodPrefault = /*@__PURE__*/ $constructor("ZodPrefault", (inst, def) => {
|
|
24246
25651
|
$ZodPrefault.init(inst, def);
|
|
24247
25652
|
ZodType.init(inst, def);
|
|
25653
|
+
inst._zod.processJSONSchema = (ctx, json, params) => prefaultProcessor(inst, ctx, json, params);
|
|
24248
25654
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24249
25655
|
});
|
|
24250
25656
|
function prefault(innerType, defaultValue) {
|
|
@@ -24259,6 +25665,7 @@ function prefault(innerType, defaultValue) {
|
|
|
24259
25665
|
const ZodNonOptional = /*@__PURE__*/ $constructor("ZodNonOptional", (inst, def) => {
|
|
24260
25666
|
$ZodNonOptional.init(inst, def);
|
|
24261
25667
|
ZodType.init(inst, def);
|
|
25668
|
+
inst._zod.processJSONSchema = (ctx, json, params) => nonoptionalProcessor(inst, ctx, json, params);
|
|
24262
25669
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24263
25670
|
});
|
|
24264
25671
|
function nonoptional(innerType, params) {
|
|
@@ -24271,6 +25678,7 @@ function nonoptional(innerType, params) {
|
|
|
24271
25678
|
const ZodCatch = /*@__PURE__*/ $constructor("ZodCatch", (inst, def) => {
|
|
24272
25679
|
$ZodCatch.init(inst, def);
|
|
24273
25680
|
ZodType.init(inst, def);
|
|
25681
|
+
inst._zod.processJSONSchema = (ctx, json, params) => catchProcessor(inst, ctx, json, params);
|
|
24274
25682
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24275
25683
|
inst.removeCatch = inst.unwrap;
|
|
24276
25684
|
});
|
|
@@ -24284,6 +25692,7 @@ function _catch(innerType, catchValue) {
|
|
|
24284
25692
|
const ZodPipe = /*@__PURE__*/ $constructor("ZodPipe", (inst, def) => {
|
|
24285
25693
|
$ZodPipe.init(inst, def);
|
|
24286
25694
|
ZodType.init(inst, def);
|
|
25695
|
+
inst._zod.processJSONSchema = (ctx, json, params) => pipeProcessor(inst, ctx, json, params);
|
|
24287
25696
|
inst.in = def.in;
|
|
24288
25697
|
inst.out = def.out;
|
|
24289
25698
|
});
|
|
@@ -24298,6 +25707,7 @@ function pipe(in_, out) {
|
|
|
24298
25707
|
const ZodReadonly = /*@__PURE__*/ $constructor("ZodReadonly", (inst, def) => {
|
|
24299
25708
|
$ZodReadonly.init(inst, def);
|
|
24300
25709
|
ZodType.init(inst, def);
|
|
25710
|
+
inst._zod.processJSONSchema = (ctx, json, params) => readonlyProcessor(inst, ctx, json, params);
|
|
24301
25711
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
24302
25712
|
});
|
|
24303
25713
|
function readonly(innerType) {
|
|
@@ -24309,6 +25719,7 @@ function readonly(innerType) {
|
|
|
24309
25719
|
const ZodCustom = /*@__PURE__*/ $constructor("ZodCustom", (inst, def) => {
|
|
24310
25720
|
$ZodCustom.init(inst, def);
|
|
24311
25721
|
ZodType.init(inst, def);
|
|
25722
|
+
inst._zod.processJSONSchema = (ctx, json, params) => customProcessor(inst, ctx);
|
|
24312
25723
|
});
|
|
24313
25724
|
function refine(fn, _params = {}) {
|
|
24314
25725
|
return _refine(ZodCustom, fn, _params);
|
|
@@ -24318,6 +25729,99 @@ function superRefine(fn) {
|
|
|
24318
25729
|
return _superRefine(fn);
|
|
24319
25730
|
}
|
|
24320
25731
|
|
|
25732
|
+
class BaseRoom {
|
|
25733
|
+
constructor() {
|
|
25734
|
+
/**
|
|
25735
|
+
* Signal containing the room's database of items, classes, and other game data
|
|
25736
|
+
*
|
|
25737
|
+
* This database can be dynamically populated using `addInDatabase()` and
|
|
25738
|
+
* `removeInDatabase()` methods. It's used to store game entities like items,
|
|
25739
|
+
* classes, skills, etc. that are available in this room.
|
|
25740
|
+
*
|
|
25741
|
+
* @example
|
|
25742
|
+
* ```ts
|
|
25743
|
+
* // Add data to database
|
|
25744
|
+
* room.addInDatabase('Potion', PotionClass);
|
|
25745
|
+
*
|
|
25746
|
+
* // Access database
|
|
25747
|
+
* const potion = room.database()['Potion'];
|
|
25748
|
+
* ```
|
|
25749
|
+
*/
|
|
25750
|
+
this.database = signal({});
|
|
25751
|
+
}
|
|
25752
|
+
/**
|
|
25753
|
+
* Add data to the room's database
|
|
25754
|
+
*
|
|
25755
|
+
* Adds an item, class, or other game entity to the room's database.
|
|
25756
|
+
* If the ID already exists and `force` is not enabled, the addition is ignored.
|
|
25757
|
+
*
|
|
25758
|
+
* ## Architecture
|
|
25759
|
+
*
|
|
25760
|
+
* This method is used by the item management system to store item definitions
|
|
25761
|
+
* in the room's database. When a player adds an item, the system first checks
|
|
25762
|
+
* if the item exists in the database, and if not, adds it using this method.
|
|
25763
|
+
*
|
|
25764
|
+
* @param id - Unique identifier for the data
|
|
25765
|
+
* @param data - The data to add (can be a class, object, etc.)
|
|
25766
|
+
* @param options - Optional configuration
|
|
25767
|
+
* @param options.force - If true, overwrites existing data with the same ID
|
|
25768
|
+
* @returns `true` if data was added, `false` if it was ignored (ID already exists)
|
|
25769
|
+
*
|
|
25770
|
+
* @example
|
|
25771
|
+
* ```ts
|
|
25772
|
+
* // Add a class to the database
|
|
25773
|
+
* room.addInDatabase('Potion', PotionClass);
|
|
25774
|
+
*
|
|
25775
|
+
* // Add an item object to the database
|
|
25776
|
+
* room.addInDatabase('custom-item', {
|
|
25777
|
+
* name: 'Custom Item',
|
|
25778
|
+
* price: 100
|
|
25779
|
+
* });
|
|
25780
|
+
*
|
|
25781
|
+
* // Force overwrite existing data
|
|
25782
|
+
* room.addInDatabase('Potion', UpdatedPotionClass, { force: true });
|
|
25783
|
+
* ```
|
|
25784
|
+
*/
|
|
25785
|
+
addInDatabase(id, data, options) {
|
|
25786
|
+
const database = this.database();
|
|
25787
|
+
if (database[id] !== void 0 && !options?.force) {
|
|
25788
|
+
return false;
|
|
25789
|
+
}
|
|
25790
|
+
database[id] = data;
|
|
25791
|
+
this.database.set(database);
|
|
25792
|
+
return true;
|
|
25793
|
+
}
|
|
25794
|
+
/**
|
|
25795
|
+
* Remove data from the room's database
|
|
25796
|
+
*
|
|
25797
|
+
* This method allows you to remove items or data from the room's database.
|
|
25798
|
+
*
|
|
25799
|
+
* @param id - Unique identifier of the data to remove
|
|
25800
|
+
* @returns `true` if data was removed, `false` if ID didn't exist
|
|
25801
|
+
*
|
|
25802
|
+
* @example
|
|
25803
|
+
* ```ts
|
|
25804
|
+
* // Remove an item from the database
|
|
25805
|
+
* room.removeInDatabase('Potion');
|
|
25806
|
+
*
|
|
25807
|
+
* // Check if removal was successful
|
|
25808
|
+
* const removed = room.removeInDatabase('custom-item');
|
|
25809
|
+
* if (removed) {
|
|
25810
|
+
* console.log('Item removed successfully');
|
|
25811
|
+
* }
|
|
25812
|
+
* ```
|
|
25813
|
+
*/
|
|
25814
|
+
removeInDatabase(id) {
|
|
25815
|
+
const database = this.database();
|
|
25816
|
+
if (database[id] === void 0) {
|
|
25817
|
+
return false;
|
|
25818
|
+
}
|
|
25819
|
+
delete database[id];
|
|
25820
|
+
this.database.set(database);
|
|
25821
|
+
return true;
|
|
25822
|
+
}
|
|
25823
|
+
}
|
|
25824
|
+
|
|
24321
25825
|
var __defProp$1 = Object.defineProperty;
|
|
24322
25826
|
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
24323
25827
|
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
@@ -24341,7 +25845,7 @@ const MapUpdateSchema = object({
|
|
|
24341
25845
|
height: number()
|
|
24342
25846
|
});
|
|
24343
25847
|
let RpgMap = class extends RpgCommonMap {
|
|
24344
|
-
constructor() {
|
|
25848
|
+
constructor(room) {
|
|
24345
25849
|
super();
|
|
24346
25850
|
this.players = signal({});
|
|
24347
25851
|
this.events = signal({});
|
|
@@ -24418,9 +25922,19 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24418
25922
|
this._shapeEntities = /* @__PURE__ */ new Map();
|
|
24419
25923
|
/** Enable/disable automatic tick processing (useful for unit tests) */
|
|
24420
25924
|
this._autoTickEnabled = true;
|
|
25925
|
+
this.autoSync = true;
|
|
24421
25926
|
this.hooks.callHooks("server-map-onStart", this).subscribe();
|
|
24422
|
-
|
|
24423
|
-
|
|
25927
|
+
const isTest = room.env.TEST === "true" ? true : false;
|
|
25928
|
+
if (isTest) {
|
|
25929
|
+
this.autoSync = false;
|
|
25930
|
+
this.setAutoTick(false);
|
|
25931
|
+
this.autoTickEnabled = false;
|
|
25932
|
+
this.throttleSync = 0;
|
|
25933
|
+
this.throttleStorage = 0;
|
|
25934
|
+
} else {
|
|
25935
|
+
this.throttleSync = this.isStandalone ? 1 : 50;
|
|
25936
|
+
this.throttleStorage = this.isStandalone ? 1 : 50;
|
|
25937
|
+
}
|
|
24424
25938
|
this.sessionExpiryTime = 1e3 * 60 * 5;
|
|
24425
25939
|
this.setupCollisionDetection();
|
|
24426
25940
|
if (this._autoTickEnabled) {
|
|
@@ -24617,12 +26131,16 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24617
26131
|
* ```
|
|
24618
26132
|
*/
|
|
24619
26133
|
onJoin(player, conn) {
|
|
24620
|
-
player.
|
|
26134
|
+
if (player.setMap) {
|
|
26135
|
+
player.setMap(this);
|
|
26136
|
+
} else {
|
|
26137
|
+
player.map = this;
|
|
26138
|
+
}
|
|
24621
26139
|
player.context = context$1;
|
|
24622
26140
|
player.conn = conn;
|
|
24623
26141
|
player._onInit();
|
|
24624
26142
|
this.dataIsReady$.pipe(
|
|
24625
|
-
finalize(async () => {
|
|
26143
|
+
finalize$1(async () => {
|
|
24626
26144
|
if (this.stopAllSoundsBeforeJoin) {
|
|
24627
26145
|
player.stopAllSounds();
|
|
24628
26146
|
}
|
|
@@ -24683,85 +26201,8 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24683
26201
|
get hooks() {
|
|
24684
26202
|
return inject$1(context$1, ModulesToken);
|
|
24685
26203
|
}
|
|
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
26204
|
guiInteraction(player, value) {
|
|
26205
|
+
this.hooks.callHooks("server-player-guiInteraction", player, value);
|
|
24765
26206
|
player.syncChanges();
|
|
24766
26207
|
}
|
|
24767
26208
|
guiExit(player, { guiId, data }) {
|
|
@@ -24804,6 +26245,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
24804
26245
|
};
|
|
24805
26246
|
await lastValueFrom(this.hooks.callHooks("server-maps-load", this));
|
|
24806
26247
|
await lastValueFrom(this.hooks.callHooks("server-worldMaps-load", this));
|
|
26248
|
+
await lastValueFrom(this.hooks.callHooks("server-databaseHooks-load", this));
|
|
24807
26249
|
map.events = map.events ?? [];
|
|
24808
26250
|
if (map.id) {
|
|
24809
26251
|
const mapFound = this.maps.find((m) => m.id === map.id);
|
|
@@ -25151,8 +26593,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25151
26593
|
/**
|
|
25152
26594
|
* Add data to the map's database
|
|
25153
26595
|
*
|
|
25154
|
-
* This method
|
|
25155
|
-
* By default, if an ID already exists, the operation is ignored to prevent overwriting existing data.
|
|
26596
|
+
* This method delegates to BaseRoom's implementation to avoid code duplication.
|
|
25156
26597
|
*
|
|
25157
26598
|
* @param id - Unique identifier for the data
|
|
25158
26599
|
* @param data - The data to store (can be a class, object, or any value)
|
|
@@ -25176,17 +26617,12 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25176
26617
|
* ```
|
|
25177
26618
|
*/
|
|
25178
26619
|
addInDatabase(id, data, options) {
|
|
25179
|
-
|
|
25180
|
-
if (database[id] !== void 0 && !options?.force) {
|
|
25181
|
-
return false;
|
|
25182
|
-
}
|
|
25183
|
-
database[id] = data;
|
|
25184
|
-
return true;
|
|
26620
|
+
return BaseRoom.prototype.addInDatabase.call(this, id, data, options);
|
|
25185
26621
|
}
|
|
25186
26622
|
/**
|
|
25187
26623
|
* Remove data from the map's database
|
|
25188
26624
|
*
|
|
25189
|
-
* This method
|
|
26625
|
+
* This method delegates to BaseRoom's implementation to avoid code duplication.
|
|
25190
26626
|
*
|
|
25191
26627
|
* @param id - Unique identifier of the data to remove
|
|
25192
26628
|
* @returns true if data was removed, false if ID didn't exist
|
|
@@ -25204,12 +26640,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25204
26640
|
* ```
|
|
25205
26641
|
*/
|
|
25206
26642
|
removeInDatabase(id) {
|
|
25207
|
-
|
|
25208
|
-
if (database[id] === void 0) {
|
|
25209
|
-
return false;
|
|
25210
|
-
}
|
|
25211
|
-
delete database[id];
|
|
25212
|
-
return true;
|
|
26643
|
+
return BaseRoom.prototype.removeInDatabase.call(this, id);
|
|
25213
26644
|
}
|
|
25214
26645
|
/**
|
|
25215
26646
|
* Creates a dynamic event on the map
|
|
@@ -25289,8 +26720,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25289
26720
|
}
|
|
25290
26721
|
eventInstance.map = this;
|
|
25291
26722
|
eventInstance.context = context$1;
|
|
25292
|
-
eventInstance.
|
|
25293
|
-
eventInstance.y.set(y);
|
|
26723
|
+
await eventInstance.teleport({ x, y });
|
|
25294
26724
|
this.events()[id] = eventInstance;
|
|
25295
26725
|
await eventInstance.execMethod("onInit");
|
|
25296
26726
|
}
|
|
@@ -25577,6 +27007,19 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
25577
27007
|
}, holder);
|
|
25578
27008
|
}
|
|
25579
27009
|
}
|
|
27010
|
+
/**
|
|
27011
|
+
* Apply sync to the client
|
|
27012
|
+
*
|
|
27013
|
+
* This method applies sync to the client by calling the `$applySync()` method.
|
|
27014
|
+
*
|
|
27015
|
+
* @example
|
|
27016
|
+
* ```ts
|
|
27017
|
+
* map.applySyncToClient();
|
|
27018
|
+
* ```
|
|
27019
|
+
*/
|
|
27020
|
+
applySyncToClient() {
|
|
27021
|
+
this.$applySync();
|
|
27022
|
+
}
|
|
25580
27023
|
/**
|
|
25581
27024
|
* Create a shape dynamically on the map
|
|
25582
27025
|
*
|
|
@@ -25983,9 +27426,15 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
25983
27426
|
if (kind && result) __defProp(target, key, result);
|
|
25984
27427
|
return result;
|
|
25985
27428
|
};
|
|
25986
|
-
let LobbyRoom = class {
|
|
25987
|
-
constructor() {
|
|
27429
|
+
let LobbyRoom = class extends BaseRoom {
|
|
27430
|
+
constructor(room) {
|
|
27431
|
+
super();
|
|
25988
27432
|
this.players = signal({});
|
|
27433
|
+
this.autoSync = true;
|
|
27434
|
+
const isTest = room.env.TEST === "true" ? true : false;
|
|
27435
|
+
if (isTest) {
|
|
27436
|
+
this.autoSync = false;
|
|
27437
|
+
}
|
|
25989
27438
|
}
|
|
25990
27439
|
onJoin(player, conn) {
|
|
25991
27440
|
player.map = this;
|
|
@@ -26338,6 +27787,19 @@ function provideServerModules(modules) {
|
|
|
26338
27787
|
}
|
|
26339
27788
|
};
|
|
26340
27789
|
}
|
|
27790
|
+
if (module.database && typeof module.database === "object") {
|
|
27791
|
+
const database = { ...module.database };
|
|
27792
|
+
module = {
|
|
27793
|
+
...module,
|
|
27794
|
+
databaseHooks: {
|
|
27795
|
+
load: (engine) => {
|
|
27796
|
+
for (const key in database) {
|
|
27797
|
+
engine.addInDatabase(key, database[key]);
|
|
27798
|
+
}
|
|
27799
|
+
}
|
|
27800
|
+
}
|
|
27801
|
+
};
|
|
27802
|
+
}
|
|
26341
27803
|
return module;
|
|
26342
27804
|
});
|
|
26343
27805
|
return modules2;
|