@rpgjs/server 4.1.2 → 4.2.0

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.
@@ -2,135 +2,6 @@
2
2
  typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@rpgjs/common"), require("@rpgjs/database")) : typeof define === "function" && define.amd ? define(["exports", "@rpgjs/common", "@rpgjs/database"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.RpgServer = {}, global2.common, global2.database));
3
3
  })(this, function(exports2, common, database) {
4
4
  "use strict";
5
- var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
6
- function getAugmentedNamespace(n) {
7
- if (n.__esModule)
8
- return n;
9
- var f = n.default;
10
- if (typeof f == "function") {
11
- var a = function a2() {
12
- if (this instanceof a2) {
13
- var args = [null];
14
- args.push.apply(args, arguments);
15
- var Ctor = Function.bind.apply(f, args);
16
- return new Ctor();
17
- }
18
- return f.apply(this, arguments);
19
- };
20
- a.prototype = f.prototype;
21
- } else
22
- a = {};
23
- Object.defineProperty(a, "__esModule", {
24
- value: true
25
- });
26
- Object.keys(n).forEach(function(k) {
27
- var d = Object.getOwnPropertyDescriptor(n, k);
28
- Object.defineProperty(a, k, d.get ? d : {
29
- enumerable: true,
30
- get: function() {
31
- return n[k];
32
- }
33
- });
34
- });
35
- return a;
36
- }
37
- /*!
38
- * isobject <https://github.com/jonschlinkert/isobject>
39
- *
40
- * Copyright (c) 2014-2017, Jon Schlinkert.
41
- * Released under the MIT License.
42
- */
43
- var isobject = function isObject2(val) {
44
- return val != null && typeof val === "object" && Array.isArray(val) === false;
45
- };
46
- /*!
47
- * get-value <https://github.com/jonschlinkert/get-value>
48
- *
49
- * Copyright (c) 2014-2018, Jon Schlinkert.
50
- * Released under the MIT License.
51
- */
52
- const isObject$3 = isobject;
53
- var getValue = function(target, path2, options2) {
54
- if (!isObject$3(options2)) {
55
- options2 = { default: options2 };
56
- }
57
- if (!isValidObject(target)) {
58
- return typeof options2.default !== "undefined" ? options2.default : target;
59
- }
60
- if (typeof path2 === "number") {
61
- path2 = String(path2);
62
- }
63
- const isArray2 = Array.isArray(path2);
64
- const isString2 = typeof path2 === "string";
65
- const splitChar = options2.separator || ".";
66
- const joinChar = options2.joinChar || (typeof splitChar === "string" ? splitChar : ".");
67
- if (!isString2 && !isArray2) {
68
- return target;
69
- }
70
- if (isString2 && path2 in target) {
71
- return isValid(path2, target, options2) ? target[path2] : options2.default;
72
- }
73
- let segs = isArray2 ? path2 : split(path2, splitChar, options2);
74
- let len = segs.length;
75
- let idx = 0;
76
- do {
77
- let prop = segs[idx];
78
- if (typeof prop === "number") {
79
- prop = String(prop);
80
- }
81
- while (prop && prop.slice(-1) === "\\") {
82
- prop = join$2([prop.slice(0, -1), segs[++idx] || ""], joinChar, options2);
83
- }
84
- if (prop in target) {
85
- if (!isValid(prop, target, options2)) {
86
- return options2.default;
87
- }
88
- target = target[prop];
89
- } else {
90
- let hasProp = false;
91
- let n = idx + 1;
92
- while (n < len) {
93
- prop = join$2([prop, segs[n++]], joinChar, options2);
94
- if (hasProp = prop in target) {
95
- if (!isValid(prop, target, options2)) {
96
- return options2.default;
97
- }
98
- target = target[prop];
99
- idx = n - 1;
100
- break;
101
- }
102
- }
103
- if (!hasProp) {
104
- return options2.default;
105
- }
106
- }
107
- } while (++idx < len && isValidObject(target));
108
- if (idx === len) {
109
- return target;
110
- }
111
- return options2.default;
112
- };
113
- function join$2(segs, joinChar, options2) {
114
- if (typeof options2.join === "function") {
115
- return options2.join(segs);
116
- }
117
- return segs[0] + joinChar + segs[1];
118
- }
119
- function split(path2, splitChar, options2) {
120
- if (typeof options2.split === "function") {
121
- return options2.split(path2);
122
- }
123
- return path2.split(splitChar);
124
- }
125
- function isValid(key, target, options2) {
126
- if (typeof options2.isValid === "function") {
127
- return options2.isValid(key, target);
128
- }
129
- return true;
130
- }
131
- function isValidObject(val) {
132
- return isObject$3(val) || Array.isArray(val) || typeof val === "function";
133
- }
134
5
  const GENERIC_KEY_SCHEMA = "@";
135
6
  class Utils {
136
7
  static isObject(val) {
@@ -161,25 +32,90 @@
161
32
  };
162
33
  return paths(obj);
163
34
  }
164
- static generateId() {
165
- return "$" + (Date.now().toString(36) + Math.random().toString(36).substr(2, 5));
35
+ static generateId(n = 5) {
36
+ return Math.random().toString(36).substring(n);
37
+ }
38
+ static async resolveValue(value) {
39
+ if (value instanceof Promise) {
40
+ return await value;
41
+ }
42
+ return value;
166
43
  }
167
- // https://stackoverflow.com/questions/54733539/javascript-implementation-of-lodash-set-method
168
44
  static set(obj, path2, value, onlyPlainObject = false) {
169
45
  if (Object(obj) !== obj)
170
46
  return obj;
171
- if (!Array.isArray(path2))
172
- path2 = path2.toString().match(/[^.[\]]+/g) || [];
173
- path2.slice(0, -1).reduce(
174
- (a, c2, i2) => (
175
- // Iterate all of them except the last one
176
- Object(a[c2]) === a[c2] ? a[c2] : a[c2] = Math.abs(path2[i2 + 1]) >> 0 === +path2[i2 + 1] ? onlyPlainObject ? {} : [] : {}
177
- ),
178
- // No: assign a new plain object
179
- obj
180
- )[path2[path2.length - 1]] = value;
47
+ if (typeof path2 === "string") {
48
+ path2 = path2.split(".");
49
+ }
50
+ let len = path2.length;
51
+ if (!len)
52
+ return obj;
53
+ let current = obj;
54
+ for (let i2 = 0; i2 < len - 1; i2++) {
55
+ let segment = path2[i2];
56
+ let nextSegment = path2[i2 + 1];
57
+ let isNextNumeric = !isNaN(nextSegment) && isFinite(nextSegment);
58
+ if (!current[segment] || typeof current[segment] !== "object") {
59
+ current[segment] = isNextNumeric && !onlyPlainObject ? [] : {};
60
+ }
61
+ current = current[segment];
62
+ }
63
+ current[path2[len - 1]] = value;
181
64
  return obj;
182
65
  }
66
+ static get(obj, path2) {
67
+ const keys2 = path2.split(".");
68
+ let current = obj;
69
+ for (let key of keys2) {
70
+ if (current[key] === void 0) {
71
+ return void 0;
72
+ }
73
+ current = current[key];
74
+ }
75
+ return current;
76
+ }
77
+ static bufferFrom(input) {
78
+ if (typeof input === "string") {
79
+ let encoder2 = new TextEncoder();
80
+ return encoder2.encode(input);
81
+ } else if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {
82
+ return new Uint8Array(input);
83
+ } else {
84
+ throw new Error("Input type not supported");
85
+ }
86
+ }
87
+ }
88
+ var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
89
+ function getAugmentedNamespace(n) {
90
+ if (n.__esModule)
91
+ return n;
92
+ var f = n.default;
93
+ if (typeof f == "function") {
94
+ var a = function a2() {
95
+ if (this instanceof a2) {
96
+ var args = [null];
97
+ args.push.apply(args, arguments);
98
+ var Ctor = Function.bind.apply(f, args);
99
+ return new Ctor();
100
+ }
101
+ return f.apply(this, arguments);
102
+ };
103
+ a.prototype = f.prototype;
104
+ } else
105
+ a = {};
106
+ Object.defineProperty(a, "__esModule", {
107
+ value: true
108
+ });
109
+ Object.keys(n).forEach(function(k) {
110
+ var d = Object.getOwnPropertyDescriptor(n, k);
111
+ Object.defineProperty(a, k, d.get ? d : {
112
+ enumerable: true,
113
+ get: function() {
114
+ return n[k];
115
+ }
116
+ });
117
+ });
118
+ return a;
183
119
  }
184
120
  var browser$2 = {};
185
121
  var encode$4 = {};
@@ -3755,16 +3691,17 @@
3755
3691
  get body() {
3756
3692
  return this.data;
3757
3693
  }
3758
- message(otherData = {}) {
3759
- return [this.roomId, Date.now(), { ...this.data, ...otherData }];
3694
+ message(otherData) {
3695
+ return [this.roomId, Date.now(), otherData ?? this.data];
3760
3696
  }
3761
3697
  clone(data) {
3762
3698
  return new Packet(data, this.roomId);
3763
3699
  }
3764
- encode(otherData = {}) {
3700
+ encode(otherData) {
3765
3701
  return browser$2.encode(this.message(otherData));
3766
3702
  }
3767
3703
  }
3704
+ const { get: get$1, set: set$1 } = Utils;
3768
3705
  class TransmitterClass {
3769
3706
  constructor() {
3770
3707
  this.encode = true;
@@ -3795,104 +3732,183 @@
3795
3732
  this.packets = {};
3796
3733
  }
3797
3734
  }
3798
- emit(user, packet, room) {
3799
- const send = (packet2) => {
3800
- const lastFramePositions = user["_lastFramePositions"];
3801
- let pos;
3802
- let lastFrame;
3803
- if (lastFramePositions) {
3804
- pos = lastFramePositions.position;
3805
- lastFrame = lastFramePositions.frame;
3806
- }
3807
- const data = { frame: lastFrame, pos };
3808
- user._socket.emit("w", this.encode ? packet2.encode(data) : packet2.message(data));
3809
- };
3810
- if (room.filterEmit) {
3811
- const objectPacket = room.filterEmit(user, packet);
3812
- const promiseObjectPacket = objectPacket;
3813
- if (promiseObjectPacket.then) {
3814
- promiseObjectPacket.then(send);
3815
- } else {
3816
- send(objectPacket);
3735
+ error(user, error) {
3736
+ const err = error instanceof Error ? error.toObject ? error.toObject() : error.message : error;
3737
+ user._socket.emit("error", err);
3738
+ }
3739
+ async emit(user, packet, room) {
3740
+ let data = packet.body;
3741
+ if (room.$additionalEmitProperties) {
3742
+ let additionalData = await Utils.resolveValue(room.$additionalEmitProperties(user, packet.body));
3743
+ if (additionalData !== void 0) {
3744
+ if (typeof additionalData === "string") {
3745
+ additionalData = [additionalData];
3746
+ }
3747
+ if (Array.isArray(additionalData)) {
3748
+ const newData = structuredClone(data);
3749
+ for (let path2 of additionalData) {
3750
+ set$1(newData, path2, get$1(room, path2));
3751
+ }
3752
+ data = newData;
3753
+ } else {
3754
+ data = { ...data, ...additionalData };
3755
+ }
3817
3756
  }
3818
- return;
3819
3757
  }
3820
- send(packet);
3758
+ user._socket.emit("w", this.encode ? packet.encode(data) : packet.message(data));
3821
3759
  }
3822
3760
  }
3823
3761
  const Transmitter = new TransmitterClass();
3824
- const { set } = Utils;
3825
- class Room {
3762
+ var UserState;
3763
+ (function(UserState2) {
3764
+ UserState2["Connected"] = "C";
3765
+ UserState2["Disconnected"] = "D";
3766
+ })(UserState || (UserState = {}));
3767
+ class User {
3826
3768
  constructor() {
3827
- this.memoryTotalObject = {};
3828
- this.memoryObject = {};
3829
- this.permanentObject = [];
3769
+ this.$state = UserState.Connected;
3770
+ this._secretSessionId = "";
3771
+ this._rooms = [];
3772
+ }
3773
+ }
3774
+ User.schema = {
3775
+ $state: String
3776
+ };
3777
+ class CustomError extends Error {
3778
+ constructor(customMessage) {
3779
+ super(customMessage);
3780
+ this.customMessage = customMessage;
3781
+ this.status = 500;
3782
+ this.code = "INTERNAL_SERVER_ERROR";
3783
+ this.message = "Internal Server error";
3784
+ }
3785
+ toObject() {
3786
+ return {
3787
+ message: this.customMessage || this.message,
3788
+ status: this.status,
3789
+ code: this.code
3790
+ };
3791
+ }
3792
+ }
3793
+ class NotAuthorized extends CustomError {
3794
+ constructor(customMessage) {
3795
+ super(customMessage);
3796
+ this.status = 401;
3797
+ this.code = "NOT_AUTHORIZED";
3798
+ this.message = "Not authorized";
3830
3799
  }
3800
+ }
3801
+ const { set, get } = Utils;
3802
+ class Room {
3831
3803
  static hasExtraProp(obj) {
3832
- return obj.$default !== void 0 || obj.$syncWithClient !== void 0 || obj.$permanent !== void 0 || obj.$validate !== void 0 || obj.$effects !== void 0;
3804
+ return obj.$default !== void 0 || obj.$syncWithClient !== void 0 || obj.$permanent !== void 0 || obj.$validate !== void 0 || obj.$effects !== void 0 || obj.$type !== void 0;
3833
3805
  }
3834
- static toDict(schema, room) {
3806
+ static compileSchema(schema, room) {
3835
3807
  const dict = {};
3808
+ const masks = {};
3836
3809
  const permanentObject = [];
3837
- function toDict(obj, path2 = "") {
3838
- for (let prop in obj) {
3839
- const val = obj[prop];
3810
+ function specialObject(val, p) {
3811
+ if (Room.hasExtraProp(val)) {
3812
+ if (val.$permanent ?? true)
3813
+ permanentObject.push(p);
3814
+ if (room && val.$default !== void 0)
3815
+ ;
3816
+ if (val.$syncWithClient === false) {
3817
+ return;
3818
+ }
3819
+ dict[p] = {
3820
+ ...val
3821
+ };
3822
+ } else {
3823
+ dict[p] = val;
3824
+ masks[p] = Utils.propertiesToArray(val);
3825
+ compile(val, p);
3826
+ }
3827
+ }
3828
+ function compile(schema2, path2 = "") {
3829
+ for (let prop in schema2) {
3830
+ const val = schema2[prop];
3840
3831
  let p = (path2 ? path2 + "." : "") + prop;
3841
3832
  if (Array.isArray(val)) {
3842
3833
  dict[p] = GENERIC_KEY_SCHEMA;
3843
3834
  p += "." + GENERIC_KEY_SCHEMA;
3844
- dict[p] = val[0];
3845
- toDict(val[0], p);
3846
- } else if (Utils.isObject(val)) {
3847
- if (Room.hasExtraProp(val)) {
3848
- if (val.$permanent ?? true)
3849
- permanentObject.push(p);
3850
- if (room && val.$default !== void 0)
3851
- ;
3852
- if (val.$syncWithClient === false) {
3853
- continue;
3854
- }
3855
- dict[p] = {
3856
- ...val
3857
- };
3835
+ if (val[0] === void 0)
3836
+ val[0] = {};
3837
+ if (Utils.isObject(val[0])) {
3838
+ specialObject(val[0], p);
3858
3839
  } else {
3859
- dict[p] = val;
3860
- toDict(val, p);
3840
+ dict[p] = val[0];
3841
+ compile(val[0], p);
3861
3842
  }
3843
+ } else if (Utils.isObject(val)) {
3844
+ specialObject(val, p);
3862
3845
  } else {
3863
3846
  permanentObject.push(p);
3864
3847
  dict[p] = val;
3865
3848
  }
3866
3849
  }
3867
3850
  }
3868
- toDict(schema);
3851
+ compile(schema);
3869
3852
  return {
3853
+ masks,
3870
3854
  dict,
3871
3855
  permanentObject
3872
3856
  };
3873
3857
  }
3874
- join(user, room) {
3875
- if (!user._rooms)
3876
- user._rooms = [];
3877
- user._rooms.push(room.id);
3878
- if (!user.id)
3879
- user.id = Utils.generateId();
3880
- if (room["onJoin"])
3881
- room["onJoin"](user);
3858
+ constructor(options2) {
3859
+ this.options = options2;
3860
+ this.memoryTotalObject = {};
3861
+ this.memoryObject = {};
3862
+ this.permanentObject = [];
3863
+ this.propagateOldRoom = true;
3864
+ if (options2.propagateOldRoom) {
3865
+ this.propagateOldRoom = options2.propagateOldRoom;
3866
+ }
3867
+ }
3868
+ async join(user, room) {
3869
+ if (room["canJoin"]) {
3870
+ const authBool = await Utils.resolveValue(room["canJoin"](user, user._socket));
3871
+ if (authBool === false || typeof authBool == "string") {
3872
+ Transmitter.error(user, new NotAuthorized(authBool));
3873
+ return false;
3874
+ }
3875
+ }
3876
+ if (World.agonesSDK) {
3877
+ await World.agonesSDK.allocate();
3878
+ }
3879
+ let firstJoin = !room.users[user.id];
3880
+ room.users[user.id] = user;
3881
+ const userProxy = World.users[user.id]["proxy"];
3882
+ userProxy.$state = UserState.Connected;
3883
+ if (firstJoin) {
3884
+ if (room["onJoin"])
3885
+ await Utils.resolveValue(room["onJoin"](userProxy));
3886
+ }
3882
3887
  if (this.getUsersLength(room) == 1) {
3883
3888
  this.memoryTotalObject = Room.extractObjectOfRoom(room, room.$schema);
3884
3889
  }
3885
3890
  const packet = new Packet({
3886
3891
  ...this.memoryTotalObject,
3887
- join: true
3892
+ join: firstJoin
3888
3893
  }, room.id);
3889
- Transmitter.emit(user, packet, room);
3894
+ await Transmitter.emit(userProxy, packet, room);
3895
+ return true;
3890
3896
  }
3891
- leave(user, room) {
3892
- const index2 = user._rooms.findIndex((id) => room.id == id);
3893
- user._rooms.splice(index2, 1);
3897
+ async leave(user, room) {
3894
3898
  if (room["onLeave"])
3895
3899
  room["onLeave"](user);
3900
+ const index2 = user._rooms.findIndex((id) => room.id == id);
3901
+ user._rooms.splice(index2, 1);
3902
+ delete room.users[user.id];
3903
+ delete World.users[user.id]["proxy"];
3904
+ if (World.nbUsers == 0 && World.agonesSDK) {
3905
+ const { onBeforeShutdown, shutdownIfNotPlayers } = World.agonesOptions;
3906
+ if (shutdownIfNotPlayers) {
3907
+ if (onBeforeShutdown)
3908
+ await onBeforeShutdown();
3909
+ await World.agonesSDK.shutdown();
3910
+ }
3911
+ }
3896
3912
  }
3897
3913
  getUsersLength(room) {
3898
3914
  return Object.keys(room.users).length;
@@ -3915,7 +3931,8 @@
3915
3931
  }
3916
3932
  setProxy(room) {
3917
3933
  const self2 = this;
3918
- const { dict, permanentObject } = Room.toDict(room.$schema, room);
3934
+ const { dict, permanentObject, masks } = Room.compileSchema(room.$schema, room);
3935
+ const proxifiedObjects = /* @__PURE__ */ new WeakSet();
3919
3936
  this.permanentObject = permanentObject;
3920
3937
  room.$dict = dict;
3921
3938
  const getInfoDict = (path2, key, dictPath) => {
@@ -3925,19 +3942,31 @@
3925
3942
  return {
3926
3943
  fullPath: p,
3927
3944
  genericPath,
3928
- infoDict: dict[genericPath]
3945
+ infoDict: dict[genericPath],
3946
+ mask: masks[genericPath]
3929
3947
  };
3930
3948
  };
3931
3949
  function deepProxy(object, path2 = "", dictPath = "") {
3950
+ if (proxifiedObjects.has(object)) {
3951
+ return object;
3952
+ }
3932
3953
  return new Proxy(object, {
3933
3954
  set(target, key, val, receiver) {
3934
- const { fullPath: p, infoDict, genericPath } = getInfoDict(path2, key, dictPath);
3955
+ const { fullPath: p, infoDict, genericPath, mask } = getInfoDict(path2, key, dictPath);
3935
3956
  if (typeof val == "object" && infoDict && val != null) {
3936
3957
  const valProxy = deepProxy(val, p, genericPath);
3958
+ proxifiedObjects.add(valProxy);
3937
3959
  if (path2 == "users") {
3960
+ if (!room.users[key]) {
3961
+ if (!valProxy._rooms)
3962
+ valProxy._rooms = [];
3963
+ valProxy._rooms.push(room.id);
3964
+ if (!valProxy.id)
3965
+ valProxy.id = Utils.generateId();
3966
+ }
3938
3967
  World.users[key]["proxy"] = valProxy;
3939
3968
  }
3940
- Reflect.set(target, key, valProxy, receiver);
3969
+ Reflect.set(target, key, val, receiver);
3941
3970
  val = target[key];
3942
3971
  } else {
3943
3972
  if (infoDict == null ? void 0 : infoDict.$validate) {
@@ -3971,7 +4000,7 @@
3971
4000
  }
3972
4001
  let newObj;
3973
4002
  if (Utils.isObject(infoDict) && val != null && !Room.hasExtraProp(infoDict)) {
3974
- newObj = Room.extractObjectOfRoom(val, infoDict);
4003
+ newObj = Room.extractObjectOfRoom(val, mask);
3975
4004
  } else if (infoDict == GENERIC_KEY_SCHEMA) {
3976
4005
  newObj = {};
3977
4006
  if (Object.keys(val).length == 0) {
@@ -4003,6 +4032,7 @@
4003
4032
  const { fullPath: p, infoDict, genericPath } = getInfoDict(path3, key, dictPath);
4004
4033
  if (typeof val2 == "object" && infoDict) {
4005
4034
  val2 = deepProxy(val2, p, genericPath);
4035
+ proxifiedObjects.add(val2);
4006
4036
  }
4007
4037
  return val2;
4008
4038
  };
@@ -4027,7 +4057,7 @@
4027
4057
  if (!room.$schema)
4028
4058
  room.$schema = {};
4029
4059
  if (!room.$schema.users)
4030
- room.$schema.users = [{ id: String }];
4060
+ room.$schema.users = [User.schema];
4031
4061
  if (!room.$inputs)
4032
4062
  room.$inputs = {};
4033
4063
  if (!room.users)
@@ -4053,16 +4083,20 @@
4053
4083
  room.$snapshotUser = (userId) => {
4054
4084
  return this.snapshotUser(room, userId);
4055
4085
  };
4056
- room.$join = (user) => {
4086
+ room.$join = async (user) => {
4087
+ if (typeof user == "string") {
4088
+ user = World.users[user];
4089
+ }
4057
4090
  if (user) {
4058
- room.users[user.id] = user;
4059
- this.join(room.users[user.id], room);
4091
+ return this.join(user, room);
4060
4092
  }
4093
+ return false;
4061
4094
  };
4062
- room.$leave = (user) => {
4063
- this.leave(user, room);
4064
- delete room.users[user.id];
4065
- delete World.users[user.id]["proxy"];
4095
+ room.$leave = async (user) => {
4096
+ if (typeof user == "string") {
4097
+ user = World.users[user]["proxy"];
4098
+ }
4099
+ await this.leave(user, room);
4066
4100
  };
4067
4101
  room.$currentState = () => this.memoryObject;
4068
4102
  room.$setCurrentState = (path2, value) => {
@@ -4071,6 +4105,7 @@
4071
4105
  room.$clearCurrentState = () => {
4072
4106
  this.memoryObject = {};
4073
4107
  };
4108
+ room.$parent = this;
4074
4109
  this.proxyRoom = room = this.setProxy(room);
4075
4110
  if (this.proxyRoom["onInit"])
4076
4111
  this.proxyRoom["onInit"]();
@@ -4078,52 +4113,59 @@
4078
4113
  }
4079
4114
  static extractObjectOfRoom(room, schema) {
4080
4115
  const newObj = {};
4081
- const schemas = [];
4082
4116
  const _schema = Array.isArray(schema) ? schema : Utils.propertiesToArray(schema);
4083
- function extract(path2) {
4084
- const match = new RegExp("^(.*?)\\.\\" + GENERIC_KEY_SCHEMA).exec(path2);
4117
+ const regex = new RegExp("^(.*?)\\.\\" + GENERIC_KEY_SCHEMA);
4118
+ function extractAndSet(obj, path2) {
4119
+ if (path2.endsWith("@")) {
4120
+ return;
4121
+ }
4122
+ const match = regex.exec(path2);
4085
4123
  if (match) {
4086
- const generic = getValue(room, match[1]);
4087
- if (generic) {
4088
- const keys2 = Object.keys(generic);
4089
- for (let key of keys2) {
4090
- extract(path2.replace(GENERIC_KEY_SCHEMA, key));
4124
+ const generic = get(room, match[1]);
4125
+ if (generic && typeof generic === "object") {
4126
+ for (let key in generic) {
4127
+ if (generic.hasOwnProperty(key)) {
4128
+ extractAndSet(obj, path2.replace(GENERIC_KEY_SCHEMA, key));
4129
+ }
4091
4130
  }
4092
4131
  }
4093
4132
  } else {
4094
- schemas.push(path2);
4133
+ set(obj, path2, get(room, path2));
4095
4134
  }
4096
4135
  }
4097
4136
  for (let path2 of _schema) {
4098
- extract(path2);
4099
- }
4100
- for (let sheme of schemas) {
4101
- set(newObj, sheme, getValue(room, sheme));
4137
+ extractAndSet(newObj, path2);
4102
4138
  }
4103
4139
  return newObj;
4104
4140
  }
4105
4141
  detectChanges(room, obj, path2) {
4142
+ const change = (room2) => {
4143
+ const roomInstance = room2.$parent;
4144
+ roomInstance.editMemoryObject(path2, obj);
4145
+ set(roomInstance.memoryTotalObject, path2, obj);
4146
+ if (roomInstance.proxyRoom["onChanges"])
4147
+ roomInstance.proxyRoom["onChanges"](roomInstance.memoryObject);
4148
+ const id = room2.id;
4149
+ World.changes.next({
4150
+ ...World.changes.value,
4151
+ [id]: room2
4152
+ });
4153
+ };
4106
4154
  if (obj != null) {
4107
4155
  const [prop, userId] = path2.split(".");
4108
4156
  if (prop == "users") {
4109
- if (!room.users[userId]) {
4157
+ if (!this.propagateOldRoom && !room.users[userId]) {
4110
4158
  return;
4111
4159
  }
4160
+ World.forEachUserRooms(userId, change);
4161
+ return;
4112
4162
  }
4113
4163
  }
4114
- this.editMemoryObject(path2, obj);
4115
- set(this.memoryTotalObject, path2, obj);
4116
- if (this.proxyRoom["onChanges"])
4117
- this.proxyRoom["onChanges"](this.memoryObject);
4118
- const id = room.id;
4119
- World.changes.next({
4120
- ...World.changes.value,
4121
- [id]: room
4122
- });
4164
+ change(room);
4123
4165
  }
4124
4166
  editMemoryObject(path2, roomOrValue) {
4125
4167
  if (roomOrValue && typeof roomOrValue == "object" && "$currentState" in roomOrValue) {
4126
- set(this.memoryObject, path2, getValue(roomOrValue, path2), true);
4168
+ set(this.memoryObject, path2, get(roomOrValue, path2), true);
4127
4169
  } else {
4128
4170
  set(this.memoryObject, path2, roomOrValue, true);
4129
4171
  }
@@ -4147,28 +4189,6 @@
4147
4189
  this.onDisconnectedCb = cb;
4148
4190
  }
4149
4191
  }
4150
- class Transport extends TransportCommon {
4151
- constructor(io) {
4152
- super();
4153
- this.io = io;
4154
- io.on("connection", (socket) => {
4155
- const id = socket.client.id;
4156
- this.onConnectedCb(socket, id);
4157
- socket.on(":input", ({ prop, value }) => this.onInputCb(id, prop, value));
4158
- socket.on(":action", ({ name, value }) => this.onActionCb(id, name, value));
4159
- socket.on(":join", (roomId) => this.onJoinCb(roomId, id));
4160
- socket.on("disconnect", () => this.onDisconnectedCb(id));
4161
- });
4162
- }
4163
- }
4164
- class User {
4165
- constructor() {
4166
- this._rooms = [];
4167
- }
4168
- }
4169
- User.schema = {
4170
- id: String
4171
- };
4172
4192
  var extendStatics = function(d, b) {
4173
4193
  extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
4174
4194
  d2.__proto__ = b2;
@@ -5057,12 +5077,132 @@
5057
5077
  };
5058
5078
  return BehaviorSubject2;
5059
5079
  }(Subject);
5080
+ class Transport extends TransportCommon {
5081
+ constructor(io, options2 = {}) {
5082
+ super();
5083
+ this.io = io;
5084
+ this.options = options2;
5085
+ this.bandwidthData = {};
5086
+ this.WINDOW_SECONDS = 10;
5087
+ io.on("connection", (socket) => {
5088
+ const id = socket.playerId;
5089
+ this.bandwidthData[id] = new BehaviorSubject({
5090
+ incoming: [],
5091
+ outgoing: []
5092
+ });
5093
+ this.handleConnection(socket, id);
5094
+ socket.on(":input", ({ prop, value }) => this.onInputCb(id, prop, value));
5095
+ socket.on(":action", ({ name, value }) => this.onActionCb(id, name, value));
5096
+ if (options2.clientCanJoinRoom)
5097
+ socket.on(":join", (roomId) => this.onJoinCb(roomId, id));
5098
+ socket.on("disconnect", () => {
5099
+ var _a;
5100
+ (_a = this.bandwidthData[id]) == null ? void 0 : _a.unsubscribe();
5101
+ delete this.bandwidthData[id];
5102
+ this.onDisconnectedCb(id);
5103
+ });
5104
+ });
5105
+ this.use();
5106
+ }
5107
+ handleConnection(socket, id) {
5108
+ this.onConnectedCb(socket, id);
5109
+ }
5110
+ use() {
5111
+ var _a, _b;
5112
+ const { maxKbpsIncoming, maxKbpsOutgoing, auth } = this.options;
5113
+ (_b = (_a = this.io).use) == null ? void 0 : _b.call(_a, async (socket, next) => {
5114
+ let playerId;
5115
+ if (auth) {
5116
+ try {
5117
+ playerId = await Utils.resolveValue(auth(socket));
5118
+ } catch (err) {
5119
+ socket.disconnect();
5120
+ next(new NotAuthorized(err).toObject());
5121
+ return;
5122
+ }
5123
+ }
5124
+ if (!playerId)
5125
+ playerId = Utils.generateId(5);
5126
+ socket.playerId = playerId;
5127
+ socket.use((packet, nextMiddleware) => {
5128
+ var _a2, _b2;
5129
+ if (packet && packet[1]) {
5130
+ const packetSize = Utils.bufferFrom(JSON.stringify(packet)).length - 2;
5131
+ const data = { size: packetSize, timestamp: Date.now() };
5132
+ this.updateBandwidthData(playerId, { incoming: data });
5133
+ const kbps = this.calculateKbps(((_a2 = this.bandwidthData[playerId]) == null ? void 0 : _a2.value.incoming) || []);
5134
+ if (maxKbpsIncoming && kbps > maxKbpsIncoming) {
5135
+ socket.disconnect();
5136
+ return;
5137
+ }
5138
+ this.cleanOldData(((_b2 = this.bandwidthData[playerId]) == null ? void 0 : _b2.value.incoming) || []);
5139
+ }
5140
+ nextMiddleware();
5141
+ });
5142
+ const originalEmit = socket.emit;
5143
+ socket.emit = (...args) => {
5144
+ var _a2, _b2;
5145
+ const packetSize = Utils.bufferFrom(JSON.stringify(args)).length - 2;
5146
+ const data = { size: packetSize, timestamp: Date.now() };
5147
+ this.updateBandwidthData(playerId, { outgoing: data });
5148
+ const kbps = this.calculateKbps(((_a2 = this.bandwidthData[playerId]) == null ? void 0 : _a2.value.outgoing) || []);
5149
+ if (maxKbpsOutgoing && kbps > maxKbpsOutgoing) {
5150
+ socket.disconnect();
5151
+ return;
5152
+ }
5153
+ this.cleanOldData(((_b2 = this.bandwidthData[playerId]) == null ? void 0 : _b2.value.outgoing) || []);
5154
+ originalEmit.apply(socket, args);
5155
+ };
5156
+ next();
5157
+ });
5158
+ }
5159
+ updateBandwidthData(socketId, data) {
5160
+ var _a, _b;
5161
+ const currentData = ((_a = this.bandwidthData[socketId]) == null ? void 0 : _a.value) || { incoming: [], outgoing: [] };
5162
+ if (data.incoming) {
5163
+ currentData.incoming.push(data.incoming);
5164
+ }
5165
+ if (data.outgoing) {
5166
+ currentData.outgoing.push(data.outgoing);
5167
+ }
5168
+ (_b = this.bandwidthData[socketId]) == null ? void 0 : _b.next(currentData);
5169
+ }
5170
+ cleanOldData(dataArray) {
5171
+ const cutOff = Date.now() - this.WINDOW_SECONDS * 1e3;
5172
+ while (dataArray.length > 0 && dataArray[0].timestamp < cutOff) {
5173
+ dataArray.shift();
5174
+ }
5175
+ }
5176
+ calculateKbps(dataArray) {
5177
+ const totalBytes = dataArray.reduce((acc, entry) => acc + entry.size, 0);
5178
+ return totalBytes * 8 / (this.WINDOW_SECONDS * 1e3);
5179
+ }
5180
+ getTelemetry() {
5181
+ const socketsData = {};
5182
+ let totalKbps = 0;
5183
+ for (const [socketId, bandwidth] of Object.entries(this.bandwidthData)) {
5184
+ const socketData = bandwidth.value;
5185
+ const incomingKbps = this.calculateKbps(socketData.incoming);
5186
+ const outgoingKbps = this.calculateKbps(socketData.outgoing);
5187
+ socketsData[socketId] = { incomingKbps, outgoingKbps };
5188
+ totalKbps += incomingKbps + outgoingKbps;
5189
+ }
5190
+ return {
5191
+ sockets: socketsData,
5192
+ totalKbps
5193
+ };
5194
+ }
5195
+ }
5060
5196
  class WorldClass {
5061
5197
  constructor() {
5062
5198
  this.rooms = /* @__PURE__ */ new Map();
5063
5199
  this.users = {};
5064
5200
  this.userClass = User;
5201
+ this.timeoutDisconnect = 0;
5065
5202
  this.changes = new BehaviorSubject({});
5203
+ this._transport = null;
5204
+ this.agonesSDK = null;
5205
+ this.agonesOptions = {};
5066
5206
  }
5067
5207
  /**
5068
5208
  * Define user class
@@ -5073,32 +5213,48 @@
5073
5213
  setUserClass(userClass) {
5074
5214
  this.userClass = userClass;
5075
5215
  }
5216
+ setAgones(agones, options2 = {}) {
5217
+ this.agonesSDK = agones;
5218
+ this.agonesOptions = options2;
5219
+ }
5076
5220
  /**
5077
5221
  * Define transportation. You can set socket.io as default
5078
5222
  *
5079
5223
  * @method transport()
5080
5224
  * @param {object} io
5081
- * @returns {void}
5225
+ * @returns {Transport}
5082
5226
  */
5083
- transport(io) {
5084
- const transport = new Transport(io);
5227
+ transport(io, options2 = {}) {
5228
+ if (options2.timeoutDisconnect) {
5229
+ this.timeoutDisconnect = options2.timeoutDisconnect;
5230
+ }
5231
+ const transport = new Transport(io, options2);
5085
5232
  transport.onConnected(this.connectUser.bind(this));
5086
5233
  transport.onDisconnected(this.disconnectUser.bind(this));
5087
5234
  transport.onJoin(this.joinRoom.bind(this));
5088
5235
  transport.onInput((id, prop, value) => {
5089
5236
  this.forEachUserRooms(id, (room, user) => {
5090
- if (room.$inputs && room.$inputs[prop]) {
5091
- room[prop] = value;
5237
+ try {
5238
+ if (room.$inputs && room.$inputs[prop]) {
5239
+ room[prop] = value;
5240
+ }
5241
+ } catch (err) {
5242
+ Transmitter.error(user, err);
5092
5243
  }
5093
5244
  });
5094
5245
  });
5095
5246
  transport.onAction((id, name, value) => {
5096
5247
  this.forEachUserRooms(id, async (room, user) => {
5097
5248
  if (room.$actions && room.$actions[name]) {
5098
- room[name](user, value);
5249
+ try {
5250
+ room[name](user, value);
5251
+ } catch (err) {
5252
+ Transmitter.error(user, err);
5253
+ }
5099
5254
  }
5100
5255
  });
5101
5256
  });
5257
+ return this._transport = transport;
5102
5258
  }
5103
5259
  /**
5104
5260
  * Loop over all rooms of a user
@@ -5117,7 +5273,7 @@
5117
5273
  * @returns {void}
5118
5274
  */
5119
5275
  forEachUserRooms(userId, cb) {
5120
- const user = this.getUser(userId);
5276
+ const user = this.getUser(userId, true);
5121
5277
  if (!user)
5122
5278
  return;
5123
5279
  for (let roomId of user._rooms) {
@@ -5156,29 +5312,32 @@
5156
5312
  this.users[user.id] = user;
5157
5313
  return this.users[user.id];
5158
5314
  }
5315
+ get nbUsers() {
5316
+ return Object.keys(this.users).length;
5317
+ }
5159
5318
  /**
5160
5319
  * Send the packages to the rooms.
5161
5320
  *
5162
5321
  * @method send()
5163
5322
  */
5164
- send() {
5165
- this.rooms.forEach((room, id) => {
5323
+ async send() {
5324
+ for (let [_, room] of this.rooms) {
5166
5325
  const obj = room.$currentState();
5167
5326
  if (Object.keys(obj).length == 0) {
5168
5327
  return;
5169
5328
  }
5170
5329
  Transmitter.addPacket(room, obj);
5171
- for (let id2 in room.users) {
5172
- const user = room.users[id2];
5330
+ for (let id in room.users) {
5331
+ const user = room.users[id];
5173
5332
  const packets = Transmitter.getPackets(room);
5174
5333
  if (packets) {
5175
5334
  for (let packet of packets) {
5176
- Transmitter.emit(user, packet, room);
5335
+ await Transmitter.emit(user, packet, room);
5177
5336
  }
5178
5337
  }
5179
5338
  }
5180
5339
  room.$clearCurrentState();
5181
- });
5340
+ }
5182
5341
  Transmitter.clear();
5183
5342
  }
5184
5343
  /**
@@ -5187,10 +5346,23 @@
5187
5346
  * @method connectUser()
5188
5347
  * @param {object} socket
5189
5348
  * @param {id} userId
5349
+ * @param {object} options
5350
+ * - getUserInstance: function that returns a new instance of the user
5190
5351
  * @returns {User}
5191
5352
  */
5192
- connectUser(socket, id) {
5193
- const user = new this.userClass();
5353
+ connectUser(socket, id, options2 = {}) {
5354
+ var _a;
5355
+ const existingUser = this.getUser(id, false);
5356
+ if (existingUser) {
5357
+ if (existingUser._timeoutDisconnect) {
5358
+ clearTimeout(existingUser._timeoutDisconnect);
5359
+ delete existingUser._timeoutDisconnect;
5360
+ }
5361
+ existingUser._socket = socket;
5362
+ existingUser.$state = UserState.Connected;
5363
+ return existingUser;
5364
+ }
5365
+ const user = ((_a = options2.getUserInstance) == null ? void 0 : _a.call(options2, socket)) ?? new this.userClass();
5194
5366
  user.id = id;
5195
5367
  socket.emit("uid", id);
5196
5368
  this.setUser(user, socket);
@@ -5204,18 +5376,52 @@
5204
5376
  * @returns {void}
5205
5377
  */
5206
5378
  disconnectUser(userId) {
5207
- this.forEachUserRooms(userId, (room, user) => {
5208
- if (room.$leave)
5209
- room.$leave(user);
5379
+ return new Promise((resolve2, reject) => {
5380
+ const user = this.getUser(userId);
5381
+ if (!user)
5382
+ return resolve2();
5383
+ user.$state = UserState.Disconnected;
5384
+ const leave = () => {
5385
+ const leaveAllPromises = [];
5386
+ this.forEachUserRooms(userId, async (room, user2) => {
5387
+ if (room.$leave)
5388
+ leaveAllPromises.push(room.$leave(user2));
5389
+ });
5390
+ delete this.users[userId];
5391
+ Promise.all(leaveAllPromises).then(resolve2).catch((err) => {
5392
+ Transmitter.error(user, err);
5393
+ reject(err);
5394
+ });
5395
+ };
5396
+ if (!this.timeoutDisconnect) {
5397
+ leave();
5398
+ return;
5399
+ }
5400
+ user._timeoutDisconnect = setTimeout(leave, this.timeoutDisconnect);
5401
+ });
5402
+ }
5403
+ httpUpgrade(httpServer, io) {
5404
+ httpServer.removeAllListeners("upgrade");
5405
+ httpServer.on("upgrade", (req, socket, head) => {
5406
+ if (req.url.startsWith("/socket.io/")) {
5407
+ io.engine.handleUpgrade(req, socket, head);
5408
+ } else {
5409
+ socket.destroy();
5410
+ }
5210
5411
  });
5211
- delete this.users[userId];
5212
5412
  }
5213
- joinOrLeaveRoom(type, roomId, userId) {
5413
+ async joinOrLeaveRoom(type, roomId, userId) {
5214
5414
  const room = this.getRoom(roomId);
5215
5415
  if (!room)
5216
5416
  return;
5217
- if (room[type])
5218
- room[type](this.getUser(userId, false));
5417
+ if (room[type]) {
5418
+ try {
5419
+ await room[type](this.getUser(userId, false));
5420
+ } catch (err) {
5421
+ Transmitter.error(this.getUser(userId, false), err);
5422
+ throw err;
5423
+ }
5424
+ }
5219
5425
  return room;
5220
5426
  }
5221
5427
  /**
@@ -5225,7 +5431,7 @@
5225
5431
  * @param {string} userId
5226
5432
  * @returns {RoomClass | undefined}
5227
5433
  */
5228
- leaveRoom(roomId, userId) {
5434
+ async leaveRoom(roomId, userId) {
5229
5435
  return this.joinOrLeaveRoom("$leave", roomId, userId);
5230
5436
  }
5231
5437
  /**
@@ -5235,7 +5441,7 @@
5235
5441
  * @param {string} userId
5236
5442
  * @returns {RoomClass | undefined}
5237
5443
  */
5238
- joinRoom(roomId, userId) {
5444
+ async joinRoom(roomId, userId) {
5239
5445
  return this.joinOrLeaveRoom("$join", roomId, userId);
5240
5446
  }
5241
5447
  /**
@@ -5265,12 +5471,15 @@
5265
5471
  * @param {Class or instance of Class} roomClass
5266
5472
  * @returns instance of Class
5267
5473
  */
5268
- addRoom(id, roomClass) {
5474
+ addRoom(id, roomClass, options2 = {}) {
5269
5475
  if (roomClass.constructor.name == "Function") {
5270
5476
  roomClass = new roomClass();
5271
5477
  }
5272
- const room = new Room().add(id, roomClass);
5478
+ const room = new Room(options2).add(id, roomClass);
5273
5479
  this.rooms.set(id, room);
5480
+ if (this.agonesSDK) {
5481
+ this.agonesSDK.setLabel("room.id", id);
5482
+ }
5274
5483
  return room;
5275
5484
  }
5276
5485
  /**
@@ -5304,11 +5513,132 @@
5304
5513
  * Remove all rooms and users
5305
5514
  */
5306
5515
  clear() {
5516
+ var _a, _b;
5307
5517
  this.rooms.clear();
5518
+ this.changes.next({});
5308
5519
  this.users = {};
5520
+ if (this._transport) {
5521
+ (_b = (_a = this._transport.io) == null ? void 0 : _a.clear) == null ? void 0 : _b.call(_a);
5522
+ }
5309
5523
  }
5310
5524
  }
5311
5525
  const World = new WorldClass();
5526
+ class MiddlewareHandler {
5527
+ constructor() {
5528
+ this.middlewares = [];
5529
+ }
5530
+ use(middleware) {
5531
+ this.middlewares.push(middleware);
5532
+ }
5533
+ run(socket, finalCallback = (err) => {
5534
+ }) {
5535
+ let index2 = 0;
5536
+ const next = (err) => {
5537
+ if (err) {
5538
+ finalCallback(err);
5539
+ return;
5540
+ }
5541
+ if (index2 >= this.middlewares.length) {
5542
+ finalCallback();
5543
+ return;
5544
+ }
5545
+ const middleware = this.middlewares[index2];
5546
+ index2 += 1;
5547
+ middleware(socket, next);
5548
+ };
5549
+ next();
5550
+ }
5551
+ clear() {
5552
+ this.middlewares = [];
5553
+ }
5554
+ }
5555
+ class MockIo {
5556
+ constructor() {
5557
+ this.events = /* @__PURE__ */ new Map();
5558
+ this.eventsOnce = /* @__PURE__ */ new Map();
5559
+ }
5560
+ on(name, value) {
5561
+ this.events.set(name, [...this.events.get(name) || [], value]);
5562
+ }
5563
+ off(name) {
5564
+ if (this.eventsOnce.has(name)) {
5565
+ this.eventsOnce.delete(name);
5566
+ return;
5567
+ }
5568
+ this.events.delete(name);
5569
+ }
5570
+ once(name, value) {
5571
+ this.eventsOnce.set(name, value);
5572
+ }
5573
+ _trigger(name, data, client) {
5574
+ const events = this.events.get(name) || [];
5575
+ for (const event of events) {
5576
+ event(data, client);
5577
+ }
5578
+ const eventOnce = this.eventsOnce.get(name);
5579
+ if (eventOnce) {
5580
+ eventOnce(data, client);
5581
+ this.eventsOnce.delete(name);
5582
+ }
5583
+ }
5584
+ }
5585
+ class MockSocket extends MockIo {
5586
+ constructor(handshake, client) {
5587
+ super();
5588
+ this.handshake = handshake;
5589
+ this.client = client;
5590
+ this.middlewares = new MiddlewareHandler();
5591
+ this.id = client.fakeId ?? "" + Math.random();
5592
+ this.client.id = this.id;
5593
+ }
5594
+ emit(name, data) {
5595
+ this.client._trigger(name, data);
5596
+ }
5597
+ removeAllListeners(name) {
5598
+ return this.off(name);
5599
+ }
5600
+ use(cb) {
5601
+ this.middlewares.use(cb);
5602
+ }
5603
+ disconnect() {
5604
+ }
5605
+ }
5606
+ class MockServerIo extends MockIo {
5607
+ constructor() {
5608
+ super(...arguments);
5609
+ this.clients = /* @__PURE__ */ new Map();
5610
+ this.middlewares = new MiddlewareHandler();
5611
+ }
5612
+ connection(client, handshake) {
5613
+ return new Promise((resolve2, reject) => {
5614
+ const socket = new MockSocket(handshake, client);
5615
+ this.clients.set(socket.id, socket);
5616
+ client.id = socket.id;
5617
+ this.middlewares.run(socket, (err) => {
5618
+ if (err) {
5619
+ client._trigger("error", err);
5620
+ return;
5621
+ }
5622
+ this._trigger("connection", socket);
5623
+ resolve2(socket);
5624
+ });
5625
+ });
5626
+ }
5627
+ emit(name, data, id) {
5628
+ var _a;
5629
+ (_a = this.clients.get(id)) == null ? void 0 : _a._trigger(name, data);
5630
+ }
5631
+ use(cb) {
5632
+ this.middlewares.use(cb);
5633
+ }
5634
+ clear() {
5635
+ this.events.clear();
5636
+ this.eventsOnce.clear();
5637
+ this.clients.clear();
5638
+ this.middlewares.clear();
5639
+ }
5640
+ }
5641
+ new MockServerIo();
5312
5642
  var TiledLayerType;
5313
5643
  (function(TiledLayerType2) {
5314
5644
  TiledLayerType2["Tile"] = "tilelayer";
@@ -12447,7 +12777,7 @@
12447
12777
  return func(value);
12448
12778
  };
12449
12779
  }
12450
- function getValue2(object, key) {
12780
+ function getValue(object, key) {
12451
12781
  return object == null ? void 0 : object[key];
12452
12782
  }
12453
12783
  function overArg(func, transform) {
@@ -12886,7 +13216,7 @@
12886
13216
  return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
12887
13217
  }
12888
13218
  function getNative(object, key) {
12889
- var value = getValue2(object, key);
13219
+ var value = getValue(object, key);
12890
13220
  return baseIsNative(value) ? value : void 0;
12891
13221
  }
12892
13222
  function getRawTag(value) {
@@ -17594,7 +17924,6 @@
17594
17924
  }
17595
17925
  // @internal
17596
17926
  removeObject(object, mode = "shared") {
17597
- var _a;
17598
17927
  const map = this.getCurrentMap();
17599
17928
  if (!map)
17600
17929
  return;
@@ -17613,7 +17942,7 @@
17613
17942
  if (object.id == playerId)
17614
17943
  continue;
17615
17944
  const otherPlayer = map.players[playerId];
17616
- if (((_a = otherPlayer.following) == null ? void 0 : _a.id) == object.id) {
17945
+ if (otherPlayer.followingId == object.id) {
17617
17946
  otherPlayer.cameraFollow(otherPlayer);
17618
17947
  }
17619
17948
  }
@@ -17622,6 +17951,13 @@
17622
17951
  }
17623
17952
  }
17624
17953
  }
17954
+ let instanceContext = null;
17955
+ function inject(service, args = []) {
17956
+ return instanceContext.inject(service, args);
17957
+ }
17958
+ function setInject(context) {
17959
+ instanceContext = context;
17960
+ }
17625
17961
  const {
17626
17962
  isPromise,
17627
17963
  applyMixins,
@@ -17681,7 +18017,7 @@
17681
18017
  sp: Number,
17682
18018
  gold: Number,
17683
18019
  level: {
17684
- $effects: ["$this.expForNextlevel"]
18020
+ $effects: ["$this.expForNextlevel", "$this.param"]
17685
18021
  },
17686
18022
  expForNextlevel: {
17687
18023
  $permanent: false
@@ -17743,8 +18079,9 @@
17743
18079
  lines: []
17744
18080
  };
17745
18081
  const _RpgPlayer = class extends common.RpgCommonPlayer {
17746
- constructor(gameEngine, playerId) {
17747
- super(gameEngine, playerId);
18082
+ constructor(playerId) {
18083
+ super(inject(common.RpgCommonGame), playerId);
18084
+ this.playerId = playerId;
17748
18085
  this.type = "player";
17749
18086
  this.layout = {
17750
18087
  top: layoutObject,
@@ -17760,8 +18097,9 @@
17760
18097
  this.touchSide = false;
17761
18098
  this.tmpPositions = null;
17762
18099
  this.otherPossessedPlayer = null;
17763
- this.following = null;
18100
+ this.followingId = null;
17764
18101
  this._dataLoading = false;
18102
+ this.gameEngine = inject(common.RpgCommonGame);
17765
18103
  this.teleported = 0;
17766
18104
  this.deleted = false;
17767
18105
  this.initialize();
@@ -17776,6 +18114,7 @@
17776
18114
  }
17777
18115
  /** @internal */
17778
18116
  initialize() {
18117
+ this.server = inject(RpgServerEngine);
17779
18118
  this.expCurve = {
17780
18119
  basis: 30,
17781
18120
  extra: 20,
@@ -18128,7 +18467,7 @@
18128
18467
  toJSON() {
18129
18468
  const {
18130
18469
  permanentObject
18131
- } = Room.toDict(this.schema);
18470
+ } = Room.compileSchema(this.schema);
18132
18471
  const snapshot = Room.extractObjectOfRoom(this, permanentObject);
18133
18472
  snapshot.variables = [...this.variables];
18134
18473
  return snapshot;
@@ -18293,9 +18632,9 @@
18293
18632
  */
18294
18633
  cameraFollow(otherPlayer, options2 = {}) {
18295
18634
  if (otherPlayer.id == this.id) {
18296
- this.following = null;
18635
+ this.followingId = null;
18297
18636
  } else {
18298
- this.following = otherPlayer;
18637
+ this.followingId = otherPlayer.id;
18299
18638
  }
18300
18639
  this.emit(SocketEvents.CallMethod, {
18301
18640
  objectId: this.playerId,
@@ -18479,8 +18818,8 @@
18479
18818
  };
18480
18819
  applyMixins(RpgPlayer, [EventManager, ItemManager, GoldManager, StateManager, SkillManager, ParameterManager, EffectManager, ClassManager, ElementManager, GuiManager, VariableManager, MoveManager, BattleManager, ComponentManager]);
18481
18820
  class RpgEvent extends RpgPlayer {
18482
- constructor(gameEngine, playerId) {
18483
- super(gameEngine, playerId);
18821
+ constructor(playerId) {
18822
+ super(playerId);
18484
18823
  this.type = "event";
18485
18824
  this.properties = {};
18486
18825
  this.playerRelated = null;
@@ -18633,6 +18972,20 @@
18633
18972
  get nbPlayers() {
18634
18973
  return Object.keys(this.players).length;
18635
18974
  }
18975
+ $additionalEmitProperties(player) {
18976
+ const lastFramePositions = player["_lastFramePositions"];
18977
+ let pos;
18978
+ let lastFrame;
18979
+ if (lastFramePositions) {
18980
+ pos = lastFramePositions.position;
18981
+ lastFrame = lastFramePositions.frame;
18982
+ }
18983
+ const data = {
18984
+ frame: lastFrame,
18985
+ pos
18986
+ };
18987
+ return data;
18988
+ }
18636
18989
  async load() {
18637
18990
  var _a;
18638
18991
  if (common.RpgCommonMap.buffer.has(this.id)) {
@@ -18917,7 +19270,6 @@
18917
19270
  const ev = this.game.addEvent(event);
18918
19271
  const _shape = shape || this.getEventShape(ev.name);
18919
19272
  ev.map = this.id;
18920
- ev.server = this._server;
18921
19273
  ev.width = event.width || this.tileWidth;
18922
19274
  ev.height = event.height || this.tileHeight;
18923
19275
  if (_shape && _shape.properties)
@@ -19019,11 +19371,11 @@
19019
19371
  return result;
19020
19372
  };
19021
19373
  class SceneMap {
19022
- constructor(sceneMapObject, server) {
19023
- this.server = server;
19374
+ constructor(sceneMapObject) {
19024
19375
  this.maps = [];
19025
19376
  this.mapsById = {};
19026
19377
  this.worldMaps = /* @__PURE__ */ new Map();
19378
+ this.server = inject(RpgServerEngine);
19027
19379
  const {
19028
19380
  maps,
19029
19381
  worldMaps,
@@ -19230,7 +19582,9 @@
19230
19582
  await player.teleport(positions || "start");
19231
19583
  return null;
19232
19584
  }
19233
- player.emit("preLoadScene", mapId);
19585
+ player.emit("preLoadScene", {
19586
+ id: mapId
19587
+ });
19234
19588
  player.prevMap = player.map;
19235
19589
  if (player.prevMap) {
19236
19590
  await player.execMethod("onLeaveMap", [player.getCurrentMap()]);
@@ -19441,16 +19795,7 @@
19441
19795
  return result;
19442
19796
  };
19443
19797
  class RpgServerEngine {
19444
- /**
19445
- * Combat formulas
19446
- *
19447
- * @prop {Socket Io Server} [io]
19448
- * @memberof RpgServerEngine
19449
- */
19450
- constructor(io, gameEngine, inputOptions) {
19451
- this.io = io;
19452
- this.gameEngine = gameEngine;
19453
- this.inputOptions = inputOptions;
19798
+ constructor() {
19454
19799
  this.database = {};
19455
19800
  this.globalConfig = {};
19456
19801
  this.damageFormulas = {};
@@ -19458,8 +19803,20 @@
19458
19803
  this.scenes = /* @__PURE__ */ new Map();
19459
19804
  this.totalConnected = 0;
19460
19805
  this.scheduler = new common.Scheduler();
19806
+ this.gameEngine = inject(common.RpgCommonGame);
19461
19807
  this.world = World;
19462
19808
  this.envs = {};
19809
+ this.inputOptions = {};
19810
+ }
19811
+ /**
19812
+ * Combat formulas
19813
+ *
19814
+ * @prop {Socket Io Server} [io]
19815
+ * @memberof RpgServerEngine
19816
+ */
19817
+ initialize(io, inputOptions) {
19818
+ this.io = io;
19819
+ this.inputOptions = inputOptions;
19463
19820
  this.envs = inputOptions.envs || {};
19464
19821
  if (this.inputOptions.workers) {
19465
19822
  console.log("workers enabled");
@@ -19493,15 +19850,16 @@
19493
19850
  if (!this.inputOptions.database)
19494
19851
  this.inputOptions.database = {};
19495
19852
  const datas = await common.RpgPlugin.emit(common.HookServer.AddDatabase, this.inputOptions.database) || [];
19496
- for (let plug of datas) {
19497
- this.inputOptions.database = {
19498
- ...plug,
19499
- ...this.inputOptions.database
19500
- };
19501
- }
19502
- for (let key in this.inputOptions.database) {
19503
- const data = this.inputOptions.database[key];
19504
- this.addInDatabase(data.id, data);
19853
+ for (let element of datas) {
19854
+ if (Array.isArray(element)) {
19855
+ for (let data of element) {
19856
+ this.addInDatabase(data.id, data);
19857
+ }
19858
+ } else {
19859
+ for (let id in element) {
19860
+ this.addInDatabase(element[id].id ?? id, element[id]);
19861
+ }
19862
+ }
19505
19863
  }
19506
19864
  this.loadScenes();
19507
19865
  }
@@ -19632,9 +19990,27 @@
19632
19990
  return Query._getShapesOfMap(map);
19633
19991
  }
19634
19992
  });
19635
- this.io.on("connection", this.onPlayerConnected.bind(this));
19993
+ this.transport(this.io);
19636
19994
  await common.RpgPlugin.emit(common.HookServer.Start, this);
19637
19995
  }
19996
+ transport(io) {
19997
+ const timeoutDisconnect = this.globalConfig.timeoutDisconnect ?? 0;
19998
+ const auth = this.globalConfig.disableAuth ? () => common.Utils.generateUID() : async (socket) => {
19999
+ const val = await common.RpgPlugin.emit(common.HookServer.Auth, [this, socket], true);
20000
+ if (val.length == 0) {
20001
+ return common.Utils.generateUID();
20002
+ }
20003
+ return val[val.length - 1];
20004
+ };
20005
+ const transport = new Transport(io, {
20006
+ timeoutDisconnect,
20007
+ auth
20008
+ });
20009
+ this.world.timeoutDisconnect = timeoutDisconnect;
20010
+ transport.onConnected(this.onPlayerConnected.bind(this));
20011
+ transport.onDisconnected(this.onPlayerDisconnected.bind(this));
20012
+ return transport;
20013
+ }
19638
20014
  get tick() {
19639
20015
  return this.scheduler.tick;
19640
20016
  }
@@ -19647,7 +20023,7 @@
19647
20023
  * @memberof RpgServerEngine
19648
20024
  */
19649
20025
  send() {
19650
- this.world.send();
20026
+ return this.world.send();
19651
20027
  }
19652
20028
  async updatePlayersMove(deltaTimeInt) {
19653
20029
  const players = this.world.getUsers();
@@ -19711,7 +20087,7 @@
19711
20087
  maps: this.inputOptions.maps,
19712
20088
  events: this.inputOptions.events,
19713
20089
  worldMaps: this.inputOptions.worldMaps
19714
- }, this));
20090
+ }));
19715
20091
  }
19716
20092
  getScene(name) {
19717
20093
  return this.scenes.get(name);
@@ -19735,13 +20111,52 @@
19735
20111
  sendToPlayer(currentPlayer, eventName, data) {
19736
20112
  currentPlayer._socket.emit(eventName, data);
19737
20113
  }
19738
- onPlayerConnected(socket) {
19739
- const {
19740
- token
19741
- } = socket.handshake.auth;
19742
- const playerId = common.Utils.generateUID();
19743
- const player = new RpgPlayer(this.gameEngine, playerId);
19744
- player.session = token;
20114
+ getPlayerBySession(session) {
20115
+ const users = this.world.getUsers();
20116
+ for (let userId in users) {
20117
+ const user = users[userId];
20118
+ if (user.session === session) {
20119
+ return user;
20120
+ }
20121
+ }
20122
+ return null;
20123
+ }
20124
+ onPlayerConnected(socket, playerId) {
20125
+ const existingUser = this.world.getUser(playerId, false);
20126
+ this.world.connectUser(socket, playerId);
20127
+ let player;
20128
+ if (!existingUser) {
20129
+ const {
20130
+ token
20131
+ } = socket.handshake.auth;
20132
+ player = new RpgPlayer(playerId);
20133
+ player.session = token;
20134
+ this.world.setUser(player, socket);
20135
+ player._init();
20136
+ if (!token) {
20137
+ const newToken = common.Utils.generateUID() + "-" + common.Utils.generateUID() + "-" + common.Utils.generateUID();
20138
+ player.session = newToken;
20139
+ }
20140
+ if (!token) {
20141
+ player.execMethod("onConnected");
20142
+ } else {
20143
+ common.RpgPlugin.emit(common.HookServer.ScalabilityPlayerConnected, player);
20144
+ }
20145
+ } else {
20146
+ player = existingUser;
20147
+ if (player.map) {
20148
+ player.emit("preLoadScene", {
20149
+ reconnect: true,
20150
+ id: player.map
20151
+ });
20152
+ player.emitSceneMap();
20153
+ this.world.joinRoom(player.map, playerId);
20154
+ }
20155
+ }
20156
+ socket.emit("playerJoined", {
20157
+ playerId,
20158
+ session: player.session
20159
+ });
19745
20160
  socket.on("move", (data) => {
19746
20161
  if (!(data == null ? void 0 : data.input))
19747
20162
  return;
@@ -19758,25 +20173,6 @@
19758
20173
  });
19759
20174
  }
19760
20175
  });
19761
- socket.on("disconnect", () => {
19762
- this.onPlayerDisconnected(playerId);
19763
- });
19764
- this.world.setUser(player, socket);
19765
- player.server = this;
19766
- player._init();
19767
- if (!token) {
19768
- const newToken = common.Utils.generateUID() + "-" + common.Utils.generateUID() + "-" + common.Utils.generateUID();
19769
- player.session = newToken;
19770
- }
19771
- socket.emit("playerJoined", {
19772
- playerId,
19773
- session: player.session
19774
- });
19775
- if (!token) {
19776
- player.execMethod("onConnected");
19777
- } else {
19778
- common.RpgPlugin.emit(common.HookServer.ScalabilityPlayerConnected, player);
19779
- }
19780
20176
  }
19781
20177
  onPlayerDisconnected(playerId) {
19782
20178
  const player = World.getUser(playerId);
@@ -21787,7 +22183,7 @@
21787
22183
  this.callback = options2.callback;
21788
22184
  }
21789
22185
  async getServer(player) {
21790
- const currentServerId = player.server.serverId;
22186
+ const currentServerId = inject(RpgServerEngine).serverId;
21791
22187
  const payload = {
21792
22188
  playerId: player.id,
21793
22189
  mapName: player.map
@@ -21816,7 +22212,9 @@
21816
22212
  }
21817
22213
  }
21818
22214
  async function entryPoint(modules, options2) {
21819
- const gameEngine = new common.RpgCommonGame(common.GameSide.Server);
22215
+ const context = new common.InjectContext();
22216
+ setInject(context);
22217
+ inject(common.RpgCommonGame, [common.GameSide.Server]);
21820
22218
  if (!options2.globalConfig)
21821
22219
  options2.globalConfig = {};
21822
22220
  const relations = {
@@ -21834,7 +22232,8 @@
21834
22232
  };
21835
22233
  const relationsEngine = {
21836
22234
  onStart: common.HookServer.Start,
21837
- onStep: common.HookServer.Step
22235
+ onStep: common.HookServer.Step,
22236
+ auth: common.HookServer.Auth
21838
22237
  };
21839
22238
  const {
21840
22239
  playerProps
@@ -21872,7 +22271,7 @@
21872
22271
  }
21873
22272
  return mod;
21874
22273
  });
21875
- const serverEngine = new RpgServerEngine(options2.io, gameEngine, {
22274
+ const serverEngine = inject(RpgServerEngine, [options2.io, {
21876
22275
  debug: {},
21877
22276
  updateRate: 10,
21878
22277
  stepRate: 60,
@@ -21880,7 +22279,7 @@
21880
22279
  countConnections: false,
21881
22280
  playerProps,
21882
22281
  ...options2
21883
- });
22282
+ }]);
21884
22283
  return serverEngine;
21885
22284
  }
21886
22285
  function EventData(options2) {
@@ -21996,5 +22395,6 @@
21996
22395
  exports2.RpgWorldMaps = RpgWorldMaps;
21997
22396
  exports2.Speed = Speed;
21998
22397
  exports2.entryPoint = entryPoint;
22398
+ exports2.inject = inject;
21999
22399
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
22000
22400
  });