@bikky/replication 1.0.1

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.
Files changed (140) hide show
  1. package/Constants/Errors.d.ts +27 -0
  2. package/Constants/Errors.js +75 -0
  3. package/Constants/Logging.d.ts +17 -0
  4. package/Constants/Logging.js +97 -0
  5. package/Constants/ReplicableRegistry.d.ts +37 -0
  6. package/Constants/ReplicableRegistry.js +234 -0
  7. package/Constants/SerialisationTypes.d.ts +82 -0
  8. package/Constants/SerialisationTypes.js +160 -0
  9. package/Constants/SourceMaps.d.ts +10 -0
  10. package/Constants/SourceMaps.js +12 -0
  11. package/Constants/TraversalStep.d.ts +5 -0
  12. package/Constants/TraversalStep.js +2 -0
  13. package/Constants/Versions.d.ts +15 -0
  14. package/Constants/Versions.js +63 -0
  15. package/Expressions/Compiler/BuiltinGrammar.d.ts +234 -0
  16. package/Expressions/Compiler/BuiltinGrammar.js +446 -0
  17. package/Expressions/Compiler/ExpressionGrammar.d.ts +89 -0
  18. package/Expressions/Compiler/ExpressionGrammar.js +70 -0
  19. package/Expressions/Compiler/Parser.d.ts +56 -0
  20. package/Expressions/Compiler/Parser.js +314 -0
  21. package/Expressions/Compiler/Tokenizer.d.ts +52 -0
  22. package/Expressions/Compiler/Tokenizer.js +222 -0
  23. package/Expressions/Compiler/__tests__/Replicable.Expressions.Parser.test.d.ts +1 -0
  24. package/Expressions/Compiler/__tests__/Replicable.Expressions.Parser.test.js +516 -0
  25. package/Expressions/Compiler/__tests__/Replicable.Expressions.Tokenizer.test.d.ts +1 -0
  26. package/Expressions/Compiler/__tests__/Replicable.Expressions.Tokenizer.test.js +68 -0
  27. package/Expressions/CreateEvaluator.d.ts +4 -0
  28. package/Expressions/CreateEvaluator.js +85 -0
  29. package/Expressions/EvaluatorChain.d.ts +19 -0
  30. package/Expressions/EvaluatorChain.js +137 -0
  31. package/Expressions/EvaluatorSteps.d.ts +19 -0
  32. package/Expressions/EvaluatorSteps.js +12 -0
  33. package/Expressions/EvaluatorString.d.ts +21 -0
  34. package/Expressions/EvaluatorString.js +26 -0
  35. package/Expressions/Expression.d.ts +36 -0
  36. package/Expressions/Expression.js +147 -0
  37. package/Expressions/Traverser.d.ts +28 -0
  38. package/Expressions/Traverser.js +348 -0
  39. package/Expressions/TypeRegistry/Accessors.d.ts +26 -0
  40. package/Expressions/TypeRegistry/Accessors.js +58 -0
  41. package/Expressions/TypeRegistry/ChainCollections.d.ts +51 -0
  42. package/Expressions/TypeRegistry/ChainCollections.js +134 -0
  43. package/Expressions/TypeRegistry/ChainTypes.d.ts +23 -0
  44. package/Expressions/TypeRegistry/ChainTypes.js +46 -0
  45. package/Expressions/TypeRegistry/CustomAPI.d.ts +36 -0
  46. package/Expressions/TypeRegistry/CustomAPI.js +181 -0
  47. package/Expressions/TypeRegistry/Primitive.d.ts +19 -0
  48. package/Expressions/TypeRegistry/Primitive.js +47 -0
  49. package/Expressions/TypeRegistry/Registry.d.ts +27 -0
  50. package/Expressions/TypeRegistry/Registry.js +270 -0
  51. package/Expressions/TypeRegistry/ReplAPI.d.ts +41 -0
  52. package/Expressions/TypeRegistry/ReplAPI.js +220 -0
  53. package/Expressions/TypeRegistry/Scope.d.ts +24 -0
  54. package/Expressions/TypeRegistry/Scope.js +44 -0
  55. package/Expressions/TypeRegistry/Types.d.ts +23 -0
  56. package/Expressions/TypeRegistry/Types.js +1 -0
  57. package/Expressions/TypeRegistry/__tests__/Replicable.Expressions.Accessors.test.d.ts +1 -0
  58. package/Expressions/TypeRegistry/__tests__/Replicable.Expressions.Accessors.test.js +31 -0
  59. package/Expressions/__tests__/ExpressionExamples.d.ts +28 -0
  60. package/Expressions/__tests__/ExpressionExamples.js +50 -0
  61. package/Expressions/__tests__/Replicable.Expressions.Expressions.test.d.ts +1 -0
  62. package/Expressions/__tests__/Replicable.Expressions.Expressions.test.js +166 -0
  63. package/IDPool.d.ts +18 -0
  64. package/IDPool.data.d.ts +17 -0
  65. package/IDPool.js +139 -0
  66. package/License.txt +1 -0
  67. package/Main.d.ts +13 -0
  68. package/Main.js +13 -0
  69. package/Networking.d.ts +60 -0
  70. package/Networking.js +626 -0
  71. package/Replicatable.d.ts +66 -0
  72. package/Replicatable.js +123 -0
  73. package/Tracking/Buffable.d.ts +68 -0
  74. package/Tracking/Buffable.js +194 -0
  75. package/Tracking/Class.d.ts +97 -0
  76. package/Tracking/Class.js +221 -0
  77. package/Tracking/Functions.d.ts +14 -0
  78. package/Tracking/Functions.js +27 -0
  79. package/Tracking/GlobalGroup.d.ts +5 -0
  80. package/Tracking/GlobalGroup.js +39 -0
  81. package/Tracking/Property.d.ts +95 -0
  82. package/Tracking/Property.js +125 -0
  83. package/Tracking/Types.d.ts +33 -0
  84. package/Tracking/Types.js +1 -0
  85. package/Tracking/__tests__/Replicable.Tracking.Decorator.test.d.ts +1 -0
  86. package/Tracking/__tests__/Replicable.Tracking.Decorator.test.js +151 -0
  87. package/Tracking/__tests__/Replicable.Tracking.Deserialisation.test.d.ts +1 -0
  88. package/Tracking/__tests__/Replicable.Tracking.Deserialisation.test.js +253 -0
  89. package/Tracking/__tests__/Replicable.Tracking.MixinSchemaGeneration.test.d.ts +1 -0
  90. package/Tracking/__tests__/Replicable.Tracking.MixinSchemaGeneration.test.js +135 -0
  91. package/Tracking/__tests__/Replicable.Tracking.Struct.test.d.ts +1 -0
  92. package/Tracking/__tests__/Replicable.Tracking.Struct.test.js +66 -0
  93. package/Tracking/__tests__/Replicable.Tracking.Type.test.d.ts +1 -0
  94. package/Tracking/__tests__/Replicable.Tracking.Type.test.js +67 -0
  95. package/Transformers/Configurer.d.ts +39 -0
  96. package/Transformers/Configurer.js +415 -0
  97. package/Transformers/Constructor.d.ts +12 -0
  98. package/Transformers/Constructor.js +44 -0
  99. package/Transformers/Definitions.d.ts +102 -0
  100. package/Transformers/Definitions.js +626 -0
  101. package/Transformers/Loader.d.ts +45 -0
  102. package/Transformers/Loader.js +350 -0
  103. package/Transformers/Progress.d.ts +32 -0
  104. package/Transformers/Progress.js +429 -0
  105. package/Transformers/Reference.d.ts +37 -0
  106. package/Transformers/Reference.js +212 -0
  107. package/Transformers/SchemaGenerator.d.ts +102 -0
  108. package/Transformers/SchemaGenerator.js +564 -0
  109. package/Transformers/Serialiser.d.ts +31 -0
  110. package/Transformers/Serialiser.js +366 -0
  111. package/Transformers/Utils.d.ts +33 -0
  112. package/Transformers/Utils.js +287 -0
  113. package/Transformers/__tests__/Examples.d.ts +168 -0
  114. package/Transformers/__tests__/Examples.js +263 -0
  115. package/Transformers/__tests__/Replicable.Transformers.Definitions.test.d.ts +1 -0
  116. package/Transformers/__tests__/Replicable.Transformers.Definitions.test.js +457 -0
  117. package/Transformers/__tests__/Replicable.Transformers.Loader.test.d.ts +1 -0
  118. package/Transformers/__tests__/Replicable.Transformers.Loader.test.js +339 -0
  119. package/Transformers/__tests__/Replicable.Transformers.Progress.test.d.ts +1 -0
  120. package/Transformers/__tests__/Replicable.Transformers.Progress.test.js +256 -0
  121. package/Transformers/__tests__/Replicable.Transformers.Reference.test.d.ts +1 -0
  122. package/Transformers/__tests__/Replicable.Transformers.Reference.test.js +167 -0
  123. package/Transformers/__tests__/Replicable.Transformers.SchemaGenerator.test.d.ts +1 -0
  124. package/Transformers/__tests__/Replicable.Transformers.SchemaGenerator.test.js +400 -0
  125. package/Transformers/__tests__/Replicable.Transformers.SchemaGeneratorOutput.test.d.ts +1 -0
  126. package/Transformers/__tests__/Replicable.Transformers.SchemaGeneratorOutput.test.js +441 -0
  127. package/Transformers/__tests__/Replicable.Transformers.Serialiser.test.d.ts +1 -0
  128. package/Transformers/__tests__/Replicable.Transformers.Serialiser.test.js +320 -0
  129. package/Transformers/__tests__/Replicable.Transformers.Utils.test.d.ts +1 -0
  130. package/Transformers/__tests__/Replicable.Transformers.Utils.test.js +534 -0
  131. package/__tests__/Replicable.Expressions.test.d.ts +1 -0
  132. package/__tests__/Replicable.Expressions.test.js +166 -0
  133. package/__tests__/Replicable.IDPool.test.d.ts +1 -0
  134. package/__tests__/Replicable.IDPool.test.js +11 -0
  135. package/__tests__/Replicable.ReplicableRegistry.test.d.ts +1 -0
  136. package/__tests__/Replicable.ReplicableRegistry.test.js +154 -0
  137. package/__tests__/Replicable.Serialisation.test.d.ts +1 -0
  138. package/__tests__/Replicable.Serialisation.test.js +283 -0
  139. package/package.json +14 -0
  140. package/tsconfig.json +19 -0
package/Networking.js ADDED
@@ -0,0 +1,626 @@
1
+ import { SmartArray } from "@bikky/smart-collections";
2
+ import { Replicable } from "./Replicatable.js";
3
+ var InstanceByProxy = new Map();
4
+ var LocalTime;
5
+ let lastUpdate = Date.now();
6
+ var Connections;
7
+ (function (Connections) {
8
+ Connections.RemotesByID = new Map();
9
+ Connections.Remotes = new SmartArray();
10
+ Connections.Interfaces = new Map();
11
+ Connections.disconnectHandlers = new Map();
12
+ /**
13
+ * There's one RemoteConnection per remote PC. All instances reference the RemoteConnection.
14
+ * The RemoteConnection handles batching as well as keeping track of the ping of clients and
15
+ * how far behind they are.
16
+ */
17
+ class RemoteConnection {
18
+ constructor(id, connection) {
19
+ this.ping = -1;
20
+ this.pingHistory = [];
21
+ this.time = -1;
22
+ this.messages = [];
23
+ this.id = id;
24
+ this.socket = connection;
25
+ if ("on" in this.socket) {
26
+ this.socket.on("message", (body) => {
27
+ var data = JSON.parse(body);
28
+ this.recieveMessages(data, id);
29
+ });
30
+ this.socket.on("close", (code, reason) => {
31
+ this.handleDisconnect();
32
+ });
33
+ }
34
+ else {
35
+ this.socket.onmessage = (event) => {
36
+ var body = event.data;
37
+ var data = JSON.parse(body);
38
+ this.recieveMessages(data, id);
39
+ };
40
+ this.socket.onclose = (event) => {
41
+ this.handleDisconnect();
42
+ };
43
+ }
44
+ Connections.disconnectHandlers.set(id, []);
45
+ Connections.RemotesByID.set(id, this);
46
+ Connections.Remotes.push(this);
47
+ }
48
+ handleDisconnect() {
49
+ for (var handler of Connections.disconnectHandlers.get(this.id)) {
50
+ handler();
51
+ }
52
+ Connections.RemotesByID.delete(this.id);
53
+ Connections.Remotes.remove(this);
54
+ for (var remoteInterface of Connections.Interfaces.values()) {
55
+ remoteInterface.removeConnection(this.id, this);
56
+ }
57
+ Connections.disconnectHandlers.delete(this.id);
58
+ }
59
+ recieveMessages(data, remoteID) {
60
+ this.ping = data.time - this.time;
61
+ this.pingHistory.unshift(this.ping);
62
+ if (this.pingHistory.length > 5) {
63
+ this.pingHistory.pop();
64
+ }
65
+ this.time = data.time;
66
+ if (!Messenger.isServer) {
67
+ //TODO: Add ping to this calculation, but ping should be calculated based on the messages' clientTime not serverTime.
68
+ LocalTime = data.time; // + this.ping / 2;
69
+ lastUpdate = Date.now();
70
+ }
71
+ for (var message of data.messages) {
72
+ var target = Connections.Interfaces.get(message.id);
73
+ if (target) {
74
+ target.recieveMessage(message, remoteID);
75
+ }
76
+ else {
77
+ console.error("Remote tried to send a message to", message.id, "but no interface by that id exists");
78
+ }
79
+ }
80
+ }
81
+ queueMessage(obj) {
82
+ this.messages.push(obj);
83
+ }
84
+ sendMessages() {
85
+ try {
86
+ this.socket.send(JSON.stringify({
87
+ time: LocalTime,
88
+ messages: this.messages
89
+ }));
90
+ this.messages = [];
91
+ }
92
+ catch (e) {
93
+ console.log("------------------------------------------------");
94
+ console.log(e);
95
+ console.log("Failed to send message batch");
96
+ console.log("------------------------------------------------");
97
+ }
98
+ }
99
+ }
100
+ Connections.RemoteConnection = RemoteConnection;
101
+ //This has the traps for the proxy to send messages over the network.
102
+ class RemoteInstance {
103
+ constructor(remoteID, connection, remoteInterface) {
104
+ this.propertyMap = new Map();
105
+ this.remoteID = remoteID;
106
+ this.connection = connection;
107
+ this.interface = remoteInterface;
108
+ }
109
+ send(message) {
110
+ try {
111
+ this.connection.queueMessage(message);
112
+ }
113
+ catch (e) {
114
+ console.log("------------------------------------------------");
115
+ console.log(e);
116
+ console.log(message);
117
+ console.log("------------------------------------------------");
118
+ }
119
+ }
120
+ get(target, property) {
121
+ if (typeof property === "symbol") {
122
+ //this can be triggered by console logging a proxy so we should handle it nicely.
123
+ console.error("Can't invoke symbol on remote!");
124
+ return "This is a proxy";
125
+ }
126
+ var send = (property, ...args) => {
127
+ var key;
128
+ var promise = new Promise((resolve, reject) => {
129
+ key = this.interface.addCompletion(resolve);
130
+ });
131
+ var data = {
132
+ id: this.interface.objectID,
133
+ property: property,
134
+ args: args.map((e) => {
135
+ if (Replicable.CanReference(e)) {
136
+ return Replicable.Reference(e);
137
+ }
138
+ return ["Plain", e];
139
+ }),
140
+ key: key,
141
+ from: Connections.LocalID,
142
+ tick: LocalTime
143
+ };
144
+ this.send(data);
145
+ return promise;
146
+ };
147
+ if (typeof property === "string") {
148
+ var result = this.propertyMap.get(property);
149
+ if (result) {
150
+ return result;
151
+ }
152
+ //Proxy has to wrap a function to be callable.
153
+ var proxy = new Proxy(() => { }, new PropertyProxy([property], send));
154
+ this.propertyMap.set(property, proxy);
155
+ return proxy;
156
+ }
157
+ else {
158
+ return (...args) => send(property, ...args);
159
+ }
160
+ }
161
+ //A trap for setting property values.
162
+ set(target, property, value, receiver) {
163
+ throw new Error("Don't set properties on remote objects directly, use the set function!");
164
+ //return false;
165
+ }
166
+ //A trap for a direct function call (not a method).
167
+ apply(...args) {
168
+ var key;
169
+ var promise = new Promise((resolve, reject) => {
170
+ key = this.interface.addCompletion(resolve);
171
+ });
172
+ var data = {
173
+ id: this.interface.objectID,
174
+ function: true,
175
+ args: args.map((e) => {
176
+ if (Replicable.CanReference(e)) {
177
+ return Replicable.Reference(e);
178
+ }
179
+ return ["Plain", e];
180
+ }),
181
+ key: key,
182
+ from: Connections.LocalID,
183
+ tick: LocalTime
184
+ };
185
+ this.send(data);
186
+ return promise;
187
+ }
188
+ //A trap for the new operator.
189
+ construct(target, args, newTarget) {
190
+ throw new Error("Construct Trap Not Implemented");
191
+ //return {};
192
+ }
193
+ }
194
+ Connections.RemoteInstance = RemoteInstance;
195
+ //This class allows you to send messages to property's functions. E.g. remote.property.foo.
196
+ //It was coded at midnight and in a rush, so it's poorly typed and named.
197
+ class PropertyProxy {
198
+ constructor(propertyPath, send) {
199
+ this.propertyMap = new Map();
200
+ this.propertyPath = propertyPath;
201
+ this.parentSend = send;
202
+ }
203
+ //A trap for getting property values.
204
+ get(target, property) {
205
+ if (typeof property === "symbol") {
206
+ //this can be triggered by console logging a proxy so we should handle it nicely.
207
+ console.error("Can't invoke symbol on remote!");
208
+ return "This is a proxy";
209
+ }
210
+ else {
211
+ if (typeof property === "string") {
212
+ var result = this.propertyMap.get(property);
213
+ if (result) {
214
+ return result;
215
+ }
216
+ //Proxy has to wrap a function to be callable.
217
+ var proxy = new Proxy(() => { }, new PropertyProxy([...this.propertyPath, property], this.parentSend));
218
+ this.propertyMap.set(property, proxy);
219
+ return proxy;
220
+ }
221
+ else {
222
+ //property can be a number here, but I didn't want to update the typings everywhere.
223
+ return (...args) => {
224
+ return this.parentSend([...this.propertyPath, property], ...args);
225
+ };
226
+ }
227
+ }
228
+ }
229
+ //A trap for setting property values.
230
+ set(target, property, value, receiver) {
231
+ throw new Error("Don't set properties on remote objects directly, use the set function!");
232
+ //return false;
233
+ }
234
+ //A trap for a direct function call (not a method).
235
+ apply(target, thisArg, args) {
236
+ return this.parentSend(this.propertyPath, ...args);
237
+ }
238
+ }
239
+ //This can hold one remote for client stuff (the server) or many remotes for server stuff (one for each client)
240
+ // and the user won't know the difference.
241
+ class RemoteInterface {
242
+ constructor(objectID, local) {
243
+ this.remotes = new Map();
244
+ this.nextKey = 0;
245
+ this.completions = new Map();
246
+ //Allows users to access sub-properties via getters.
247
+ this.propertyMap = new Map();
248
+ this.objectID = objectID;
249
+ this.local = local;
250
+ Connections.Interfaces.set(this.objectID, this);
251
+ }
252
+ divertMessages(newLocal) {
253
+ if (!this.oldLocal) {
254
+ this.oldLocal = this.local;
255
+ }
256
+ this.local = newLocal;
257
+ }
258
+ restoreMessageRecipient() {
259
+ if (this.oldLocal) {
260
+ this.local = this.oldLocal;
261
+ delete this.oldLocal;
262
+ }
263
+ }
264
+ getNewKey() {
265
+ var key = this.nextKey;
266
+ this.nextKey++;
267
+ return key;
268
+ }
269
+ addCompletion(resolver) {
270
+ var key = this.getNewKey();
271
+ this.completions.set(key, resolver);
272
+ return key;
273
+ }
274
+ addConnection(remoteID, connection) {
275
+ var remoteInstance = new RemoteInstance(remoteID, connection, this);
276
+ remoteInstance.proxy = new Proxy({}, remoteInstance);
277
+ InstanceByProxy.set(remoteInstance.proxy, remoteInstance);
278
+ this.remotes.set(remoteID, remoteInstance);
279
+ }
280
+ removeConnection(remoteID, connection) {
281
+ var instance = this.remotes.get(remoteID);
282
+ this.remotes.delete(remoteID);
283
+ return instance;
284
+ }
285
+ recieveMessage(data, remoteID) {
286
+ var remote = this.remotes.get(remoteID);
287
+ if (!remote) {
288
+ return;
289
+ }
290
+ if ("completion" in data) {
291
+ var completion = this.completions.get(data.key);
292
+ if (completion) {
293
+ this.completions.delete(data.key);
294
+ completion(data.result);
295
+ return;
296
+ }
297
+ else {
298
+ //throw new Error("Got a message for a completion that's already been completed");
299
+ console.error("Got a message for a completion that's already been completed", data);
300
+ return;
301
+ }
302
+ }
303
+ if (data.property) {
304
+ var objectID = this.objectID;
305
+ function sendResponse(result) {
306
+ var response = {
307
+ id: objectID,
308
+ property: data.property,
309
+ completion: true, //the function has finished being called.
310
+ key: data.key,
311
+ result: result,
312
+ from: Connections.LocalID,
313
+ tick: LocalTime
314
+ };
315
+ remote.send(response);
316
+ }
317
+ let args = data.args.map((e) => {
318
+ if (Array.isArray(e) && e[0] === "Plain") {
319
+ return e[1];
320
+ }
321
+ if (Replicable.IsReference(e)) {
322
+ return Replicable.Dereference(e);
323
+ }
324
+ return e;
325
+ });
326
+ args.push({ connection: remote.proxy, id: data.from, tick: data.tick });
327
+ var target = this.local;
328
+ var prop = data.property;
329
+ if (Array.isArray(prop)) {
330
+ for (var i = 0; i < prop.length - 1; i++) {
331
+ target = target[prop[i]];
332
+ }
333
+ //Store the last one.
334
+ prop = prop[i];
335
+ }
336
+ var returned = target[prop].apply(target, args);
337
+ if (returned instanceof Promise) {
338
+ returned.then(sendResponse.bind(this));
339
+ }
340
+ else {
341
+ sendResponse.call(this, returned);
342
+ }
343
+ }
344
+ if (data.function) {
345
+ let args = data.args.map((e) => {
346
+ if (Array.isArray(e) && e[0] === "Plain") {
347
+ return e[1];
348
+ }
349
+ if (Replicable.IsReference(e)) {
350
+ return Replicable.Dereference(e);
351
+ }
352
+ return e;
353
+ });
354
+ args.push({ connection: remote.proxy, id: data.from, tick: data.tick });
355
+ this.local
356
+ .apply(this.local, args)
357
+ .then((result) => {
358
+ var response = {
359
+ id: this.objectID,
360
+ property: data.property,
361
+ completion: true, //the function has finished being called.
362
+ key: data.key,
363
+ result: result,
364
+ from: Connections.LocalID,
365
+ tick: LocalTime
366
+ };
367
+ remote.send(response);
368
+ });
369
+ }
370
+ }
371
+ //A trap for getting property values.
372
+ get(target, property) {
373
+ if (typeof property === "symbol") {
374
+ //this can be triggered by console logging a proxy so we should handle it nicely.
375
+ console.error("Can't invoke symbol on remote!");
376
+ return "This is a proxy";
377
+ }
378
+ else {
379
+ var send = (property, ...args) => {
380
+ if (Messenger.isServer) {
381
+ var promises = [];
382
+ for (var remote of this.remotes.values()) {
383
+ let remoteFunction = remote.get(target, property);
384
+ promises.push(remoteFunction.apply(remote, args));
385
+ }
386
+ //Don't return results from every client - as this is probably unintentional.
387
+ return new Promise((res, rej) => {
388
+ Promise.all(promises)
389
+ .then(() => res())
390
+ .catch(rej);
391
+ });
392
+ }
393
+ else {
394
+ for (var remote of this.remotes.values()) {
395
+ let remoteFunction = remote.get(target, property);
396
+ return remoteFunction.apply(remote, args);
397
+ }
398
+ }
399
+ };
400
+ if (typeof property === "string") {
401
+ var result = this.propertyMap.get(property);
402
+ if (result) {
403
+ return result;
404
+ }
405
+ //Proxy has to wrap a function to be callable.
406
+ var proxy = new Proxy(() => { }, new PropertyProxy([property], send));
407
+ this.propertyMap.set(property, proxy);
408
+ return proxy;
409
+ }
410
+ else {
411
+ return (...args) => send(property, ...args);
412
+ }
413
+ }
414
+ }
415
+ //A trap for setting property values.
416
+ set(target, property, value, receiver) {
417
+ throw new Error("Don't set properties on remote objects directly, use the set function!");
418
+ //return false;
419
+ }
420
+ //A trap for a direct function call (not a method).
421
+ apply(...args) {
422
+ return (...args) => {
423
+ if (Messenger.isServer) {
424
+ var promises = [];
425
+ for (var remote of this.remotes.values()) {
426
+ promises.push(remote.apply(remote, args));
427
+ }
428
+ //Don't return results from every client - as this is probably unintentional.
429
+ return new Promise((res, rej) => {
430
+ Promise.all(promises)
431
+ .then(() => res())
432
+ .catch(rej);
433
+ });
434
+ }
435
+ else {
436
+ for (var remote of this.remotes.values()) {
437
+ return remote.apply(remote, args);
438
+ }
439
+ }
440
+ };
441
+ }
442
+ //A trap for the new operator.
443
+ construct(target, args, newTarget) {
444
+ throw new Error("Construct Trap Not Implemented");
445
+ //return {};
446
+ }
447
+ }
448
+ Connections.RemoteInterface = RemoteInterface;
449
+ })(Connections || (Connections = {}));
450
+ export var Messenger;
451
+ (function (Messenger) {
452
+ var InterfaceByProxy = new Map();
453
+ Messenger.isConnected = false;
454
+ var resolveConnectPromise;
455
+ Messenger.connect = new Promise((resolve) => (resolveConnectPromise = resolve));
456
+ let serverID = null;
457
+ function initialise(localID, isTheServer, time) {
458
+ Connections.LocalID = localID;
459
+ Messenger.isServer = isTheServer;
460
+ Messenger.isConnected = Messenger.isServer;
461
+ if (Messenger.isServer) {
462
+ LocalTime = 0;
463
+ lastUpdate = Date.now();
464
+ serverID = localID;
465
+ resolveConnectPromise();
466
+ }
467
+ else {
468
+ if (typeof time === "undefined") {
469
+ throw new Error("Can't initialise client without server time");
470
+ }
471
+ LocalTime = time;
472
+ lastUpdate = Date.now();
473
+ }
474
+ }
475
+ Messenger.initialise = initialise;
476
+ //var lastMessage = 0;
477
+ function tick() {
478
+ let nextUpdate = Date.now();
479
+ LocalTime += nextUpdate - lastUpdate;
480
+ lastUpdate = nextUpdate;
481
+ }
482
+ Messenger.tick = tick;
483
+ function sendMessages() {
484
+ for (var conn of Connections.Remotes) {
485
+ conn.sendMessages();
486
+ }
487
+ }
488
+ Messenger.sendMessages = sendMessages;
489
+ function getLocalTime() {
490
+ return LocalTime;
491
+ }
492
+ Messenger.getLocalTime = getLocalTime;
493
+ function onDisconnect(id, handler) {
494
+ if (Connections.disconnectHandlers.has(id)) {
495
+ Connections.disconnectHandlers.get(id).push(handler);
496
+ return;
497
+ }
498
+ throw new Error("Can't add handler for connection that doesn't exist");
499
+ }
500
+ Messenger.onDisconnect = onDisconnect;
501
+ //Connection is any because it throws an error during compile on the server - WebSocket the type isn't defined on the server.
502
+ function addRemoteConnection(id, connection) {
503
+ var websocket = connection;
504
+ var remote = new Connections.RemoteConnection(id, websocket);
505
+ for (var remoteInterface of Connections.Interfaces.values()) {
506
+ remoteInterface.addConnection(id, remote);
507
+ }
508
+ if (!Messenger.isServer) {
509
+ serverID = id;
510
+ resolveConnectPromise();
511
+ }
512
+ }
513
+ Messenger.addRemoteConnection = addRemoteConnection;
514
+ //Local will usually be different to type even though they represent the same object/entity,
515
+ // because usually the server will have different functions to the client.
516
+ function newRemoteInterface(name, object) {
517
+ var remoteInterface = new Connections.RemoteInterface(name, object);
518
+ Connections.Interfaces.set(name, remoteInterface);
519
+ var proxy = new Proxy({}, remoteInterface);
520
+ InterfaceByProxy.set(proxy, remoteInterface);
521
+ for (var [id, connection] of Connections.RemotesByID.entries()) {
522
+ remoteInterface.addConnection(id, connection);
523
+ }
524
+ console.info("Made new interface", name, "for", object.__proto__.constructor.name, object.name || "");
525
+ return proxy;
526
+ }
527
+ Messenger.newRemoteInterface = newRemoteInterface;
528
+ function getInstanceForID(remoteInterface, id) {
529
+ var trueRemoteInterface = InterfaceByProxy.get(remoteInterface);
530
+ if (trueRemoteInterface) {
531
+ var remote = trueRemoteInterface.remotes.get(id);
532
+ if (remote) {
533
+ return remote.proxy;
534
+ }
535
+ }
536
+ return null;
537
+ }
538
+ Messenger.getInstanceForID = getInstanceForID;
539
+ function getAllInstancesExceptID(remoteInterface, id) {
540
+ var trueRemoteInterface = InterfaceByProxy.get(remoteInterface);
541
+ if (trueRemoteInterface) {
542
+ var instances = [];
543
+ for (var remote of trueRemoteInterface.remotes.values()) {
544
+ if (remote.remoteID !== id) {
545
+ instances.push(remote.proxy);
546
+ }
547
+ }
548
+ return instances;
549
+ }
550
+ return null;
551
+ }
552
+ Messenger.getAllInstancesExceptID = getAllInstancesExceptID;
553
+ function getAllInstancesExcept(remoteInterface, remoteInstance) {
554
+ var trueRemoteInterface = InterfaceByProxy.get(remoteInterface);
555
+ if (trueRemoteInterface) {
556
+ var instances = [];
557
+ for (var remote of trueRemoteInterface.remotes.values()) {
558
+ if (remote.proxy != remoteInstance) {
559
+ instances.push(remote.proxy);
560
+ }
561
+ }
562
+ return instances;
563
+ }
564
+ return null;
565
+ }
566
+ Messenger.getAllInstancesExcept = getAllInstancesExcept;
567
+ function getRemoteTime(id) {
568
+ var _a, _b;
569
+ return (_b = (_a = Connections.RemotesByID.get(id)) === null || _a === void 0 ? void 0 : _a.time) !== null && _b !== void 0 ? _b : null;
570
+ }
571
+ Messenger.getRemoteTime = getRemoteTime;
572
+ function getRemotePing(id) {
573
+ var _a, _b;
574
+ return (_b = (_a = Connections.RemotesByID.get(id)) === null || _a === void 0 ? void 0 : _a.ping) !== null && _b !== void 0 ? _b : null;
575
+ }
576
+ Messenger.getRemotePing = getRemotePing;
577
+ function getRemoteAvgPing(id) {
578
+ var remote = Connections.RemotesByID.get(id);
579
+ if (!remote)
580
+ return null;
581
+ return remote.pingHistory.reduce((a, b) => a + b) / remote.pingHistory.length;
582
+ }
583
+ Messenger.getRemoteAvgPing = getRemoteAvgPing;
584
+ function getIDForInstance(remoteInterface, remoteInstance) {
585
+ var trueRemoteInterface = InterfaceByProxy.get(remoteInterface);
586
+ if (trueRemoteInterface) {
587
+ for (var remote of trueRemoteInterface.remotes.values()) {
588
+ if (remote.proxy == remoteInstance) {
589
+ return remote.remoteID;
590
+ }
591
+ }
592
+ }
593
+ return null;
594
+ }
595
+ Messenger.getIDForInstance = getIDForInstance;
596
+ function isRemoteProxy(remote) {
597
+ return InterfaceByProxy.has(remote) || InstanceByProxy.has(remote);
598
+ }
599
+ Messenger.isRemoteProxy = isRemoteProxy;
600
+ function getLocalID() {
601
+ return Connections.LocalID;
602
+ }
603
+ Messenger.getLocalID = getLocalID;
604
+ /**
605
+ * Will return the local id if on the server. Assumes that only the server connects to clients.
606
+ */
607
+ function getServerID() {
608
+ if (serverID === null) {
609
+ throw new Error(`Cannot get remote ID before server has connected/initialised.`);
610
+ }
611
+ return serverID;
612
+ }
613
+ Messenger.getServerID = getServerID;
614
+ //Diverts messages from their original target to a new target. Good for proxies.
615
+ function divertMessages(remote, newTarget) {
616
+ var rInterface = InterfaceByProxy.get(remote);
617
+ rInterface.divertMessages(newTarget);
618
+ }
619
+ Messenger.divertMessages = divertMessages;
620
+ //Restores diverted messages to their original target.
621
+ function restoreMessages(remote) {
622
+ var rInterface = InterfaceByProxy.get(remote);
623
+ rInterface.restoreMessageRecipient();
624
+ }
625
+ Messenger.restoreMessages = restoreMessages;
626
+ })(Messenger || (Messenger = {}));
@@ -0,0 +1,66 @@
1
+ import { ReplicableRegistry } from "./Constants/ReplicableRegistry.js";
2
+ import { getClassOfObject as GetClassOfObjectInternal } from "./Constants/SerialisationTypes.js";
3
+ import { SourceMap } from "./Constants/SourceMaps.js";
4
+ import { ConstructorArgs as ConstArgs } from "./Tracking/Types.js";
5
+ import { Definitions } from "./Transformers/Definitions.js";
6
+ import { Referencer } from "./Transformers/Reference.js";
7
+ import { Utils } from "./Transformers/Utils.js";
8
+ import { Serialiser } from "./Transformers/Serialiser.js";
9
+ export declare namespace Replicable {
10
+ /**
11
+ * Can be used to create a new instance of a replicable class, even from serialised data.
12
+ * When restoring serialised data provide the serialised data as the "data" parameter of the options.
13
+ * @param Class the class to create an instance of.
14
+ * @param opts the options for creating the instance.
15
+ */
16
+ function Create<C extends AnyClass<any>, T extends (C extends {
17
+ new (...args: any[]): infer J;
18
+ } ? J : never), A extends (C extends {
19
+ new (...args: infer J): object;
20
+ } ? J : never)>(Class: C | string, opts?: {
21
+ args?: A;
22
+ data?: any | [string, any];
23
+ source?: SourceMap;
24
+ owner?: any;
25
+ }): T;
26
+ function Initialise<T extends object>(object: T, data: ConstructorArgs, expressionParams?: {
27
+ type: any;
28
+ scope: {
29
+ [key: string]: any;
30
+ };
31
+ }): T;
32
+ function Load<T extends object>(object: T, data: any, source: SourceMap, expressionParams?: {
33
+ type: any;
34
+ scope: {
35
+ [key: string]: any;
36
+ };
37
+ }): T;
38
+ /**
39
+ * Get the original value loaded into this porperty.
40
+ * @param object
41
+ * @param property
42
+ */
43
+ function GetOriginalPropertyValue<T extends object, K extends keyof T>(object: T, property: K): T[K];
44
+ function GetChildClassesNames(type: any | string): string[];
45
+ type ReferenceType<R extends any[] = any[]> = Referencer.Reference<R>;
46
+ const GetClassOfObject: typeof GetClassOfObjectInternal;
47
+ export import GetDataName = ReplicableRegistry.GetDataName;
48
+ export import GetTypesForName = ReplicableRegistry.GetTypesForName;
49
+ export import GetTypeForDataName = ReplicableRegistry.GetTypeForDataName;
50
+ export import IsType = ReplicableRegistry.IsType;
51
+ export import getDataNameOfObjectType = ReplicableRegistry.GetDataNameOfObjectType;
52
+ export import InitialiseData = Definitions.PrePrepareData;
53
+ export import CanReference = Referencer.CanReference;
54
+ export import IsReference = Referencer.IsReference;
55
+ export import Reference = Referencer.Reference;
56
+ export import Dereference = Referencer.Dereference;
57
+ export import CompareReferences = Utils.CompareUtils.CompareReferences;
58
+ export import Serialise = Serialiser.Serialise;
59
+ export import IsSerialisable = Serialiser.IsSerialisable;
60
+ export import Deserialise = Serialiser.Deserialise;
61
+ export import Compare = Utils.CompareUtils.Compare;
62
+ export import OnReady = ReplicableRegistry.Initialise;
63
+ export import RegisterTypeAlias = ReplicableRegistry.RegisterTypeAlias;
64
+ export import ReplaceClass = ReplicableRegistry.ReplaceClass;
65
+ type ConstructorArgs<DefinitionType = any, OwnerType = any> = ConstArgs<DefinitionType, OwnerType>;
66
+ }