@rpgjs/client 5.0.0-alpha.3 → 5.0.0-alpha.30

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 (275) hide show
  1. package/dist/Game/AnimationManager.d.ts +8 -0
  2. package/dist/{index19.js → Game/AnimationManager.js} +4 -3
  3. package/dist/Game/AnimationManager.js.map +1 -0
  4. package/dist/{index30.js → Game/Event.js} +2 -2
  5. package/dist/Game/Event.js.map +1 -0
  6. package/dist/Game/Map.d.ts +8 -1
  7. package/dist/Game/Map.js +54 -0
  8. package/dist/Game/Map.js.map +1 -0
  9. package/dist/Game/Object.d.ts +129 -0
  10. package/dist/Game/Object.js +218 -0
  11. package/dist/Game/Object.js.map +1 -0
  12. package/dist/{index29.js → Game/Player.js} +2 -2
  13. package/dist/Game/Player.js.map +1 -0
  14. package/dist/Gui/Gui.d.ts +177 -5
  15. package/dist/Gui/Gui.js +478 -0
  16. package/dist/Gui/Gui.js.map +1 -0
  17. package/dist/Gui/NotificationManager.d.ts +23 -0
  18. package/dist/Gui/NotificationManager.js +51 -0
  19. package/dist/Gui/NotificationManager.js.map +1 -0
  20. package/dist/Resource.d.ts +97 -0
  21. package/dist/Resource.js +114 -0
  22. package/dist/Resource.js.map +1 -0
  23. package/dist/RpgClient.d.ts +259 -59
  24. package/dist/RpgClientEngine.d.ts +632 -9
  25. package/dist/RpgClientEngine.js +1262 -0
  26. package/dist/RpgClientEngine.js.map +1 -0
  27. package/dist/Sound.d.ts +199 -0
  28. package/dist/Sound.js +97 -0
  29. package/dist/Sound.js.map +1 -0
  30. package/dist/components/animations/animation.ce.js +21 -0
  31. package/dist/components/animations/animation.ce.js.map +1 -0
  32. package/dist/{index23.js → components/animations/hit.ce.js} +3 -3
  33. package/dist/components/animations/hit.ce.js.map +1 -0
  34. package/dist/components/animations/index.d.ts +4 -0
  35. package/dist/components/animations/index.js +10 -0
  36. package/dist/components/animations/index.js.map +1 -0
  37. package/dist/components/character.ce.js +316 -0
  38. package/dist/components/character.ce.js.map +1 -0
  39. package/dist/components/dynamics/parse-value.d.ts +1 -0
  40. package/dist/components/dynamics/parse-value.js +54 -0
  41. package/dist/components/dynamics/parse-value.js.map +1 -0
  42. package/dist/components/dynamics/text.ce.js +141 -0
  43. package/dist/components/dynamics/text.ce.js.map +1 -0
  44. package/dist/components/gui/box.ce.js +27 -0
  45. package/dist/components/gui/box.ce.js.map +1 -0
  46. package/dist/components/gui/dialogbox/index.ce.js +152 -0
  47. package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
  48. package/dist/components/gui/gameover.ce.js +141 -0
  49. package/dist/components/gui/gameover.ce.js.map +1 -0
  50. package/dist/components/gui/hud/hud.ce.js +35 -0
  51. package/dist/components/gui/hud/hud.ce.js.map +1 -0
  52. package/dist/components/gui/index.d.ts +15 -3
  53. package/dist/components/gui/menu/equip-menu.ce.js +349 -0
  54. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -0
  55. package/dist/components/gui/menu/exit-menu.ce.js +35 -0
  56. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -0
  57. package/dist/components/gui/menu/items-menu.ce.js +229 -0
  58. package/dist/components/gui/menu/items-menu.ce.js.map +1 -0
  59. package/dist/components/gui/menu/main-menu.ce.js +205 -0
  60. package/dist/components/gui/menu/main-menu.ce.js.map +1 -0
  61. package/dist/components/gui/menu/options-menu.ce.js +28 -0
  62. package/dist/components/gui/menu/options-menu.ce.js.map +1 -0
  63. package/dist/components/gui/menu/skills-menu.ce.js +53 -0
  64. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -0
  65. package/dist/components/gui/mobile/index.d.ts +8 -0
  66. package/dist/components/gui/mobile/index.js +24 -0
  67. package/dist/components/gui/mobile/index.js.map +1 -0
  68. package/dist/components/gui/mobile/mobile.ce.js +17 -0
  69. package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
  70. package/dist/components/gui/notification/notification.ce.js +38 -0
  71. package/dist/components/gui/notification/notification.ce.js.map +1 -0
  72. package/dist/components/gui/save-load.ce.js +242 -0
  73. package/dist/components/gui/save-load.ce.js.map +1 -0
  74. package/dist/components/gui/shop/shop.ce.js +322 -0
  75. package/dist/components/gui/shop/shop.ce.js.map +1 -0
  76. package/dist/components/gui/title-screen.ce.js +148 -0
  77. package/dist/components/gui/title-screen.ce.js.map +1 -0
  78. package/dist/components/index.d.ts +3 -1
  79. package/dist/components/prebuilt/hp-bar.ce.js +106 -0
  80. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
  81. package/dist/components/prebuilt/index.d.ts +19 -0
  82. package/dist/components/prebuilt/light-halo.ce.js +76 -0
  83. package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
  84. package/dist/components/scenes/canvas.ce.js +44 -0
  85. package/dist/components/scenes/canvas.ce.js.map +1 -0
  86. package/dist/components/scenes/draw-map.ce.js +34 -0
  87. package/dist/components/scenes/draw-map.ce.js.map +1 -0
  88. package/dist/{index13.js → components/scenes/event-layer.ce.js} +7 -6
  89. package/dist/components/scenes/event-layer.ce.js.map +1 -0
  90. package/dist/{index6.js → core/inject.js} +2 -2
  91. package/dist/core/inject.js.map +1 -0
  92. package/dist/core/setup.js +16 -0
  93. package/dist/core/setup.js.map +1 -0
  94. package/dist/index.d.ts +15 -1
  95. package/dist/index.js +40 -12
  96. package/dist/index.js.map +1 -1
  97. package/dist/module.d.ts +43 -4
  98. package/dist/module.js +175 -0
  99. package/dist/module.js.map +1 -0
  100. package/dist/node_modules/.pnpm/@signe_di@2.8.2/node_modules/@signe/di/dist/index.js +366 -0
  101. package/dist/node_modules/.pnpm/@signe_di@2.8.2/node_modules/@signe/di/dist/index.js.map +1 -0
  102. package/dist/{index27.js → node_modules/.pnpm/@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js} +229 -11
  103. package/dist/node_modules/.pnpm/@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js.map +1 -0
  104. package/dist/{index20.js → node_modules/.pnpm/@signe_room@2.8.2/node_modules/@signe/room/dist/index.js} +308 -40
  105. package/dist/node_modules/.pnpm/@signe_room@2.8.2/node_modules/@signe/room/dist/index.js.map +1 -0
  106. package/dist/{index26.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js} +1 -1
  107. package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
  108. package/dist/{index21.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/client/index.js} +5 -5
  109. package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  110. package/dist/{index17.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js} +89 -12
  111. package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js.map +1 -0
  112. package/dist/{index33.js → node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js} +1 -1
  113. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
  114. package/dist/{index31.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js} +2 -2
  115. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
  116. package/dist/{index32.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js} +1 -1
  117. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
  118. package/dist/{index34.js → node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js} +1 -1
  119. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
  120. package/dist/presets/animation.d.ts +31 -0
  121. package/dist/presets/animation.js +27 -0
  122. package/dist/presets/animation.js.map +1 -0
  123. package/dist/presets/faceset.d.ts +30 -0
  124. package/dist/presets/faceset.js +24 -0
  125. package/dist/presets/faceset.js.map +1 -0
  126. package/dist/presets/icon.d.ts +20 -0
  127. package/dist/presets/icon.js +15 -0
  128. package/dist/presets/icon.js.map +1 -0
  129. package/dist/presets/index.d.ts +123 -0
  130. package/dist/presets/index.js +16 -0
  131. package/dist/presets/index.js.map +1 -0
  132. package/dist/presets/lpc.d.ts +89 -0
  133. package/dist/presets/lpc.js +95 -0
  134. package/dist/presets/lpc.js.map +1 -0
  135. package/dist/{index25.js → presets/rmspritesheet.js} +1 -1
  136. package/dist/presets/rmspritesheet.js.map +1 -0
  137. package/dist/{index16.js → services/AbstractSocket.js} +1 -1
  138. package/dist/services/AbstractSocket.js.map +1 -0
  139. package/dist/services/keyboardControls.d.ts +15 -0
  140. package/dist/services/keyboardControls.js +21 -0
  141. package/dist/services/keyboardControls.js.map +1 -0
  142. package/dist/services/loadMap.d.ts +123 -2
  143. package/dist/{index7.js → services/loadMap.js} +12 -4
  144. package/dist/services/loadMap.js.map +1 -0
  145. package/dist/services/mmorpg.d.ts +16 -4
  146. package/dist/services/mmorpg.js +84 -0
  147. package/dist/services/mmorpg.js.map +1 -0
  148. package/dist/services/save.d.ts +19 -0
  149. package/dist/services/save.js +69 -0
  150. package/dist/services/save.js.map +1 -0
  151. package/dist/services/standalone.d.ts +65 -3
  152. package/dist/services/standalone.js +170 -0
  153. package/dist/services/standalone.js.map +1 -0
  154. package/dist/utils/getEntityProp.d.ts +39 -0
  155. package/dist/utils/getEntityProp.js +54 -0
  156. package/dist/utils/getEntityProp.js.map +1 -0
  157. package/package.json +24 -18
  158. package/src/Game/{EffectManager.ts → AnimationManager.ts} +3 -2
  159. package/src/Game/Map.ts +37 -2
  160. package/src/Game/Object.ts +296 -11
  161. package/src/Gui/Gui.ts +506 -18
  162. package/src/Gui/NotificationManager.ts +69 -0
  163. package/src/Resource.ts +150 -0
  164. package/src/RpgClient.ts +264 -58
  165. package/src/RpgClientEngine.ts +1421 -44
  166. package/src/Sound.ts +253 -0
  167. package/src/components/{effects → animations}/animation.ce +3 -6
  168. package/src/components/{effects → animations}/index.ts +1 -1
  169. package/src/components/character.ce +406 -40
  170. package/src/components/dynamics/parse-value.ts +80 -0
  171. package/src/components/dynamics/text.ce +183 -0
  172. package/src/components/gui/box.ce +17 -0
  173. package/src/components/gui/dialogbox/index.ce +204 -187
  174. package/src/components/gui/gameover.ce +158 -0
  175. package/src/components/gui/hud/hud.ce +56 -0
  176. package/src/components/gui/index.ts +30 -4
  177. package/src/components/gui/menu/equip-menu.ce +410 -0
  178. package/src/components/gui/menu/exit-menu.ce +41 -0
  179. package/src/components/gui/menu/items-menu.ce +317 -0
  180. package/src/components/gui/menu/main-menu.ce +291 -0
  181. package/src/components/gui/menu/options-menu.ce +35 -0
  182. package/src/components/gui/menu/skills-menu.ce +83 -0
  183. package/src/components/gui/mobile/index.ts +24 -0
  184. package/src/components/gui/mobile/mobile.ce +80 -0
  185. package/src/components/gui/notification/notification.ce +51 -0
  186. package/src/components/gui/save-load.ce +208 -0
  187. package/src/components/gui/shop/shop.ce +493 -0
  188. package/src/components/gui/title-screen.ce +163 -0
  189. package/src/components/index.ts +5 -1
  190. package/src/components/prebuilt/hp-bar.ce +255 -0
  191. package/src/components/prebuilt/index.ts +24 -0
  192. package/src/components/prebuilt/light-halo.ce +148 -0
  193. package/src/components/scenes/canvas.ce +19 -14
  194. package/src/components/scenes/draw-map.ce +21 -29
  195. package/src/components/scenes/event-layer.ce +10 -3
  196. package/src/components/scenes/transition.ce +60 -0
  197. package/src/core/setup.ts +2 -0
  198. package/src/index.ts +16 -2
  199. package/src/module.ts +145 -9
  200. package/src/presets/animation.ts +46 -0
  201. package/src/presets/faceset.ts +60 -0
  202. package/src/presets/icon.ts +17 -0
  203. package/src/presets/index.ts +9 -1
  204. package/src/presets/lpc.ts +108 -0
  205. package/src/services/keyboardControls.ts +20 -0
  206. package/src/services/loadMap.ts +132 -3
  207. package/src/services/mmorpg.ts +39 -5
  208. package/src/services/save.ts +103 -0
  209. package/src/services/standalone.ts +107 -15
  210. package/src/utils/getEntityProp.ts +87 -0
  211. package/tsconfig.json +1 -1
  212. package/vite.config.ts +5 -3
  213. package/CHANGELOG.md +0 -9
  214. package/dist/Game/EffectManager.d.ts +0 -5
  215. package/dist/components/effects/index.d.ts +0 -4
  216. package/dist/index10.js +0 -8
  217. package/dist/index10.js.map +0 -1
  218. package/dist/index11.js +0 -10
  219. package/dist/index11.js.map +0 -1
  220. package/dist/index12.js +0 -8
  221. package/dist/index12.js.map +0 -1
  222. package/dist/index13.js.map +0 -1
  223. package/dist/index14.js +0 -50
  224. package/dist/index14.js.map +0 -1
  225. package/dist/index15.js +0 -191
  226. package/dist/index15.js.map +0 -1
  227. package/dist/index16.js.map +0 -1
  228. package/dist/index17.js.map +0 -1
  229. package/dist/index18.js +0 -31
  230. package/dist/index18.js.map +0 -1
  231. package/dist/index19.js.map +0 -1
  232. package/dist/index2.js +0 -112
  233. package/dist/index2.js.map +0 -1
  234. package/dist/index20.js.map +0 -1
  235. package/dist/index21.js.map +0 -1
  236. package/dist/index22.js +0 -109
  237. package/dist/index22.js.map +0 -1
  238. package/dist/index23.js.map +0 -1
  239. package/dist/index24.js +0 -21
  240. package/dist/index24.js.map +0 -1
  241. package/dist/index25.js.map +0 -1
  242. package/dist/index26.js.map +0 -1
  243. package/dist/index27.js.map +0 -1
  244. package/dist/index28.js +0 -25
  245. package/dist/index28.js.map +0 -1
  246. package/dist/index29.js.map +0 -1
  247. package/dist/index3.js +0 -87
  248. package/dist/index3.js.map +0 -1
  249. package/dist/index30.js.map +0 -1
  250. package/dist/index31.js.map +0 -1
  251. package/dist/index32.js.map +0 -1
  252. package/dist/index33.js.map +0 -1
  253. package/dist/index34.js.map +0 -1
  254. package/dist/index35.js +0 -91
  255. package/dist/index35.js.map +0 -1
  256. package/dist/index36.js +0 -61
  257. package/dist/index36.js.map +0 -1
  258. package/dist/index37.js +0 -20
  259. package/dist/index37.js.map +0 -1
  260. package/dist/index38.js +0 -20
  261. package/dist/index38.js.map +0 -1
  262. package/dist/index4.js +0 -54
  263. package/dist/index4.js.map +0 -1
  264. package/dist/index5.js +0 -15
  265. package/dist/index5.js.map +0 -1
  266. package/dist/index6.js.map +0 -1
  267. package/dist/index7.js.map +0 -1
  268. package/dist/index8.js +0 -90
  269. package/dist/index8.js.map +0 -1
  270. package/dist/index9.js +0 -76
  271. package/dist/index9.js.map +0 -1
  272. package/src/components/gui/dialogbox/itemMenu.ce +0 -23
  273. package/src/components/gui/dialogbox/selection.ce +0 -67
  274. package/src/components/scenes/element-map.ce +0 -23
  275. /package/src/components/{effects → animations}/hit.ce +0 -0
@@ -1,7 +1,7 @@
1
- import { dset } from './index33.js';
2
- import z from './index34.js';
3
- import { syncClass, generateShortUUID as generateShortUUID$1, createStatesSnapshot, id, sync, persist, load, getByPath, DELETE_TOKEN } from './index17.js';
4
- import { signal } from './index27.js';
1
+ import { dset } from '../../../../../dset@3.1.4/node_modules/dset/dist/index.js';
2
+ import z from '../../../../../zod@3.24.2/node_modules/zod/lib/index.js';
3
+ import { createStatesSnapshotDeep, syncClass, generateShortUUID as generateShortUUID$1, load, id, sync, persist, getByPath, createStatesSnapshot, DELETE_TOKEN } from '../../../../../@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js';
4
+ import { signal } from '../../../../../@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js';
5
5
 
6
6
  var __defProp = Object.defineProperty;
7
7
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -521,6 +521,11 @@ var Server = class {
521
521
  this.subRoom = await this.createRoom();
522
522
  }
523
523
  }
524
+ async runGarbageCollector() {
525
+ await this.garbageCollector({
526
+ sessionExpiryTime: -1
527
+ });
528
+ }
524
529
  async garbageCollector(options) {
525
530
  const subRoom = await this.getSubRoom();
526
531
  if (!subRoom) return;
@@ -606,12 +611,104 @@ var Server = class {
606
611
  load(instance, tmpObject, true);
607
612
  }, "loadMemory");
608
613
  instance.$memoryAll = {};
614
+ instance.$autoSync = instance["autoSync"] !== false;
615
+ instance.$pendingSync = /* @__PURE__ */ new Map();
616
+ instance.$pendingInitialSync = /* @__PURE__ */ new Map();
609
617
  instance.$send = (conn, obj) => {
610
618
  return this.send(conn, obj, instance);
611
619
  };
612
620
  instance.$broadcast = (obj) => {
613
621
  return this.broadcast(obj, instance);
614
622
  };
623
+ instance.$applySync = () => {
624
+ let packet;
625
+ if (instance.$pendingSync.size > 0) {
626
+ if (options.getMemoryAll) {
627
+ buildObject(instance.$pendingSync, instance.$memoryAll);
628
+ }
629
+ packet = buildObject(instance.$pendingSync, instance.$memoryAll);
630
+ instance.$pendingSync.clear();
631
+ } else {
632
+ packet = instance.$memoryAll;
633
+ }
634
+ const pendingConnections = new Set(instance.$pendingInitialSync.keys());
635
+ for (const [conn, publicId] of instance.$pendingInitialSync) {
636
+ this.send(conn, {
637
+ type: "sync",
638
+ value: {
639
+ pId: publicId,
640
+ ...packet
641
+ }
642
+ }, instance);
643
+ }
644
+ instance.$pendingInitialSync.clear();
645
+ for (const conn of this.room.getConnections()) {
646
+ if (!pendingConnections.has(conn)) {
647
+ this.send(conn, {
648
+ type: "sync",
649
+ value: packet
650
+ }, instance);
651
+ }
652
+ }
653
+ };
654
+ instance.$sessionTransfer = async (conn, targetRoomId) => {
655
+ let user;
656
+ const signal2 = this.getUsersProperty(instance);
657
+ if (!signal2) {
658
+ console.error("[sessionTransfer] `users` property not defined in the room.");
659
+ return null;
660
+ }
661
+ const { publicId } = conn.state;
662
+ user = signal2()[publicId];
663
+ if (!user) {
664
+ console.error(`[sessionTransfer] User with publicId ${publicId} not found.`);
665
+ return null;
666
+ }
667
+ const sessions = await this.room.storage.list();
668
+ let userSession = null;
669
+ let privateId = null;
670
+ for (const [key, session] of sessions) {
671
+ if (key.startsWith("session:") && session.publicId === publicId) {
672
+ userSession = session;
673
+ privateId = key.replace("session:", "");
674
+ break;
675
+ }
676
+ }
677
+ if (!userSession || !privateId) {
678
+ console.error(`[sessionTransfer] Session for publicId ${publicId} not found.`);
679
+ return null;
680
+ }
681
+ const usersPropName = this.getUsersPropName(instance);
682
+ if (!usersPropName) {
683
+ console.error("[sessionTransfer] `users` property not defined in the room.");
684
+ return null;
685
+ }
686
+ const userSnapshot = createStatesSnapshotDeep(user);
687
+ const transferData = {
688
+ privateId,
689
+ userSnapshot,
690
+ sessionState: userSession.state,
691
+ publicId
692
+ };
693
+ try {
694
+ const targetRoomParty = await this.room.context.parties.main.get(targetRoomId);
695
+ const response2 = await targetRoomParty.fetch("/session-transfer", {
696
+ method: "POST",
697
+ body: JSON.stringify(transferData),
698
+ headers: {
699
+ "Content-Type": "application/json"
700
+ }
701
+ });
702
+ if (!response2.ok) {
703
+ throw new Error(`Transfer request failed: ${await response2.text()}`);
704
+ }
705
+ const { transferToken } = await response2.json();
706
+ return transferToken;
707
+ } catch (error) {
708
+ console.error(`[sessionTransfer] Failed to transfer session to room ${targetRoomId}:`, error);
709
+ return null;
710
+ }
711
+ };
615
712
  const syncCb = /* @__PURE__ */ __name((values) => {
616
713
  if (options.getMemoryAll) {
617
714
  buildObject(values, instance.$memoryAll);
@@ -620,6 +717,13 @@ var Server = class {
620
717
  init = false;
621
718
  return;
622
719
  }
720
+ if (!instance.$autoSync) {
721
+ for (const [path, value] of values) {
722
+ instance.$pendingSync.set(path, value);
723
+ }
724
+ values.clear();
725
+ return;
726
+ }
623
727
  const packet = buildObject(values, instance.$memoryAll);
624
728
  this.broadcast({
625
729
  type: "sync",
@@ -644,11 +748,12 @@ var Server = class {
644
748
  values.clear();
645
749
  }, "persistCb");
646
750
  syncClass(instance, {
647
- onSync: throttle(syncCb, instance["throttleSync"] ?? 500),
648
- onPersist: throttle(persistCb, instance["throttleStorage"] ?? 2e3)
751
+ onSync: instance["throttleSync"] ? throttle(syncCb, instance["throttleSync"]) : syncCb,
752
+ onPersist: instance["throttleStorage"] ? throttle(persistCb, instance["throttleStorage"]) : persistCb
649
753
  });
650
754
  await loadMemory();
651
755
  initPersist = false;
756
+ init = false;
652
757
  return instance;
653
758
  }
654
759
  /**
@@ -802,29 +907,46 @@ var Server = class {
802
907
  });
803
908
  const roomGuards = subRoom.constructor["_roomGuards"] || [];
804
909
  for (const guard of roomGuards) {
805
- const isAuthorized = await guard(conn, ctx);
910
+ const isAuthorized = await guard(conn, ctx, this.room);
806
911
  if (!isAuthorized) {
807
912
  conn.close();
808
913
  return;
809
914
  }
810
915
  }
916
+ let transferToken = null;
917
+ if (ctx.request?.url) {
918
+ const url = new URL(ctx.request.url);
919
+ transferToken = url.searchParams.get("transferToken");
920
+ }
921
+ let transferData = null;
922
+ if (transferToken) {
923
+ transferData = await this.room.storage.get(`transfer:${transferToken}`);
924
+ if (transferData) {
925
+ await this.room.storage.delete(`transfer:${transferToken}`);
926
+ }
927
+ }
811
928
  const existingSession = await this.getSession(conn.id);
812
- const publicId = existingSession?.publicId || generateShortUUID$1();
929
+ const publicId = existingSession?.publicId || transferData?.publicId || generateShortUUID$1();
813
930
  let user = null;
814
931
  const signal2 = this.getUsersProperty(subRoom);
815
932
  const usersPropName = this.getUsersPropName(subRoom);
816
933
  if (signal2) {
817
934
  const { classType } = signal2.options;
818
935
  if (!existingSession?.publicId) {
819
- user = isClass(classType) ? new classType() : classType(conn, ctx);
820
- signal2()[publicId] = user;
821
- const snapshot = createStatesSnapshot(user);
822
- this.room.storage.put(`${usersPropName}.${publicId}`, snapshot);
936
+ if (transferData?.restored && signal2()[publicId]) {
937
+ user = signal2()[publicId];
938
+ } else {
939
+ user = isClass(classType) ? new classType() : classType(conn, ctx);
940
+ signal2()[publicId] = user;
941
+ const snapshot = createStatesSnapshotDeep(user);
942
+ this.room.storage.put(`${usersPropName}.${publicId}`, snapshot);
943
+ }
823
944
  } else {
824
945
  user = signal2()[existingSession.publicId];
825
946
  }
826
947
  if (!existingSession) {
827
- await this.saveSession(conn.id, {
948
+ const sessionPrivateId = transferData?.privateId || conn.id;
949
+ await this.saveSession(sessionPrivateId, {
828
950
  publicId
829
951
  });
830
952
  } else {
@@ -832,18 +954,22 @@ var Server = class {
832
954
  }
833
955
  }
834
956
  this.updateUserConnectionStatus(user, true);
835
- await awaitReturn(subRoom["onJoin"]?.(user, conn, ctx));
836
957
  conn.setState({
837
958
  ...conn.state,
838
959
  publicId
839
960
  });
840
- this.send(conn, {
841
- type: "sync",
842
- value: {
843
- pId: publicId,
844
- ...subRoom.$memoryAll
845
- }
846
- }, subRoom);
961
+ await awaitReturn(subRoom["onJoin"]?.(user, conn, ctx));
962
+ if (subRoom.$autoSync) {
963
+ this.send(conn, {
964
+ type: "sync",
965
+ value: {
966
+ pId: publicId,
967
+ ...subRoom.$memoryAll
968
+ }
969
+ }, subRoom);
970
+ } else {
971
+ subRoom.$pendingInitialSync.set(conn, publicId);
972
+ }
847
973
  }
848
974
  /**
849
975
  * @method onConnect
@@ -1112,7 +1238,7 @@ var Server = class {
1112
1238
  * @method onClose
1113
1239
  * @async
1114
1240
  * @param {Party.Connection} conn - The connection object of the disconnecting user.
1115
- * @description Handles user disconnection, removing them from the room and triggering the onLeave event.
1241
+ * @description Handles user disconnection, removing them from the room and triggering the onLeave event..
1116
1242
  * @returns {Promise<void>}
1117
1243
  *
1118
1244
  * @example
@@ -1128,6 +1254,9 @@ var Server = class {
1128
1254
  if (!subRoom) {
1129
1255
  return;
1130
1256
  }
1257
+ if (subRoom.$pendingInitialSync) {
1258
+ subRoom.$pendingInitialSync.delete(conn);
1259
+ }
1131
1260
  const signal2 = this.getUsersProperty(subRoom);
1132
1261
  if (!conn.state) {
1133
1262
  return;
@@ -1178,6 +1307,66 @@ var Server = class {
1178
1307
  return this.handleDirectRequest(req, res);
1179
1308
  }
1180
1309
  /**
1310
+ * @method handleSessionRestore
1311
+ * @private
1312
+ * @async
1313
+ * @param {Party.Request} req - The HTTP request for session restore
1314
+ * @param {ServerResponse} res - The response object
1315
+ * @description Handles session restoration from transfer data, creates session from privateId
1316
+ * @returns {Promise<Response>} The response to return to the client
1317
+ */
1318
+ async handleSessionRestore(req, res) {
1319
+ try {
1320
+ const transferData = await req.json();
1321
+ const { privateId, userSnapshot, sessionState, publicId } = transferData;
1322
+ if (!privateId || !publicId) {
1323
+ return res.badRequest("Missing privateId or publicId in transfer data");
1324
+ }
1325
+ const subRoom = await this.getSubRoom();
1326
+ if (!subRoom) {
1327
+ return res.serverError("Room not available");
1328
+ }
1329
+ await this.saveSession(privateId, {
1330
+ publicId,
1331
+ state: sessionState,
1332
+ created: Date.now(),
1333
+ connected: false
1334
+ // Will be set to true when user connects
1335
+ });
1336
+ if (userSnapshot) {
1337
+ const signal2 = this.getUsersProperty(subRoom);
1338
+ const usersPropName = this.getUsersPropName(subRoom);
1339
+ if (signal2 && usersPropName) {
1340
+ const { classType } = signal2.options;
1341
+ const user = isClass(classType) ? new classType() : classType();
1342
+ const hydratedSnapshot = await awaitReturn(subRoom["onSessionRestore"]?.({
1343
+ userSnapshot,
1344
+ user,
1345
+ publicId,
1346
+ privateId,
1347
+ sessionState,
1348
+ room: this.room
1349
+ })) ?? userSnapshot;
1350
+ load(user, hydratedSnapshot, true);
1351
+ signal2()[publicId] = user;
1352
+ await this.room.storage.put(`${usersPropName}.${publicId}`, hydratedSnapshot);
1353
+ }
1354
+ }
1355
+ const transferToken = generateShortUUID$1();
1356
+ await this.room.storage.put(`transfer:${transferToken}`, {
1357
+ privateId,
1358
+ publicId,
1359
+ restored: true
1360
+ });
1361
+ return res.success({
1362
+ transferToken
1363
+ });
1364
+ } catch (error) {
1365
+ console.error("Error restoring session:", error);
1366
+ return res.serverError("Failed to restore session");
1367
+ }
1368
+ }
1369
+ /**
1181
1370
  * @method handleDirectRequest
1182
1371
  * @private
1183
1372
  * @async
@@ -1190,6 +1379,10 @@ var Server = class {
1190
1379
  if (!subRoom) {
1191
1380
  return res.notFound();
1192
1381
  }
1382
+ const url = new URL(req.url);
1383
+ if (url.pathname.endsWith("/session-transfer") && req.method === "POST") {
1384
+ return this.handleSessionRestore(req, res);
1385
+ }
1193
1386
  const response2 = await this.tryMatchRequestHandler(req, res, subRoom);
1194
1387
  if (response2) {
1195
1388
  return response2;
@@ -1288,7 +1481,7 @@ var Server = class {
1288
1481
  */
1289
1482
  pathMatches(requestPath, handlerPath) {
1290
1483
  const pathRegexString = handlerPath.replace(/\//g, "\\/").replace(/:([^\/]+)/g, "([^/]+)");
1291
- const pathRegex = new RegExp(`^${pathRegexString}$`);
1484
+ const pathRegex = new RegExp(`^${pathRegexString}`);
1292
1485
  return pathRegex.test(requestPath);
1293
1486
  }
1294
1487
  /**
@@ -1308,7 +1501,7 @@ var Server = class {
1308
1501
  }
1309
1502
  });
1310
1503
  const pathRegexString = handlerPath.replace(/\//g, "\\/").replace(/:([^\/]+)/g, "([^/]+)");
1311
- const pathRegex = new RegExp(`^${pathRegexString}$`);
1504
+ const pathRegex = new RegExp(`^${pathRegexString}`);
1312
1505
  const matches = requestPath.match(pathRegex);
1313
1506
  if (matches && matches.length > 1) {
1314
1507
  for (let i = 0; i < paramNames.length; i++) {
@@ -1584,10 +1777,14 @@ async function testRoom(Room3, options = {}) {
1584
1777
  const isShard = options.shard || false;
1585
1778
  const io = new ServerIo(Room3.path, isShard ? {
1586
1779
  parties: {
1587
- game: createServer
1780
+ game: createServer,
1781
+ ...options.parties || {}
1588
1782
  },
1783
+ partyFn: options.partyFn,
1589
1784
  env: options.env
1590
1785
  } : {
1786
+ parties: options.parties,
1787
+ partyFn: options.partyFn,
1591
1788
  env: options.env
1592
1789
  });
1593
1790
  Room3.prototype.throttleSync = 0;
@@ -1598,20 +1795,34 @@ async function testRoom(Room3, options = {}) {
1598
1795
  const shardServer = new Shard(io);
1599
1796
  shardServer.subRoom = null;
1600
1797
  server = shardServer;
1601
- for (const lobby of io.context.parties.main.values()) {
1602
- await lobby.server.onStart();
1798
+ if (io.context.parties.main instanceof Map) {
1799
+ for (const lobby of io.context.parties.main.values()) {
1800
+ await lobby.server.onStart();
1801
+ }
1603
1802
  }
1604
1803
  } else {
1605
1804
  server = await createServer(io);
1805
+ if (io.context.parties.main instanceof Map) {
1806
+ for (const lobby of io.context.parties.main.values()) {
1807
+ if (lobby.server && lobby.server !== server) {
1808
+ await lobby.server.onStart();
1809
+ }
1810
+ }
1811
+ }
1606
1812
  }
1607
1813
  await server.onStart();
1608
1814
  return {
1609
1815
  server,
1610
1816
  room: server.subRoom,
1611
- createClient: /* @__PURE__ */ __name(async (id2) => {
1612
- const client = await io.connection(server, id2);
1817
+ createClient: /* @__PURE__ */ __name(async (id2, opts) => {
1818
+ const client = await io.connection(server, id2, opts);
1613
1819
  return client;
1614
- }, "createClient")
1820
+ }, "createClient"),
1821
+ getServerUser: /* @__PURE__ */ __name(async (client, prop = "users") => {
1822
+ const privateId = client.conn.id;
1823
+ const session = await server.getSession(privateId);
1824
+ return server.subRoom[prop]()[session?.publicId];
1825
+ }, "getServerUser")
1615
1826
  };
1616
1827
  }
1617
1828
  __name(testRoom, "testRoom");
@@ -1624,6 +1835,10 @@ async function request(room, path, options = {
1624
1835
  return response2;
1625
1836
  }
1626
1837
  __name(request, "request");
1838
+ function tick(ms = 0) {
1839
+ return new Promise((resolve) => setTimeout(resolve, ms));
1840
+ }
1841
+ __name(tick, "tick");
1627
1842
 
1628
1843
  // src/mock.ts
1629
1844
  var MockPartyClient = class {
@@ -1674,14 +1889,22 @@ var MockLobby = class MockLobby2 {
1674
1889
  __name(this, "MockLobby");
1675
1890
  }
1676
1891
  server;
1677
- constructor(server) {
1892
+ lobbyId;
1893
+ constructor(server, lobbyId) {
1678
1894
  this.server = server;
1895
+ this.lobbyId = lobbyId;
1679
1896
  }
1680
- socket() {
1897
+ socket(_init) {
1681
1898
  return new MockPartyClient(this.server);
1682
1899
  }
1900
+ async connection(idOrOptions, maybeOptions) {
1901
+ const id2 = typeof idOrOptions === "string" ? idOrOptions : idOrOptions?.id;
1902
+ const options = (typeof idOrOptions === "string" ? maybeOptions : idOrOptions) || {};
1903
+ return this.server.room.connection(this.server, id2, options);
1904
+ }
1683
1905
  fetch(url, options) {
1684
- return request(this.server, url, options);
1906
+ const baseUrl = url.includes("shard") ? "" : "/parties/main/" + this.lobbyId;
1907
+ return request(this.server, baseUrl + url, options);
1685
1908
  }
1686
1909
  };
1687
1910
  var MockContext = class MockContext2 {
@@ -1696,8 +1919,22 @@ var MockContext = class MockContext2 {
1696
1919
  main: /* @__PURE__ */ new Map()
1697
1920
  };
1698
1921
  const parties = options.parties || {};
1699
- for (let lobbyId in parties) {
1700
- this.parties.main.set(lobbyId, new MockLobby(parties[lobbyId](room)));
1922
+ if (options.partyFn) {
1923
+ const serverCache = /* @__PURE__ */ new Map();
1924
+ this.parties.main = {
1925
+ get: /* @__PURE__ */ __name(async (lobbyId) => {
1926
+ if (!serverCache.has(lobbyId)) {
1927
+ const server = await options.partyFn(lobbyId);
1928
+ serverCache.set(lobbyId, new MockLobby(server, lobbyId));
1929
+ }
1930
+ return serverCache.get(lobbyId);
1931
+ }, "get")
1932
+ };
1933
+ } else {
1934
+ for (let lobbyId in parties) {
1935
+ const server = parties[lobbyId](room);
1936
+ this.parties.main.set(lobbyId, new MockLobby(server, lobbyId));
1937
+ }
1701
1938
  }
1702
1939
  }
1703
1940
  };
@@ -1717,17 +1954,24 @@ var MockPartyRoom = class MockPartyRoom2 {
1717
1954
  this.env = {};
1718
1955
  this.id = id2 || generateShortUUID();
1719
1956
  this.context = new MockContext(this, {
1720
- parties: options.parties || {}
1957
+ parties: options.parties,
1958
+ partyFn: options.partyFn
1721
1959
  });
1722
1960
  this.env = options.env || {};
1723
1961
  }
1724
- async connection(server, id2) {
1962
+ async connection(server, id2, opts) {
1725
1963
  const socket = new MockPartyClient(server, id2);
1726
1964
  const url = new URL("http://localhost");
1965
+ if (opts?.query) {
1966
+ for (const [key, value] of Object.entries(opts.query)) {
1967
+ url.searchParams.set(key, String(value));
1968
+ }
1969
+ }
1727
1970
  const request2 = new Request(url.toString(), {
1728
1971
  method: "GET",
1729
1972
  headers: {
1730
- "Content-Type": "application/json"
1973
+ "Content-Type": "application/json",
1974
+ ...opts?.headers || {}
1731
1975
  }
1732
1976
  });
1733
1977
  await server.onConnect(socket.conn, {
@@ -2417,5 +2661,29 @@ WorldRoom = _ts_decorate([
2417
2661
  ])
2418
2662
  ], WorldRoom);
2419
2663
 
2420
- export { Action, ClientIo, Guard, MockConnection, Request2 as Request, Room, RoomGuard, Server, ServerIo, ServerResponse, Shard, WorldRoom, request, testRoom };
2421
- //# sourceMappingURL=index20.js.map
2664
+ // src/session.guard.ts
2665
+ function createRequireSessionGuard(storage) {
2666
+ return async (sender, value) => {
2667
+ if (!sender || !sender.id) {
2668
+ return false;
2669
+ }
2670
+ try {
2671
+ const session = await storage.get(`session:${sender.id}`);
2672
+ if (!session) {
2673
+ return false;
2674
+ }
2675
+ const typedSession = session;
2676
+ if (!typedSession.publicId) {
2677
+ return false;
2678
+ }
2679
+ return true;
2680
+ } catch (error) {
2681
+ console.error("Error checking session in requireSession guard:", error);
2682
+ return false;
2683
+ }
2684
+ };
2685
+ }
2686
+ __name(createRequireSessionGuard, "createRequireSessionGuard");
2687
+
2688
+ export { Action, ClientIo, Guard, MockConnection, Request2 as Request, Room, RoomGuard, Server, ServerIo, ServerResponse, Shard, WorldRoom, createRequireSessionGuard, request, testRoom, tick };
2689
+ //# sourceMappingURL=index.js.map