@rpgjs/common 4.3.0 → 5.0.0-alpha.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.
Files changed (148) hide show
  1. package/dist/Physic.d.ts +619 -0
  2. package/dist/Player.d.ts +198 -0
  3. package/{lib → dist}/Utils.d.ts +19 -2
  4. package/dist/database/Item.d.ts +10 -0
  5. package/dist/database/index.d.ts +1 -0
  6. package/dist/index.d.ts +9 -0
  7. package/dist/index.js +16741 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/modules.d.ts +92 -0
  10. package/dist/movement/MovementManager.d.ts +84 -0
  11. package/dist/movement/MovementStrategy.d.ts +39 -0
  12. package/dist/movement/index.d.ts +12 -0
  13. package/dist/movement/strategies/CompositeMovement.d.ts +76 -0
  14. package/dist/movement/strategies/Dash.d.ts +52 -0
  15. package/dist/movement/strategies/IceMovement.d.ts +87 -0
  16. package/dist/movement/strategies/Knockback.d.ts +50 -0
  17. package/dist/movement/strategies/LinearMove.d.ts +43 -0
  18. package/dist/movement/strategies/LinearRepulsion.d.ts +55 -0
  19. package/dist/movement/strategies/Oscillate.d.ts +60 -0
  20. package/dist/movement/strategies/PathFollow.d.ts +78 -0
  21. package/dist/movement/strategies/ProjectileMovement.d.ts +138 -0
  22. package/dist/movement/strategies/SeekAvoid.d.ts +27 -0
  23. package/dist/rooms/Map.d.ts +109 -0
  24. package/dist/services/updateMap.d.ts +7 -0
  25. package/package.json +17 -17
  26. package/src/Physic.ts +1644 -0
  27. package/src/Player.ts +262 -26
  28. package/src/{gui/PrebuiltGui.ts → PrebuiltGui.ts} +1 -1
  29. package/src/Utils.ts +184 -123
  30. package/src/database/Item.ts +19 -0
  31. package/src/database/index.ts +1 -0
  32. package/src/index.ts +9 -25
  33. package/src/modules.ts +230 -0
  34. package/src/movement/MovementManager.ts +142 -0
  35. package/src/movement/MovementStrategy.ts +42 -0
  36. package/src/movement/index.ts +15 -0
  37. package/src/movement/strategies/CompositeMovement.ts +173 -0
  38. package/src/movement/strategies/Dash.ts +82 -0
  39. package/src/movement/strategies/IceMovement.ts +158 -0
  40. package/src/movement/strategies/Knockback.ts +81 -0
  41. package/src/movement/strategies/LinearMove.ts +58 -0
  42. package/src/movement/strategies/LinearRepulsion.ts +128 -0
  43. package/src/movement/strategies/Oscillate.ts +144 -0
  44. package/src/movement/strategies/PathFollow.ts +156 -0
  45. package/src/movement/strategies/ProjectileMovement.ts +322 -0
  46. package/src/movement/strategies/SeekAvoid.ts +123 -0
  47. package/src/rooms/Map.ts +272 -0
  48. package/src/services/updateMap.ts +9 -0
  49. package/tests/physic.spec.ts +454 -0
  50. package/tsconfig.json +8 -3
  51. package/vite.config.ts +21 -0
  52. package/CHANGELOG.md +0 -160
  53. package/LICENSE +0 -19
  54. package/browser/manifest.json +0 -7
  55. package/browser/rpg.common.js +0 -11357
  56. package/browser/rpg.common.umd.cjs +0 -11358
  57. package/lib/AbstractObject.d.ts +0 -322
  58. package/lib/AbstractObject.js +0 -872
  59. package/lib/AbstractObject.js.map +0 -1
  60. package/lib/Color.d.ts +0 -1
  61. package/lib/Color.js +0 -25
  62. package/lib/Color.js.map +0 -1
  63. package/lib/DefaultInput.d.ts +0 -2
  64. package/lib/DefaultInput.js +0 -26
  65. package/lib/DefaultInput.js.map +0 -1
  66. package/lib/Event.d.ts +0 -3
  67. package/lib/Event.js +0 -4
  68. package/lib/Event.js.map +0 -1
  69. package/lib/EventEmitter.d.ts +0 -10
  70. package/lib/EventEmitter.js +0 -61
  71. package/lib/EventEmitter.js.map +0 -1
  72. package/lib/Game.d.ts +0 -28
  73. package/lib/Game.js +0 -127
  74. package/lib/Game.js.map +0 -1
  75. package/lib/Hit.d.ts +0 -16
  76. package/lib/Hit.js +0 -65
  77. package/lib/Hit.js.map +0 -1
  78. package/lib/Inject.d.ts +0 -9
  79. package/lib/Inject.js +0 -17
  80. package/lib/Inject.js.map +0 -1
  81. package/lib/Logger.d.ts +0 -2
  82. package/lib/Logger.js +0 -7
  83. package/lib/Logger.js.map +0 -1
  84. package/lib/Map.d.ts +0 -174
  85. package/lib/Map.js +0 -263
  86. package/lib/Map.js.map +0 -1
  87. package/lib/Module.d.ts +0 -16
  88. package/lib/Module.js +0 -139
  89. package/lib/Module.js.map +0 -1
  90. package/lib/Player.d.ts +0 -26
  91. package/lib/Player.js +0 -19
  92. package/lib/Player.js.map +0 -1
  93. package/lib/Plugin.d.ts +0 -67
  94. package/lib/Plugin.js +0 -92
  95. package/lib/Plugin.js.map +0 -1
  96. package/lib/Scheduler.d.ts +0 -26
  97. package/lib/Scheduler.js +0 -90
  98. package/lib/Scheduler.js.map +0 -1
  99. package/lib/Shape.d.ts +0 -127
  100. package/lib/Shape.js +0 -261
  101. package/lib/Shape.js.map +0 -1
  102. package/lib/Utils.js +0 -181
  103. package/lib/Utils.js.map +0 -1
  104. package/lib/Vector2d.d.ts +0 -20
  105. package/lib/Vector2d.js +0 -63
  106. package/lib/Vector2d.js.map +0 -1
  107. package/lib/VirtualGrid.d.ts +0 -26
  108. package/lib/VirtualGrid.js +0 -68
  109. package/lib/VirtualGrid.js.map +0 -1
  110. package/lib/Worker.d.ts +0 -7
  111. package/lib/Worker.js +0 -13
  112. package/lib/Worker.js.map +0 -1
  113. package/lib/WorldMaps.d.ts +0 -105
  114. package/lib/WorldMaps.js +0 -184
  115. package/lib/WorldMaps.js.map +0 -1
  116. package/lib/gui/PrebuiltGui.js +0 -29
  117. package/lib/gui/PrebuiltGui.js.map +0 -1
  118. package/lib/index.d.ts +0 -25
  119. package/lib/index.js +0 -26
  120. package/lib/index.js.map +0 -1
  121. package/lib/transports/io.d.ts +0 -22
  122. package/lib/transports/io.js +0 -82
  123. package/lib/transports/io.js.map +0 -1
  124. package/lib/workers/move.d.ts +0 -1
  125. package/lib/workers/move.js +0 -57
  126. package/lib/workers/move.js.map +0 -1
  127. package/rpg.toml +0 -11
  128. package/src/AbstractObject.ts +0 -973
  129. package/src/Color.ts +0 -29
  130. package/src/DefaultInput.ts +0 -26
  131. package/src/Event.ts +0 -3
  132. package/src/EventEmitter.ts +0 -65
  133. package/src/Game.ts +0 -159
  134. package/src/Hit.ts +0 -70
  135. package/src/Inject.ts +0 -22
  136. package/src/Logger.ts +0 -7
  137. package/src/Map.ts +0 -335
  138. package/src/Module.ts +0 -144
  139. package/src/Plugin.ts +0 -100
  140. package/src/Scheduler.ts +0 -95
  141. package/src/Shape.ts +0 -302
  142. package/src/Vector2d.ts +0 -70
  143. package/src/VirtualGrid.ts +0 -78
  144. package/src/Worker.ts +0 -17
  145. package/src/WorldMaps.ts +0 -204
  146. package/src/transports/io.ts +0 -91
  147. package/src/workers/move.ts +0 -61
  148. /package/{lib/gui → dist}/PrebuiltGui.d.ts +0 -0
package/src/Utils.ts CHANGED
@@ -1,208 +1,269 @@
1
- import { constructor } from "@rpgjs/types";
1
+ export type Constructor<T = {}> = new (...args: any[]) => T;
2
2
 
3
3
  export function random(min: number, max: number): number {
4
- return Math.floor(Math.random() * (max - min + 1) + min)
4
+ return Math.floor(Math.random() * (max - min + 1) + min);
5
5
  }
6
6
 
7
7
  export function isBrowser(): boolean {
8
- return typeof window !== 'undefined'
8
+ return typeof window !== "undefined";
9
9
  }
10
10
 
11
11
  export function isFunction(val: unknown): boolean {
12
- return {}.toString.call(val) === '[object Function]'
12
+ return {}.toString.call(val) === "[object Function]";
13
13
  }
14
14
 
15
15
  export function isClass(func: unknown): boolean {
16
- return typeof func === 'function';
16
+ return typeof func === "function";
17
17
  }
18
18
 
19
19
  export function isPromise(val: unknown) {
20
- return isInstanceOf<Promise<unknown>>(val, Promise)
20
+ return isInstanceOf<Promise<unknown>>(val, Promise);
21
21
  }
22
22
 
23
23
  export function isArray(val: unknown) {
24
- return isInstanceOf<Array<unknown>>(val, Array)
24
+ return isInstanceOf<Array<unknown>>(val, Array);
25
25
  }
26
26
 
27
27
  export function isObject(val: unknown): boolean {
28
- return typeof val == 'object' && val != null && !isArray(val)
28
+ return typeof val == "object" && val != null && !isArray(val);
29
29
  }
30
30
 
31
31
  export function isString(val: unknown): boolean {
32
- return typeof val == 'string'
32
+ return typeof val == "string";
33
33
  }
34
34
 
35
35
  export function isInstanceOf<T = any>(val: unknown, _class: any) {
36
- return val instanceof _class
36
+ return val instanceof _class;
37
37
  }
38
38
 
39
39
  export function arrayUniq(array: any[]): any[] {
40
- return [...new Set(array)]
40
+ return [...new Set(array)];
41
41
  }
42
42
 
43
43
  export function arrayFlat(array: any[]): any[] {
44
- return array.reduce((acc, val) => acc.concat(val), [])
44
+ return array.reduce((acc, val) => acc.concat(val), []);
45
45
  }
46
46
 
47
- export function intersection([start1, end1]: [number, number], [start2, end2]: [number, number]): boolean {
48
- return (start1 >= start2 && start1 <= end2) || (start2 >= start1 && start2 < end1)
47
+ export function intersection(
48
+ [start1, end1]: [number, number],
49
+ [start2, end2]: [number, number]
50
+ ): boolean {
51
+ return (
52
+ (start1 >= start2 && start1 <= end2) || (start2 >= start1 && start2 < end1)
53
+ );
49
54
  }
50
55
 
51
56
  export function capitalize(s: unknown): string {
52
- if (typeof s !== 'string') return ''
53
- return s.charAt(0).toUpperCase() + s.slice(1)
57
+ if (typeof s !== "string") return "";
58
+ return s.charAt(0).toUpperCase() + s.slice(1);
54
59
  }
55
60
 
56
61
  export function camelToKebab(str: string): string {
57
- return str
58
- .replace(/([a-z])([A-Z])/g, '$1-$2')
59
- .toLowerCase();
62
+ return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
60
63
  }
61
64
 
62
65
  export function arrayEquals(a: any[], b: any[]): boolean {
63
- return a.length === b.length && a.every((v, i) => v === b[i])
66
+ return a.length === b.length && a.every((v, i) => v === b[i]);
64
67
  }
65
68
 
66
- export function applyMixins(derivedCtor: constructor<any>, baseCtors: constructor<any>[]) {
67
- baseCtors.forEach((baseCtor) => {
68
- Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
69
- const baseCtorName = Object.getOwnPropertyDescriptor(baseCtor.prototype, name)
70
- if (!baseCtorName) {
71
- return
72
- }
73
- Object.defineProperty(derivedCtor.prototype, name, baseCtorName)
74
- })
75
- })
69
+ /**
70
+ * Combines multiple mixins into one
71
+ *
72
+ * @param mixins - Array of mixin functions to combine
73
+ * @returns A single mixin function that applies all mixins
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const AllMixins = combineMixins([WithStats, WithInventory, WithComponentManager]);
78
+ * class MyClass extends AllMixins(BaseClass) {
79
+ * // MyClass now has all capabilities from all mixins
80
+ * }
81
+ * ```
82
+ */
83
+ export function combineMixins(
84
+ mixins: Array<<T extends Constructor>(Base: T) => any>
85
+ ) {
86
+ return <T extends Constructor>(Base: T) =>
87
+ mixins.reduce((ExtendedClass, mixin) => mixin(ExtendedClass), Base);
88
+ }
89
+
90
+ export function applyMixins(derivedCtor: any, baseCtors: any[]) {
91
+ baseCtors.forEach((baseCtor) => {
92
+ Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
93
+ const baseCtorName = Object.getOwnPropertyDescriptor(
94
+ baseCtor.prototype,
95
+ name
96
+ );
97
+ if (!baseCtorName) {
98
+ return;
99
+ }
100
+ Object.defineProperty(derivedCtor.prototype, name, baseCtorName);
101
+ });
102
+ });
76
103
  }
77
104
 
78
105
  export function generateUID(): string {
79
- let firstPart: any = (Math.random() * 46656) | 0
80
- let secondPart: any = (Math.random() * 46656) | 0
81
- firstPart = ("000" + firstPart.toString(36)).slice(-3)
82
- secondPart = ("000" + secondPart.toString(36)).slice(-3)
83
- return firstPart + secondPart
106
+ let firstPart: any = (Math.random() * 46656) | 0;
107
+ let secondPart: any = (Math.random() * 46656) | 0;
108
+ firstPart = ("000" + firstPart.toString(36)).slice(-3);
109
+ secondPart = ("000" + secondPart.toString(36)).slice(-3);
110
+ return firstPart + secondPart;
84
111
  }
85
112
 
86
113
  export function createConstructor<T>(...propNames: any[]): T {
87
- return class {
88
- constructor(...propValues) {
89
- propNames.forEach((name, idx) => {
90
- this[name] = propValues[idx]
91
- })
92
- }
93
- } as unknown as T
114
+ return class {
115
+ constructor(...propValues) {
116
+ propNames.forEach((name, idx) => {
117
+ this[name] = propValues[idx];
118
+ });
119
+ }
120
+ } as unknown as T;
94
121
  }
95
122
 
96
123
  export function sharedArrayBuffer() {
97
- let buffer
98
- if (typeof SharedArrayBuffer != 'undefined') {
99
- buffer = SharedArrayBuffer
100
- }
101
- else {
102
- buffer = ArrayBuffer
103
- }
104
- return buffer
124
+ let buffer;
125
+ if (typeof SharedArrayBuffer != "undefined") {
126
+ buffer = SharedArrayBuffer;
127
+ } else {
128
+ buffer = ArrayBuffer;
129
+ }
130
+ return buffer;
105
131
  }
106
132
 
107
133
  export function toRadians(angle: number) {
108
- return angle * (Math.PI / 180)
134
+ return angle * (Math.PI / 180);
109
135
  }
110
136
 
111
137
  export function hexaToNumber(hexa: string): {
112
- value: number,
113
- alpha: number
138
+ value: number;
139
+ alpha: number;
114
140
  } {
115
- let val = hexa.replace('#', '')
116
- let alpha = 1
117
- if (val.length === 3) {
118
- val = val.split('').map((v) => v + v).join('')
119
- }
120
- if (val.length === 8) {
121
- alpha = parseInt(val.substring(0, 2), 16) / 255
122
- val = val.substring(2)
123
- }
124
- return {
125
- value: parseInt(val, 16),
126
- alpha
127
- }
141
+ let val = hexa.replace("#", "");
142
+ let alpha = 1;
143
+ if (val.length === 3) {
144
+ val = val
145
+ .split("")
146
+ .map((v) => v + v)
147
+ .join("");
148
+ }
149
+ if (val.length === 8) {
150
+ alpha = parseInt(val.substring(0, 2), 16) / 255;
151
+ val = val.substring(2);
152
+ }
153
+ return {
154
+ value: parseInt(val, 16),
155
+ alpha,
156
+ };
128
157
  }
129
158
 
130
159
  export function extractId(path: string): string | null {
131
- const id = path.match(/([a-zA-Z0-9-_$!]+)\.[a-z0-9]+$/i)
132
- if (!id) return null
133
- return id[1]
160
+ const id = path.match(/([a-zA-Z0-9-_$!]+)\.[a-z0-9]+$/i);
161
+ if (!id) return null;
162
+ return id[1];
134
163
  }
135
164
 
136
165
  export function basename(path: string): string {
137
- return path.substring(path.lastIndexOf('/') + 1)
166
+ return path.substring(path.lastIndexOf("/") + 1);
138
167
  }
139
168
 
140
169
  export function fps2ms(fps: number): number {
141
- return 1000 / fps
170
+ return 1000 / fps;
142
171
  }
143
172
 
144
173
  export function preciseNow(): number {
145
- return typeof performance !== 'undefined' ? performance.now() : Date.now()
174
+ return typeof performance !== "undefined" ? performance.now() : Date.now();
146
175
  }
147
176
 
148
177
  export function round(num: number, decimals: number = 100): number {
149
- return Math.round(num * decimals) / decimals
178
+ return Math.round(num * decimals) / decimals;
150
179
  }
151
180
 
152
181
  // https://stackoverflow.com/questions/54733539/javascript-implementation-of-lodash-set-method
153
182
  export function set(obj, path, value, onlyPlainObject = false) {
154
- if (Object(obj) !== obj) return obj; // When obj is not an object
155
- // If not yet an array, get the keys from the string-path
156
- if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
157
- path.slice(0, -1).reduce((a, c, i) => // Iterate all of them except the last one
158
- Object(a[c]) === a[c] // Does the key exist and is its value an object?
159
- // Yes: then follow that path
160
- ? a[c]
161
- // No: create the key. Is the next key a potential array-index?
162
- : a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1]
163
- ? onlyPlainObject ? {} : [] // Yes: assign a new array object
164
- : {}, // No: assign a new plain object
165
- obj)[path[path.length - 1]] = value; // Finally assign the value to the last key
166
- return obj; // Return the top-level object to allow chaining
167
- };
183
+ if (Object(obj) !== obj) return obj; // When obj is not an object
184
+ // If not yet an array, get the keys from the string-path
185
+ if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
186
+ path.slice(0, -1).reduce(
187
+ (
188
+ a,
189
+ c,
190
+ i // Iterate all of them except the last one
191
+ ) =>
192
+ Object(a[c]) === a[c] // Does the key exist and is its value an object?
193
+ ? // Yes: then follow that path
194
+ a[c]
195
+ : // No: create the key. Is the next key a potential array-index?
196
+ (a[c] =
197
+ Math.abs(path[i + 1]) >> 0 === +path[i + 1]
198
+ ? onlyPlainObject
199
+ ? {}
200
+ : [] // Yes: assign a new array object
201
+ : {}), // No: assign a new plain object
202
+ obj
203
+ )[path[path.length - 1]] = value; // Finally assign the value to the last key
204
+ return obj; // Return the top-level object to allow chaining
205
+ }
168
206
 
169
207
  export function elementToPositionAbsolute(element: HTMLElement) {
170
- element.style.position = 'absolute'
171
- element.style.top = '0'
172
- element.style.left = '0'
173
- element.style.right = '0'
174
- element.style.bottom = '0'
175
- element.style.width = '100%'
176
- element.style.height = '100%'
208
+ element.style.position = "absolute";
209
+ element.style.top = "0";
210
+ element.style.left = "0";
211
+ element.style.right = "0";
212
+ element.style.bottom = "0";
213
+ element.style.width = "100%";
214
+ element.style.height = "100%";
215
+ }
216
+
217
+
218
+ export function mergeObjectWithMethods<T, S>(target: T, source: S): T & S {
219
+ // Copier toutes les propriétés propres (énumérables et non-énumérables)
220
+ const propertyNames = Object.getOwnPropertyNames(source);
221
+ for (const name of propertyNames) {
222
+ if (name !== 'constructor') {
223
+ const descriptor = Object.getOwnPropertyDescriptor(source, name);
224
+ if (descriptor) {
225
+ Object.defineProperty(target, name, descriptor);
226
+ }
227
+ }
228
+ }
229
+
230
+ // Configurer le prototype pour hériter des méthodes de la classe
231
+ const sourceProto = Object.getPrototypeOf(source);
232
+ if (sourceProto && sourceProto !== Object.prototype) {
233
+ Object.setPrototypeOf(target, sourceProto);
234
+ }
235
+
236
+ return target as T & S;
177
237
  }
178
238
 
179
239
  export default {
180
- random,
181
- isBrowser,
182
- isPromise,
183
- isArray,
184
- isObject,
185
- isString,
186
- isFunction,
187
- isClass,
188
- isInstanceOf,
189
- arrayUniq,
190
- arrayFlat,
191
- arrayEquals,
192
- intersection,
193
- applyMixins,
194
- capitalize,
195
- sharedArrayBuffer,
196
- generateUID,
197
- createConstructor,
198
- toRadians,
199
- extractId,
200
- basename,
201
- fps2ms,
202
- preciseNow,
203
- hexaToNumber,
204
- set,
205
- round,
206
- camelToKebab,
207
- elementToPositionAbsolute
208
- }
240
+ random,
241
+ isBrowser,
242
+ isPromise,
243
+ isArray,
244
+ isObject,
245
+ isString,
246
+ isFunction,
247
+ isClass,
248
+ isInstanceOf,
249
+ arrayUniq,
250
+ arrayFlat,
251
+ arrayEquals,
252
+ intersection,
253
+ applyMixins,
254
+ capitalize,
255
+ sharedArrayBuffer,
256
+ generateUID,
257
+ createConstructor,
258
+ toRadians,
259
+ extractId,
260
+ basename,
261
+ fps2ms,
262
+ preciseNow,
263
+ hexaToNumber,
264
+ set,
265
+ round,
266
+ camelToKebab,
267
+ elementToPositionAbsolute,
268
+ mergeObjectWithMethods
269
+ };
@@ -0,0 +1,19 @@
1
+ import { signal } from "@signe/reactive";
2
+ import { id, sync } from "@signe/sync";
3
+ import { RpgCommonPlayer } from "../Player";
4
+
5
+ export class Item {
6
+ @id() id = signal('');
7
+ @sync() name = signal('');
8
+ @sync() description = signal('');
9
+ @sync() price = signal(0);
10
+ @sync() quantity = signal(1);
11
+
12
+ onAdd: (player: RpgCommonPlayer) => void = () => {};
13
+
14
+ constructor(data: any) {
15
+ this.description.set(data.description);
16
+ this.price.set(data.price);
17
+ this.onAdd = data.onAdd?.bind(this) ?? (() => {});
18
+ }
19
+ }
@@ -0,0 +1 @@
1
+ export * from "./Item";
package/src/index.ts CHANGED
@@ -1,25 +1,9 @@
1
- import AbstractObject from './Player';
2
- export { LiteralDirection, RpgCommonPlayer } from './Player'
3
- export { AbstractObject }
4
- export { RpgCommonEvent } from './Event'
5
- export { RpgCommonMap } from './Map'
6
- export { RpgCommonGame, GameSide } from './Game'
7
- export { EventEmitter } from './EventEmitter'
8
- export { PrebuiltGui } from './gui/PrebuiltGui'
9
- export *as Utils from './Utils'
10
- export { RpgPlugin, type Plugin, HookServer, HookClient } from './Plugin'
11
- export * as TransportIo from './transports/io'
12
- export { Input, Control } from '@rpgjs/types'
13
- export { Hit } from './Hit'
14
- export { Scheduler } from './Scheduler'
15
- export { RpgModule, loadModules, type ModuleType } from './Module'
16
- export * as MockIo from './transports/io'
17
- export * as Logger from './Logger';
18
- export { RpgShape, ShapePositioning } from './Shape'
19
- export { VirtualGrid } from './VirtualGrid'
20
- export { RpgCommonWorldMaps } from './WorldMaps'
21
- export { Vector2d } from './Vector2d'
22
- export { Direction } from '@rpgjs/types'
23
- export { transitionColor } from './Color'
24
- export { DefaultInput } from './DefaultInput'
25
- export { type InjectInit, InjectContext } from './Inject'
1
+ export * from "./Player";
2
+ export * from "./rooms/Map";
3
+ export * from "./modules";
4
+ export * from "./services/updateMap";
5
+ export * from "./Utils";
6
+ export * from "./PrebuiltGui";
7
+ export * from "./movement";
8
+ export * as Matter from "matter-js";
9
+ export * from "./database";
package/src/modules.ts ADDED
@@ -0,0 +1,230 @@
1
+ export const ModulesToken = "ModulesToken";
2
+
3
+ import { Context, Provider, Providers } from "@signe/di";
4
+ import { Subject, Observable, from } from "rxjs";
5
+ import { mergeMap, toArray } from "rxjs/operators";
6
+
7
+ export class Hooks {
8
+ /**
9
+ * Store of all module hooks by ID
10
+ */
11
+ private moduleHooks: Record<string, Subject<any>> = {};
12
+
13
+ /**
14
+ * Store of all hook functions by ID
15
+ */
16
+ private hookFunctions: Record<string, Function[]> = {};
17
+
18
+ constructor(private modules: any[], private namespace: string) {
19
+ this.init();
20
+ }
21
+
22
+ private init() {
23
+ for (const module of this.modules) {
24
+ for (const type in module) {
25
+ const hookObject = module[type];
26
+ for (const hook in hookObject) {
27
+ const hookFunction = hookObject[hook];
28
+ if (hookFunction) {
29
+ const hookId = `${this.namespace}-${type}-${hook}`;
30
+
31
+ // Créer un Subject pour ce hook s'il n'existe pas déjà
32
+ if (!this.moduleHooks[hookId]) {
33
+ this.moduleHooks[hookId] = new Subject<any>();
34
+ }
35
+
36
+ // Initialiser le tableau de fonctions pour cet ID si nécessaire
37
+ if (!this.hookFunctions[hookId]) {
38
+ this.hookFunctions[hookId] = [];
39
+ }
40
+
41
+ // Ajouter la fonction au tableau des hooks pour cet ID
42
+ // (sans l'exécuter immédiatement)
43
+ if (!this.hookFunctions[hookId].includes(hookFunction)) {
44
+ this.hookFunctions[hookId].push(hookFunction);
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+
51
+ return this.moduleHooks;
52
+ }
53
+
54
+ /**
55
+ * Call hooks for a specific ID, passing arguments to all subscribed hooks
56
+ *
57
+ * @param hookId - The unique identifier of the module hook
58
+ * @param args - Arguments to pass to the hook functions
59
+ * @returns An Observable that emits an array with all hook results when subscribed
60
+ * @example
61
+ * ```ts
62
+ * // Call all hook functions for the ID 'my-namespace-type-hook'
63
+ * callHooks('my-namespace-type-hook', { x: 10, y: 20 }).subscribe(results => {
64
+ * console.log('Hook results:', results); // Array of all hook function results
65
+ * });
66
+ *
67
+ * // Hook functions are only executed when you subscribe to the returned Observable
68
+ * const observable = callHooks('my-namespace-type-hook', player);
69
+ * // ... later ...
70
+ * observable.subscribe(results => {
71
+ * // Process results array
72
+ * });
73
+ * ```
74
+ */
75
+ public callHooks(hookId: string, ...args: any[]): Observable<any[]> {
76
+ if (!this.moduleHooks[hookId]) {
77
+ this.moduleHooks[hookId] = new Subject<any>();
78
+ }
79
+
80
+ // Create an Observable that will execute all hook functions when subscribed
81
+ return new Observable<any[]>((subscriber) => {
82
+ if (this.hookFunctions[hookId] && this.hookFunctions[hookId].length > 0) {
83
+ // Map each hook function to an Observable that can handle both synchronous values and Promises
84
+ const hookResults$ = from(this.hookFunctions[hookId]).pipe(
85
+ mergeMap((hookFunction) => {
86
+ let result;
87
+ try {
88
+ result = hookFunction(...args);
89
+ return from(Promise.resolve(result));
90
+ } catch (error) {
91
+ subscriber.error(error);
92
+ return [];
93
+ }
94
+ }),
95
+ toArray() // Collect all results into an array
96
+ );
97
+
98
+ // Subscribe to the hook results Observable
99
+ const subscription = hookResults$.subscribe({
100
+ next: (results) => {
101
+ // Emit all collected results to subscribers of this hook
102
+ this.moduleHooks[hookId].next(results);
103
+ subscriber.next(results);
104
+ subscriber.complete();
105
+ },
106
+ error: (err) => {
107
+ subscriber.error(err);
108
+ }
109
+ });
110
+
111
+ // Return cleanup function
112
+ return () => {
113
+ subscription.unsubscribe();
114
+ };
115
+ } else {
116
+ // No hook functions to execute, emit an empty array
117
+ subscriber.next([]);
118
+ subscriber.complete();
119
+ return () => {};
120
+ }
121
+ });
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Provide modules configuration to Angular Dependency Injection
127
+ * Registers hook functions for later execution
128
+ *
129
+ * @param modules - Array of modules to provide
130
+ * @param namespace - Namespace to prefix hook IDs
131
+ * @returns Provider configuration for Angular DI
132
+ * @example
133
+ * ```ts
134
+ * // Define modules
135
+ * const modules = [
136
+ * {
137
+ * player: {
138
+ * onMove: (player) => {
139
+ * // Handle player movement
140
+ * }
141
+ * }
142
+ * }
143
+ * ];
144
+ *
145
+ * // Provide modules
146
+ * const provider = provideModules(modules, 'game');
147
+ * ```
148
+ */
149
+ export function provideModules(modules: any[], namespace: string, transform?: (modules: any, context: Context) => any) {
150
+ return {
151
+ provide: ModulesToken,
152
+ useFactory: (context: Context) => {
153
+ modules = transform ? transform(modules, context) : modules
154
+ return new Hooks(modules, namespace);
155
+ },
156
+ };
157
+ }
158
+
159
+ export function findModules(context: Context, namespace: string) {
160
+ let modules: any[] = []
161
+ for (let key in context['values']) {
162
+ if (key.endsWith('Module' + namespace)) {
163
+ modules.push(context['values'][key])
164
+ }
165
+ }
166
+ return modules
167
+ }
168
+
169
+ /**
170
+ * Create module providers from a token name and array of providers
171
+ * Transforms objects with server/client properties into separate ModuleServer and ModuleClient providers
172
+ *
173
+ * @param tokenName - The base token name for the module
174
+ * @param providers - Array of providers that can be regular providers or objects with server/client properties
175
+ * @returns Flattened array of providers with transformed server/client objects
176
+ * @example
177
+ * ```ts
178
+ * // Input: createModule('battle', [{ server: serverModule, client: clientModule }])
179
+ * // Output: [
180
+ * // { provide: 'battleModuleServer', useValue: { server: serverModule, client: clientModule }, meta: { server: true, isModule: true } },
181
+ * // { provide: 'battleModuleClient', useValue: { server: serverModule, client: clientModule }, meta: { client: true, isModule: true } }
182
+ * // ]
183
+ *
184
+ * // Regular providers are passed through unchanged
185
+ * createModule('battle', [regularProvider, { server, client }])
186
+ * ```
187
+ */
188
+ export function createModule(tokenName: string, providers:(Provider | Provider[] | ({ server?: any, client?: any }))[]) {
189
+ const results = providers.map(provider => {
190
+ const results: any[] = [];
191
+
192
+ if (!provider) {
193
+ return []
194
+ }
195
+
196
+ if ('server' in provider) {
197
+ results.push({
198
+ provide: tokenName + 'ModuleServer',
199
+ useValue: provider,
200
+ meta: {
201
+ server: true,
202
+ isModule: true,
203
+ }
204
+ });
205
+ }
206
+
207
+ if ('client' in provider) {
208
+ results.push({
209
+ provide: tokenName + 'ModuleClient',
210
+ useValue: provider,
211
+ meta: {
212
+ client: true,
213
+ isModule: true,
214
+ }
215
+ });
216
+ }
217
+
218
+ // If neither server nor client properties, return the provider as-is
219
+ if (!('server' in provider) && !('client' in provider)) {
220
+ results.push(provider);
221
+ }
222
+
223
+ return results;
224
+ }).flat(); // Flatten the array to handle multiple results per provider
225
+ return results.flat();
226
+ }
227
+
228
+ export function defineModule<T>(options: T) {
229
+ return options
230
+ }