@rpgjs/server 5.0.0-alpha.8 → 5.0.0-beta.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 (116) hide show
  1. package/dist/Gui/DialogGui.d.ts +5 -0
  2. package/dist/Gui/GameoverGui.d.ts +23 -0
  3. package/dist/Gui/Gui.d.ts +6 -0
  4. package/dist/Gui/MenuGui.d.ts +22 -3
  5. package/dist/Gui/NotificationGui.d.ts +1 -2
  6. package/dist/Gui/SaveLoadGui.d.ts +13 -0
  7. package/dist/Gui/ShopGui.d.ts +28 -3
  8. package/dist/Gui/TitleGui.d.ts +23 -0
  9. package/dist/Gui/index.d.ts +10 -1
  10. package/dist/Player/BattleManager.d.ts +44 -32
  11. package/dist/Player/ClassManager.d.ts +24 -4
  12. package/dist/Player/ComponentManager.d.ts +100 -7
  13. package/dist/Player/Components.d.ts +345 -0
  14. package/dist/Player/EffectManager.d.ts +50 -4
  15. package/dist/Player/ElementManager.d.ts +77 -4
  16. package/dist/Player/GoldManager.d.ts +1 -1
  17. package/dist/Player/GuiManager.d.ts +233 -5
  18. package/dist/Player/ItemFixture.d.ts +1 -1
  19. package/dist/Player/ItemManager.d.ts +431 -4
  20. package/dist/Player/MoveManager.d.ts +301 -34
  21. package/dist/Player/ParameterManager.d.ts +364 -28
  22. package/dist/Player/Player.d.ts +558 -14
  23. package/dist/Player/SkillManager.d.ts +187 -13
  24. package/dist/Player/StateManager.d.ts +75 -4
  25. package/dist/Player/VariableManager.d.ts +62 -4
  26. package/dist/RpgServer.d.ts +278 -63
  27. package/dist/RpgServerEngine.d.ts +2 -1
  28. package/dist/decorators/event.d.ts +46 -0
  29. package/dist/decorators/map.d.ts +299 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.js +17920 -29866
  32. package/dist/index.js.map +1 -1
  33. package/dist/logs/log.d.ts +2 -3
  34. package/dist/module-CaCW1SDh.js +11018 -0
  35. package/dist/module-CaCW1SDh.js.map +1 -0
  36. package/dist/module.d.ts +43 -1
  37. package/dist/node/connection.d.ts +51 -0
  38. package/dist/node/index.d.ts +5 -0
  39. package/dist/node/index.js +551 -0
  40. package/dist/node/index.js.map +1 -0
  41. package/dist/node/map.d.ts +16 -0
  42. package/dist/node/room.d.ts +21 -0
  43. package/dist/node/transport.d.ts +28 -0
  44. package/dist/node/types.d.ts +47 -0
  45. package/dist/presets/index.d.ts +0 -9
  46. package/dist/rooms/BaseRoom.d.ts +132 -0
  47. package/dist/rooms/lobby.d.ts +10 -2
  48. package/dist/rooms/map.d.ts +1359 -32
  49. package/dist/services/save.d.ts +43 -0
  50. package/dist/storage/index.d.ts +1 -0
  51. package/dist/storage/localStorage.d.ts +23 -0
  52. package/package.json +25 -10
  53. package/src/Gui/DialogGui.ts +19 -4
  54. package/src/Gui/GameoverGui.ts +39 -0
  55. package/src/Gui/Gui.ts +23 -1
  56. package/src/Gui/MenuGui.ts +155 -6
  57. package/src/Gui/NotificationGui.ts +1 -2
  58. package/src/Gui/SaveLoadGui.ts +60 -0
  59. package/src/Gui/ShopGui.ts +146 -16
  60. package/src/Gui/TitleGui.ts +39 -0
  61. package/src/Gui/index.ts +15 -2
  62. package/src/Player/BattleManager.ts +39 -56
  63. package/src/Player/ClassManager.ts +82 -74
  64. package/src/Player/ComponentManager.ts +401 -37
  65. package/src/Player/Components.ts +380 -0
  66. package/src/Player/EffectManager.ts +50 -96
  67. package/src/Player/ElementManager.ts +74 -152
  68. package/src/Player/GuiManager.ts +284 -149
  69. package/src/Player/ItemManager.ts +747 -341
  70. package/src/Player/MoveManager.ts +1532 -750
  71. package/src/Player/ParameterManager.ts +636 -106
  72. package/src/Player/Player.ts +1273 -79
  73. package/src/Player/SkillManager.ts +558 -197
  74. package/src/Player/StateManager.ts +131 -258
  75. package/src/Player/VariableManager.ts +85 -157
  76. package/src/RpgServer.ts +293 -62
  77. package/src/decorators/event.ts +61 -0
  78. package/src/decorators/map.ts +343 -0
  79. package/src/index.ts +11 -1
  80. package/src/logs/log.ts +10 -3
  81. package/src/module.ts +126 -3
  82. package/src/node/connection.ts +254 -0
  83. package/src/node/index.ts +22 -0
  84. package/src/node/map.ts +328 -0
  85. package/src/node/room.ts +63 -0
  86. package/src/node/transport.ts +532 -0
  87. package/src/node/types.ts +61 -0
  88. package/src/presets/index.ts +1 -10
  89. package/src/rooms/BaseRoom.ts +232 -0
  90. package/src/rooms/lobby.ts +25 -7
  91. package/src/rooms/map.ts +2682 -206
  92. package/src/services/save.ts +147 -0
  93. package/src/storage/index.ts +1 -0
  94. package/src/storage/localStorage.ts +76 -0
  95. package/tests/battle.spec.ts +375 -0
  96. package/tests/change-map.spec.ts +72 -0
  97. package/tests/class.spec.ts +274 -0
  98. package/tests/custom-websocket.spec.ts +127 -0
  99. package/tests/effect.spec.ts +219 -0
  100. package/tests/element.spec.ts +221 -0
  101. package/tests/event.spec.ts +80 -0
  102. package/tests/gold.spec.ts +99 -0
  103. package/tests/item.spec.ts +609 -0
  104. package/tests/module.spec.ts +38 -0
  105. package/tests/move.spec.ts +601 -0
  106. package/tests/node-transport.spec.ts +223 -0
  107. package/tests/player-param.spec.ts +45 -0
  108. package/tests/prediction-reconciliation.spec.ts +182 -0
  109. package/tests/random-move.spec.ts +65 -0
  110. package/tests/skill.spec.ts +658 -0
  111. package/tests/state.spec.ts +467 -0
  112. package/tests/variable.spec.ts +185 -0
  113. package/tests/world-maps.spec.ts +896 -0
  114. package/vite.config.ts +36 -3
  115. package/dist/Player/Event.d.ts +0 -0
  116. package/src/Player/Event.ts +0 -0
@@ -46,103 +46,79 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
46
46
  return class extends Base {
47
47
  _statesEfficiency = signal<any[]>([]);
48
48
 
49
+ private _getStateMap(required: boolean = true) {
50
+ // Use this.map directly to support both RpgMap and LobbyRoom
51
+ const map = (this as any).getCurrentMap?.() || (this as any).map;
52
+ if (required && (!map || !map.database)) {
53
+ throw new Error('Player must be on a map to resolve states');
54
+ }
55
+ return map;
56
+ }
57
+
58
+ private _resolveStateInput(
59
+ stateInput: StateClass | string,
60
+ databaseByIdOverride?: (id: string) => any
61
+ ) {
62
+ if (isString(stateInput)) {
63
+ return databaseByIdOverride
64
+ ? databaseByIdOverride(stateInput)
65
+ : (this as any).databaseById(stateInput);
66
+ }
67
+ return stateInput;
68
+ }
69
+
70
+ private _createStateInstance(stateClass: StateClass) {
71
+ return new (stateClass as StateClass)();
72
+ }
73
+
49
74
  /**
50
- * Recovers the player's states defense on inventory. This list is generated from the `statesDefense` property defined on the weapons or armors equipped.
51
- * If several items have the same element, only the highest rate will be taken into account.
52
- *
53
- * Gets the defensive capabilities against various states from equipped items.
54
- * The system automatically consolidates multiple defensive items, keeping only
55
- * the highest protection rate for each state type. This provides comprehensive
56
- * protection against debuffs and negative status effects.
57
- *
58
- * @returns Array of state defense objects with rate and state properties
59
- *
60
- * @example
61
- * ```ts
62
- * import { Armor, State } from '@rpgjs/server'
63
- *
64
- * @State({
65
- * name: 'Paralyze'
66
- * })
67
- * class Paralyze {}
68
- *
69
- * @Armor({
70
- * name: 'Shield',
71
- * statesDefense: [{ rate: 1, state: Paralyze }]
72
- * })
73
- * class Shield {}
74
- *
75
- * @Armor({
76
- * name: 'FireShield',
77
- * statesDefense: [{ rate: 0.5, state: Paralyze }]
78
- * })
79
- * class FireShield {}
80
- *
81
- * player.addItem(Shield)
82
- * player.addItem(FireShield)
83
- * player.equip(Shield)
84
- * player.equip(FireShield)
85
- *
86
- * console.log(player.statesDefense) // [{ rate: 1, state: instance of Paralyze }]
87
- *
88
- * // Check specific state defense
89
- * const paralyzeDefense = player.statesDefense.find(def => def.state instanceof Paralyze);
90
- * if (paralyzeDefense) {
91
- * console.log(`Paralyze defense rate: ${paralyzeDefense.rate}`);
92
- * }
93
- * ```
75
+ * Create a state instance without side effects.
94
76
  */
95
- get statesDefense(): { rate: number; state: any }[] {
96
- return (this as any).getFeature("statesDefense", "state");
77
+ createStateInstance(stateInput: StateClass | string) {
78
+ const stateClass = this._resolveStateInput(stateInput);
79
+ const instance = this._createStateInstance(stateClass as StateClass);
80
+ return { stateClass, instance };
97
81
  }
98
82
 
99
83
  /**
100
- * Set or retrieves all the states where the player is vulnerable or not.
101
- *
102
- * Manages the player's state efficiency modifiers, which determine how
103
- * effective different states are against this player. Values greater than 1
104
- * indicate vulnerability, while values less than 1 indicate resistance.
105
- * This combines both class-based efficiency and player-specific modifiers.
106
- *
107
- * @returns Array of state efficiency objects with rate and state properties
108
- *
109
- * @example
110
- * ```ts
111
- * import { Class, State } from '@rpgjs/server'
112
- *
113
- * @State({
114
- * name: 'Paralyze'
115
- * })
116
- * class Paralyze {}
117
- *
118
- * @State({
119
- * name: 'Sleep'
120
- * })
121
- * class Sleep {}
122
- *
123
- * @Class({
124
- * name: 'Fighter',
125
- * statesEfficiency: [{ rate: 1, state: Paralyze }]
126
- * })
127
- * class Hero {}
128
- *
129
- * player.setClass(Hero)
130
- *
131
- * console.log(player.statesEfficiency) // [{ rate: 1, instance of Paralyze }]
132
- *
133
- * player.statesEfficiency = [{ rate: 2, state: Sleep }]
134
- *
135
- * console.log(player.statesEfficiency) // [{ rate: 1, state: instance of Paralyze }, { rate: 2, state: instance of Sleep }]
136
- *
137
- * // Check for vulnerabilities
138
- * const vulnerabilities = player.statesEfficiency.filter(eff => eff.rate > 1);
139
- * console.log('Vulnerable to states:', vulnerabilities.map(v => v.state.name));
140
- *
141
- * // Check for resistances
142
- * const resistances = player.statesEfficiency.filter(eff => eff.rate < 1);
143
- * console.log('Resistant to states:', resistances.map(r => r.state.name));
144
- * ```
84
+ * Resolve state snapshot entries into state instances without side effects.
145
85
  */
86
+ resolveStatesSnapshot(snapshot: { states?: any[] }, mapOverride?: any) {
87
+ if (!snapshot || !Array.isArray(snapshot.states)) {
88
+ return snapshot;
89
+ }
90
+
91
+ const map = mapOverride ?? this._getStateMap(false);
92
+ if (!map || !map.database) {
93
+ return snapshot;
94
+ }
95
+
96
+ const databaseByIdOverride = (id: string) => {
97
+ const data = map.database()[id];
98
+ if (!data) {
99
+ throw new Error(
100
+ `The ID=${id} data is not found in the database. Add the data in the property "database"`
101
+ );
102
+ }
103
+ return data;
104
+ };
105
+
106
+ const states = snapshot.states.map((entry: any) => {
107
+ const stateId = isString(entry) ? entry : entry?.id;
108
+ if (!stateId) {
109
+ return entry;
110
+ }
111
+ const stateClass = this._resolveStateInput(stateId, databaseByIdOverride);
112
+ return this._createStateInstance(stateClass as StateClass);
113
+ });
114
+
115
+ return { ...snapshot, states };
116
+ }
117
+
118
+ get statesDefense(): { rate: number; state: any }[] {
119
+ return (this as any).getFeature("statesDefense", "state");
120
+ }
121
+
146
122
  get statesEfficiency() {
147
123
  return this._statesEfficiency;
148
124
  }
@@ -151,35 +127,6 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
151
127
  this._statesEfficiency = val;
152
128
  }
153
129
 
154
- /**
155
- * Apply states to a player from skill or item effects
156
- *
157
- * Processes state application and removal based on skill or item effects.
158
- * This method handles both adding beneficial states and removing negative ones,
159
- * with proper chance calculation and resistance checks.
160
- *
161
- * @param player - The target player to apply states to
162
- * @param states - Object containing arrays of states to add or remove
163
- *
164
- * @example
165
- * ```ts
166
- * // Apply states from a healing skill
167
- * const healingStates = {
168
- * addStates: [{ state: Regeneration, rate: 0.8 }],
169
- * removeStates: [{ state: Poison, rate: 1.0 }]
170
- * };
171
- * player.applyStates(targetPlayer, healingStates);
172
- *
173
- * // Apply debuff from an enemy attack
174
- * const debuffStates = {
175
- * addStates: [
176
- * { state: Paralyze, rate: 0.3 },
177
- * { state: Slow, rate: 0.5 }
178
- * ]
179
- * };
180
- * player.applyStates(targetPlayer, debuffStates);
181
- * ```
182
- */
183
130
  applyStates(
184
131
  player: RpgPlayer,
185
132
  { addStates, removeStates }
@@ -196,40 +143,6 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
196
143
  }
197
144
  }
198
145
 
199
- /**
200
- * Get a state to the player. Returns `null` if the state is not present on the player
201
- *
202
- * Retrieves a specific state instance from the player's active states.
203
- * This is useful for checking state properties, duration, or performing
204
- * state-specific operations. Returns null if the state is not currently active.
205
- *
206
- * @param stateClass - The state class constructor or state ID to search for
207
- * @returns The state instance if found, null otherwise
208
- *
209
- * @example
210
- * ```ts
211
- * import Paralyze from 'your-database/states/paralyze'
212
- *
213
- * // Check if player has a specific state
214
- * const paralyzeState = player.getState(Paralyze);
215
- * if (paralyzeState) {
216
- * console.log('Player is paralyzed');
217
- * console.log('Remaining duration:', paralyzeState.duration);
218
- * }
219
- *
220
- * // Check using string ID
221
- * const poisonState = player.getState('poison');
222
- * if (poisonState) {
223
- * console.log('Player is poisoned');
224
- * }
225
- *
226
- * // Use in conditional logic
227
- * if (player.getState(Sleep)) {
228
- * console.log('Player cannot act while sleeping');
229
- * return; // Skip player turn
230
- * }
231
- * ```
232
- */
233
146
  getState(stateClass: StateClass | string) {
234
147
  if (isString(stateClass)) stateClass = (this as any).databaseById(stateClass);
235
148
  return this.states().find((state) => {
@@ -240,54 +153,6 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
240
153
  });
241
154
  }
242
155
 
243
- /**
244
- * Adds a state to the player. Set the chance between 0 and 1 that the state can apply
245
- *
246
- * Attempts to apply a state to the player with a specified success chance.
247
- * The method considers state resistance, efficiency modifiers, and random chance
248
- * to determine if the state is successfully applied. If successful, the state
249
- * is added to the player's active states list.
250
- *
251
- * @param stateClass - The state class constructor or state ID to apply
252
- * @param chance - Probability of successful application (0-1, default 1)
253
- * @returns The state instance if successfully applied, null if already present
254
- * @throws StateLog.addFailed if the chance roll fails
255
- *
256
- * @example
257
- * ```ts
258
- * import Paralyze from 'your-database/states/paralyze'
259
- *
260
- * try {
261
- * // Attempt to apply paralyze with 100% chance
262
- * const state = player.addState(Paralyze);
263
- * if (state) {
264
- * console.log('Paralyze applied successfully');
265
- * }
266
- * } catch (err) {
267
- * console.log('Failed to apply paralyze:', err.msg);
268
- * }
269
- *
270
- * // Apply with reduced chance
271
- * try {
272
- * player.addState(Poison, 0.3); // 30% chance
273
- * } catch (err) {
274
- * console.log('Poison application failed');
275
- * }
276
- *
277
- * // Apply multiple states with different chances
278
- * const debuffs = [
279
- * { state: Slow, chance: 0.8 },
280
- * { state: Weak, chance: 0.6 }
281
- * ];
282
- * debuffs.forEach(({ state, chance }) => {
283
- * try {
284
- * player.addState(state, chance);
285
- * } catch (err) {
286
- * // Handle failed applications
287
- * }
288
- * });
289
- * ```
290
- */
291
156
  addState(stateClass: StateClass | string, chance = 1): object | null {
292
157
  const state = this.getState(stateClass);
293
158
  if (isString(stateClass)) {
@@ -298,7 +163,7 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
298
163
  throw StateLog.addFailed(stateClass);
299
164
  }
300
165
  //const efficiency = this.findStateEfficiency(stateClass)
301
- const instance = new (stateClass as StateClass)();
166
+ const instance = this._createStateInstance(stateClass as StateClass);
302
167
  this.states().push(instance);
303
168
  this.applyStates(<any>this, instance);
304
169
  return instance;
@@ -306,52 +171,6 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
306
171
  return null;
307
172
  }
308
173
 
309
- /**
310
- * Remove a state to the player. Set the chance between 0 and 1 that the state can be removed
311
- *
312
- * Attempts to remove a state from the player with a specified success chance.
313
- * This is useful for cure spells, items, or time-based state removal.
314
- * The method considers removal resistance and random chance.
315
- *
316
- * @param stateClass - The state class constructor or state ID to remove
317
- * @param chance - Probability of successful removal (0-1, default 1)
318
- * @throws StateLog.removeFailed if the chance roll fails
319
- * @throws StateLog.notApplied if the state is not currently active
320
- *
321
- * @example
322
- * ```ts
323
- * import Paralyze from 'your-database/states/paralyze'
324
- *
325
- * try {
326
- * // Attempt to remove paralyze with 100% chance
327
- * player.removeState(Paralyze);
328
- * console.log('Paralyze removed successfully');
329
- * } catch (err) {
330
- * if (err.id === 'STATE_NOT_APPLIED') {
331
- * console.log('Player was not paralyzed');
332
- * } else {
333
- * console.log('Failed to remove paralyze:', err.msg);
334
- * }
335
- * }
336
- *
337
- * // Remove with reduced chance (for weak cure spells)
338
- * try {
339
- * player.removeState(Poison, 0.7); // 70% chance
340
- * } catch (err) {
341
- * console.log('Cure failed');
342
- * }
343
- *
344
- * // Remove all negative states (cure-all effect)
345
- * const negativeStates = [Poison, Paralyze, Sleep, Slow];
346
- * negativeStates.forEach(state => {
347
- * try {
348
- * player.removeState(state);
349
- * } catch (err) {
350
- * // State wasn't active, continue
351
- * }
352
- * });
353
- * ```
354
- */
355
174
  removeState(stateClass: StateClass | string, chance = 1) {
356
175
  const index = this.states().findIndex((state) => {
357
176
  if (isString(stateClass)) {
@@ -369,12 +188,6 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
369
188
  }
370
189
  }
371
190
 
372
- /**
373
- * Find state efficiency modifier for a specific state class
374
- *
375
- * @param stateClass - The state class to find efficiency for
376
- * @returns The efficiency object if found, undefined otherwise
377
- */
378
191
  findStateEfficiency(stateClass) {
379
192
  return this.statesEfficiency().find((state) =>
380
193
  isInstanceOf(state.state, stateClass)
@@ -384,7 +197,67 @@ export function WithStateManager<TBase extends PlayerCtor>(Base: TBase) {
384
197
  }
385
198
 
386
199
  /**
387
- * Type helper to extract the interface from the WithStateManager mixin
388
- * This provides the type without duplicating method signatures
200
+ * Interface for State Manager functionality
201
+ *
202
+ * Provides state management capabilities including state defense, efficiency modifiers,
203
+ * and state application/removal. This interface defines the public API of the StateManager mixin.
389
204
  */
390
- export type IStateManager = InstanceType<ReturnType<typeof WithStateManager>>;
205
+ export interface IStateManager {
206
+ /**
207
+ * Gets the defensive capabilities against various states from equipped items
208
+ *
209
+ * @returns Array of state defense objects with rate and state properties
210
+ */
211
+ statesDefense: { rate: number; state: any }[];
212
+
213
+ /**
214
+ * Manages the player's state efficiency modifiers
215
+ *
216
+ * @returns Signal containing array of state efficiency objects
217
+ */
218
+ statesEfficiency: any;
219
+
220
+ /**
221
+ * Apply states to a player from skill or item effects
222
+ *
223
+ * @param player - The target player to apply states to
224
+ * @param states - Object containing arrays of states to add or remove
225
+ */
226
+ applyStates(player: RpgPlayer, states: { addStates?: Array<{ state: any; rate: number }>; removeStates?: Array<{ state: any; rate: number }> }): void;
227
+
228
+ /**
229
+ * Get a state to the player. Returns null if the state is not present
230
+ *
231
+ * @param stateClass - The state class constructor or state ID to search for
232
+ * @returns The state instance if found, null otherwise
233
+ */
234
+ getState(stateClass: StateClass | string): any | null;
235
+
236
+ /**
237
+ * Adds a state to the player
238
+ *
239
+ * @param stateClass - The state class constructor or state ID to apply
240
+ * @param chance - Probability of successful application (0-1, default 1)
241
+ * @returns The state instance if successfully applied, null if already present
242
+ * @throws StateLog.addFailed if the chance roll fails
243
+ */
244
+ addState(stateClass: StateClass | string, chance?: number): object | null;
245
+
246
+ /**
247
+ * Remove a state to the player
248
+ *
249
+ * @param stateClass - The state class constructor or state ID to remove
250
+ * @param chance - Probability of successful removal (0-1, default 1)
251
+ * @throws StateLog.removeFailed if the chance roll fails
252
+ * @throws StateLog.notApplied if the state is not currently active
253
+ */
254
+ removeState(stateClass: StateClass | string, chance?: number): void;
255
+
256
+ /**
257
+ * Find state efficiency modifier for a specific state class
258
+ *
259
+ * @param stateClass - The state class to find efficiency for
260
+ * @returns The efficiency object if found, undefined otherwise
261
+ */
262
+ findStateEfficiency(stateClass: any): any | undefined;
263
+ }