@rpgjs/server 5.0.0-alpha.7 → 5.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgjs/server",
3
- "version": "5.0.0-alpha.7",
3
+ "version": "5.0.0-alpha.9",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "publishConfig": {
@@ -11,7 +11,7 @@
11
11
  "license": "MIT",
12
12
  "description": "",
13
13
  "dependencies": {
14
- "@rpgjs/common": "5.0.0-alpha.7",
14
+ "@rpgjs/common": "5.0.0-alpha.9",
15
15
  "@rpgjs/database": "^4.3.0",
16
16
  "@signe/di": "^2.3.2",
17
17
  "@signe/reactive": "^2.3.2",
@@ -24,9 +24,24 @@ import { RpgCommonPlayer } from "@rpgjs/common";
24
24
  * player.setGraphic(["hero_idle", "hero_walk"]);
25
25
  * ```
26
26
  */
27
- export function WithComponentManager<TBase extends PlayerCtor>(Base: TBase) {
27
+ export function WithComponentManager<TBase extends PlayerCtor>(Base: TBase): new (...args: ConstructorParameters<TBase>) => InstanceType<TBase> & IComponentManager {
28
28
  return class extends Base {
29
- /**
29
+ setGraphic(graphic: string | string[]): void {
30
+ if (Array.isArray(graphic)) {
31
+ this.graphics.set(graphic);
32
+ } else {
33
+ this.graphics.set([graphic]);
34
+ }
35
+ }
36
+ } as unknown as any;
37
+ }
38
+
39
+ /**
40
+ * Interface for component management capabilities
41
+ * Defines the method signature that will be available on the player
42
+ */
43
+ export interface IComponentManager {
44
+ /**
30
45
  * Set the graphic(s) for this player
31
46
  *
32
47
  * Allows setting either a single graphic or multiple graphics for the player.
@@ -54,18 +69,5 @@ export function WithComponentManager<TBase extends PlayerCtor>(Base: TBase) {
54
69
  * player.setGraphic(["mage_cast_1", "mage_cast_2", "mage_cast_3"]);
55
70
  * ```
56
71
  */
57
- setGraphic(graphic: string | string[]): void {
58
- if (Array.isArray(graphic)) {
59
- this.graphics.set(graphic);
60
- } else {
61
- this.graphics.set([graphic]);
62
- }
63
- }
64
- } as unknown as TBase;
72
+ setGraphic(graphic: string | string[]): void;
65
73
  }
66
-
67
- /**
68
- * Type helper to extract the interface from the WithComponentManager mixin
69
- * This provides the type without duplicating method signatures
70
- */
71
- export type IComponentManager = InstanceType<ReturnType<typeof WithComponentManager>>;
@@ -1,18 +1,18 @@
1
1
  import { RpgPlayer } from "./Player";
2
2
  import { Gui, DialogGui, MenuGui, ShopGui, NotificationGui } from "../Gui";
3
3
  import { DialogOptions, Choice } from "../Gui/DialogGui";
4
- import { PlayerCtor } from "@rpgjs/common";
4
+ import { Constructor, PlayerCtor } from "@rpgjs/common";
5
5
 
6
6
  /**
7
7
  * GUI Manager Mixin
8
- *
8
+ *
9
9
  * Provides graphical user interface management capabilities to any class. This mixin handles
10
10
  * dialog boxes, menus, notifications, shops, and custom GUI components. It manages the
11
11
  * complete GUI system including opening, closing, and data passing between client and server.
12
- *
12
+ *
13
13
  * @param Base - The base class to extend with GUI management
14
14
  * @returns Extended class with GUI management methods
15
- *
15
+ *
16
16
  * @example
17
17
  * ```ts
18
18
  * class MyPlayer extends WithGuiManager(BasePlayer) {
@@ -21,129 +21,25 @@ import { PlayerCtor } from "@rpgjs/common";
21
21
  * // GUI system is automatically initialized
22
22
  * }
23
23
  * }
24
- *
24
+ *
25
25
  * const player = new MyPlayer();
26
26
  * await player.showText('Hello World!');
27
27
  * player.callMainMenu();
28
28
  * ```
29
29
  */
30
- export function WithGuiManager<TBase extends PlayerCtor>(Base: TBase) {
31
- return class extends Base {
30
+ export function WithGuiManager<TBase extends PlayerCtor>(
31
+ Base: TBase
32
+ ): new (...args: ConstructorParameters<TBase>) => InstanceType<TBase> &
33
+ IGuiManager {
34
+ class GuiManagerMixin extends Base {
32
35
  _gui: { [id: string]: Gui } = {};
33
36
 
34
- /**
35
- * Show a text. This is a graphical interface already built. Opens the GUI named `rpg-dialog`
36
- *
37
- * ```ts
38
- * player.showText('Hello World')
39
- * ```
40
- *
41
- * The method returns a promise. It is resolved when the dialog box is closed.
42
- *
43
- * ```ts
44
- * await player.showText('Hello World')
45
- * // dialog box is closed, then ...
46
- * ```
47
- *
48
- * **Option: position**
49
- *
50
- * You can define how the dialog box is displayed:
51
- * - top
52
- * - middle
53
- * - bottom
54
- *
55
- * (bottom by default)
56
- *
57
- * ```ts
58
- * player.showText('Hello World', {
59
- * position: 'top'
60
- * })
61
- * ```
62
- *
63
- * **Option: fullWidth**
64
- *
65
- * `boolean` (true by default)
66
- *
67
- * Indicate that the dialog box will take the full width of the screen.
68
- *
69
- * ```ts
70
- * player.showText('Hello World', {
71
- * fullWidth: true
72
- * })
73
- * ```
74
- *
75
- * **Option: autoClose**
76
- *
77
- * `boolean` (false by default)
78
- *
79
- * If false, the user will have to press Enter to close the dialog box.
80
- *
81
- * ```ts
82
- * player.showText('Hello World', {
83
- * autoClose: true
84
- * })
85
- * ```
86
- *
87
- * **Option: typewriterEffect**
88
- *
89
- * `boolean` (true by default)
90
- *
91
- * Performs a typewriter effect
92
- *
93
- * ```ts
94
- * player.showText('Hello World', {
95
- * typewriterEffect: false
96
- * })
97
- * ```
98
- *
99
- * **Option: talkWith**
100
- *
101
- * `RpgPlayer` (nothing by default)
102
- *
103
- * If you specify the event or another player, the other player will stop his or her movement and look in the player's direction.
104
- *
105
- * ```ts
106
- * // Code in an event
107
- * player.showText('Hello World', {
108
- * talkWith: this
109
- * })
110
- * ```
111
- *
112
- * @title Show Text
113
- * @method player.showText(text,options)
114
- * @param {string} text
115
- * @param {object} [options] the different options, see usage below
116
- * @returns {Promise}
117
- * @memberof GuiManager
118
- */
119
37
  showText(msg: string, options: DialogOptions = {}): Promise<any> {
120
38
  const gui = new DialogGui(<any>this);
121
39
  this._gui[gui.id] = gui;
122
40
  return gui.openDialog(msg, options);
123
41
  }
124
42
 
125
- /**
126
- * Shows a dialog box with a choice. Opens the GUI named `rpg-dialog`
127
- *
128
- * ```ts
129
- * const choice = await player.showChoices('What color do you prefer?', [
130
- * { text: 'Black', value: 'black' },
131
- * { text: 'Rather the blue', value: 'blue' },
132
- * { text: 'I don\'t have a preference!', value: 'none' }
133
- * ])
134
- *
135
- * // If the player selects the first
136
- * console.log(choice) // { text: 'Black', value: 'black' }
137
- * ```
138
- *
139
- * @title Show Choices
140
- * @method player.showChoices(text,choices)
141
- * @param {string} text
142
- * @param {Array<{ text: string, value: any }>} choices
143
- * @param {object} [options] Same options as the openDialog method
144
- * @returns {Promise<Choice | null>}
145
- * @memberof GuiManager
146
- */
147
43
  showChoices(
148
44
  msg: string,
149
45
  choices: Choice[],
@@ -158,19 +54,6 @@ export function WithGuiManager<TBase extends PlayerCtor>(Base: TBase) {
158
54
  });
159
55
  }
160
56
 
161
- /**
162
- * Displays a notification . Opens the GUI named `rpg-notification`
163
- *
164
- * @title Displays a notification
165
- * @method player.showNotification()
166
- * @param {string} message - The message to display in the notification
167
- * @param {object} options - An object containing options for the notification
168
- * @param {number} options.time - The time to display the notification for (in ms). Default: 2000ms
169
- * @param {string} options.icon - The icon to display in the notification. Put the identifier of the spritesheet (defined on the client side)
170
- * @param {string} options.sound - The sound to play when the notification is shown. Set the sound ID (defined on the client side)
171
- * @returns {void}
172
- * @memberof GuiManager
173
- */
174
57
  showNotification(
175
58
  message: string,
176
59
  options: { time?: number; icon?: string; sound?: string } = {}
@@ -184,14 +67,6 @@ export function WithGuiManager<TBase extends PlayerCtor>(Base: TBase) {
184
67
  return gui.open(data);
185
68
  }
186
69
 
187
- /**
188
- * Calls main menu. Opens the GUI named `rpg-main-menu`
189
- *
190
- * @title Call Main Menu
191
- * @method player.callMainMenu()
192
- * @returns {void}
193
- * @memberof GuiManager
194
- */
195
70
  callMainMenu() {
196
71
  const gui = new MenuGui(<any>this);
197
72
  this._gui[gui.id] = gui;
@@ -330,11 +205,160 @@ export function WithGuiManager<TBase extends PlayerCtor>(Base: TBase) {
330
205
  const _players = players || this;
331
206
  this._attachedGui(_players as RpgPlayer[], false);
332
207
  }
333
- } as unknown as TBase;
208
+ }
209
+
210
+ return GuiManagerMixin as unknown as any;
334
211
  }
335
212
 
336
213
  /**
337
- * Type helper to extract the interface from the WithGuiManager mixin
338
- * This provides the type without duplicating method signatures
214
+ * Interface for GUI management capabilities
215
+ * Defines the methods that will be available on the player
339
216
  */
340
- export type IGuiManager = InstanceType<ReturnType<typeof WithGuiManager>>;
217
+ export interface IGuiManager {
218
+ /**
219
+ * Show a text. This is a graphical interface already built. Opens the GUI named `rpg-dialog`
220
+ *
221
+ * ```ts
222
+ * player.showText('Hello World')
223
+ * ```
224
+ *
225
+ * The method returns a promise. It is resolved when the dialog box is closed.
226
+ *
227
+ * ```ts
228
+ * await player.showText('Hello World')
229
+ * // dialog box is closed, then ...
230
+ * ```
231
+ *
232
+ * **Option: position**
233
+ *
234
+ * You can define how the dialog box is displayed:
235
+ * - top
236
+ * - middle
237
+ * - bottom
238
+ *
239
+ * (bottom by default)
240
+ *
241
+ * ```ts
242
+ * player.showText('Hello World', {
243
+ * position: 'top'
244
+ * })
245
+ * ```
246
+ *
247
+ * **Option: fullWidth**
248
+ *
249
+ * `boolean` (true by default)
250
+ *
251
+ * Indicate that the dialog box will take the full width of the screen.
252
+ *
253
+ * ```ts
254
+ * player.showText('Hello World', {
255
+ * fullWidth: true
256
+ * })
257
+ * ```
258
+ *
259
+ * **Option: autoClose**
260
+ *
261
+ * `boolean` (false by default)
262
+ *
263
+ * If false, the user will have to press Enter to close the dialog box.
264
+ *
265
+ * ```ts
266
+ * player.showText('Hello World', {
267
+ * autoClose: true
268
+ * })
269
+ * ```
270
+ *
271
+ * **Option: typewriterEffect**
272
+ *
273
+ * `boolean` (true by default)
274
+ *
275
+ * Performs a typewriter effect
276
+ *
277
+ * ```ts
278
+ * player.showText('Hello World', {
279
+ * typewriterEffect: false
280
+ * })
281
+ * ```
282
+ *
283
+ * **Option: talkWith**
284
+ *
285
+ * `RpgPlayer` (nothing by default)
286
+ *
287
+ * If you specify the event or another player, the other player will stop his or her movement and look in the player's direction.
288
+ *
289
+ * ```ts
290
+ * // Code in an event
291
+ * player.showText('Hello World', {
292
+ * talkWith: this
293
+ * })
294
+ * ```
295
+ *
296
+ * @title Show Text
297
+ * @method player.showText(text,options)
298
+ * @param {string} text
299
+ * @param {object} [options] the different options, see usage below
300
+ * @returns {Promise}
301
+ * @memberof GuiManager
302
+ */
303
+ showText(msg: string, options?: DialogOptions): Promise<any>;
304
+
305
+ /**
306
+ * Shows a dialog box with a choice. Opens the GUI named `rpg-dialog`
307
+ *
308
+ * ```ts
309
+ * const choice = await player.showChoices('What color do you prefer?', [
310
+ * { text: 'Black', value: 'black' },
311
+ * { text: 'Rather the blue', value: 'blue' },
312
+ * { text: 'I don\'t have a preference!', value: 'none' }
313
+ * ])
314
+ *
315
+ * // If the player selects the first
316
+ * console.log(choice) // { text: 'Black', value: 'black' }
317
+ * ```
318
+ *
319
+ * @title Show Choices
320
+ * @method player.showChoices(text,choices)
321
+ * @param {string} text
322
+ * @param {Array<{ text: string, value: any }>} choices
323
+ * @param {object} [options] Same options as the openDialog method
324
+ * @returns {Promise<Choice | null>}
325
+ * @memberof GuiManager
326
+ */
327
+ showChoices(
328
+ msg: string,
329
+ choices: Choice[],
330
+ options?: DialogOptions
331
+ ): Promise<Choice | null>;
332
+
333
+ /**
334
+ * Displays a notification . Opens the GUI named `rpg-notification`
335
+ *
336
+ * @title Displays a notification
337
+ * @method player.showNotification()
338
+ * @param {string} message - The message to display in the notification
339
+ * @param {object} options - An object containing options for the notification
340
+ * @param {number} options.time - The time to display the notification for (in ms). Default: 2000ms
341
+ * @param {string} options.icon - The icon to display in the notification. Put the identifier of the spritesheet (defined on the client side)
342
+ * @param {string} options.sound - The sound to play when the notification is shown. Set the sound ID (defined on the client side)
343
+ * @returns {void}
344
+ * @memberof GuiManager
345
+ */
346
+ showNotification(
347
+ message: string,
348
+ options?: { time?: number; icon?: string; sound?: string }
349
+ ): Promise<any>;
350
+ /**
351
+ * Calls main menu. Opens the GUI named `rpg-main-menu`
352
+ *
353
+ * @title Call Main Menu
354
+ * @method player.callMainMenu()
355
+ * @returns {void}
356
+ * @memberof GuiManager
357
+ */
358
+ callMainMenu(): void;
359
+ callShop(items: any[]): void;
360
+ gui(guiId: string): Gui;
361
+ removeGui(guiId: string, data?: any): void;
362
+ showAttachedGui(players?: RpgPlayer[] | RpgPlayer): void;
363
+ hideAttachedGui(players?: RpgPlayer[] | RpgPlayer): void;
364
+ }
package/src/RpgServer.ts CHANGED
@@ -227,20 +227,251 @@ export interface RpgPlayerHooks {
227
227
  canChangeMap?: (player: RpgPlayer, nextMap: RpgClassMap<RpgMap>) => boolean | Promise<boolean>
228
228
  }
229
229
 
230
+ /**
231
+ * Event hooks interface for handling various event lifecycle methods
232
+ *
233
+ * @interface RpgEventHooks
234
+ * @since 4.0.0
235
+ */
230
236
  export interface RpgEventHooks {
237
+ /**
238
+ * Called as soon as the event is created on the map
239
+ *
240
+ * @param {RpgEvent} event - The event instance being initialized
241
+ * @returns {any}
242
+ * @memberof RpgEventHooks
243
+ * @example
244
+ * ```ts
245
+ * const eventHooks: RpgEventHooks = {
246
+ * onInit(event) {
247
+ * console.log(`Event ${event.name} initialized`)
248
+ * event.graphic('default-sprite')
249
+ * }
250
+ * }
251
+ * ```
252
+ */
231
253
  onInit?: (event: RpgEvent) => any,
254
+
255
+ /**
256
+ * Called when the event collides with a player and the player presses the action key
257
+ *
258
+ * @param {RpgEvent} event - The event being interacted with
259
+ * @param {RpgPlayer} player - The player performing the action
260
+ * @returns {any}
261
+ * @memberof RpgEventHooks
262
+ * @example
263
+ * ```ts
264
+ * const eventHooks: RpgEventHooks = {
265
+ * onAction(event, player) {
266
+ * player.showText('You activated the chest!')
267
+ * player.addItem('POTION', 1)
268
+ * }
269
+ * }
270
+ * ```
271
+ */
232
272
  onAction?: (event: RpgEvent, player: RpgPlayer) => any
273
+
274
+ /**
275
+ * Called before an event object is created and added to the map
276
+ * Allows modification of event properties before instantiation
277
+ *
278
+ * @param {any} object - The event object data before creation
279
+ * @param {RpgMap} map - The map where the event will be created
280
+ * @returns {any}
281
+ * @memberof RpgEventHooks
282
+ * @example
283
+ * ```ts
284
+ * const eventHooks: RpgEventHooks = {
285
+ * onBeforeCreated(object, map) {
286
+ * // Modify event properties based on map conditions
287
+ * if (map.id === 'dungeon') {
288
+ * object.graphic = 'monster-sprite'
289
+ * }
290
+ * }
291
+ * }
292
+ * ```
293
+ */
233
294
  onBeforeCreated?: (object: any, map: RpgMap) => any
295
+
296
+ /**
297
+ * Called when a player or another event enters a shape attached to this event
298
+ *
299
+ * @param {RpgEvent} event - The event with the attached shape
300
+ * @param {RpgPlayer} player - The player entering the shape
301
+ * @param {RpgShape} shape - The shape being entered
302
+ * @returns {any}
303
+ * @since 4.1.0
304
+ * @memberof RpgEventHooks
305
+ * @example
306
+ * ```ts
307
+ * const eventHooks: RpgEventHooks = {
308
+ * onDetectInShape(event, player, shape) {
309
+ * console.log(`Player ${player.name} entered detection zone`)
310
+ * player.showText('You are being watched...')
311
+ * }
312
+ * }
313
+ * ```
314
+ */
234
315
  onDetectInShape?: (event: RpgEvent, player: RpgPlayer, shape: RpgShape) => any
316
+
317
+ /**
318
+ * Called when a player or another event leaves a shape attached to this event
319
+ *
320
+ * @param {RpgEvent} event - The event with the attached shape
321
+ * @param {RpgPlayer} player - The player leaving the shape
322
+ * @param {RpgShape} shape - The shape being left
323
+ * @returns {any}
324
+ * @since 4.1.0
325
+ * @memberof RpgEventHooks
326
+ * @example
327
+ * ```ts
328
+ * const eventHooks: RpgEventHooks = {
329
+ * onDetectOutShape(event, player, shape) {
330
+ * console.log(`Player ${player.name} left detection zone`)
331
+ * player.showText('You escaped the watch...')
332
+ * }
333
+ * }
334
+ * ```
335
+ */
235
336
  onDetectOutShape?: (event: RpgEvent, player: RpgPlayer, shape: RpgShape) => any
337
+
338
+ /**
339
+ * Called when the event enters a shape on the map
340
+ *
341
+ * @param {RpgEvent} event - The event entering the shape
342
+ * @param {RpgShape} shape - The shape being entered
343
+ * @returns {any}
344
+ * @memberof RpgEventHooks
345
+ * @example
346
+ * ```ts
347
+ * const eventHooks: RpgEventHooks = {
348
+ * onInShape(event, shape) {
349
+ * console.log(`Event entered shape: ${shape.id}`)
350
+ * event.speed = 1 // Slow down in this area
351
+ * }
352
+ * }
353
+ * ```
354
+ */
236
355
  onInShape?: (event: RpgEvent, shape: RpgShape) => any
356
+
357
+ /**
358
+ * Called when the event leaves a shape on the map
359
+ *
360
+ * @param {RpgEvent} event - The event leaving the shape
361
+ * @param {RpgShape} shape - The shape being left
362
+ * @returns {any}
363
+ * @memberof RpgEventHooks
364
+ * @example
365
+ * ```ts
366
+ * const eventHooks: RpgEventHooks = {
367
+ * onOutShape(event, shape) {
368
+ * console.log(`Event left shape: ${shape.id}`)
369
+ * event.speed = 3 // Resume normal speed
370
+ * }
371
+ * }
372
+ * ```
373
+ */
237
374
  onOutShape?: (event: RpgEvent, shape: RpgShape) => any
375
+
376
+ /**
377
+ * Called when the event collides with a player (without requiring action key press)
378
+ *
379
+ * @param {RpgEvent} event - The event touching the player
380
+ * @param {RpgPlayer} player - The player being touched
381
+ * @returns {any}
382
+ * @memberof RpgEventHooks
383
+ * @example
384
+ * ```ts
385
+ * const eventHooks: RpgEventHooks = {
386
+ * onPlayerTouch(event, player) {
387
+ * player.hp -= 10 // Damage on touch
388
+ * player.showText('Ouch! You touched a spike!')
389
+ * }
390
+ * }
391
+ * ```
392
+ */
238
393
  onPlayerTouch?: (event: RpgEvent, player: RpgPlayer) => any
394
+
395
+ /**
396
+ * Called whenever any event on the map (including itself) is executed or changes state
397
+ * Useful for creating reactive events that respond to map state changes
398
+ *
399
+ * @param {RpgEvent} event - The event listening for changes
400
+ * @param {RpgPlayer} player - The player involved in the change
401
+ * @returns {any}
402
+ * @memberof RpgEventHooks
403
+ * @example
404
+ * ```ts
405
+ * const eventHooks: RpgEventHooks = {
406
+ * onChanges(event, player) {
407
+ * // Change chest graphic based on game state
408
+ * if (player.getVariable('BATTLE_END')) {
409
+ * event.graphic('chest-open')
410
+ * } else {
411
+ * event.graphic('chest-close')
412
+ * }
413
+ * }
414
+ * }
415
+ * ```
416
+ */
239
417
  onChanges?: (event: RpgEvent, player: RpgPlayer) => any
240
418
  }
241
419
 
420
+ /**
421
+ * Map hooks interface for handling map lifecycle events
422
+ *
423
+ * @interface RpgMapHooks
424
+ * @since 4.0.0
425
+ */
242
426
  export interface RpgMapHooks {
243
- onBeforeUpdate<T = RpgMap>(mapData: any, map: T): T
427
+ /**
428
+ * Called before a map is updated with new data
429
+ * Allows modification of map data before the update is applied
430
+ *
431
+ * The `mapData` parameter contains the loaded map data (retrieved from request body)
432
+ * You can modify the map before the update is processed
433
+ *
434
+ * @template T - Type of the incoming map data
435
+ * @template U - Type of the map instance (defaults to RpgMap)
436
+ * @param {T} mapData - The map data loaded from external source (e.g., request body)
437
+ * @param {U} map - The current map instance being updated
438
+ * @returns {U | Promise<U>} The modified map instance or a promise resolving to it
439
+ * @memberof RpgMapHooks
440
+ * @example
441
+ * ```ts
442
+ * const mapHooks: RpgMapHooks = {
443
+ * onBeforeUpdate(mapData, map) {
444
+ * // Modify map properties based on incoming data
445
+ * if (mapData.weather === 'rain') {
446
+ * map.setWeatherEffect('rain')
447
+ * }
448
+ *
449
+ * // Add custom properties from external data
450
+ * map.customProperty = mapData.customValue
451
+ *
452
+ * return map
453
+ * }
454
+ * }
455
+ * ```
456
+ *
457
+ * @example
458
+ * ```ts
459
+ * // Async example with database operations
460
+ * const mapHooks: RpgMapHooks = {
461
+ * async onBeforeUpdate(mapData, map) {
462
+ * // Load additional data from database
463
+ * const additionalData = await database.getMapExtras(map.id)
464
+ *
465
+ * // Apply modifications
466
+ * map.events = [...map.events, ...additionalData.events]
467
+ * map.npcs = additionalData.npcs
468
+ *
469
+ * return map
470
+ * }
471
+ * }
472
+ * ```
473
+ */
474
+ onBeforeUpdate<T, U = RpgMap>(mapData: T, map: U): U | Promise<U>
244
475
  }
245
476
 
246
477
  export interface RpgServer {
@@ -1,3 +1,4 @@
1
1
  import { Context } from "@signe/di";
2
2
 
3
3
  export const context = new Context();
4
+ context['side'] = 'server'
File without changes
File without changes