@rpgjs/server 5.0.0-alpha.32 → 5.0.0-alpha.35
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/Gui/ShopGui.d.ts +5 -1
- package/dist/Player/ItemManager.d.ts +8 -9
- package/dist/decorators/map.d.ts +22 -0
- package/dist/index.js +406 -336
- package/dist/index.js.map +1 -1
- package/dist/logs/log.d.ts +2 -3
- package/dist/rooms/map.d.ts +38 -3
- package/package.json +9 -9
- package/src/Gui/ShopGui.ts +4 -3
- package/src/Player/ClassManager.ts +7 -4
- package/src/Player/ItemManager.ts +21 -18
- package/src/Player/ParameterManager.ts +36 -2
- package/src/Player/Player.ts +30 -8
- package/src/decorators/map.ts +26 -1
- package/src/logs/log.ts +10 -3
- package/src/module.ts +1 -0
- package/src/rooms/map.ts +296 -50
- package/tests/item.spec.ts +19 -1
- package/tests/prediction-reconciliation.spec.ts +182 -0
- package/tests/world-maps.spec.ts +83 -1
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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);
|
|
@@ -8543,9 +8295,9 @@ var Server = class {
|
|
|
8543
8295
|
sessionState,
|
|
8544
8296
|
room: this.room
|
|
8545
8297
|
})) ?? userSnapshot;
|
|
8546
|
-
load(user, hydratedSnapshot, true);
|
|
8547
8298
|
signal2()[publicId] = user;
|
|
8548
|
-
|
|
8299
|
+
load(user, hydratedSnapshot, true);
|
|
8300
|
+
await this.room.storage.put(`${usersPropName}.${publicId}`, userSnapshot);
|
|
8549
8301
|
}
|
|
8550
8302
|
}
|
|
8551
8303
|
const transferToken = generateShortUUID$1();
|
|
@@ -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
|
|
16376
|
-
const
|
|
16377
|
-
|
|
16378
|
-
|
|
16379
|
-
|
|
16380
|
-
|
|
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
|
|
17027
|
-
|
|
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
|
|
17031
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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.
|
|
21041
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
21176
21042
|
}
|
|
21177
21043
|
}
|
|
21178
21044
|
|
|
@@ -21549,13 +21415,17 @@ function WithItemManager(Base) {
|
|
|
21549
21415
|
this.removeItem(itemClass);
|
|
21550
21416
|
return inventory;
|
|
21551
21417
|
}
|
|
21552
|
-
equip(
|
|
21553
|
-
const
|
|
21554
|
-
const
|
|
21418
|
+
equip(itemId, equip = true) {
|
|
21419
|
+
const autoAdd = equip === "auto";
|
|
21420
|
+
const equipState = equip === "auto" ? true : equip;
|
|
21421
|
+
const data = this.databaseById(itemId);
|
|
21422
|
+
let inventory = this.getItem(itemId);
|
|
21423
|
+
if (!inventory && autoAdd) {
|
|
21424
|
+
inventory = this.addItem(itemId, 1);
|
|
21425
|
+
}
|
|
21555
21426
|
if (!inventory) {
|
|
21556
21427
|
throw ItemLog.notInInventory(itemId);
|
|
21557
21428
|
}
|
|
21558
|
-
const data = this.databaseById(itemId);
|
|
21559
21429
|
if (data._type == "item") {
|
|
21560
21430
|
throw ItemLog.invalidToEquiped(itemId);
|
|
21561
21431
|
}
|
|
@@ -21570,18 +21440,18 @@ function WithItemManager(Base) {
|
|
|
21570
21440
|
}
|
|
21571
21441
|
}
|
|
21572
21442
|
const item = inventory;
|
|
21573
|
-
if (item.equipped &&
|
|
21443
|
+
if (item.equipped && equipState) {
|
|
21574
21444
|
throw ItemLog.isAlreadyEquiped(itemId);
|
|
21575
21445
|
}
|
|
21576
|
-
item.equipped =
|
|
21577
|
-
if (!
|
|
21446
|
+
item.equipped = equipState;
|
|
21447
|
+
if (!equipState) {
|
|
21578
21448
|
const index = this.equipments().findIndex((it) => it.id() == item.id());
|
|
21579
21449
|
this.equipments().splice(index, 1);
|
|
21580
21450
|
} else {
|
|
21581
21451
|
this.equipments().push(item);
|
|
21582
21452
|
}
|
|
21583
21453
|
const hookTarget = item._itemInstance || item;
|
|
21584
|
-
this["execMethod"]("onEquip", [this,
|
|
21454
|
+
this["execMethod"]("onEquip", [this, equipState], hookTarget);
|
|
21585
21455
|
}
|
|
21586
21456
|
};
|
|
21587
21457
|
}
|
|
@@ -22180,8 +22050,11 @@ function WithClassManager(Base) {
|
|
|
22180
22050
|
this.addParameter(param, actor.parameters[param]);
|
|
22181
22051
|
}
|
|
22182
22052
|
for (let item of actor.startingEquipment) {
|
|
22183
|
-
this.addItem(item);
|
|
22184
|
-
|
|
22053
|
+
const inventory = this.addItem(item);
|
|
22054
|
+
const itemId = inventory?.id?.();
|
|
22055
|
+
if (itemId) {
|
|
22056
|
+
this.equip(itemId, true);
|
|
22057
|
+
}
|
|
22185
22058
|
}
|
|
22186
22059
|
if (actor.class) this.setClass(actor.class);
|
|
22187
22060
|
this["execMethod"]("onSet", [this], actor);
|
|
@@ -22365,7 +22238,9 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22365
22238
|
this._lastFramePositions = null;
|
|
22366
22239
|
this.frames = [];
|
|
22367
22240
|
this.events = signal([]);
|
|
22368
|
-
|
|
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 };
|
|
22369
22244
|
let pendingUpdate = null;
|
|
22370
22245
|
let updateScheduled = false;
|
|
22371
22246
|
combineLatest([this.x.observable, this.y.observable]).subscribe(([x, y]) => {
|
|
@@ -22467,6 +22342,7 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22467
22342
|
}
|
|
22468
22343
|
setMap(map2) {
|
|
22469
22344
|
this.map = map2;
|
|
22345
|
+
this.touchSide = true;
|
|
22470
22346
|
}
|
|
22471
22347
|
applyFrames() {
|
|
22472
22348
|
this._frames.set(this.frames);
|
|
@@ -22508,12 +22384,13 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22508
22384
|
}));
|
|
22509
22385
|
if (canChange.some((v) => v === false)) return false;
|
|
22510
22386
|
if (positions && typeof positions === "object") {
|
|
22511
|
-
this.teleport(positions);
|
|
22387
|
+
await this.teleport(positions);
|
|
22512
22388
|
}
|
|
22513
|
-
await room?.$sessionTransfer(this.conn, realMapId);
|
|
22389
|
+
const transferToken = await room?.$sessionTransfer(this.conn, realMapId);
|
|
22514
22390
|
this.emit("changeMap", {
|
|
22515
22391
|
mapId: realMapId,
|
|
22516
|
-
positions
|
|
22392
|
+
positions,
|
|
22393
|
+
transferToken: typeof transferToken === "string" ? transferToken : void 0
|
|
22517
22394
|
});
|
|
22518
22395
|
return true;
|
|
22519
22396
|
}
|
|
@@ -22525,16 +22402,28 @@ const _RpgPlayer = class _RpgPlayer extends BasicPlayerMixins(RpgCommonPlayer) {
|
|
|
22525
22402
|
const direction = this.getDirection();
|
|
22526
22403
|
const marginLeftRight = map2.tileWidth / 2;
|
|
22527
22404
|
const marginTopDown = map2.tileHeight / 2;
|
|
22528
|
-
const
|
|
22529
|
-
|
|
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) {
|
|
22530
22411
|
return false;
|
|
22531
22412
|
}
|
|
22532
|
-
this.touchSide =
|
|
22413
|
+
this.touchSide = false;
|
|
22414
|
+
}
|
|
22415
|
+
const changeMap = async (adjacent, to) => {
|
|
22533
22416
|
const [nextMap] = worldMaps.getAdjacentMaps(map2, adjacent);
|
|
22534
|
-
if (!nextMap)
|
|
22417
|
+
if (!nextMap) {
|
|
22418
|
+
return false;
|
|
22419
|
+
}
|
|
22535
22420
|
const id = nextMap.id;
|
|
22536
22421
|
const nextMapInfo = worldMaps.getMapInfo(id);
|
|
22537
|
-
|
|
22422
|
+
const changed = !!await this.changeMap(id, to(nextMapInfo));
|
|
22423
|
+
if (changed) {
|
|
22424
|
+
this.touchSide = true;
|
|
22425
|
+
}
|
|
22426
|
+
return changed;
|
|
22538
22427
|
};
|
|
22539
22428
|
if (nextPosition.x < marginLeftRight && direction == Direction.Left) {
|
|
22540
22429
|
ret = await changeMap({
|
|
@@ -24517,7 +24406,7 @@ class Doc {
|
|
|
24517
24406
|
const version = {
|
|
24518
24407
|
major: 4,
|
|
24519
24408
|
minor: 3,
|
|
24520
|
-
patch:
|
|
24409
|
+
patch: 6,
|
|
24521
24410
|
};
|
|
24522
24411
|
|
|
24523
24412
|
const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
|
|
@@ -26574,7 +26463,7 @@ function finalize(ctx, schema) {
|
|
|
26574
26463
|
}
|
|
26575
26464
|
}
|
|
26576
26465
|
// When ref was extracted to $defs, remove properties that match the definition
|
|
26577
|
-
if (refSchema.$ref) {
|
|
26466
|
+
if (refSchema.$ref && refSeen.def) {
|
|
26578
26467
|
for (const key in schema) {
|
|
26579
26468
|
if (key === "$ref" || key === "allOf")
|
|
26580
26469
|
continue;
|
|
@@ -27935,6 +27824,9 @@ var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
|
27935
27824
|
if (kind && result) __defProp$1(target, key, result);
|
|
27936
27825
|
return result;
|
|
27937
27826
|
};
|
|
27827
|
+
function isRpgLog(error) {
|
|
27828
|
+
return error instanceof Log || typeof error === "object" && error !== null && "id" in error && error.name === "RpgLog";
|
|
27829
|
+
}
|
|
27938
27830
|
const MapUpdateSchema = object({
|
|
27939
27831
|
/** Configuration object for the map (optional) */
|
|
27940
27832
|
config: any().optional(),
|
|
@@ -27947,6 +27839,8 @@ const MapUpdateSchema = object({
|
|
|
27947
27839
|
/** Height of the map in pixels (required) */
|
|
27948
27840
|
height: number()
|
|
27949
27841
|
});
|
|
27842
|
+
const SAFE_MAP_WIDTH = 1e3;
|
|
27843
|
+
const SAFE_MAP_HEIGHT = 1e3;
|
|
27950
27844
|
let RpgMap = class extends RpgCommonMap {
|
|
27951
27845
|
constructor(room) {
|
|
27952
27846
|
super();
|
|
@@ -28019,6 +27913,7 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28019
27913
|
* with custom formulas when the map is loaded.
|
|
28020
27914
|
*/
|
|
28021
27915
|
this.damageFormulas = {};
|
|
27916
|
+
this._weatherState = null;
|
|
28022
27917
|
/** Internal: Map of shapes by name */
|
|
28023
27918
|
this._shapes = /* @__PURE__ */ new Map();
|
|
28024
27919
|
/** Internal: Map of shape entity UUIDs to RpgShape instances */
|
|
@@ -28047,6 +27942,19 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28047
27942
|
onStart() {
|
|
28048
27943
|
return BaseRoom.prototype.onStart.call(this);
|
|
28049
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
|
+
}
|
|
28050
27958
|
/**
|
|
28051
27959
|
* Setup collision detection between players, events, and shapes
|
|
28052
27960
|
*
|
|
@@ -28090,8 +27998,8 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28090
27998
|
const activeCollisions = /* @__PURE__ */ new Set();
|
|
28091
27999
|
const activeShapeCollisions = /* @__PURE__ */ new Set();
|
|
28092
28000
|
const hasDifferentZ = (entityA, entityB) => {
|
|
28093
|
-
const zA = entityA.owner
|
|
28094
|
-
const zB = entityB.owner
|
|
28001
|
+
const zA = entityA.owner?.z();
|
|
28002
|
+
const zB = entityB.owner?.z();
|
|
28095
28003
|
return zA !== zB;
|
|
28096
28004
|
};
|
|
28097
28005
|
this.physic.getEvents().onCollisionEnter((collision) => {
|
|
@@ -28200,12 +28108,19 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28200
28108
|
if (packet && typeof packet === "object") {
|
|
28201
28109
|
obj.timestamp = Date.now();
|
|
28202
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();
|
|
28203
28117
|
const lastFramePositions = player._lastFramePositions;
|
|
28204
28118
|
obj.ack = {
|
|
28205
|
-
frame: lastFramePositions?.frame ??
|
|
28206
|
-
|
|
28207
|
-
|
|
28208
|
-
|
|
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()
|
|
28209
28124
|
};
|
|
28210
28125
|
}
|
|
28211
28126
|
}
|
|
@@ -28255,18 +28170,40 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28255
28170
|
}
|
|
28256
28171
|
player.context = context;
|
|
28257
28172
|
player.conn = conn;
|
|
28173
|
+
player.pendingInputs = [];
|
|
28174
|
+
player.lastProcessedInputTs = 0;
|
|
28175
|
+
player._lastFramePositions = null;
|
|
28258
28176
|
player._onInit();
|
|
28259
28177
|
this.dataIsReady$.pipe(
|
|
28260
|
-
finalize$1(
|
|
28261
|
-
|
|
28262
|
-
|
|
28263
|
-
|
|
28264
|
-
|
|
28265
|
-
|
|
28266
|
-
|
|
28267
|
-
|
|
28268
|
-
|
|
28269
|
-
|
|
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
|
+
})();
|
|
28270
28207
|
})
|
|
28271
28208
|
).subscribe();
|
|
28272
28209
|
}
|
|
@@ -28300,6 +28237,8 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28300
28237
|
}
|
|
28301
28238
|
await lastValueFrom(this.hooks.callHooks("server-player-onLeaveMap", player, this));
|
|
28302
28239
|
player.pendingInputs = [];
|
|
28240
|
+
player.lastProcessedInputTs = 0;
|
|
28241
|
+
player._lastFramePositions = null;
|
|
28303
28242
|
}
|
|
28304
28243
|
/**
|
|
28305
28244
|
* Get the hooks system for this map
|
|
@@ -28342,18 +28281,60 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28342
28281
|
player.execMethod("onInput", [action]);
|
|
28343
28282
|
}
|
|
28344
28283
|
async onInput(player, input) {
|
|
28345
|
-
|
|
28346
|
-
|
|
28347
|
-
|
|
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") {
|
|
28348
28289
|
return;
|
|
28349
28290
|
}
|
|
28350
|
-
|
|
28351
|
-
|
|
28352
|
-
|
|
28353
|
-
|
|
28354
|
-
|
|
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);
|
|
28355
28329
|
}
|
|
28356
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
|
+
}
|
|
28357
28338
|
async saveSlot(player, value) {
|
|
28358
28339
|
BaseRoom.prototype.saveSlot(player, value);
|
|
28359
28340
|
}
|
|
@@ -28378,9 +28359,15 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28378
28359
|
await lastValueFrom(this.hooks.callHooks("server-maps-load", this));
|
|
28379
28360
|
await lastValueFrom(this.hooks.callHooks("server-worldMaps-load", this));
|
|
28380
28361
|
await lastValueFrom(this.hooks.callHooks("server-databaseHooks-load", this));
|
|
28362
|
+
this.resolveTrustedMapDimensions(map);
|
|
28363
|
+
this.data.set(map);
|
|
28381
28364
|
map.events = map.events ?? [];
|
|
28365
|
+
let initialWeather = this.globalConfig?.weather;
|
|
28382
28366
|
if (map.id) {
|
|
28383
28367
|
const mapFound = this.maps.find((m) => m.id === map.id);
|
|
28368
|
+
if (typeof mapFound?.weather !== "undefined") {
|
|
28369
|
+
initialWeather = mapFound.weather;
|
|
28370
|
+
}
|
|
28384
28371
|
if (mapFound?.events) {
|
|
28385
28372
|
map.events = [
|
|
28386
28373
|
...mapFound.events,
|
|
@@ -28408,6 +28395,11 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28408
28395
|
this.stopAllSoundsBeforeJoin = mapFound.stopAllSoundsBeforeJoin;
|
|
28409
28396
|
}
|
|
28410
28397
|
}
|
|
28398
|
+
if (typeof initialWeather !== "undefined") {
|
|
28399
|
+
this.setWeather(initialWeather);
|
|
28400
|
+
} else {
|
|
28401
|
+
this.clearWeather();
|
|
28402
|
+
}
|
|
28411
28403
|
await lastValueFrom(this.hooks.callHooks("server-map-onBeforeUpdate", map, this));
|
|
28412
28404
|
this.loadPhysic();
|
|
28413
28405
|
for (let event of map.events ?? []) {
|
|
@@ -28447,10 +28439,11 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28447
28439
|
/**
|
|
28448
28440
|
* Process pending inputs for a player with anti-cheat validation
|
|
28449
28441
|
*
|
|
28450
|
-
* This method processes
|
|
28442
|
+
* This method processes pending inputs for a player while performing
|
|
28451
28443
|
* anti-cheat validation to prevent time manipulation and frame skipping.
|
|
28452
28444
|
* It validates the time deltas between inputs and ensures they are within
|
|
28453
|
-
* acceptable ranges.
|
|
28445
|
+
* acceptable ranges. To preserve movement itinerary under network bursts,
|
|
28446
|
+
* the number of inputs processed per call is capped.
|
|
28454
28447
|
*
|
|
28455
28448
|
* ## Architecture
|
|
28456
28449
|
*
|
|
@@ -28500,14 +28493,16 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28500
28493
|
// Max 10 frames skipped
|
|
28501
28494
|
minTimeBetweenInputs: 16,
|
|
28502
28495
|
// ~60fps minimum
|
|
28503
|
-
enableAntiCheat: false
|
|
28496
|
+
enableAntiCheat: false,
|
|
28497
|
+
maxInputsPerTick: 1
|
|
28504
28498
|
};
|
|
28505
28499
|
const config = { ...defaultControls, ...controls };
|
|
28506
28500
|
let lastProcessedTime = player.lastProcessedInputTs || 0;
|
|
28507
|
-
let lastProcessedFrame = 0;
|
|
28501
|
+
let lastProcessedFrame = player._lastFramePositions?.frame ?? 0;
|
|
28508
28502
|
player.pendingInputs.sort((a, b) => (a.frame || 0) - (b.frame || 0));
|
|
28509
28503
|
let hasProcessedInputs = false;
|
|
28510
|
-
|
|
28504
|
+
let processedThisTick = 0;
|
|
28505
|
+
while (player.pendingInputs.length > 0 && processedThisTick < config.maxInputsPerTick) {
|
|
28511
28506
|
const input = player.pendingInputs.shift();
|
|
28512
28507
|
if (!input || typeof input.frame !== "number") {
|
|
28513
28508
|
continue;
|
|
@@ -28537,6 +28532,19 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28537
28532
|
processedInputs.push(input.input);
|
|
28538
28533
|
hasProcessedInputs = true;
|
|
28539
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
|
+
};
|
|
28540
28548
|
}
|
|
28541
28549
|
lastProcessedFrame = input.frame;
|
|
28542
28550
|
}
|
|
@@ -28579,20 +28587,17 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
28579
28587
|
if (this._inputLoopSubscription) {
|
|
28580
28588
|
this._inputLoopSubscription.unsubscribe();
|
|
28581
28589
|
}
|
|
28582
|
-
this._inputLoopSubscription = this.tick$.
|
|
28583
|
-
throttleTime(50)
|
|
28584
|
-
// Throttle to 50ms for input processing
|
|
28585
|
-
).subscribe(async ({ timestamp }) => {
|
|
28590
|
+
this._inputLoopSubscription = this.tick$.subscribe(() => {
|
|
28586
28591
|
for (const player of this.getPlayers()) {
|
|
28587
|
-
|
|
28588
|
-
|
|
28589
|
-
|
|
28590
|
-
|
|
28591
|
-
await this.processInput(player.id).finally(() => {
|
|
28592
|
-
anyPlayer._isProcessingInputs = false;
|
|
28593
|
-
});
|
|
28594
|
-
}
|
|
28592
|
+
const anyPlayer = player;
|
|
28593
|
+
const shouldProcess = player.pendingInputs.length > 0 || (player.lastProcessedInputTs || 0) > 0;
|
|
28594
|
+
if (!shouldProcess || anyPlayer._isProcessingInputs) {
|
|
28595
|
+
continue;
|
|
28595
28596
|
}
|
|
28597
|
+
anyPlayer._isProcessingInputs = true;
|
|
28598
|
+
void this.processInput(player.id).finally(() => {
|
|
28599
|
+
anyPlayer._isProcessingInputs = false;
|
|
28600
|
+
});
|
|
28596
28601
|
}
|
|
28597
28602
|
});
|
|
28598
28603
|
}
|
|
@@ -29090,6 +29095,66 @@ let RpgMap = class extends RpgCommonMap {
|
|
|
29090
29095
|
animationName
|
|
29091
29096
|
});
|
|
29092
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
|
+
}
|
|
29093
29158
|
/**
|
|
29094
29159
|
* Configure runtime synchronized properties on the map
|
|
29095
29160
|
*
|
|
@@ -29530,6 +29595,9 @@ __decorateClass$1([
|
|
|
29530
29595
|
__decorateClass$1([
|
|
29531
29596
|
Action("move")
|
|
29532
29597
|
], RpgMap.prototype, "onInput", 1);
|
|
29598
|
+
__decorateClass$1([
|
|
29599
|
+
Action("ping")
|
|
29600
|
+
], RpgMap.prototype, "onPing", 1);
|
|
29533
29601
|
__decorateClass$1([
|
|
29534
29602
|
Action("save.save")
|
|
29535
29603
|
], RpgMap.prototype, "saveSlot", 1);
|
|
@@ -29894,6 +29962,7 @@ function provideServerModules(modules) {
|
|
|
29894
29962
|
type: MapClass.type,
|
|
29895
29963
|
name: MapClass.prototype?.name,
|
|
29896
29964
|
sounds: MapClass.prototype?.sounds,
|
|
29965
|
+
weather: MapClass.prototype?.weather,
|
|
29897
29966
|
lowMemory: MapClass.prototype?.lowMemory,
|
|
29898
29967
|
stopAllSoundsBeforeJoin: MapClass.prototype?.stopAllSoundsBeforeJoin,
|
|
29899
29968
|
events: MapClass.prototype?._events,
|
|
@@ -30027,6 +30096,7 @@ function MapData(options) {
|
|
|
30027
30096
|
target.prototype.file = options.file;
|
|
30028
30097
|
target.prototype.id = options.id;
|
|
30029
30098
|
target.prototype.sounds = options.sounds;
|
|
30099
|
+
target.prototype.weather = options.weather;
|
|
30030
30100
|
target.prototype.lowMemory = options.lowMemory;
|
|
30031
30101
|
target.prototype.stopAllSoundsBeforeJoin = options.stopAllSoundsBeforeJoin;
|
|
30032
30102
|
target.prototype.$schema = {};
|