@colyseus/core 0.16.24 → 0.17.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 (258) hide show
  1. package/build/Debug.js +16 -4
  2. package/build/Debug.js.map +2 -2
  3. package/build/Debug.mjs +11 -1
  4. package/build/Debug.mjs.map +2 -2
  5. package/build/IPC.js +5 -3
  6. package/build/IPC.js.map +2 -2
  7. package/build/IPC.mjs +1 -0
  8. package/build/IPC.mjs.map +2 -2
  9. package/build/Logger.js +1 -0
  10. package/build/Logger.js.map +1 -1
  11. package/build/MatchMaker.js +148 -84
  12. package/build/MatchMaker.js.map +3 -3
  13. package/build/MatchMaker.mjs +130 -70
  14. package/build/MatchMaker.mjs.map +3 -3
  15. package/build/Protocol.js +54 -41
  16. package/build/Protocol.js.map +3 -3
  17. package/build/Protocol.mjs +52 -41
  18. package/build/Protocol.mjs.map +3 -3
  19. package/build/Room.js +430 -195
  20. package/build/Room.js.map +3 -3
  21. package/build/Room.mjs +417 -175
  22. package/build/Room.mjs.map +3 -3
  23. package/build/Server.js +49 -108
  24. package/build/Server.js.map +3 -3
  25. package/build/Server.mjs +40 -102
  26. package/build/Server.mjs.map +3 -3
  27. package/build/Stats.js +2 -1
  28. package/build/Stats.js.map +2 -2
  29. package/build/Stats.mjs.map +1 -1
  30. package/build/Transport.js +29 -11
  31. package/build/Transport.js.map +3 -3
  32. package/build/Transport.mjs +15 -9
  33. package/build/Transport.mjs.map +3 -3
  34. package/build/errors/RoomExceptions.js +9 -5
  35. package/build/errors/RoomExceptions.js.map +2 -2
  36. package/build/errors/RoomExceptions.mjs +8 -5
  37. package/build/errors/RoomExceptions.mjs.map +2 -2
  38. package/build/errors/SeatReservationError.js +1 -0
  39. package/build/errors/SeatReservationError.js.map +1 -1
  40. package/build/errors/ServerError.js +2 -1
  41. package/build/errors/ServerError.js.map +2 -2
  42. package/build/errors/ServerError.mjs.map +1 -1
  43. package/build/index.js +60 -26
  44. package/build/index.js.map +2 -2
  45. package/build/index.mjs +33 -7
  46. package/build/index.mjs.map +2 -2
  47. package/build/matchmaker/Lobby.js +13 -3
  48. package/build/matchmaker/Lobby.js.map +2 -2
  49. package/build/matchmaker/Lobby.mjs +11 -2
  50. package/build/matchmaker/Lobby.mjs.map +2 -2
  51. package/build/matchmaker/LocalDriver/LocalDriver.js +94 -0
  52. package/build/matchmaker/LocalDriver/LocalDriver.js.map +7 -0
  53. package/build/matchmaker/LocalDriver/LocalDriver.mjs +71 -0
  54. package/build/matchmaker/LocalDriver/LocalDriver.mjs.map +7 -0
  55. package/build/matchmaker/LocalDriver/Query.js +111 -0
  56. package/build/matchmaker/LocalDriver/Query.js.map +7 -0
  57. package/build/matchmaker/LocalDriver/Query.mjs +88 -0
  58. package/build/matchmaker/LocalDriver/Query.mjs.map +7 -0
  59. package/build/matchmaker/RegisteredHandler.js +57 -7
  60. package/build/matchmaker/RegisteredHandler.js.map +2 -2
  61. package/build/matchmaker/RegisteredHandler.mjs +54 -5
  62. package/build/matchmaker/RegisteredHandler.mjs.map +2 -2
  63. package/build/matchmaker/controller.js +8 -8
  64. package/build/matchmaker/controller.js.map +2 -2
  65. package/build/matchmaker/controller.mjs +4 -5
  66. package/build/matchmaker/controller.mjs.map +2 -2
  67. package/build/matchmaker/driver/api.js +21 -2
  68. package/build/matchmaker/driver/api.js.map +2 -2
  69. package/build/matchmaker/driver/api.mjs +18 -1
  70. package/build/matchmaker/driver/api.mjs.map +2 -2
  71. package/build/matchmaker/driver/local/LocalDriver.js +36 -7
  72. package/build/matchmaker/driver/local/LocalDriver.js.map +2 -2
  73. package/build/matchmaker/driver/local/LocalDriver.mjs +33 -5
  74. package/build/matchmaker/driver/local/LocalDriver.mjs.map +2 -2
  75. package/build/matchmaker/driver/local/Query.js +51 -18
  76. package/build/matchmaker/driver/local/Query.js.map +2 -2
  77. package/build/matchmaker/driver/local/Query.mjs +50 -18
  78. package/build/matchmaker/driver/local/Query.mjs.map +2 -2
  79. package/build/matchmaker/driver.js +44 -0
  80. package/build/matchmaker/driver.js.map +7 -0
  81. package/build/matchmaker/driver.mjs +20 -0
  82. package/build/matchmaker/driver.mjs.map +7 -0
  83. package/build/matchmaker/routes.js +79 -0
  84. package/build/matchmaker/routes.js.map +7 -0
  85. package/build/matchmaker/routes.mjs +45 -0
  86. package/build/matchmaker/routes.mjs.map +7 -0
  87. package/build/presence/LocalPresence.js +13 -27
  88. package/build/presence/LocalPresence.js.map +3 -3
  89. package/build/presence/LocalPresence.mjs +11 -16
  90. package/build/presence/LocalPresence.mjs.map +2 -2
  91. package/build/presence/Presence.js +37 -0
  92. package/build/presence/Presence.js.map +2 -2
  93. package/build/presence/Presence.mjs +29 -0
  94. package/build/presence/Presence.mjs.map +3 -3
  95. package/build/rooms/LobbyRoom.js +5 -5
  96. package/build/rooms/LobbyRoom.js.map +2 -2
  97. package/build/rooms/LobbyRoom.mjs +1 -2
  98. package/build/rooms/LobbyRoom.mjs.map +2 -2
  99. package/build/rooms/RankedQueueRoom.js +224 -0
  100. package/build/rooms/RankedQueueRoom.js.map +7 -0
  101. package/build/rooms/RankedQueueRoom.mjs +201 -0
  102. package/build/rooms/RankedQueueRoom.mjs.map +7 -0
  103. package/build/rooms/RelayRoom.js +6 -6
  104. package/build/rooms/RelayRoom.js.map +2 -2
  105. package/build/rooms/RelayRoom.mjs +4 -5
  106. package/build/rooms/RelayRoom.mjs.map +2 -2
  107. package/build/rooms/createRoom.js +51 -0
  108. package/build/rooms/createRoom.js.map +7 -0
  109. package/build/rooms/createRoom.mjs +28 -0
  110. package/build/rooms/createRoom.mjs.map +7 -0
  111. package/build/router/default_routes.js +79 -0
  112. package/build/router/default_routes.js.map +7 -0
  113. package/build/router/default_routes.mjs +45 -0
  114. package/build/router/default_routes.mjs.map +7 -0
  115. package/build/router/index.js +55 -0
  116. package/build/router/index.js.map +7 -0
  117. package/build/router/index.mjs +30 -0
  118. package/build/router/index.mjs.map +7 -0
  119. package/build/serializer/NoneSerializer.js +1 -0
  120. package/build/serializer/NoneSerializer.js.map +2 -2
  121. package/build/serializer/NoneSerializer.mjs.map +2 -2
  122. package/build/serializer/SchemaSerializer.js +6 -7
  123. package/build/serializer/SchemaSerializer.js.map +2 -2
  124. package/build/serializer/SchemaSerializer.mjs +3 -5
  125. package/build/serializer/SchemaSerializer.mjs.map +2 -2
  126. package/build/serializer/SchemaSerializerDebug.js +29 -0
  127. package/build/serializer/SchemaSerializerDebug.js.map +3 -3
  128. package/build/serializer/SchemaSerializerDebug.mjs +7 -0
  129. package/build/serializer/SchemaSerializerDebug.mjs.map +3 -3
  130. package/build/serializer/Serializer.js +1 -0
  131. package/build/serializer/Serializer.js.map +2 -2
  132. package/build/{Debug.d.ts → src/Debug.d.ts} +2 -1
  133. package/build/{IPC.d.ts → src/IPC.d.ts} +2 -2
  134. package/build/{MatchMaker.d.ts → src/MatchMaker.d.ts} +58 -33
  135. package/build/src/Protocol.d.ts +53 -0
  136. package/build/src/Room.d.ts +497 -0
  137. package/build/{Server.d.ts → src/Server.d.ts} +23 -25
  138. package/build/{Transport.d.ts → src/Transport.d.ts} +65 -22
  139. package/build/{errors → src/errors}/RoomExceptions.d.ts +8 -7
  140. package/build/src/index.d.ts +27 -0
  141. package/build/src/matchmaker/Lobby.d.ts +4 -0
  142. package/build/src/matchmaker/LocalDriver/LocalDriver.d.ts +17 -0
  143. package/build/src/matchmaker/LocalDriver/Query.d.ts +12 -0
  144. package/build/src/matchmaker/RegisteredHandler.d.ts +81 -0
  145. package/build/{matchmaker → src/matchmaker}/controller.d.ts +5 -6
  146. package/build/src/matchmaker/driver/api.d.ts +145 -0
  147. package/build/src/matchmaker/driver/local/LocalDriver.d.ts +17 -0
  148. package/build/src/matchmaker/driver/local/Query.d.ts +12 -0
  149. package/build/src/matchmaker/driver.d.ts +145 -0
  150. package/build/src/matchmaker/routes.d.ts +92 -0
  151. package/build/{presence → src/presence}/LocalPresence.d.ts +1 -1
  152. package/build/{presence → src/presence}/Presence.d.ts +2 -0
  153. package/build/{rooms → src/rooms}/LobbyRoom.d.ts +4 -4
  154. package/build/src/rooms/RankedQueueRoom.d.ts +125 -0
  155. package/build/{rooms → src/rooms}/RelayRoom.d.ts +5 -4
  156. package/build/src/rooms/createRoom.d.ts +65 -0
  157. package/build/src/router/default_routes.d.ts +103 -0
  158. package/build/src/router/index.d.ts +68 -0
  159. package/build/{serializer → src/serializer}/NoneSerializer.d.ts +2 -2
  160. package/build/{serializer → src/serializer}/SchemaSerializer.d.ts +9 -9
  161. package/build/{serializer → src/serializer}/Serializer.d.ts +3 -3
  162. package/build/{utils → src/utils}/DevMode.d.ts +5 -4
  163. package/build/{utils → src/utils}/StandardSchema.d.ts +1 -1
  164. package/build/{utils → src/utils}/Utils.d.ts +15 -4
  165. package/build/utils/DevMode.js +54 -26
  166. package/build/utils/DevMode.js.map +3 -3
  167. package/build/utils/DevMode.mjs +44 -19
  168. package/build/utils/DevMode.mjs.map +2 -2
  169. package/build/utils/StandardSchema.js.map +1 -1
  170. package/build/utils/StandardSchema.mjs.map +1 -1
  171. package/build/utils/Utils.js +8 -15
  172. package/build/utils/Utils.js.map +3 -3
  173. package/build/utils/Utils.mjs +6 -4
  174. package/build/utils/Utils.mjs.map +2 -2
  175. package/package.json +21 -16
  176. package/src/Debug.ts +37 -0
  177. package/src/IPC.ts +124 -0
  178. package/src/Logger.ts +30 -0
  179. package/src/MatchMaker.ts +1119 -0
  180. package/src/Protocol.ts +160 -0
  181. package/src/Room.ts +1797 -0
  182. package/src/Server.ts +325 -0
  183. package/src/Stats.ts +107 -0
  184. package/src/Transport.ts +207 -0
  185. package/src/errors/RoomExceptions.ts +141 -0
  186. package/src/errors/SeatReservationError.ts +5 -0
  187. package/src/errors/ServerError.ts +17 -0
  188. package/src/index.ts +81 -0
  189. package/src/matchmaker/Lobby.ts +68 -0
  190. package/src/matchmaker/LocalDriver/LocalDriver.ts +92 -0
  191. package/src/matchmaker/LocalDriver/Query.ts +94 -0
  192. package/src/matchmaker/RegisteredHandler.ts +172 -0
  193. package/src/matchmaker/controller.ts +64 -0
  194. package/src/matchmaker/driver.ts +191 -0
  195. package/src/presence/LocalPresence.ts +331 -0
  196. package/src/presence/Presence.ts +263 -0
  197. package/src/rooms/LobbyRoom.ts +135 -0
  198. package/src/rooms/RankedQueueRoom.ts +425 -0
  199. package/src/rooms/RelayRoom.ts +90 -0
  200. package/src/router/default_routes.ts +58 -0
  201. package/src/router/index.ts +43 -0
  202. package/src/serializer/NoneSerializer.ts +16 -0
  203. package/src/serializer/SchemaSerializer.ts +194 -0
  204. package/src/serializer/SchemaSerializerDebug.ts +148 -0
  205. package/src/serializer/Serializer.ts +9 -0
  206. package/src/utils/DevMode.ts +133 -0
  207. package/src/utils/StandardSchema.ts +20 -0
  208. package/src/utils/Utils.ts +169 -0
  209. package/src/utils/nanoevents.ts +20 -0
  210. package/build/Protocol.d.ts +0 -37
  211. package/build/Room.d.ts +0 -265
  212. package/build/discovery/index.d.ts +0 -8
  213. package/build/discovery/index.js +0 -50
  214. package/build/discovery/index.js.map +0 -7
  215. package/build/discovery/index.mjs +0 -26
  216. package/build/discovery/index.mjs.map +0 -7
  217. package/build/index.d.ts +0 -24
  218. package/build/matchmaker/Lobby.d.ts +0 -4
  219. package/build/matchmaker/RegisteredHandler.d.ts +0 -19
  220. package/build/matchmaker/driver/Query.d.ts +0 -8
  221. package/build/matchmaker/driver/Query.js +0 -68
  222. package/build/matchmaker/driver/Query.js.map +0 -7
  223. package/build/matchmaker/driver/Query.mjs +0 -45
  224. package/build/matchmaker/driver/Query.mjs.map +0 -7
  225. package/build/matchmaker/driver/RoomData.d.ts +0 -19
  226. package/build/matchmaker/driver/RoomData.js +0 -79
  227. package/build/matchmaker/driver/RoomData.js.map +0 -7
  228. package/build/matchmaker/driver/RoomData.mjs +0 -56
  229. package/build/matchmaker/driver/RoomData.mjs.map +0 -7
  230. package/build/matchmaker/driver/api.d.ts +0 -104
  231. package/build/matchmaker/driver/index.d.ts +0 -13
  232. package/build/matchmaker/driver/index.js +0 -64
  233. package/build/matchmaker/driver/index.js.map +0 -7
  234. package/build/matchmaker/driver/index.mjs +0 -42
  235. package/build/matchmaker/driver/index.mjs.map +0 -7
  236. package/build/matchmaker/driver/interfaces.d.ts +0 -73
  237. package/build/matchmaker/driver/interfaces.js +0 -15
  238. package/build/matchmaker/driver/interfaces.js.map +0 -7
  239. package/build/matchmaker/driver/interfaces.mjs +0 -0
  240. package/build/matchmaker/driver/interfaces.mjs.map +0 -7
  241. package/build/matchmaker/driver/local/LocalDriver.d.ts +0 -13
  242. package/build/matchmaker/driver/local/Query.d.ts +0 -9
  243. package/build/matchmaker/driver/local/RoomData.d.ts +0 -19
  244. package/build/matchmaker/driver/local/RoomData.js +0 -79
  245. package/build/matchmaker/driver/local/RoomData.js.map +0 -7
  246. package/build/matchmaker/driver/local/RoomData.mjs +0 -57
  247. package/build/matchmaker/driver/local/RoomData.mjs.map +0 -7
  248. package/build/utils/types.d.ts +0 -1
  249. package/build/utils/types.js +0 -15
  250. package/build/utils/types.js.map +0 -7
  251. package/build/utils/types.mjs +0 -0
  252. package/build/utils/types.mjs.map +0 -7
  253. /package/build/{Logger.d.ts → src/Logger.d.ts} +0 -0
  254. /package/build/{Stats.d.ts → src/Stats.d.ts} +0 -0
  255. /package/build/{errors → src/errors}/SeatReservationError.d.ts +0 -0
  256. /package/build/{errors → src/errors}/ServerError.d.ts +0 -0
  257. /package/build/{serializer → src/serializer}/SchemaSerializerDebug.d.ts +0 -0
  258. /package/build/{utils → src/utils}/nanoevents.d.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/matchmaker/Lobby.ts"],
4
- "sourcesContent": ["import * as matchMaker from '../MatchMaker.js';\n\nimport type { Room } from '../Room.js';\nimport { IRoomCache } from './driver/api.js';\n\nconst LOBBY_CHANNEL = '$lobby';\n\n/*\n * TODO: refactor this on v0.16\n *\n * Some users might be relying on \"1\" = \"removed\" from the lobby due to this workaround: https://github.com/colyseus/colyseus/issues/617\n * Though, for consistency, we should invert as \"0\" = \"invisible\" and \"1\" = \"visible\".\n *\n * - rename \"removed\" to \"isVisible\" and swap the logic\n * - emit \"visibility-change\" with inverted value (isVisible)\n * - update \"subscribeLobby\" to check \"1\" as \"isVisible\" instead of \"removed\"\n */\n\nexport function updateLobby(room: Room, removed: boolean = false) {\n const listing = room.listing;\n\n if (listing.unlisted) return;\n\n if (removed) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},1`);\n } else if (!listing.private) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},0`);\n }\n}\n\nexport async function subscribeLobby(callback: (roomId: string, roomListing: IRoomCache) => void) {\n const cb = async (message) => {\n const [roomId, isRemove] = message.split(',');\n\n if (isRemove === '1') {\n callback(roomId, null);\n\n } else {\n const room = (await matchMaker.query({ roomId }))[0];\n callback(roomId, room);\n }\n };\n\n await matchMaker.presence.subscribe(LOBBY_CHANNEL, cb);\n\n return () => matchMaker.presence.unsubscribe(LOBBY_CHANNEL, cb);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA4B;AAK5B,MAAM,gBAAgB;AAaf,SAAS,YAAY,MAAY,UAAmB,OAAO;AAChE,QAAM,UAAU,KAAK;AAErB,MAAI,QAAQ,SAAU;AAEtB,MAAI,SAAS;AACX,eAAW,SAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE,WAAW,CAAC,QAAQ,SAAS;AAC3B,eAAW,SAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE;AACF;AAEA,eAAsB,eAAe,UAA6D;AAChG,QAAM,KAAK,OAAO,YAAY;AAC5B,UAAM,CAAC,QAAQ,QAAQ,IAAI,QAAQ,MAAM,GAAG;AAE5C,QAAI,aAAa,KAAK;AACpB,eAAS,QAAQ,IAAI;AAAA,IAEvB,OAAO;AACL,YAAM,QAAQ,MAAM,WAAW,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC;AACnD,eAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,UAAU,eAAe,EAAE;AAErD,SAAO,MAAM,WAAW,SAAS,YAAY,eAAe,EAAE;AAChE;",
4
+ "sourcesContent": ["import * as matchMaker from '../MatchMaker.ts';\n\nimport type { Room } from '../Room.ts';\nimport type { IRoomCache } from './driver.ts';\n\nconst LOBBY_CHANNEL = '$lobby';\n\n/*\n * TODO: refactor this on 1.0\n *\n * Some users might be relying on \"1\" = \"removed\" from the lobby due to this workaround: https://github.com/colyseus/colyseus/issues/617\n * Though, for consistency, we should invert as \"0\" = \"invisible\" and \"1\" = \"visible\".\n *\n * - rename \"removed\" to \"isVisible\" and swap the logic\n * - emit \"visibility-change\" with inverted value (isVisible)\n * - update \"subscribeLobby\" to check \"1\" as \"isVisible\" instead of \"removed\"\n */\n\nexport function updateLobby<T extends Room>(room: T, removed: boolean = false) {\n const listing = room['_listing'];\n\n if (listing.unlisted || !listing.roomId) {\n return;\n }\n\n if (removed) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},1`);\n } else if (!listing.private) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},0`);\n }\n}\n\nexport async function subscribeLobby(callback: (roomId: string, roomListing: IRoomCache) => void) {\n // Track removed roomIds to prevent race conditions where pending queries\n // complete after a room has been removed\n const removedRoomIds = new Set<string>();\n\n const cb = async (message: string) => {\n const [roomId, isRemove] = message.split(',');\n\n if (isRemove === '1') {\n // Mark as removed and process immediately\n removedRoomIds.add(roomId);\n callback(roomId, null);\n\n // Clean up after a short timeout to prevent memory leaks\n setTimeout(() => removedRoomIds.delete(roomId), 2000);\n\n } else {\n // Clear removed status - room might be coming back (e.g., visibility change)\n removedRoomIds.delete(roomId);\n\n const room = (await matchMaker.query({ roomId }))[0];\n\n // Check if room was removed while we were querying\n // See \"updating metadata should not cause race condition\" test in LobbyRoom.test.ts\n if (removedRoomIds.has(roomId)) {\n return;\n }\n\n callback(roomId, room);\n }\n };\n\n await matchMaker.presence.subscribe(LOBBY_CHANNEL, cb);\n\n return () => matchMaker.presence.unsubscribe(LOBBY_CHANNEL, cb);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAA4B;AAK5B,MAAM,gBAAgB;AAaf,SAAS,YAA4B,MAAS,UAAmB,OAAO;AAC7E,QAAM,UAAU,KAAK,UAAU;AAE/B,MAAI,QAAQ,YAAY,CAAC,QAAQ,QAAQ;AACvC;AAAA,EACF;AAEA,MAAI,SAAS;AACX,eAAW,SAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE,WAAW,CAAC,QAAQ,SAAS;AAC3B,eAAW,SAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE;AACF;AAEA,eAAsB,eAAe,UAA6D;AAGhG,QAAM,iBAAiB,oBAAI,IAAY;AAEvC,QAAM,KAAK,OAAO,YAAoB;AACpC,UAAM,CAAC,QAAQ,QAAQ,IAAI,QAAQ,MAAM,GAAG;AAE5C,QAAI,aAAa,KAAK;AAEpB,qBAAe,IAAI,MAAM;AACzB,eAAS,QAAQ,IAAI;AAGrB,iBAAW,MAAM,eAAe,OAAO,MAAM,GAAG,GAAI;AAAA,IAEtD,OAAO;AAEL,qBAAe,OAAO,MAAM;AAE5B,YAAM,QAAQ,MAAM,WAAW,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC;AAInD,UAAI,eAAe,IAAI,MAAM,GAAG;AAC9B;AAAA,MACF;AAEA,eAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,UAAU,eAAe,EAAE;AAErD,SAAO,MAAM,WAAW,SAAS,YAAY,eAAe,EAAE;AAChE;",
6
6
  "names": []
7
7
  }
@@ -2,8 +2,10 @@
2
2
  import * as matchMaker from "../MatchMaker.mjs";
3
3
  var LOBBY_CHANNEL = "$lobby";
4
4
  function updateLobby(room, removed = false) {
5
- const listing = room.listing;
6
- if (listing.unlisted) return;
5
+ const listing = room["_listing"];
6
+ if (listing.unlisted || !listing.roomId) {
7
+ return;
8
+ }
7
9
  if (removed) {
8
10
  matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},1`);
9
11
  } else if (!listing.private) {
@@ -11,12 +13,19 @@ function updateLobby(room, removed = false) {
11
13
  }
12
14
  }
13
15
  async function subscribeLobby(callback) {
16
+ const removedRoomIds = /* @__PURE__ */ new Set();
14
17
  const cb = async (message) => {
15
18
  const [roomId, isRemove] = message.split(",");
16
19
  if (isRemove === "1") {
20
+ removedRoomIds.add(roomId);
17
21
  callback(roomId, null);
22
+ setTimeout(() => removedRoomIds.delete(roomId), 2e3);
18
23
  } else {
24
+ removedRoomIds.delete(roomId);
19
25
  const room = (await matchMaker.query({ roomId }))[0];
26
+ if (removedRoomIds.has(roomId)) {
27
+ return;
28
+ }
20
29
  callback(roomId, room);
21
30
  }
22
31
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/matchmaker/Lobby.ts"],
4
- "sourcesContent": ["import * as matchMaker from '../MatchMaker.js';\n\nimport type { Room } from '../Room.js';\nimport { IRoomCache } from './driver/api.js';\n\nconst LOBBY_CHANNEL = '$lobby';\n\n/*\n * TODO: refactor this on v0.16\n *\n * Some users might be relying on \"1\" = \"removed\" from the lobby due to this workaround: https://github.com/colyseus/colyseus/issues/617\n * Though, for consistency, we should invert as \"0\" = \"invisible\" and \"1\" = \"visible\".\n *\n * - rename \"removed\" to \"isVisible\" and swap the logic\n * - emit \"visibility-change\" with inverted value (isVisible)\n * - update \"subscribeLobby\" to check \"1\" as \"isVisible\" instead of \"removed\"\n */\n\nexport function updateLobby(room: Room, removed: boolean = false) {\n const listing = room.listing;\n\n if (listing.unlisted) return;\n\n if (removed) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},1`);\n } else if (!listing.private) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},0`);\n }\n}\n\nexport async function subscribeLobby(callback: (roomId: string, roomListing: IRoomCache) => void) {\n const cb = async (message) => {\n const [roomId, isRemove] = message.split(',');\n\n if (isRemove === '1') {\n callback(roomId, null);\n\n } else {\n const room = (await matchMaker.query({ roomId }))[0];\n callback(roomId, room);\n }\n };\n\n await matchMaker.presence.subscribe(LOBBY_CHANNEL, cb);\n\n return () => matchMaker.presence.unsubscribe(LOBBY_CHANNEL, cb);\n}\n"],
5
- "mappings": ";AAAA,YAAY,gBAAgB;AAK5B,IAAM,gBAAgB;AAaf,SAAS,YAAY,MAAY,UAAmB,OAAO;AAChE,QAAM,UAAU,KAAK;AAErB,MAAI,QAAQ,SAAU;AAEtB,MAAI,SAAS;AACX,IAAW,oBAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE,WAAW,CAAC,QAAQ,SAAS;AAC3B,IAAW,oBAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE;AACF;AAEA,eAAsB,eAAe,UAA6D;AAChG,QAAM,KAAK,OAAO,YAAY;AAC5B,UAAM,CAAC,QAAQ,QAAQ,IAAI,QAAQ,MAAM,GAAG;AAE5C,QAAI,aAAa,KAAK;AACpB,eAAS,QAAQ,IAAI;AAAA,IAEvB,OAAO;AACL,YAAM,QAAQ,MAAiB,iBAAM,EAAE,OAAO,CAAC,GAAG,CAAC;AACnD,eAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,QAAiB,oBAAS,UAAU,eAAe,EAAE;AAErD,SAAO,MAAiB,oBAAS,YAAY,eAAe,EAAE;AAChE;",
4
+ "sourcesContent": ["import * as matchMaker from '../MatchMaker.ts';\n\nimport type { Room } from '../Room.ts';\nimport type { IRoomCache } from './driver.ts';\n\nconst LOBBY_CHANNEL = '$lobby';\n\n/*\n * TODO: refactor this on 1.0\n *\n * Some users might be relying on \"1\" = \"removed\" from the lobby due to this workaround: https://github.com/colyseus/colyseus/issues/617\n * Though, for consistency, we should invert as \"0\" = \"invisible\" and \"1\" = \"visible\".\n *\n * - rename \"removed\" to \"isVisible\" and swap the logic\n * - emit \"visibility-change\" with inverted value (isVisible)\n * - update \"subscribeLobby\" to check \"1\" as \"isVisible\" instead of \"removed\"\n */\n\nexport function updateLobby<T extends Room>(room: T, removed: boolean = false) {\n const listing = room['_listing'];\n\n if (listing.unlisted || !listing.roomId) {\n return;\n }\n\n if (removed) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},1`);\n } else if (!listing.private) {\n matchMaker.presence.publish(LOBBY_CHANNEL, `${listing.roomId},0`);\n }\n}\n\nexport async function subscribeLobby(callback: (roomId: string, roomListing: IRoomCache) => void) {\n // Track removed roomIds to prevent race conditions where pending queries\n // complete after a room has been removed\n const removedRoomIds = new Set<string>();\n\n const cb = async (message: string) => {\n const [roomId, isRemove] = message.split(',');\n\n if (isRemove === '1') {\n // Mark as removed and process immediately\n removedRoomIds.add(roomId);\n callback(roomId, null);\n\n // Clean up after a short timeout to prevent memory leaks\n setTimeout(() => removedRoomIds.delete(roomId), 2000);\n\n } else {\n // Clear removed status - room might be coming back (e.g., visibility change)\n removedRoomIds.delete(roomId);\n\n const room = (await matchMaker.query({ roomId }))[0];\n\n // Check if room was removed while we were querying\n // See \"updating metadata should not cause race condition\" test in LobbyRoom.test.ts\n if (removedRoomIds.has(roomId)) {\n return;\n }\n\n callback(roomId, room);\n }\n };\n\n await matchMaker.presence.subscribe(LOBBY_CHANNEL, cb);\n\n return () => matchMaker.presence.unsubscribe(LOBBY_CHANNEL, cb);\n}\n"],
5
+ "mappings": ";AAAA,YAAY,gBAAgB;AAK5B,IAAM,gBAAgB;AAaf,SAAS,YAA4B,MAAS,UAAmB,OAAO;AAC7E,QAAM,UAAU,KAAK,UAAU;AAE/B,MAAI,QAAQ,YAAY,CAAC,QAAQ,QAAQ;AACvC;AAAA,EACF;AAEA,MAAI,SAAS;AACX,IAAW,oBAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE,WAAW,CAAC,QAAQ,SAAS;AAC3B,IAAW,oBAAS,QAAQ,eAAe,GAAG,QAAQ,MAAM,IAAI;AAAA,EAClE;AACF;AAEA,eAAsB,eAAe,UAA6D;AAGhG,QAAM,iBAAiB,oBAAI,IAAY;AAEvC,QAAM,KAAK,OAAO,YAAoB;AACpC,UAAM,CAAC,QAAQ,QAAQ,IAAI,QAAQ,MAAM,GAAG;AAE5C,QAAI,aAAa,KAAK;AAEpB,qBAAe,IAAI,MAAM;AACzB,eAAS,QAAQ,IAAI;AAGrB,iBAAW,MAAM,eAAe,OAAO,MAAM,GAAG,GAAI;AAAA,IAEtD,OAAO;AAEL,qBAAe,OAAO,MAAM;AAE5B,YAAM,QAAQ,MAAiB,iBAAM,EAAE,OAAO,CAAC,GAAG,CAAC;AAInD,UAAI,eAAe,IAAI,MAAM,GAAG;AAC9B;AAAA,MACF;AAEA,eAAS,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,QAAiB,oBAAS,UAAU,eAAe,EAAE;AAErD,SAAO,MAAiB,oBAAS,YAAY,eAAe,EAAE;AAChE;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var LocalDriver_exports = {};
20
+ __export(LocalDriver_exports, {
21
+ LocalDriver: () => LocalDriver
22
+ });
23
+ module.exports = __toCommonJS(LocalDriver_exports);
24
+ var import_Debug = require("../../Debug.ts");
25
+ var import_Query = require("./Query.ts");
26
+ class LocalDriver {
27
+ constructor() {
28
+ this.rooms = [];
29
+ }
30
+ has(roomId) {
31
+ return this.rooms.some((room) => room.roomId === roomId);
32
+ }
33
+ query(conditions, sortOptions) {
34
+ const query = new import_Query.Query(this.rooms, conditions);
35
+ if (sortOptions) {
36
+ query.sort(sortOptions);
37
+ }
38
+ return query.filter(conditions);
39
+ }
40
+ cleanup(processId) {
41
+ const cachedRooms = this.query({ processId });
42
+ (0, import_Debug.debugMatchMaking)("removing stale rooms by processId %s (%s rooms found)", processId, cachedRooms.length);
43
+ cachedRooms.forEach((room) => this.remove(room.roomId));
44
+ return Promise.resolve();
45
+ }
46
+ findOne(conditions, sortOptions) {
47
+ const query = new import_Query.Query(this.rooms, conditions);
48
+ if (sortOptions) {
49
+ query.sort(sortOptions);
50
+ }
51
+ return query;
52
+ }
53
+ update(room, operations) {
54
+ if (operations.$set) {
55
+ for (const field in operations.$set) {
56
+ if (operations.$set.hasOwnProperty(field)) {
57
+ room[field] = operations.$set[field];
58
+ }
59
+ }
60
+ }
61
+ if (operations.$inc) {
62
+ for (const field in operations.$inc) {
63
+ if (operations.$inc.hasOwnProperty(field)) {
64
+ room[field] += operations.$inc[field];
65
+ }
66
+ }
67
+ }
68
+ return true;
69
+ }
70
+ persist(room, create = false) {
71
+ if (!create) {
72
+ return false;
73
+ }
74
+ this.rooms.push(room);
75
+ return true;
76
+ }
77
+ remove(roomId) {
78
+ const roomIndex = this.rooms.findIndex((room) => room.roomId === roomId);
79
+ if (roomIndex !== -1) {
80
+ this.rooms.splice(roomIndex, 1);
81
+ return true;
82
+ }
83
+ return false;
84
+ }
85
+ clear() {
86
+ this.rooms = [];
87
+ }
88
+ shutdown() {
89
+ }
90
+ }
91
+ // Annotate the CommonJS export names for ESM import in node:
92
+ 0 && (module.exports = {
93
+ LocalDriver
94
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/matchmaker/LocalDriver/LocalDriver.ts"],
4
+ "sourcesContent": ["import { debugMatchMaking } from '../../Debug.ts';\nimport type { IRoomCache, SortOptions, MatchMakerDriver } from '../driver.ts';\nimport { Query } from './Query.ts';\n\n// re-export\nexport type { IRoomCache, SortOptions, MatchMakerDriver };\n\nexport class LocalDriver implements MatchMakerDriver {\n public rooms: IRoomCache[] = [];\n\n public has(roomId: string) {\n return this.rooms.some((room) => room.roomId === roomId);\n }\n\n public query(conditions: Partial<IRoomCache>, sortOptions?: SortOptions) {\n const query = new Query<IRoomCache>(this.rooms, conditions);\n\n if (sortOptions) {\n query.sort(sortOptions);\n }\n\n return query.filter(conditions);\n }\n\n public cleanup(processId: string) {\n const cachedRooms = this.query({ processId });\n debugMatchMaking(\"removing stale rooms by processId %s (%s rooms found)\", processId, cachedRooms.length);\n\n cachedRooms.forEach((room) => this.remove(room.roomId));\n return Promise.resolve();\n }\n\n public findOne(conditions: Partial<IRoomCache>, sortOptions?: SortOptions) {\n const query = new Query<IRoomCache>(this.rooms, conditions);\n\n if (sortOptions) {\n query.sort(sortOptions);\n }\n\n return query as unknown as Promise<IRoomCache>;\n }\n\n public update(room: IRoomCache, operations: Partial<{ $set: Partial<IRoomCache>, $inc: Partial<IRoomCache> }>) {\n if (operations.$set) {\n for (const field in operations.$set) {\n if (operations.$set.hasOwnProperty(field)) {\n room[field] = operations.$set[field];\n }\n }\n }\n\n if (operations.$inc) {\n for (const field in operations.$inc) {\n if (operations.$inc.hasOwnProperty(field)) {\n room[field] += operations.$inc[field];\n }\n }\n }\n\n return true;\n }\n\n public persist(room: IRoomCache, create: boolean = false) {\n // if (this.rooms.indexOf(room) !== -1) {\n // // already in the list\n // return true;\n // }\n\n if (!create) { return false; }\n\n // add to the list\n this.rooms.push(room);\n\n return true;\n }\n\n public remove(roomId: string) {\n const roomIndex = this.rooms.findIndex((room) => room.roomId === roomId);\n if (roomIndex !== -1) {\n this.rooms.splice(roomIndex, 1);\n return true;\n }\n return false;\n }\n\n public clear() {\n this.rooms = [];\n }\n\n public shutdown() {\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AAEjC,mBAAsB;AAKf,MAAM,YAAwC;AAAA,EAA9C;AACL,SAAO,QAAsB,CAAC;AAAA;AAAA,EAEvB,IAAI,QAAgB;AACzB,WAAO,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,WAAW,MAAM;AAAA,EACzD;AAAA,EAEO,MAAM,YAAiC,aAA2B;AACvE,UAAM,QAAQ,IAAI,mBAAkB,KAAK,OAAO,UAAU;AAE1D,QAAI,aAAa;AACf,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,WAAO,MAAM,OAAO,UAAU;AAAA,EAChC;AAAA,EAEO,QAAQ,WAAmB;AAChC,UAAM,cAAc,KAAK,MAAM,EAAE,UAAU,CAAC;AAC5C,uCAAiB,yDAAyD,WAAW,YAAY,MAAM;AAEvG,gBAAY,QAAQ,CAAC,SAAS,KAAK,OAAO,KAAK,MAAM,CAAC;AACtD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEO,QAAQ,YAAiC,aAA2B;AACzE,UAAM,QAAQ,IAAI,mBAAkB,KAAK,OAAO,UAAU;AAE1D,QAAI,aAAa;AACf,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,OAAO,MAAkB,YAA+E;AAC7G,QAAI,WAAW,MAAM;AACnB,iBAAW,SAAS,WAAW,MAAM;AACnC,YAAI,WAAW,KAAK,eAAe,KAAK,GAAG;AACzC,eAAK,KAAK,IAAI,WAAW,KAAK,KAAK;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,WAAW,MAAM;AACnB,iBAAW,SAAS,WAAW,MAAM;AACnC,YAAI,WAAW,KAAK,eAAe,KAAK,GAAG;AACzC,eAAK,KAAK,KAAK,WAAW,KAAK,KAAK;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,QAAQ,MAAkB,SAAkB,OAAO;AAMxD,QAAI,CAAC,QAAQ;AAAE,aAAO;AAAA,IAAO;AAG7B,SAAK,MAAM,KAAK,IAAI;AAEpB,WAAO;AAAA,EACT;AAAA,EAEO,OAAO,QAAgB;AAC5B,UAAM,YAAY,KAAK,MAAM,UAAU,CAAC,SAAS,KAAK,WAAW,MAAM;AACvE,QAAI,cAAc,IAAI;AACpB,WAAK,MAAM,OAAO,WAAW,CAAC;AAC9B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEO,QAAQ;AACb,SAAK,QAAQ,CAAC;AAAA,EAChB;AAAA,EAEO,WAAW;AAAA,EAClB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ // packages/core/src/matchmaker/LocalDriver/LocalDriver.ts
2
+ import { debugMatchMaking } from "../../Debug.mjs";
3
+ import { Query } from "./Query.mjs";
4
+ var LocalDriver = class {
5
+ constructor() {
6
+ this.rooms = [];
7
+ }
8
+ has(roomId) {
9
+ return this.rooms.some((room) => room.roomId === roomId);
10
+ }
11
+ query(conditions, sortOptions) {
12
+ const query = new Query(this.rooms, conditions);
13
+ if (sortOptions) {
14
+ query.sort(sortOptions);
15
+ }
16
+ return query.filter(conditions);
17
+ }
18
+ cleanup(processId) {
19
+ const cachedRooms = this.query({ processId });
20
+ debugMatchMaking("removing stale rooms by processId %s (%s rooms found)", processId, cachedRooms.length);
21
+ cachedRooms.forEach((room) => this.remove(room.roomId));
22
+ return Promise.resolve();
23
+ }
24
+ findOne(conditions, sortOptions) {
25
+ const query = new Query(this.rooms, conditions);
26
+ if (sortOptions) {
27
+ query.sort(sortOptions);
28
+ }
29
+ return query;
30
+ }
31
+ update(room, operations) {
32
+ if (operations.$set) {
33
+ for (const field in operations.$set) {
34
+ if (operations.$set.hasOwnProperty(field)) {
35
+ room[field] = operations.$set[field];
36
+ }
37
+ }
38
+ }
39
+ if (operations.$inc) {
40
+ for (const field in operations.$inc) {
41
+ if (operations.$inc.hasOwnProperty(field)) {
42
+ room[field] += operations.$inc[field];
43
+ }
44
+ }
45
+ }
46
+ return true;
47
+ }
48
+ persist(room, create = false) {
49
+ if (!create) {
50
+ return false;
51
+ }
52
+ this.rooms.push(room);
53
+ return true;
54
+ }
55
+ remove(roomId) {
56
+ const roomIndex = this.rooms.findIndex((room) => room.roomId === roomId);
57
+ if (roomIndex !== -1) {
58
+ this.rooms.splice(roomIndex, 1);
59
+ return true;
60
+ }
61
+ return false;
62
+ }
63
+ clear() {
64
+ this.rooms = [];
65
+ }
66
+ shutdown() {
67
+ }
68
+ };
69
+ export {
70
+ LocalDriver
71
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/matchmaker/LocalDriver/LocalDriver.ts"],
4
+ "sourcesContent": ["import { debugMatchMaking } from '../../Debug.ts';\nimport type { IRoomCache, SortOptions, MatchMakerDriver } from '../driver.ts';\nimport { Query } from './Query.ts';\n\n// re-export\nexport type { IRoomCache, SortOptions, MatchMakerDriver };\n\nexport class LocalDriver implements MatchMakerDriver {\n public rooms: IRoomCache[] = [];\n\n public has(roomId: string) {\n return this.rooms.some((room) => room.roomId === roomId);\n }\n\n public query(conditions: Partial<IRoomCache>, sortOptions?: SortOptions) {\n const query = new Query<IRoomCache>(this.rooms, conditions);\n\n if (sortOptions) {\n query.sort(sortOptions);\n }\n\n return query.filter(conditions);\n }\n\n public cleanup(processId: string) {\n const cachedRooms = this.query({ processId });\n debugMatchMaking(\"removing stale rooms by processId %s (%s rooms found)\", processId, cachedRooms.length);\n\n cachedRooms.forEach((room) => this.remove(room.roomId));\n return Promise.resolve();\n }\n\n public findOne(conditions: Partial<IRoomCache>, sortOptions?: SortOptions) {\n const query = new Query<IRoomCache>(this.rooms, conditions);\n\n if (sortOptions) {\n query.sort(sortOptions);\n }\n\n return query as unknown as Promise<IRoomCache>;\n }\n\n public update(room: IRoomCache, operations: Partial<{ $set: Partial<IRoomCache>, $inc: Partial<IRoomCache> }>) {\n if (operations.$set) {\n for (const field in operations.$set) {\n if (operations.$set.hasOwnProperty(field)) {\n room[field] = operations.$set[field];\n }\n }\n }\n\n if (operations.$inc) {\n for (const field in operations.$inc) {\n if (operations.$inc.hasOwnProperty(field)) {\n room[field] += operations.$inc[field];\n }\n }\n }\n\n return true;\n }\n\n public persist(room: IRoomCache, create: boolean = false) {\n // if (this.rooms.indexOf(room) !== -1) {\n // // already in the list\n // return true;\n // }\n\n if (!create) { return false; }\n\n // add to the list\n this.rooms.push(room);\n\n return true;\n }\n\n public remove(roomId: string) {\n const roomIndex = this.rooms.findIndex((room) => room.roomId === roomId);\n if (roomIndex !== -1) {\n this.rooms.splice(roomIndex, 1);\n return true;\n }\n return false;\n }\n\n public clear() {\n this.rooms = [];\n }\n\n public shutdown() {\n }\n}\n"],
5
+ "mappings": ";AAAA,SAAS,wBAAwB;AAEjC,SAAS,aAAa;AAKf,IAAM,cAAN,MAA8C;AAAA,EAA9C;AACL,SAAO,QAAsB,CAAC;AAAA;AAAA,EAEvB,IAAI,QAAgB;AACzB,WAAO,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,WAAW,MAAM;AAAA,EACzD;AAAA,EAEO,MAAM,YAAiC,aAA2B;AACvE,UAAM,QAAQ,IAAI,MAAkB,KAAK,OAAO,UAAU;AAE1D,QAAI,aAAa;AACf,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,WAAO,MAAM,OAAO,UAAU;AAAA,EAChC;AAAA,EAEO,QAAQ,WAAmB;AAChC,UAAM,cAAc,KAAK,MAAM,EAAE,UAAU,CAAC;AAC5C,qBAAiB,yDAAyD,WAAW,YAAY,MAAM;AAEvG,gBAAY,QAAQ,CAAC,SAAS,KAAK,OAAO,KAAK,MAAM,CAAC;AACtD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEO,QAAQ,YAAiC,aAA2B;AACzE,UAAM,QAAQ,IAAI,MAAkB,KAAK,OAAO,UAAU;AAE1D,QAAI,aAAa;AACf,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,OAAO,MAAkB,YAA+E;AAC7G,QAAI,WAAW,MAAM;AACnB,iBAAW,SAAS,WAAW,MAAM;AACnC,YAAI,WAAW,KAAK,eAAe,KAAK,GAAG;AACzC,eAAK,KAAK,IAAI,WAAW,KAAK,KAAK;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,WAAW,MAAM;AACnB,iBAAW,SAAS,WAAW,MAAM;AACnC,YAAI,WAAW,KAAK,eAAe,KAAK,GAAG;AACzC,eAAK,KAAK,KAAK,WAAW,KAAK,KAAK;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,QAAQ,MAAkB,SAAkB,OAAO;AAMxD,QAAI,CAAC,QAAQ;AAAE,aAAO;AAAA,IAAO;AAG7B,SAAK,MAAM,KAAK,IAAI;AAEpB,WAAO;AAAA,EACT;AAAA,EAEO,OAAO,QAAgB;AAC5B,UAAM,YAAY,KAAK,MAAM,UAAU,CAAC,SAAS,KAAK,WAAW,MAAM;AACvE,QAAI,cAAc,IAAI;AACpB,WAAK,MAAM,OAAO,WAAW,CAAC;AAC9B,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEO,QAAQ;AACb,SAAK,QAAQ,CAAC;AAAA,EAChB;AAAA,EAEO,WAAW;AAAA,EAClB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var Query_exports = {};
20
+ __export(Query_exports, {
21
+ Query: () => Query
22
+ });
23
+ module.exports = __toCommonJS(Query_exports);
24
+ class Query {
25
+ constructor(rooms, conditions) {
26
+ this.$rooms = rooms.slice(0);
27
+ this.conditions = conditions;
28
+ }
29
+ sort(options) {
30
+ this.sortOptions = options;
31
+ return this;
32
+ }
33
+ applySort(rooms) {
34
+ if (!this.sortOptions) {
35
+ return rooms;
36
+ }
37
+ return rooms.sort((room1, room2) => {
38
+ for (const field in this.sortOptions) {
39
+ const direction = this.sortOptions[field];
40
+ if (room1.hasOwnProperty(field)) {
41
+ if (direction === 1 || direction === "asc" || direction === "ascending") {
42
+ if (room1[field] > room2[field]) {
43
+ return 1;
44
+ }
45
+ if (room1[field] < room2[field]) {
46
+ return -1;
47
+ }
48
+ } else {
49
+ if (room1[field] > room2[field]) {
50
+ return -1;
51
+ }
52
+ if (room1[field] < room2[field]) {
53
+ return 1;
54
+ }
55
+ }
56
+ } else if (room1.metadata?.hasOwnProperty(field)) {
57
+ if (direction === 1 || direction === "asc" || direction === "ascending") {
58
+ if (room1.metadata[field] > room2.metadata[field]) {
59
+ return 1;
60
+ }
61
+ if (room1.metadata[field] < room2.metadata[field]) {
62
+ return -1;
63
+ }
64
+ } else {
65
+ if (room1.metadata[field] > room2.metadata[field]) {
66
+ return -1;
67
+ }
68
+ if (room1.metadata[field] < room2.metadata[field]) {
69
+ return 1;
70
+ }
71
+ }
72
+ }
73
+ }
74
+ return 0;
75
+ });
76
+ }
77
+ applyFilter(rooms, conditions) {
78
+ return rooms.filter(((room) => {
79
+ for (const field in conditions) {
80
+ if (conditions.hasOwnProperty(field)) {
81
+ if (room.hasOwnProperty(field)) {
82
+ if (room[field] !== conditions[field]) {
83
+ return false;
84
+ }
85
+ } else if (room.metadata?.hasOwnProperty(field)) {
86
+ if (room.metadata[field] !== conditions[field]) {
87
+ return false;
88
+ }
89
+ } else {
90
+ return false;
91
+ }
92
+ }
93
+ }
94
+ return true;
95
+ }));
96
+ }
97
+ filter(conditions) {
98
+ const filtered = this.applyFilter(this.$rooms, conditions);
99
+ return this.applySort(filtered);
100
+ }
101
+ then(resolve, reject) {
102
+ const filtered = this.applyFilter(this.$rooms, this.conditions);
103
+ const sorted = this.applySort(filtered);
104
+ const result = sorted[0];
105
+ return resolve(result);
106
+ }
107
+ }
108
+ // Annotate the CommonJS export names for ESM import in node:
109
+ 0 && (module.exports = {
110
+ Query
111
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/matchmaker/LocalDriver/Query.ts"],
4
+ "sourcesContent": ["import type { IRoomCache, SortOptions } from '../driver.ts';\n\nexport class Query<T extends IRoomCache> {\n private $rooms: T[];\n private conditions: any;\n private sortOptions?: SortOptions;\n\n constructor(rooms: any[], conditions) {\n this.$rooms = rooms.slice(0);\n this.conditions = conditions;\n }\n\n public sort(options: SortOptions) {\n // Store sort options instead of sorting immediately\n // This allows filtering first, then sorting fewer items\n this.sortOptions = options;\n return this;\n }\n\n private applySort(rooms: T[]): T[] {\n if (!this.sortOptions) {\n return rooms;\n }\n\n return rooms.sort((room1: T, room2: T) => {\n for (const field in this.sortOptions) {\n const direction = this.sortOptions[field];\n if (room1.hasOwnProperty(field)) {\n /**\n * IRoomCache field\n */\n if (direction === 1 || direction === 'asc' || direction === 'ascending') {\n if (room1[field] > room2[field]) { return 1; }\n if (room1[field] < room2[field]) { return -1; }\n\n } else {\n if (room1[field] > room2[field]) { return -1; }\n if (room1[field] < room2[field]) { return 1; }\n }\n } else if (room1.metadata?.hasOwnProperty(field)) {\n /**\n * metadata field\n */\n if (direction === 1 || direction === 'asc' || direction === 'ascending') {\n if (room1.metadata[field] > room2.metadata[field]) { return 1; }\n if (room1.metadata[field] < room2.metadata[field]) { return -1; }\n } else {\n if (room1.metadata[field] > room2.metadata[field]) { return -1; }\n if (room1.metadata[field] < room2.metadata[field]) { return 1; }\n }\n }\n }\n return 0;\n });\n }\n\n private applyFilter(rooms: T[], conditions: any): T[] {\n return rooms.filter(((room) => {\n for (const field in conditions) {\n if (conditions.hasOwnProperty(field)) {\n // Check if field exists in room (IRoomCache base fields)\n if (room.hasOwnProperty(field)) {\n if (room[field] !== conditions[field]) {\n return false;\n }\n } else if (room.metadata?.hasOwnProperty(field)) {\n // Check if field exists in metadata\n if (room.metadata[field] !== conditions[field]) {\n return false;\n }\n } else {\n // Field doesn't exist in room or metadata\n return false;\n }\n }\n }\n return true;\n }));\n }\n\n public filter(conditions: any) {\n // Filter first to reduce the number of items to sort\n const filtered = this.applyFilter(this.$rooms, conditions);\n return this.applySort(filtered);\n }\n\n public then(resolve, reject) {\n // Filter first to reduce the number of items to sort\n const filtered = this.applyFilter(this.$rooms, this.conditions);\n const sorted = this.applySort(filtered);\n const result: any = sorted[0];\n return resolve(result);\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,MAA4B;AAAA,EAKvC,YAAY,OAAc,YAAY;AACpC,SAAK,SAAS,MAAM,MAAM,CAAC;AAC3B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEO,KAAK,SAAsB;AAGhC,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,OAAiB;AACjC,QAAI,CAAC,KAAK,aAAa;AACrB,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,KAAK,CAAC,OAAU,UAAa;AACxC,iBAAW,SAAS,KAAK,aAAa;AACpC,cAAM,YAAY,KAAK,YAAY,KAAK;AACxC,YAAI,MAAM,eAAe,KAAK,GAAG;AAI/B,cAAI,cAAc,KAAK,cAAc,SAAS,cAAc,aAAa;AACvE,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAC7C,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAAA,UAEhD,OAAO;AACL,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAC9C,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAAA,UAC/C;AAAA,QACF,WAAW,MAAM,UAAU,eAAe,KAAK,GAAG;AAIhD,cAAI,cAAc,KAAK,cAAc,SAAS,cAAc,aAAa;AACvE,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAC/D,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAAA,UAClE,OAAO;AACL,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAChE,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,OAAY,YAAsB;AACpD,WAAO,MAAM,QAAQ,CAAC,SAAS;AAC7B,iBAAW,SAAS,YAAY;AAC9B,YAAI,WAAW,eAAe,KAAK,GAAG;AAEpC,cAAI,KAAK,eAAe,KAAK,GAAG;AAC9B,gBAAI,KAAK,KAAK,MAAM,WAAW,KAAK,GAAG;AACrC,qBAAO;AAAA,YACT;AAAA,UACF,WAAW,KAAK,UAAU,eAAe,KAAK,GAAG;AAE/C,gBAAI,KAAK,SAAS,KAAK,MAAM,WAAW,KAAK,GAAG;AAC9C,qBAAO;AAAA,YACT;AAAA,UACF,OAAO;AAEL,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,EAAE;AAAA,EACJ;AAAA,EAEO,OAAO,YAAiB;AAE7B,UAAM,WAAW,KAAK,YAAY,KAAK,QAAQ,UAAU;AACzD,WAAO,KAAK,UAAU,QAAQ;AAAA,EAChC;AAAA,EAEO,KAAK,SAAS,QAAQ;AAE3B,UAAM,WAAW,KAAK,YAAY,KAAK,QAAQ,KAAK,UAAU;AAC9D,UAAM,SAAS,KAAK,UAAU,QAAQ;AACtC,UAAM,SAAc,OAAO,CAAC;AAC5B,WAAO,QAAQ,MAAM;AAAA,EACvB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,88 @@
1
+ // packages/core/src/matchmaker/LocalDriver/Query.ts
2
+ var Query = class {
3
+ constructor(rooms, conditions) {
4
+ this.$rooms = rooms.slice(0);
5
+ this.conditions = conditions;
6
+ }
7
+ sort(options) {
8
+ this.sortOptions = options;
9
+ return this;
10
+ }
11
+ applySort(rooms) {
12
+ if (!this.sortOptions) {
13
+ return rooms;
14
+ }
15
+ return rooms.sort((room1, room2) => {
16
+ for (const field in this.sortOptions) {
17
+ const direction = this.sortOptions[field];
18
+ if (room1.hasOwnProperty(field)) {
19
+ if (direction === 1 || direction === "asc" || direction === "ascending") {
20
+ if (room1[field] > room2[field]) {
21
+ return 1;
22
+ }
23
+ if (room1[field] < room2[field]) {
24
+ return -1;
25
+ }
26
+ } else {
27
+ if (room1[field] > room2[field]) {
28
+ return -1;
29
+ }
30
+ if (room1[field] < room2[field]) {
31
+ return 1;
32
+ }
33
+ }
34
+ } else if (room1.metadata?.hasOwnProperty(field)) {
35
+ if (direction === 1 || direction === "asc" || direction === "ascending") {
36
+ if (room1.metadata[field] > room2.metadata[field]) {
37
+ return 1;
38
+ }
39
+ if (room1.metadata[field] < room2.metadata[field]) {
40
+ return -1;
41
+ }
42
+ } else {
43
+ if (room1.metadata[field] > room2.metadata[field]) {
44
+ return -1;
45
+ }
46
+ if (room1.metadata[field] < room2.metadata[field]) {
47
+ return 1;
48
+ }
49
+ }
50
+ }
51
+ }
52
+ return 0;
53
+ });
54
+ }
55
+ applyFilter(rooms, conditions) {
56
+ return rooms.filter(((room) => {
57
+ for (const field in conditions) {
58
+ if (conditions.hasOwnProperty(field)) {
59
+ if (room.hasOwnProperty(field)) {
60
+ if (room[field] !== conditions[field]) {
61
+ return false;
62
+ }
63
+ } else if (room.metadata?.hasOwnProperty(field)) {
64
+ if (room.metadata[field] !== conditions[field]) {
65
+ return false;
66
+ }
67
+ } else {
68
+ return false;
69
+ }
70
+ }
71
+ }
72
+ return true;
73
+ }));
74
+ }
75
+ filter(conditions) {
76
+ const filtered = this.applyFilter(this.$rooms, conditions);
77
+ return this.applySort(filtered);
78
+ }
79
+ then(resolve, reject) {
80
+ const filtered = this.applyFilter(this.$rooms, this.conditions);
81
+ const sorted = this.applySort(filtered);
82
+ const result = sorted[0];
83
+ return resolve(result);
84
+ }
85
+ };
86
+ export {
87
+ Query
88
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/matchmaker/LocalDriver/Query.ts"],
4
+ "sourcesContent": ["import type { IRoomCache, SortOptions } from '../driver.ts';\n\nexport class Query<T extends IRoomCache> {\n private $rooms: T[];\n private conditions: any;\n private sortOptions?: SortOptions;\n\n constructor(rooms: any[], conditions) {\n this.$rooms = rooms.slice(0);\n this.conditions = conditions;\n }\n\n public sort(options: SortOptions) {\n // Store sort options instead of sorting immediately\n // This allows filtering first, then sorting fewer items\n this.sortOptions = options;\n return this;\n }\n\n private applySort(rooms: T[]): T[] {\n if (!this.sortOptions) {\n return rooms;\n }\n\n return rooms.sort((room1: T, room2: T) => {\n for (const field in this.sortOptions) {\n const direction = this.sortOptions[field];\n if (room1.hasOwnProperty(field)) {\n /**\n * IRoomCache field\n */\n if (direction === 1 || direction === 'asc' || direction === 'ascending') {\n if (room1[field] > room2[field]) { return 1; }\n if (room1[field] < room2[field]) { return -1; }\n\n } else {\n if (room1[field] > room2[field]) { return -1; }\n if (room1[field] < room2[field]) { return 1; }\n }\n } else if (room1.metadata?.hasOwnProperty(field)) {\n /**\n * metadata field\n */\n if (direction === 1 || direction === 'asc' || direction === 'ascending') {\n if (room1.metadata[field] > room2.metadata[field]) { return 1; }\n if (room1.metadata[field] < room2.metadata[field]) { return -1; }\n } else {\n if (room1.metadata[field] > room2.metadata[field]) { return -1; }\n if (room1.metadata[field] < room2.metadata[field]) { return 1; }\n }\n }\n }\n return 0;\n });\n }\n\n private applyFilter(rooms: T[], conditions: any): T[] {\n return rooms.filter(((room) => {\n for (const field in conditions) {\n if (conditions.hasOwnProperty(field)) {\n // Check if field exists in room (IRoomCache base fields)\n if (room.hasOwnProperty(field)) {\n if (room[field] !== conditions[field]) {\n return false;\n }\n } else if (room.metadata?.hasOwnProperty(field)) {\n // Check if field exists in metadata\n if (room.metadata[field] !== conditions[field]) {\n return false;\n }\n } else {\n // Field doesn't exist in room or metadata\n return false;\n }\n }\n }\n return true;\n }));\n }\n\n public filter(conditions: any) {\n // Filter first to reduce the number of items to sort\n const filtered = this.applyFilter(this.$rooms, conditions);\n return this.applySort(filtered);\n }\n\n public then(resolve, reject) {\n // Filter first to reduce the number of items to sort\n const filtered = this.applyFilter(this.$rooms, this.conditions);\n const sorted = this.applySort(filtered);\n const result: any = sorted[0];\n return resolve(result);\n }\n}\n"],
5
+ "mappings": ";AAEO,IAAM,QAAN,MAAkC;AAAA,EAKvC,YAAY,OAAc,YAAY;AACpC,SAAK,SAAS,MAAM,MAAM,CAAC;AAC3B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEO,KAAK,SAAsB;AAGhC,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,OAAiB;AACjC,QAAI,CAAC,KAAK,aAAa;AACrB,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,KAAK,CAAC,OAAU,UAAa;AACxC,iBAAW,SAAS,KAAK,aAAa;AACpC,cAAM,YAAY,KAAK,YAAY,KAAK;AACxC,YAAI,MAAM,eAAe,KAAK,GAAG;AAI/B,cAAI,cAAc,KAAK,cAAc,SAAS,cAAc,aAAa;AACvE,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAC7C,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAAA,UAEhD,OAAO;AACL,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAC9C,gBAAI,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAAA,UAC/C;AAAA,QACF,WAAW,MAAM,UAAU,eAAe,KAAK,GAAG;AAIhD,cAAI,cAAc,KAAK,cAAc,SAAS,cAAc,aAAa;AACvE,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAC/D,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAAA,UAClE,OAAO;AACL,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAI;AAChE,gBAAI,MAAM,SAAS,KAAK,IAAI,MAAM,SAAS,KAAK,GAAG;AAAE,qBAAO;AAAA,YAAG;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,OAAY,YAAsB;AACpD,WAAO,MAAM,QAAQ,CAAC,SAAS;AAC7B,iBAAW,SAAS,YAAY;AAC9B,YAAI,WAAW,eAAe,KAAK,GAAG;AAEpC,cAAI,KAAK,eAAe,KAAK,GAAG;AAC9B,gBAAI,KAAK,KAAK,MAAM,WAAW,KAAK,GAAG;AACrC,qBAAO;AAAA,YACT;AAAA,UACF,WAAW,KAAK,UAAU,eAAe,KAAK,GAAG;AAE/C,gBAAI,KAAK,SAAS,KAAK,MAAM,WAAW,KAAK,GAAG;AAC9C,qBAAO;AAAA,YACT;AAAA,UACF,OAAO;AAEL,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,EAAE;AAAA,EACJ;AAAA,EAEO,OAAO,YAAiB;AAE7B,UAAM,WAAW,KAAK,YAAY,KAAK,QAAQ,UAAU;AACzD,WAAO,KAAK,UAAU,QAAQ;AAAA,EAChC;AAAA,EAEO,KAAK,SAAS,QAAQ;AAE3B,UAAM,WAAW,KAAK,YAAY,KAAK,QAAQ,KAAK,UAAU;AAC9D,UAAM,SAAS,KAAK,UAAU,QAAQ;AACtC,UAAM,SAAc,OAAO,CAAC;AAC5B,WAAO,QAAQ,MAAM;AAAA,EACvB;AACF;",
6
+ "names": []
7
+ }
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -22,8 +23,9 @@ __export(RegisteredHandler_exports, {
22
23
  });
23
24
  module.exports = __toCommonJS(RegisteredHandler_exports);
24
25
  var import_events = require("events");
25
- var import_Logger = require("../Logger.js");
26
- var import_Lobby = require("./Lobby.js");
26
+ var import_Logger = require("../Logger.ts");
27
+ var import_Room = require("./../Room.ts");
28
+ var import_Lobby = require("./Lobby.ts");
27
29
  const INVALID_OPTION_KEYS = [
28
30
  "clients",
29
31
  "locked",
@@ -35,18 +37,19 @@ const INVALID_OPTION_KEYS = [
35
37
  "roomId"
36
38
  ];
37
39
  class RegisteredHandler extends import_events.EventEmitter {
38
- constructor(name, klass, options) {
40
+ constructor(klass, options) {
39
41
  super();
40
- this.name = name;
42
+ this.filterOptions = [];
43
+ this.realtimeListingEnabled = false;
41
44
  this.klass = klass;
42
45
  this.options = options;
43
- this.filterOptions = [];
44
46
  if (typeof klass !== "function") {
45
47
  import_Logger.logger.debug("You are likely not importing your room class correctly.");
46
48
  throw new Error(`class is expected but ${typeof klass} was provided.`);
47
49
  }
48
50
  }
49
51
  enableRealtimeListing() {
52
+ this.realtimeListingEnabled = true;
50
53
  this.on("create", (room) => (0, import_Lobby.updateLobby)(room));
51
54
  this.on("lock", (room) => (0, import_Lobby.updateLobby)(room));
52
55
  this.on("unlock", (room) => (0, import_Lobby.updateLobby)(room));
@@ -56,21 +59,68 @@ class RegisteredHandler extends import_events.EventEmitter {
56
59
  (0, import_Lobby.updateLobby)(room);
57
60
  }
58
61
  });
59
- this.on("dispose", (room) => (0, import_Lobby.updateLobby)(room, false));
60
62
  this.on("visibility-change", (room, isVisible) => (0, import_Lobby.updateLobby)(room, isVisible));
63
+ this.on("metadata-change", (room) => (0, import_Lobby.updateLobby)(room));
64
+ this.on("dispose", (room) => (0, import_Lobby.updateLobby)(room, true));
61
65
  return this;
62
66
  }
67
+ /**
68
+ * Define which fields should be used for filtering rooms.
69
+ * Supports both onCreate options and metadata fields using dot notation.
70
+ *
71
+ * @example
72
+ * // Filter by IRoomCache fields
73
+ * .filterBy(['maxClients'])
74
+ *
75
+ * @example
76
+ * // Filter by metadata fields
77
+ * .filterBy(['difficulty', 'metadata.region'])
78
+ *
79
+ * @example
80
+ * // Mix both
81
+ * .filterBy(['mode', 'difficulty', 'maxClients'])
82
+ */
63
83
  filterBy(options) {
64
84
  this.filterOptions = options;
65
85
  return this;
66
86
  }
87
+ /**
88
+ * Define how rooms should be sorted when querying.
89
+ * Supports both room cache fields and metadata fields using dot notation.
90
+ *
91
+ * @example
92
+ * // Sort by number of clients (descending)
93
+ * .sortBy({ clients: -1 })
94
+ *
95
+ * @example
96
+ * // Sort by metadata field
97
+ * .sortBy({ 'metadata.rating': -1 })
98
+ *
99
+ * @example
100
+ * // Multiple sort criteria
101
+ * .sortBy({ 'metadata.skillLevel': 1, clients: -1 })
102
+ */
67
103
  sortBy(options) {
68
104
  this.sortOptions = options;
69
105
  return this;
70
106
  }
107
+ getMetadataFromOptions(options) {
108
+ const metadata = this.getFilterOptions(options);
109
+ if (this.sortOptions) {
110
+ for (const field in this.sortOptions) {
111
+ if (field in options && !(field in metadata)) {
112
+ metadata[field] = options[field];
113
+ }
114
+ }
115
+ }
116
+ return Object.keys(metadata).length > 0 ? { metadata } : {};
117
+ }
118
+ /**
119
+ * Extract filter options from client options.
120
+ */
71
121
  getFilterOptions(options) {
72
122
  return this.filterOptions.reduce((prev, curr, i, arr) => {
73
- const field = arr[i];
123
+ const field = String(arr[i]);
74
124
  if (options.hasOwnProperty(field)) {
75
125
  if (INVALID_OPTION_KEYS.indexOf(field) !== -1) {
76
126
  import_Logger.logger.warn(`option "${field}" has internal usage and is going to be ignored.`);