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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5284,171 +5284,6 @@ var BehaviorSubject = (function (_super) {
5284
5284
  return BehaviorSubject;
5285
5285
  }(Subject));
5286
5286
 
5287
- var dateTimestampProvider = {
5288
- now: function () {
5289
- return (Date).now();
5290
- }};
5291
-
5292
- var Action$1 = (function (_super) {
5293
- __extends(Action, _super);
5294
- function Action(scheduler, work) {
5295
- return _super.call(this) || this;
5296
- }
5297
- Action.prototype.schedule = function (state, delay) {
5298
- return this;
5299
- };
5300
- return Action;
5301
- }(Subscription));
5302
-
5303
- var intervalProvider = {
5304
- setInterval: function (handler, timeout) {
5305
- var args = [];
5306
- for (var _i = 2; _i < arguments.length; _i++) {
5307
- args[_i - 2] = arguments[_i];
5308
- }
5309
- return setInterval.apply(void 0, __spreadArray([handler, timeout], __read(args)));
5310
- },
5311
- clearInterval: function (handle) {
5312
- return (clearInterval)(handle);
5313
- },
5314
- delegate: undefined,
5315
- };
5316
-
5317
- var AsyncAction = (function (_super) {
5318
- __extends(AsyncAction, _super);
5319
- function AsyncAction(scheduler, work) {
5320
- var _this = _super.call(this, scheduler, work) || this;
5321
- _this.scheduler = scheduler;
5322
- _this.work = work;
5323
- _this.pending = false;
5324
- return _this;
5325
- }
5326
- AsyncAction.prototype.schedule = function (state, delay) {
5327
- var _a;
5328
- if (delay === void 0) { delay = 0; }
5329
- if (this.closed) {
5330
- return this;
5331
- }
5332
- this.state = state;
5333
- var id = this.id;
5334
- var scheduler = this.scheduler;
5335
- if (id != null) {
5336
- this.id = this.recycleAsyncId(scheduler, id, delay);
5337
- }
5338
- this.pending = true;
5339
- this.delay = delay;
5340
- this.id = (_a = this.id) !== null && _a !== void 0 ? _a : this.requestAsyncId(scheduler, this.id, delay);
5341
- return this;
5342
- };
5343
- AsyncAction.prototype.requestAsyncId = function (scheduler, _id, delay) {
5344
- if (delay === void 0) { delay = 0; }
5345
- return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);
5346
- };
5347
- AsyncAction.prototype.recycleAsyncId = function (_scheduler, id, delay) {
5348
- if (delay === void 0) { delay = 0; }
5349
- if (delay != null && this.delay === delay && this.pending === false) {
5350
- return id;
5351
- }
5352
- if (id != null) {
5353
- intervalProvider.clearInterval(id);
5354
- }
5355
- return undefined;
5356
- };
5357
- AsyncAction.prototype.execute = function (state, delay) {
5358
- if (this.closed) {
5359
- return new Error('executing a cancelled action');
5360
- }
5361
- this.pending = false;
5362
- var error = this._execute(state, delay);
5363
- if (error) {
5364
- return error;
5365
- }
5366
- else if (this.pending === false && this.id != null) {
5367
- this.id = this.recycleAsyncId(this.scheduler, this.id, null);
5368
- }
5369
- };
5370
- AsyncAction.prototype._execute = function (state, _delay) {
5371
- var errored = false;
5372
- var errorValue;
5373
- try {
5374
- this.work(state);
5375
- }
5376
- catch (e) {
5377
- errored = true;
5378
- errorValue = e ? e : new Error('Scheduled action threw falsy error');
5379
- }
5380
- if (errored) {
5381
- this.unsubscribe();
5382
- return errorValue;
5383
- }
5384
- };
5385
- AsyncAction.prototype.unsubscribe = function () {
5386
- if (!this.closed) {
5387
- var _a = this, id = _a.id, scheduler = _a.scheduler;
5388
- var actions = scheduler.actions;
5389
- this.work = this.state = this.scheduler = null;
5390
- this.pending = false;
5391
- arrRemove(actions, this);
5392
- if (id != null) {
5393
- this.id = this.recycleAsyncId(scheduler, id, null);
5394
- }
5395
- this.delay = null;
5396
- _super.prototype.unsubscribe.call(this);
5397
- }
5398
- };
5399
- return AsyncAction;
5400
- }(Action$1));
5401
-
5402
- var Scheduler = (function () {
5403
- function Scheduler(schedulerActionCtor, now) {
5404
- if (now === void 0) { now = Scheduler.now; }
5405
- this.schedulerActionCtor = schedulerActionCtor;
5406
- this.now = now;
5407
- }
5408
- Scheduler.prototype.schedule = function (work, delay, state) {
5409
- if (delay === void 0) { delay = 0; }
5410
- return new this.schedulerActionCtor(this, work).schedule(state, delay);
5411
- };
5412
- Scheduler.now = dateTimestampProvider.now;
5413
- return Scheduler;
5414
- }());
5415
-
5416
- var AsyncScheduler = (function (_super) {
5417
- __extends(AsyncScheduler, _super);
5418
- function AsyncScheduler(SchedulerAction, now) {
5419
- if (now === void 0) { now = Scheduler.now; }
5420
- var _this = _super.call(this, SchedulerAction, now) || this;
5421
- _this.actions = [];
5422
- _this._active = false;
5423
- return _this;
5424
- }
5425
- AsyncScheduler.prototype.flush = function (action) {
5426
- var actions = this.actions;
5427
- if (this._active) {
5428
- actions.push(action);
5429
- return;
5430
- }
5431
- var error;
5432
- this._active = true;
5433
- do {
5434
- if ((error = action.execute(action.state, action.delay))) {
5435
- break;
5436
- }
5437
- } while ((action = actions.shift()));
5438
- this._active = false;
5439
- if (error) {
5440
- while ((action = actions.shift())) {
5441
- action.unsubscribe();
5442
- }
5443
- throw error;
5444
- }
5445
- };
5446
- return AsyncScheduler;
5447
- }(Scheduler));
5448
-
5449
- var asyncScheduler = new AsyncScheduler(AsyncAction);
5450
- var async = asyncScheduler;
5451
-
5452
5287
  function isScheduler(value) {
5453
5288
  return value && isFunction$2(value.schedule);
5454
5289
  }
@@ -5828,10 +5663,6 @@ function lastValueFrom(source, config) {
5828
5663
  });
5829
5664
  }
5830
5665
 
5831
- function isValidDate(value) {
5832
- return value instanceof Date && !isNaN(value);
5833
- }
5834
-
5835
5666
  function map(project, thisArg) {
5836
5667
  return operate(function (source, subscriber) {
5837
5668
  var index = 0;
@@ -5997,37 +5828,6 @@ function mergeMap(project, resultSelector, concurrent) {
5997
5828
  return operate(function (source, subscriber) { return mergeInternals(source, subscriber, project, concurrent); });
5998
5829
  }
5999
5830
 
6000
- function timer(dueTime, intervalOrScheduler, scheduler) {
6001
- if (scheduler === void 0) { scheduler = async; }
6002
- var intervalDuration = -1;
6003
- if (intervalOrScheduler != null) {
6004
- if (isScheduler(intervalOrScheduler)) {
6005
- scheduler = intervalOrScheduler;
6006
- }
6007
- else {
6008
- intervalDuration = intervalOrScheduler;
6009
- }
6010
- }
6011
- return new Observable(function (subscriber) {
6012
- var due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;
6013
- if (due < 0) {
6014
- due = 0;
6015
- }
6016
- var n = 0;
6017
- return scheduler.schedule(function () {
6018
- if (!subscriber.closed) {
6019
- subscriber.next(n++);
6020
- if (0 <= intervalDuration) {
6021
- this.schedule(undefined, intervalDuration);
6022
- }
6023
- else {
6024
- subscriber.complete();
6025
- }
6026
- }
6027
- }, due);
6028
- });
6029
- }
6030
-
6031
5831
  function filter(predicate, thisArg) {
6032
5832
  return operate(function (source, subscriber) {
6033
5833
  var index = 0;
@@ -6156,54 +5956,6 @@ function handleReset(reset, on) {
6156
5956
  return innerFrom(on.apply(void 0, __spreadArray([], __read(args)))).subscribe(onSubscriber);
6157
5957
  }
6158
5958
 
6159
- function throttle$1(durationSelector, config) {
6160
- return operate(function (source, subscriber) {
6161
- var _a = config !== null && config !== void 0 ? config : {}, _b = _a.leading, leading = _b === void 0 ? true : _b, _c = _a.trailing, trailing = _c === void 0 ? false : _c;
6162
- var hasValue = false;
6163
- var sendValue = null;
6164
- var throttled = null;
6165
- var isComplete = false;
6166
- var endThrottling = function () {
6167
- throttled === null || throttled === void 0 ? void 0 : throttled.unsubscribe();
6168
- throttled = null;
6169
- if (trailing) {
6170
- send();
6171
- isComplete && subscriber.complete();
6172
- }
6173
- };
6174
- var cleanupThrottling = function () {
6175
- throttled = null;
6176
- isComplete && subscriber.complete();
6177
- };
6178
- var startThrottle = function (value) {
6179
- return (throttled = innerFrom(durationSelector(value)).subscribe(createOperatorSubscriber(subscriber, endThrottling, cleanupThrottling)));
6180
- };
6181
- var send = function () {
6182
- if (hasValue) {
6183
- hasValue = false;
6184
- var value = sendValue;
6185
- sendValue = null;
6186
- subscriber.next(value);
6187
- !isComplete && startThrottle(value);
6188
- }
6189
- };
6190
- source.subscribe(createOperatorSubscriber(subscriber, function (value) {
6191
- hasValue = true;
6192
- sendValue = value;
6193
- !(throttled && !throttled.closed) && (leading ? send() : startThrottle(value));
6194
- }, function () {
6195
- isComplete = true;
6196
- !(trailing && hasValue && throttled && !throttled.closed) && subscriber.complete();
6197
- }));
6198
- });
6199
- }
6200
-
6201
- function throttleTime(duration, scheduler, config) {
6202
- if (scheduler === void 0) { scheduler = asyncScheduler; }
6203
- var duration$ = timer(duration, scheduler);
6204
- return throttle$1(function () { return duration$; }, config);
6205
- }
6206
-
6207
5959
  var __defProp$9 = Object.defineProperty;
6208
5960
  var __name$2 = (target, value) => __defProp$9(target, "name", { value, configurable: true });
6209
5961
  var ArraySubject = class extends BehaviorSubject {
@@ -6749,7 +6501,7 @@ function isClass$1(obj) {
6749
6501
  return typeof obj === "function" && obj.prototype && obj.prototype.constructor === obj;
6750
6502
  }
6751
6503
  __name$3(isClass$1, "isClass");
6752
- var isObject$1 = /* @__PURE__ */ __name$3((item) => item && typeof item === "object" && !Array.isArray(item) && item !== null, "isObject");
6504
+ var isObject$2 = /* @__PURE__ */ __name$3((item) => item && typeof item === "object" && !Array.isArray(item) && item !== null, "isObject");
6753
6505
  function isInstanceOfClass(value) {
6754
6506
  if (value === null || typeof value !== "object" || value === void 0 || Array.isArray(value)) {
6755
6507
  return false;
@@ -6799,7 +6551,7 @@ function createStatesSnapshot(instance) {
6799
6551
  const signal = instance.$snapshot.get(key);
6800
6552
  const persist2 = signal.options.persist ?? true;
6801
6553
  let value = signal();
6802
- if (isObject$1(value) || Array.isArray(value)) {
6554
+ if (isObject$2(value) || Array.isArray(value)) {
6803
6555
  continue;
6804
6556
  }
6805
6557
  if (persist2) {
@@ -6904,7 +6656,7 @@ var createSyncClass = /* @__PURE__ */ __name$3((currentClass, parentKey = null,
6904
6656
  if (transform) {
6905
6657
  signalValue = transform(signalValue);
6906
6658
  }
6907
- if (isObject$1(signalValue) || Array.isArray(signalValue)) {
6659
+ if (isObject$2(signalValue) || Array.isArray(signalValue)) {
6908
6660
  signalValue = {
6909
6661
  ...signalValue
6910
6662
  };
@@ -6940,7 +6692,7 @@ var type = /* @__PURE__ */ __name$3((_signal, path, options = {}, currentInstanc
6940
6692
  ].includes(value.type)) {
6941
6693
  if (isInstanceOfClass(value.value)) {
6942
6694
  createSyncClass(value.value, value.key, currentInstance, newPath);
6943
- } else if (value.type === "update" && (isObject$1(value.value) || Array.isArray(value.value))) {
6695
+ } else if (value.type === "update" && (isObject$2(value.value) || Array.isArray(value.value))) {
6944
6696
  createSyncClass(value.value, value.key, currentInstance, newPath);
6945
6697
  } else {
6946
6698
  savePath(newPath, value.value);
@@ -6969,7 +6721,7 @@ var type = /* @__PURE__ */ __name$3((_signal, path, options = {}, currentInstanc
6969
6721
  ].includes(value.type) && firstItem !== void 0) {
6970
6722
  if (isInstanceOfClass(firstItem)) {
6971
6723
  createSyncClass(firstItem, value.key, currentInstance, newPath);
6972
- } else if (value.type === "update" && (isObject$1(firstItem) || Array.isArray(firstItem))) {
6724
+ } else if (value.type === "update" && (isObject$2(firstItem) || Array.isArray(firstItem))) {
6973
6725
  createSyncClass(firstItem, value.key, currentInstance, newPath);
6974
6726
  } else {
6975
6727
  savePath(newPath, firstItem);
@@ -9898,6 +9650,7 @@ class Item {
9898
9650
  this.atk = signal(0);
9899
9651
  this.pdef = signal(0);
9900
9652
  this.sdef = signal(0);
9653
+ this.icon = signal("");
9901
9654
  this.quantity = signal(1);
9902
9655
  this.onAdd = () => {
9903
9656
  };
@@ -9907,6 +9660,7 @@ class Item {
9907
9660
  this.atk.set(data?.atk ?? 0);
9908
9661
  this.pdef.set(data?.pdef ?? 0);
9909
9662
  this.sdef.set(data?.sdef ?? 0);
9663
+ this.icon.set(data?.icon ?? "");
9910
9664
  this.onAdd = data?.onAdd?.bind(this) ?? (() => {
9911
9665
  });
9912
9666
  }
@@ -9914,6 +9668,12 @@ class Item {
9914
9668
  __decorateClass$6([
9915
9669
  id()
9916
9670
  ], Item.prototype, "id");
9671
+ __decorateClass$6([
9672
+ sync()
9673
+ ], Item.prototype, "name");
9674
+ __decorateClass$6([
9675
+ sync()
9676
+ ], Item.prototype, "icon");
9917
9677
  __decorateClass$6([
9918
9678
  sync()
9919
9679
  ], Item.prototype, "quantity");
@@ -9933,6 +9693,7 @@ class Skill {
9933
9693
  this.name = signal("");
9934
9694
  this.description = signal("");
9935
9695
  this.spCost = signal(0);
9696
+ this.icon = signal("");
9936
9697
  this.hitRate = signal(0);
9937
9698
  this.power = signal(0);
9938
9699
  this.coefficient = signal({});
@@ -9943,11 +9704,21 @@ class Skill {
9943
9704
  this.hitRate.set(data?.hitRate ?? 0);
9944
9705
  this.power.set(data?.power ?? 0);
9945
9706
  this.coefficient.set(data?.coefficient ?? {});
9707
+ this.icon.set(data?.icon ?? "");
9946
9708
  }
9947
9709
  }
9948
9710
  __decorateClass$5([
9949
9711
  id()
9950
9712
  ], Skill.prototype, "id");
9713
+ __decorateClass$5([
9714
+ sync()
9715
+ ], Skill.prototype, "name");
9716
+ __decorateClass$5([
9717
+ sync()
9718
+ ], Skill.prototype, "spCost");
9719
+ __decorateClass$5([
9720
+ sync()
9721
+ ], Skill.prototype, "icon");
9951
9722
 
9952
9723
  var __defProp$5 = Object.defineProperty;
9953
9724
  var __decorateClass$4 = (decorators, target, key, kind) => {
@@ -16372,12 +16143,17 @@ class RpgCommonMap {
16372
16143
  }
16373
16144
  loadPhysic() {
16374
16145
  this.clearPhysic();
16375
- const hitboxes = this.data()?.hitboxes ?? [];
16376
- const gap = 100;
16377
- this.addStaticHitbox("map-width-left", -gap, 0, gap, this.data().height);
16378
- this.addStaticHitbox("map-width-right", this.data().width, 0, gap, this.data().height);
16379
- this.addStaticHitbox("map-height-top", 0, -gap, this.data().width, gap);
16380
- this.addStaticHitbox("map-height-bottom", 0, this.data().height, this.data().width, gap);
16146
+ const mapData = this.data?.();
16147
+ const mapWidth = typeof mapData?.width === "number" ? mapData.width : 0;
16148
+ const mapHeight = typeof mapData?.height === "number" ? mapData.height : 0;
16149
+ const hitboxes = Array.isArray(mapData?.hitboxes) ? mapData.hitboxes : [];
16150
+ if (mapWidth > 0 && mapHeight > 0) {
16151
+ const gap = 100;
16152
+ this.addStaticHitbox("map-width-left", -gap, 0, gap, mapHeight);
16153
+ this.addStaticHitbox("map-width-right", mapWidth, 0, gap, mapHeight);
16154
+ this.addStaticHitbox("map-height-top", 0, -gap, mapWidth, gap);
16155
+ this.addStaticHitbox("map-height-bottom", 0, mapHeight, mapWidth, gap);
16156
+ }
16381
16157
  for (let staticHitbox of hitboxes) {
16382
16158
  if ("x" in staticHitbox) {
16383
16159
  this.addStaticHitbox(staticHitbox.id ?? generateShortUUID$1(), staticHitbox.x, staticHitbox.y, staticHitbox.width, staticHitbox.height);
@@ -16387,13 +16163,29 @@ class RpgCommonMap {
16387
16163
  }
16388
16164
  this.playersSubscription = this.players.observable.subscribe(
16389
16165
  ({ value: player, type, key }) => {
16166
+ if (type === "remove") {
16167
+ this.removeHitbox(key);
16168
+ return;
16169
+ }
16170
+ if (type == "reset") {
16171
+ if (!player) return;
16172
+ for (let id in player) {
16173
+ const _player = player[id];
16174
+ _player.id = _player.id ?? id;
16175
+ this.createCharacterHitbox(_player, "hero");
16176
+ }
16177
+ return;
16178
+ }
16390
16179
  if (!player) return;
16391
16180
  if (type === "add") {
16392
16181
  player.id = key;
16393
16182
  this.createCharacterHitbox(player, "hero");
16394
- } else if (type === "remove") {
16395
- this.removeHitbox(key);
16396
16183
  } else if (type === "update") {
16184
+ player.id = player.id ?? key;
16185
+ if (!this.getBody(key)) {
16186
+ this.createCharacterHitbox(player, "hero");
16187
+ return;
16188
+ }
16397
16189
  if (this.isPhysicsSyncingSignals) {
16398
16190
  return;
16399
16191
  }
@@ -16414,9 +16206,41 @@ class RpgCommonMap {
16414
16206
  }
16415
16207
  this.removeHitbox(key);
16416
16208
  } else if (type === "update") {
16209
+ event.id = event.id ?? key;
16210
+ if (!this.getBody(key)) {
16211
+ this.createCharacterHitbox(event, "npc", {
16212
+ mass: 100
16213
+ });
16214
+ return;
16215
+ }
16417
16216
  this.updateCharacterHitbox(event);
16217
+ } else if (type === "reset") {
16218
+ for (const id in event) {
16219
+ const _event = event[id];
16220
+ if (!_event) continue;
16221
+ _event.id = _event.id ?? id;
16222
+ this.createCharacterHitbox(_event, "npc", {
16223
+ mass: 100
16224
+ });
16225
+ }
16418
16226
  }
16419
16227
  });
16228
+ const players = this.players();
16229
+ for (const id in players) {
16230
+ const player = players[id];
16231
+ if (!player) continue;
16232
+ player.id = player.id ?? id;
16233
+ this.createCharacterHitbox(player, "hero");
16234
+ }
16235
+ const events = this.events();
16236
+ for (const id in events) {
16237
+ const event = events[id];
16238
+ if (!event) continue;
16239
+ event.id = event.id ?? id;
16240
+ this.createCharacterHitbox(event, "npc", {
16241
+ mass: 100
16242
+ });
16243
+ }
16420
16244
  if (this.autoTickEnabled) {
16421
16245
  this.tickSubscription = this.tick$.subscribe(({ delta }) => {
16422
16246
  this.runFixedTicks(delta);
@@ -16614,6 +16438,12 @@ class RpgCommonMap {
16614
16438
  if (!owner?.id) {
16615
16439
  return;
16616
16440
  }
16441
+ const existingEntity = this.physic.getEntityByUUID(owner.id);
16442
+ if (existingEntity) {
16443
+ existingEntity.owner = owner;
16444
+ this.updateCharacterHitbox(owner);
16445
+ return;
16446
+ }
16617
16447
  const hitbox = typeof owner.hitbox === "function" ? owner.hitbox() : owner.hitbox;
16618
16448
  const width = hitbox?.w ?? 32;
16619
16449
  const height = hitbox?.h ?? 32;
@@ -16630,6 +16460,9 @@ class RpgCommonMap {
16630
16460
  }
16631
16461
  updateCharacterHitbox(owner) {
16632
16462
  if (!owner?.id) return;
16463
+ const entity = this.physic.getEntityByUUID(owner.id);
16464
+ if (!entity) return;
16465
+ entity.owner = owner;
16633
16466
  const hitbox = typeof owner.hitbox === "function" ? owner.hitbox() : owner.hitbox;
16634
16467
  const width = hitbox?.w ?? 32;
16635
16468
  const height = hitbox?.h ?? 32;
@@ -17017,22 +16850,26 @@ class RpgCommonMap {
17017
16850
  }
17018
16851
  }
17019
16852
  });
17020
- const entityWidth = width;
17021
- const entityHeight = height;
17022
16853
  entity.onPositionChange(({ x, y }) => {
16854
+ const currentOwner = entity.owner;
16855
+ if (!currentOwner) {
16856
+ return;
16857
+ }
16858
+ const entityWidth = entity.width || width;
16859
+ const entityHeight = entity.height || height;
17023
16860
  const topLeftX2 = x - entityWidth / 2;
17024
16861
  const topLeftY2 = y - entityHeight / 2;
17025
16862
  let changed = false;
17026
- if (typeof owner.x === "function" && typeof owner.x.set === "function") {
17027
- owner.x.set(Math.round(topLeftX2));
16863
+ if (typeof currentOwner.x === "function" && typeof currentOwner.x.set === "function") {
16864
+ currentOwner.x.set(Math.round(topLeftX2));
17028
16865
  changed = true;
17029
16866
  }
17030
- if (typeof owner.y === "function" && typeof owner.y.set === "function") {
17031
- owner.y.set(Math.round(topLeftY2));
16867
+ if (typeof currentOwner.y === "function" && typeof currentOwner.y.set === "function") {
16868
+ currentOwner.y.set(Math.round(topLeftY2));
17032
16869
  changed = true;
17033
16870
  }
17034
16871
  if (changed) {
17035
- owner.applyFrames?.();
16872
+ currentOwner.applyFrames?.();
17036
16873
  }
17037
16874
  });
17038
16875
  entity.addResolutionFilter((self, other) => {
@@ -20669,6 +20506,27 @@ function WithVariableManager(Base) {
20669
20506
  };
20670
20507
  }
20671
20508
 
20509
+ const DEFAULT_EXP_CURVE = {
20510
+ basis: 30,
20511
+ extra: 20,
20512
+ accelerationA: 30,
20513
+ accelerationB: 30
20514
+ };
20515
+ function isObject$1(value) {
20516
+ return typeof value === "object" && value !== null;
20517
+ }
20518
+ function toValidNumber(value, fallback) {
20519
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
20520
+ }
20521
+ function normalizeExpCurve(value) {
20522
+ if (!isObject$1(value)) return DEFAULT_EXP_CURVE;
20523
+ return {
20524
+ basis: toValidNumber(value.basis, DEFAULT_EXP_CURVE.basis),
20525
+ extra: toValidNumber(value.extra, DEFAULT_EXP_CURVE.extra),
20526
+ accelerationA: toValidNumber(value.accelerationA, DEFAULT_EXP_CURVE.accelerationA),
20527
+ accelerationB: toValidNumber(value.accelerationB, DEFAULT_EXP_CURVE.accelerationB)
20528
+ };
20529
+ }
20672
20530
  function WithParameterManager(Base) {
20673
20531
  return class extends Base {
20674
20532
  constructor() {
@@ -20771,7 +20629,7 @@ function WithParameterManager(Base) {
20771
20629
  * ```
20772
20630
  * @memberof ParameterManager
20773
20631
  * */
20774
- this._expCurveSignal = type(signal(""), "_expCurveSignal", { persist: true }, this);
20632
+ this._expCurveSignal = type(signal(JSON.stringify(DEFAULT_EXP_CURVE)), "_expCurveSignal", { persist: true }, this);
20775
20633
  }
20776
20634
  /**
20777
20635
  * Aggregates parameter modifiers from all sources (direct modifiers, states, equipment)
@@ -20820,7 +20678,13 @@ function WithParameterManager(Base) {
20820
20678
  return params;
20821
20679
  }
20822
20680
  get expCurve() {
20823
- return JSON.parse(this._expCurveSignal());
20681
+ const raw = this._expCurveSignal();
20682
+ if (!raw) return DEFAULT_EXP_CURVE;
20683
+ try {
20684
+ return normalizeExpCurve(JSON.parse(raw));
20685
+ } catch {
20686
+ return DEFAULT_EXP_CURVE;
20687
+ }
20824
20688
  }
20825
20689
  set expCurve(val) {
20826
20690
  this._expCurveSignal.set(JSON.stringify(val));
@@ -21169,10 +21033,12 @@ function WithItemFixture(Base) {
21169
21033
  };
21170
21034
  }
21171
21035
 
21172
- class Log {
21036
+ class Log extends Error {
21173
21037
  constructor(id, msg) {
21038
+ super(`[${id}] ${msg}`);
21039
+ this.name = "RpgLog";
21174
21040
  this.id = id;
21175
- this.msg = msg;
21041
+ Object.setPrototypeOf(this, new.target.prototype);
21176
21042
  }
21177
21043
  }
21178
21044
 
@@ -22372,7 +22238,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
22372
22238
  this._lastFramePositions = null;
22373
22239
  this.frames = [];
22374
22240
  this.events = signal([]);
22375
- let lastEmitted = null;
22241
+ const initialX = typeof this.x === "function" ? Number(this.x()) || 0 : 0;
22242
+ const initialY = typeof this.y === "function" ? Number(this.y()) || 0 : 0;
22243
+ let lastEmitted = { x: initialX, y: initialY };
22376
22244
  let pendingUpdate = null;
22377
22245
  let updateScheduled = false;
22378
22246
  combineLatest([this.x.observable, this.y.observable]).subscribe(([x, y]) => {
@@ -22474,6 +22342,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
22474
22342
  }
22475
22343
  setMap(map2) {
22476
22344
  this.map = map2;
22345
+ this.touchSide = true;
22477
22346
  }
22478
22347
  applyFrames() {
22479
22348
  this._frames.set(this.frames);
@@ -22515,12 +22384,13 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
22515
22384
  }));
22516
22385
  if (canChange.some((v) => v === false)) return false;
22517
22386
  if (positions && typeof positions === "object") {
22518
- this.teleport(positions);
22387
+ await this.teleport(positions);
22519
22388
  }
22520
- await room?.$sessionTransfer(this.conn, realMapId);
22389
+ const transferToken = await room?.$sessionTransfer(this.conn, realMapId);
22521
22390
  this.emit("changeMap", {
22522
22391
  mapId: realMapId,
22523
- positions
22392
+ positions,
22393
+ transferToken: typeof transferToken === "string" ? transferToken : void 0
22524
22394
  });
22525
22395
  return true;
22526
22396
  }
@@ -22532,16 +22402,28 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
22532
22402
  const direction = this.getDirection();
22533
22403
  const marginLeftRight = map2.tileWidth / 2;
22534
22404
  const marginTopDown = map2.tileHeight / 2;
22535
- const changeMap = async (adjacent, to) => {
22536
- if (this.touchSide) {
22405
+ const hitbox = this.hitbox();
22406
+ const currentX = this.x();
22407
+ const currentY = this.y();
22408
+ const nearBorder = currentX < marginLeftRight || currentX > map2.widthPx - hitbox.w - marginLeftRight || currentY < marginTopDown || currentY > map2.heightPx - hitbox.h - marginTopDown;
22409
+ if (this.touchSide) {
22410
+ if (nearBorder) {
22537
22411
  return false;
22538
22412
  }
22539
- this.touchSide = true;
22413
+ this.touchSide = false;
22414
+ }
22415
+ const changeMap = async (adjacent, to) => {
22540
22416
  const [nextMap] = worldMaps.getAdjacentMaps(map2, adjacent);
22541
- if (!nextMap) return false;
22417
+ if (!nextMap) {
22418
+ return false;
22419
+ }
22542
22420
  const id = nextMap.id;
22543
22421
  const nextMapInfo = worldMaps.getMapInfo(id);
22544
- return !!await this.changeMap(id, to(nextMapInfo));
22422
+ const changed = !!await this.changeMap(id, to(nextMapInfo));
22423
+ if (changed) {
22424
+ this.touchSide = true;
22425
+ }
22426
+ return changed;
22545
22427
  };
22546
22428
  if (nextPosition.x < marginLeftRight && direction == Direction.Left) {
22547
22429
  ret = await changeMap({
@@ -24524,7 +24406,7 @@ class Doc {
24524
24406
  const version = {
24525
24407
  major: 4,
24526
24408
  minor: 3,
24527
- patch: 5,
24409
+ patch: 6,
24528
24410
  };
24529
24411
 
24530
24412
  const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
@@ -26581,7 +26463,7 @@ function finalize(ctx, schema) {
26581
26463
  }
26582
26464
  }
26583
26465
  // When ref was extracted to $defs, remove properties that match the definition
26584
- if (refSchema.$ref) {
26466
+ if (refSchema.$ref && refSeen.def) {
26585
26467
  for (const key in schema) {
26586
26468
  if (key === "$ref" || key === "allOf")
26587
26469
  continue;
@@ -27942,6 +27824,9 @@ var __decorateClass$1 = (decorators, target, key, kind) => {
27942
27824
  if (kind && result) __defProp$1(target, key, result);
27943
27825
  return result;
27944
27826
  };
27827
+ function isRpgLog(error) {
27828
+ return error instanceof Log || typeof error === "object" && error !== null && "id" in error && error.name === "RpgLog";
27829
+ }
27945
27830
  const MapUpdateSchema = object({
27946
27831
  /** Configuration object for the map (optional) */
27947
27832
  config: any().optional(),
@@ -27954,6 +27839,8 @@ const MapUpdateSchema = object({
27954
27839
  /** Height of the map in pixels (required) */
27955
27840
  height: number()
27956
27841
  });
27842
+ const SAFE_MAP_WIDTH = 1e3;
27843
+ const SAFE_MAP_HEIGHT = 1e3;
27957
27844
  let RpgMap = class extends RpgCommonMap {
27958
27845
  constructor(room) {
27959
27846
  super();
@@ -28026,6 +27913,7 @@ let RpgMap = class extends RpgCommonMap {
28026
27913
  * with custom formulas when the map is loaded.
28027
27914
  */
28028
27915
  this.damageFormulas = {};
27916
+ this._weatherState = null;
28029
27917
  /** Internal: Map of shapes by name */
28030
27918
  this._shapes = /* @__PURE__ */ new Map();
28031
27919
  /** Internal: Map of shape entity UUIDs to RpgShape instances */
@@ -28054,6 +27942,19 @@ let RpgMap = class extends RpgCommonMap {
28054
27942
  onStart() {
28055
27943
  return BaseRoom.prototype.onStart.call(this);
28056
27944
  }
27945
+ isPositiveNumber(value) {
27946
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
27947
+ }
27948
+ resolveTrustedMapDimensions(map) {
27949
+ const normalizedId = typeof map?.id === "string" ? map.id.replace(/^map-/, "") : "";
27950
+ const worldMapInfo = normalizedId ? this.worldMapsManager?.getMapInfo(normalizedId) : null;
27951
+ if (!this.isPositiveNumber(map?.width)) {
27952
+ map.width = this.isPositiveNumber(worldMapInfo?.width) ? worldMapInfo.width : SAFE_MAP_WIDTH;
27953
+ }
27954
+ if (!this.isPositiveNumber(map?.height)) {
27955
+ map.height = this.isPositiveNumber(worldMapInfo?.height) ? worldMapInfo.height : SAFE_MAP_HEIGHT;
27956
+ }
27957
+ }
28057
27958
  /**
28058
27959
  * Setup collision detection between players, events, and shapes
28059
27960
  *
@@ -28097,8 +27998,8 @@ let RpgMap = class extends RpgCommonMap {
28097
27998
  const activeCollisions = /* @__PURE__ */ new Set();
28098
27999
  const activeShapeCollisions = /* @__PURE__ */ new Set();
28099
28000
  const hasDifferentZ = (entityA, entityB) => {
28100
- const zA = entityA.owner.z();
28101
- const zB = entityB.owner.z();
28001
+ const zA = entityA.owner?.z();
28002
+ const zB = entityB.owner?.z();
28102
28003
  return zA !== zB;
28103
28004
  };
28104
28005
  this.physic.getEvents().onCollisionEnter((collision) => {
@@ -28207,12 +28108,19 @@ let RpgMap = class extends RpgCommonMap {
28207
28108
  if (packet && typeof packet === "object") {
28208
28109
  obj.timestamp = Date.now();
28209
28110
  if (player) {
28111
+ const value = packet.value && typeof packet.value === "object" ? packet.value : void 0;
28112
+ const packetPlayers = value?.players && typeof value.players === "object" ? value.players : void 0;
28113
+ const playerSnapshot = packetPlayers?.[player.id];
28114
+ const bodyPos = this.getBodyPosition(player.id, "top-left");
28115
+ const ackX = typeof playerSnapshot?.x === "number" ? playerSnapshot.x : bodyPos?.x ?? player.x();
28116
+ const ackY = typeof playerSnapshot?.y === "number" ? playerSnapshot.y : bodyPos?.y ?? player.y();
28210
28117
  const lastFramePositions = player._lastFramePositions;
28211
28118
  obj.ack = {
28212
- frame: lastFramePositions?.frame ?? player.pendingInputs.length,
28213
- x: lastFramePositions?.position?.x ?? player.x(),
28214
- y: lastFramePositions?.position?.y ?? player.y(),
28215
- direction: lastFramePositions?.position?.direction ?? player.direction()
28119
+ frame: lastFramePositions?.frame ?? 0,
28120
+ serverTick: this.getTick(),
28121
+ x: Math.round(ackX),
28122
+ y: Math.round(ackY),
28123
+ direction: playerSnapshot?.direction ?? player.direction()
28216
28124
  };
28217
28125
  }
28218
28126
  }
@@ -28262,18 +28170,40 @@ let RpgMap = class extends RpgCommonMap {
28262
28170
  }
28263
28171
  player.context = context;
28264
28172
  player.conn = conn;
28173
+ player.pendingInputs = [];
28174
+ player.lastProcessedInputTs = 0;
28175
+ player._lastFramePositions = null;
28265
28176
  player._onInit();
28266
28177
  this.dataIsReady$.pipe(
28267
- finalize$1(async () => {
28268
- if (this.stopAllSoundsBeforeJoin) {
28269
- player.stopAllSounds();
28270
- }
28271
- this.sounds.forEach((sound) => player.playSound(sound, { loop: true }));
28272
- await lastValueFrom(this.hooks.callHooks("server-map-onJoin", player, this));
28273
- if (typeof this._onJoin === "function") {
28274
- await this._onJoin(player);
28275
- }
28276
- await lastValueFrom(this.hooks.callHooks("server-player-onJoinMap", player, this));
28178
+ finalize$1(() => {
28179
+ void (async () => {
28180
+ try {
28181
+ const hitbox = typeof player.hitbox === "function" ? player.hitbox() : player.hitbox;
28182
+ const width = hitbox?.w ?? 32;
28183
+ const height = hitbox?.h ?? 32;
28184
+ const body = this.getBody(player.id);
28185
+ if (body) {
28186
+ body.owner = player;
28187
+ }
28188
+ this.updateHitbox(player.id, player.x(), player.y(), width, height);
28189
+ if (this.stopAllSoundsBeforeJoin) {
28190
+ player.stopAllSounds();
28191
+ }
28192
+ this.sounds.forEach((sound) => player.playSound(sound, { loop: true }));
28193
+ player.emit("weatherState", this.getWeather());
28194
+ await lastValueFrom(this.hooks.callHooks("server-map-onJoin", player, this));
28195
+ if (typeof this._onJoin === "function") {
28196
+ await this._onJoin(player);
28197
+ }
28198
+ await lastValueFrom(this.hooks.callHooks("server-player-onJoinMap", player, this));
28199
+ } catch (error) {
28200
+ if (isRpgLog(error)) {
28201
+ console.warn(`[RpgLog:${error.id}] ${error.message}`);
28202
+ return;
28203
+ }
28204
+ console.error("[RPGJS] Error during map onJoin hooks:", error);
28205
+ }
28206
+ })();
28277
28207
  })
28278
28208
  ).subscribe();
28279
28209
  }
@@ -28307,6 +28237,8 @@ let RpgMap = class extends RpgCommonMap {
28307
28237
  }
28308
28238
  await lastValueFrom(this.hooks.callHooks("server-player-onLeaveMap", player, this));
28309
28239
  player.pendingInputs = [];
28240
+ player.lastProcessedInputTs = 0;
28241
+ player._lastFramePositions = null;
28310
28242
  }
28311
28243
  /**
28312
28244
  * Get the hooks system for this map
@@ -28349,18 +28281,60 @@ let RpgMap = class extends RpgCommonMap {
28349
28281
  player.execMethod("onInput", [action]);
28350
28282
  }
28351
28283
  async onInput(player, input) {
28352
- if (typeof input?.frame === "number") {
28353
- const existingInput = player.pendingInputs.find((pending) => pending.frame === input.frame);
28354
- if (existingInput) {
28284
+ const lastAckedFrame = player._lastFramePositions?.frame ?? 0;
28285
+ const now = Date.now();
28286
+ const candidates = [];
28287
+ const enqueueCandidate = (entry) => {
28288
+ if (typeof entry?.frame !== "number") {
28355
28289
  return;
28356
28290
  }
28357
- player.pendingInputs.push({
28358
- input: input.input,
28359
- frame: input.frame,
28360
- timestamp: input.timestamp || Date.now()
28361
- });
28291
+ if (!entry?.input) {
28292
+ return;
28293
+ }
28294
+ const candidate = {
28295
+ input: entry.input,
28296
+ frame: entry.frame,
28297
+ tick: typeof entry.tick === "number" ? entry.tick : void 0,
28298
+ timestamp: typeof entry.timestamp === "number" ? entry.timestamp : now
28299
+ };
28300
+ if (typeof entry.x === "number" && typeof entry.y === "number") {
28301
+ candidate.clientState = {
28302
+ x: entry.x,
28303
+ y: entry.y,
28304
+ direction: entry.direction
28305
+ };
28306
+ }
28307
+ candidates.push(candidate);
28308
+ };
28309
+ for (const trajectoryEntry of Array.isArray(input?.trajectory) ? input.trajectory : []) {
28310
+ enqueueCandidate(trajectoryEntry);
28311
+ }
28312
+ enqueueCandidate(input);
28313
+ if (candidates.length === 0) {
28314
+ return;
28315
+ }
28316
+ candidates.sort((a, b) => a.frame - b.frame);
28317
+ const existingFrames = new Set(
28318
+ player.pendingInputs.map((pending) => pending?.frame).filter((frame) => typeof frame === "number")
28319
+ );
28320
+ for (const candidate of candidates) {
28321
+ if (candidate.frame <= lastAckedFrame) {
28322
+ continue;
28323
+ }
28324
+ if (existingFrames.has(candidate.frame)) {
28325
+ continue;
28326
+ }
28327
+ player.pendingInputs.push(candidate);
28328
+ existingFrames.add(candidate.frame);
28362
28329
  }
28363
28330
  }
28331
+ onPing(player, payload) {
28332
+ player.emit("pong", {
28333
+ serverTick: this.getTick(),
28334
+ clientTime: typeof payload?.clientTime === "number" ? payload.clientTime : Date.now(),
28335
+ clientFrame: typeof payload?.clientFrame === "number" ? payload.clientFrame : 0
28336
+ });
28337
+ }
28364
28338
  async saveSlot(player, value) {
28365
28339
  BaseRoom.prototype.saveSlot(player, value);
28366
28340
  }
@@ -28385,9 +28359,15 @@ let RpgMap = class extends RpgCommonMap {
28385
28359
  await lastValueFrom(this.hooks.callHooks("server-maps-load", this));
28386
28360
  await lastValueFrom(this.hooks.callHooks("server-worldMaps-load", this));
28387
28361
  await lastValueFrom(this.hooks.callHooks("server-databaseHooks-load", this));
28362
+ this.resolveTrustedMapDimensions(map);
28363
+ this.data.set(map);
28388
28364
  map.events = map.events ?? [];
28365
+ let initialWeather = this.globalConfig?.weather;
28389
28366
  if (map.id) {
28390
28367
  const mapFound = this.maps.find((m) => m.id === map.id);
28368
+ if (typeof mapFound?.weather !== "undefined") {
28369
+ initialWeather = mapFound.weather;
28370
+ }
28391
28371
  if (mapFound?.events) {
28392
28372
  map.events = [
28393
28373
  ...mapFound.events,
@@ -28415,6 +28395,11 @@ let RpgMap = class extends RpgCommonMap {
28415
28395
  this.stopAllSoundsBeforeJoin = mapFound.stopAllSoundsBeforeJoin;
28416
28396
  }
28417
28397
  }
28398
+ if (typeof initialWeather !== "undefined") {
28399
+ this.setWeather(initialWeather);
28400
+ } else {
28401
+ this.clearWeather();
28402
+ }
28418
28403
  await lastValueFrom(this.hooks.callHooks("server-map-onBeforeUpdate", map, this));
28419
28404
  this.loadPhysic();
28420
28405
  for (let event of map.events ?? []) {
@@ -28454,10 +28439,11 @@ let RpgMap = class extends RpgCommonMap {
28454
28439
  /**
28455
28440
  * Process pending inputs for a player with anti-cheat validation
28456
28441
  *
28457
- * This method processes all pending inputs for a player while performing
28442
+ * This method processes pending inputs for a player while performing
28458
28443
  * anti-cheat validation to prevent time manipulation and frame skipping.
28459
28444
  * It validates the time deltas between inputs and ensures they are within
28460
- * acceptable ranges.
28445
+ * acceptable ranges. To preserve movement itinerary under network bursts,
28446
+ * the number of inputs processed per call is capped.
28461
28447
  *
28462
28448
  * ## Architecture
28463
28449
  *
@@ -28507,14 +28493,16 @@ let RpgMap = class extends RpgCommonMap {
28507
28493
  // Max 10 frames skipped
28508
28494
  minTimeBetweenInputs: 16,
28509
28495
  // ~60fps minimum
28510
- enableAntiCheat: false
28496
+ enableAntiCheat: false,
28497
+ maxInputsPerTick: 1
28511
28498
  };
28512
28499
  const config = { ...defaultControls, ...controls };
28513
28500
  let lastProcessedTime = player.lastProcessedInputTs || 0;
28514
- let lastProcessedFrame = 0;
28501
+ let lastProcessedFrame = player._lastFramePositions?.frame ?? 0;
28515
28502
  player.pendingInputs.sort((a, b) => (a.frame || 0) - (b.frame || 0));
28516
28503
  let hasProcessedInputs = false;
28517
- while (player.pendingInputs.length > 0) {
28504
+ let processedThisTick = 0;
28505
+ while (player.pendingInputs.length > 0 && processedThisTick < config.maxInputsPerTick) {
28518
28506
  const input = player.pendingInputs.shift();
28519
28507
  if (!input || typeof input.frame !== "number") {
28520
28508
  continue;
@@ -28544,6 +28532,19 @@ let RpgMap = class extends RpgCommonMap {
28544
28532
  processedInputs.push(input.input);
28545
28533
  hasProcessedInputs = true;
28546
28534
  lastProcessedTime = input.timestamp || Date.now();
28535
+ processedThisTick += 1;
28536
+ const bodyPos = this.getBodyPosition(player.id, "top-left");
28537
+ const ackX = typeof input.clientState?.x === "number" ? input.clientState.x : bodyPos?.x ?? player.x();
28538
+ const ackY = typeof input.clientState?.y === "number" ? input.clientState.y : bodyPos?.y ?? player.y();
28539
+ player._lastFramePositions = {
28540
+ frame: input.frame,
28541
+ position: {
28542
+ x: Math.round(ackX),
28543
+ y: Math.round(ackY),
28544
+ direction: input.clientState?.direction ?? player.direction()
28545
+ },
28546
+ serverTick: this.getTick()
28547
+ };
28547
28548
  }
28548
28549
  lastProcessedFrame = input.frame;
28549
28550
  }
@@ -28586,20 +28587,17 @@ let RpgMap = class extends RpgCommonMap {
28586
28587
  if (this._inputLoopSubscription) {
28587
28588
  this._inputLoopSubscription.unsubscribe();
28588
28589
  }
28589
- this._inputLoopSubscription = this.tick$.pipe(
28590
- throttleTime(50)
28591
- // Throttle to 50ms for input processing
28592
- ).subscribe(async ({ timestamp }) => {
28590
+ this._inputLoopSubscription = this.tick$.subscribe(() => {
28593
28591
  for (const player of this.getPlayers()) {
28594
- if (player.pendingInputs.length > 0) {
28595
- const anyPlayer = player;
28596
- if (!anyPlayer._isProcessingInputs) {
28597
- anyPlayer._isProcessingInputs = true;
28598
- await this.processInput(player.id).finally(() => {
28599
- anyPlayer._isProcessingInputs = false;
28600
- });
28601
- }
28592
+ const anyPlayer = player;
28593
+ const shouldProcess = player.pendingInputs.length > 0 || (player.lastProcessedInputTs || 0) > 0;
28594
+ if (!shouldProcess || anyPlayer._isProcessingInputs) {
28595
+ continue;
28602
28596
  }
28597
+ anyPlayer._isProcessingInputs = true;
28598
+ void this.processInput(player.id).finally(() => {
28599
+ anyPlayer._isProcessingInputs = false;
28600
+ });
28603
28601
  }
28604
28602
  });
28605
28603
  }
@@ -29097,6 +29095,66 @@ let RpgMap = class extends RpgCommonMap {
29097
29095
  animationName
29098
29096
  });
29099
29097
  }
29098
+ cloneWeatherState(weather) {
29099
+ if (!weather) {
29100
+ return null;
29101
+ }
29102
+ return {
29103
+ ...weather,
29104
+ params: weather.params ? { ...weather.params } : void 0
29105
+ };
29106
+ }
29107
+ /**
29108
+ * Get the current map weather state.
29109
+ */
29110
+ getWeather() {
29111
+ return this.cloneWeatherState(this._weatherState);
29112
+ }
29113
+ /**
29114
+ * Set the full weather state for this map.
29115
+ *
29116
+ * When `sync` is true (default), all connected clients receive the new weather.
29117
+ */
29118
+ setWeather(next, options = {}) {
29119
+ const sync2 = options.sync !== false;
29120
+ if (next && !next.effect) {
29121
+ throw new Error("setWeather: 'effect' is required when weather is not null.");
29122
+ }
29123
+ this._weatherState = this.cloneWeatherState(next);
29124
+ if (sync2) {
29125
+ this.$broadcast({
29126
+ type: "weatherState",
29127
+ value: this._weatherState
29128
+ });
29129
+ }
29130
+ return this.getWeather();
29131
+ }
29132
+ /**
29133
+ * Patch the current weather state.
29134
+ *
29135
+ * Nested `params` values are merged.
29136
+ */
29137
+ patchWeather(patch, options = {}) {
29138
+ const current = this._weatherState ?? null;
29139
+ if (!current && !patch.effect) {
29140
+ throw new Error("patchWeather: 'effect' is required when no weather is currently set.");
29141
+ }
29142
+ const next = {
29143
+ ...current ?? {},
29144
+ ...patch,
29145
+ params: {
29146
+ ...current?.params ?? {},
29147
+ ...patch.params ?? {}
29148
+ }
29149
+ };
29150
+ return this.setWeather(next, options);
29151
+ }
29152
+ /**
29153
+ * Clear weather for this map.
29154
+ */
29155
+ clearWeather(options = {}) {
29156
+ this.setWeather(null, options);
29157
+ }
29100
29158
  /**
29101
29159
  * Configure runtime synchronized properties on the map
29102
29160
  *
@@ -29537,6 +29595,9 @@ __decorateClass$1([
29537
29595
  __decorateClass$1([
29538
29596
  Action("move")
29539
29597
  ], RpgMap.prototype, "onInput", 1);
29598
+ __decorateClass$1([
29599
+ Action("ping")
29600
+ ], RpgMap.prototype, "onPing", 1);
29540
29601
  __decorateClass$1([
29541
29602
  Action("save.save")
29542
29603
  ], RpgMap.prototype, "saveSlot", 1);
@@ -29901,6 +29962,7 @@ function provideServerModules(modules) {
29901
29962
  type: MapClass.type,
29902
29963
  name: MapClass.prototype?.name,
29903
29964
  sounds: MapClass.prototype?.sounds,
29965
+ weather: MapClass.prototype?.weather,
29904
29966
  lowMemory: MapClass.prototype?.lowMemory,
29905
29967
  stopAllSoundsBeforeJoin: MapClass.prototype?.stopAllSoundsBeforeJoin,
29906
29968
  events: MapClass.prototype?._events,
@@ -30034,6 +30096,7 @@ function MapData(options) {
30034
30096
  target.prototype.file = options.file;
30035
30097
  target.prototype.id = options.id;
30036
30098
  target.prototype.sounds = options.sounds;
30099
+ target.prototype.weather = options.weather;
30037
30100
  target.prototype.lowMemory = options.lowMemory;
30038
30101
  target.prototype.stopAllSoundsBeforeJoin = options.stopAllSoundsBeforeJoin;
30039
30102
  target.prototype.$schema = {};