@rpgjs/server 5.0.0-alpha.33 → 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/decorators/map.d.ts +22 -0
- package/dist/index.js +387 -324
- 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 +5 -5
- 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/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);
|
|
@@ -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
|
|
|
@@ -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
|
-
|
|
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
|
|
22536
|
-
|
|
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 =
|
|
22413
|
+
this.touchSide = false;
|
|
22414
|
+
}
|
|
22415
|
+
const changeMap = async (adjacent, to) => {
|
|
22540
22416
|
const [nextMap] = worldMaps.getAdjacentMaps(map2, adjacent);
|
|
22541
|
-
if (!nextMap)
|
|
22417
|
+
if (!nextMap) {
|
|
22418
|
+
return false;
|
|
22419
|
+
}
|
|
22542
22420
|
const id = nextMap.id;
|
|
22543
22421
|
const nextMapInfo = worldMaps.getMapInfo(id);
|
|
22544
|
-
|
|
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:
|
|
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
|
|
28101
|
-
const zB = entityB.owner
|
|
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 ??
|
|
28213
|
-
|
|
28214
|
-
|
|
28215
|
-
|
|
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(
|
|
28268
|
-
|
|
28269
|
-
|
|
28270
|
-
|
|
28271
|
-
|
|
28272
|
-
|
|
28273
|
-
|
|
28274
|
-
|
|
28275
|
-
|
|
28276
|
-
|
|
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
|
-
|
|
28353
|
-
|
|
28354
|
-
|
|
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
|
-
|
|
28358
|
-
|
|
28359
|
-
|
|
28360
|
-
|
|
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
|
|
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
|
-
|
|
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$.
|
|
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
|
-
|
|
28595
|
-
|
|
28596
|
-
|
|
28597
|
-
|
|
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 = {};
|