@mnbroatch/boardgame.io 0.0.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 (296) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/ai/package.json +7 -0
  4. package/client/package.json +7 -0
  5. package/core/package.json +7 -0
  6. package/debug/package.json +7 -0
  7. package/dist/boardgameio.es.js +14238 -0
  8. package/dist/boardgameio.js +14277 -0
  9. package/dist/boardgameio.min.js +16 -0
  10. package/dist/cjs/Debug-9d141c06.js +9586 -0
  11. package/dist/cjs/ai-e0e8a768.js +377 -0
  12. package/dist/cjs/ai.js +20 -0
  13. package/dist/cjs/client-76dec77b.js +258 -0
  14. package/dist/cjs/client-a22d7500.js +524 -0
  15. package/dist/cjs/client.js +26 -0
  16. package/dist/cjs/core.js +52 -0
  17. package/dist/cjs/debug.js +18 -0
  18. package/dist/cjs/filter-player-view-bb02e2f6.js +89 -0
  19. package/dist/cjs/initialize-267fcd69.js +61 -0
  20. package/dist/cjs/internal.js +25 -0
  21. package/dist/cjs/master-2904879d.js +320 -0
  22. package/dist/cjs/master.js +18 -0
  23. package/dist/cjs/multiplayer.js +23 -0
  24. package/dist/cjs/plugin-random-7425844d.js +229 -0
  25. package/dist/cjs/plugins.js +59 -0
  26. package/dist/cjs/react-native.js +182 -0
  27. package/dist/cjs/react.js +727 -0
  28. package/dist/cjs/reducer-16eec232.js +1203 -0
  29. package/dist/cjs/server.js +4087 -0
  30. package/dist/cjs/socketio-7a0837eb.js +478 -0
  31. package/dist/cjs/testing.js +30 -0
  32. package/dist/cjs/transport-b1874dfa.js +37 -0
  33. package/dist/cjs/turn-order-b2ff8740.js +1136 -0
  34. package/dist/cjs/util-fcfd8fb8.js +140 -0
  35. package/dist/esm/Debug-0141fe2d.js +9577 -0
  36. package/dist/esm/ai-5c06e761.js +371 -0
  37. package/dist/esm/ai.js +8 -0
  38. package/dist/esm/client-2e653027.js +522 -0
  39. package/dist/esm/client-5f57c3f2.js +255 -0
  40. package/dist/esm/client.js +16 -0
  41. package/dist/esm/core.js +40 -0
  42. package/dist/esm/debug.js +10 -0
  43. package/dist/esm/filter-player-view-2c6cc96f.js +87 -0
  44. package/dist/esm/initialize-11d626ca.js +59 -0
  45. package/dist/esm/internal.js +10 -0
  46. package/dist/esm/master-fa8f2e43.js +318 -0
  47. package/dist/esm/master.js +10 -0
  48. package/dist/esm/multiplayer.js +14 -0
  49. package/dist/esm/plugin-random-087f861e.js +226 -0
  50. package/dist/esm/plugins.js +55 -0
  51. package/dist/esm/react-native.js +173 -0
  52. package/dist/esm/react.js +716 -0
  53. package/dist/esm/reducer-c46da7e5.js +1198 -0
  54. package/dist/esm/socketio-c22ffa65.js +455 -0
  55. package/dist/esm/testing.js +26 -0
  56. package/dist/esm/transport-ce07b771.js +35 -0
  57. package/dist/esm/turn-order-376d315e.js +1091 -0
  58. package/dist/esm/util-b6147cef.js +135 -0
  59. package/dist/types/packages/ai.d.ts +5 -0
  60. package/dist/types/packages/client.d.ts +3 -0
  61. package/dist/types/packages/core.d.ts +5 -0
  62. package/dist/types/packages/debug.d.ts +2 -0
  63. package/dist/types/packages/internal.d.ts +8 -0
  64. package/dist/types/packages/master.d.ts +2 -0
  65. package/dist/types/packages/multiplayer.d.ts +3 -0
  66. package/dist/types/packages/plugins.d.ts +3 -0
  67. package/dist/types/packages/react-native.d.ts +2 -0
  68. package/dist/types/packages/react.d.ts +3 -0
  69. package/dist/types/packages/server.d.ts +6 -0
  70. package/dist/types/packages/testing.d.ts +1 -0
  71. package/dist/types/src/ai/ai.d.ts +53 -0
  72. package/dist/types/src/ai/ai.test.d.ts +1 -0
  73. package/dist/types/src/ai/bot.d.ts +40 -0
  74. package/dist/types/src/ai/mcts-bot.d.ts +60 -0
  75. package/dist/types/src/ai/random-bot.d.ts +27 -0
  76. package/dist/types/src/client/client.d.ts +104 -0
  77. package/dist/types/src/client/client.test.d.ts +1 -0
  78. package/dist/types/src/client/debug/tests/debug.test.d.ts +1 -0
  79. package/dist/types/src/client/manager.d.ts +61 -0
  80. package/dist/types/src/client/react.d.ts +75 -0
  81. package/dist/types/src/client/react.ssr.test.d.ts +4 -0
  82. package/dist/types/src/client/react.test.d.ts +1 -0
  83. package/dist/types/src/client/transport/dummy.d.ts +18 -0
  84. package/dist/types/src/client/transport/local.d.ts +59 -0
  85. package/dist/types/src/client/transport/local.test.d.ts +1 -0
  86. package/dist/types/src/client/transport/socketio.d.ts +45 -0
  87. package/dist/types/src/client/transport/socketio.test.d.ts +1 -0
  88. package/dist/types/src/client/transport/transport.d.ts +50 -0
  89. package/dist/types/src/client/transport/transport.test.d.ts +1 -0
  90. package/dist/types/src/core/action-creators.d.ts +144 -0
  91. package/dist/types/src/core/action-types.d.ts +10 -0
  92. package/dist/types/src/core/backwards-compatibility.d.ts +12 -0
  93. package/dist/types/src/core/constants.d.ts +6 -0
  94. package/dist/types/src/core/errors.d.ts +15 -0
  95. package/dist/types/src/core/flow.d.ts +28 -0
  96. package/dist/types/src/core/flow.test.d.ts +1 -0
  97. package/dist/types/src/core/game-methods.d.ts +9 -0
  98. package/dist/types/src/core/game.d.ts +26 -0
  99. package/dist/types/src/core/game.test.d.ts +1 -0
  100. package/dist/types/src/core/initialize.d.ts +9 -0
  101. package/dist/types/src/core/logger.d.ts +2 -0
  102. package/dist/types/src/core/player-view.d.ts +7 -0
  103. package/dist/types/src/core/player-view.test.d.ts +1 -0
  104. package/dist/types/src/core/reducer.d.ts +155 -0
  105. package/dist/types/src/core/reducer.test.d.ts +1 -0
  106. package/dist/types/src/core/turn-order.d.ts +179 -0
  107. package/dist/types/src/core/turn-order.test.d.ts +8 -0
  108. package/dist/types/src/lobby/client.d.ts +194 -0
  109. package/dist/types/src/lobby/client.test.d.ts +1 -0
  110. package/dist/types/src/lobby/connection.d.ts +44 -0
  111. package/dist/types/src/lobby/connection.test.d.ts +1 -0
  112. package/dist/types/src/lobby/create-match-form.d.ts +26 -0
  113. package/dist/types/src/lobby/login-form.d.ts +23 -0
  114. package/dist/types/src/lobby/match-instance.d.ts +31 -0
  115. package/dist/types/src/lobby/react.d.ts +113 -0
  116. package/dist/types/src/lobby/react.ssr.test.d.ts +4 -0
  117. package/dist/types/src/lobby/react.test.d.ts +1 -0
  118. package/dist/types/src/master/filter-player-view.d.ts +96 -0
  119. package/dist/types/src/master/filter-player-view.test.d.ts +1 -0
  120. package/dist/types/src/master/master.d.ts +94 -0
  121. package/dist/types/src/master/master.test.d.ts +1 -0
  122. package/dist/types/src/plugins/events/events.d.ts +54 -0
  123. package/dist/types/src/plugins/events/events.test.d.ts +1 -0
  124. package/dist/types/src/plugins/main.d.ts +75 -0
  125. package/dist/types/src/plugins/main.test.d.ts +1 -0
  126. package/dist/types/src/plugins/plugin-events.d.ts +5 -0
  127. package/dist/types/src/plugins/plugin-immer.d.ts +7 -0
  128. package/dist/types/src/plugins/plugin-immer.test.d.ts +1 -0
  129. package/dist/types/src/plugins/plugin-log.d.ts +14 -0
  130. package/dist/types/src/plugins/plugin-log.test.d.ts +1 -0
  131. package/dist/types/src/plugins/plugin-player.d.ts +29 -0
  132. package/dist/types/src/plugins/plugin-player.test.d.ts +1 -0
  133. package/dist/types/src/plugins/plugin-random.d.ts +4 -0
  134. package/dist/types/src/plugins/plugin-serializable.d.ts +7 -0
  135. package/dist/types/src/plugins/plugin-serializable.test.d.ts +1 -0
  136. package/dist/types/src/plugins/random/random.alea.d.ts +19 -0
  137. package/dist/types/src/plugins/random/random.d.ts +54 -0
  138. package/dist/types/src/plugins/random/random.test.d.ts +1 -0
  139. package/dist/types/src/server/api.d.ts +13 -0
  140. package/dist/types/src/server/api.test.d.ts +1 -0
  141. package/dist/types/src/server/auth.d.ts +38 -0
  142. package/dist/types/src/server/auth.test.d.ts +1 -0
  143. package/dist/types/src/server/cors.d.ts +4 -0
  144. package/dist/types/src/server/cors.test.d.ts +1 -0
  145. package/dist/types/src/server/db/base.d.ts +192 -0
  146. package/dist/types/src/server/db/flatfile.d.ts +44 -0
  147. package/dist/types/src/server/db/flatfile.test.d.ts +1 -0
  148. package/dist/types/src/server/db/index.d.ts +4 -0
  149. package/dist/types/src/server/db/index.test.d.ts +1 -0
  150. package/dist/types/src/server/db/inmemory.d.ts +43 -0
  151. package/dist/types/src/server/db/inmemory.test.d.ts +1 -0
  152. package/dist/types/src/server/db/localstorage.d.ts +7 -0
  153. package/dist/types/src/server/db/localstorage.test.d.ts +1 -0
  154. package/dist/types/src/server/index.d.ts +68 -0
  155. package/dist/types/src/server/index.test.d.ts +1 -0
  156. package/dist/types/src/server/transport/pubsub/generic-pub-sub.d.ts +6 -0
  157. package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.d.ts +7 -0
  158. package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.test.d.ts +1 -0
  159. package/dist/types/src/server/transport/socketio-simultaneous.test.d.ts +1 -0
  160. package/dist/types/src/server/transport/socketio.d.ts +65 -0
  161. package/dist/types/src/server/transport/socketio.test.d.ts +1 -0
  162. package/dist/types/src/server/util.d.ts +35 -0
  163. package/dist/types/src/testing/mock-random.d.ts +15 -0
  164. package/dist/types/src/testing/mock-random.test.d.ts +1 -0
  165. package/dist/types/src/types.d.ts +387 -0
  166. package/internal/package.json +7 -0
  167. package/master/package.json +7 -0
  168. package/multiplayer/package.json +7 -0
  169. package/package.json +211 -0
  170. package/plugins/package.json +7 -0
  171. package/react/package.json +7 -0
  172. package/react-native/package.json +7 -0
  173. package/server/package.json +6 -0
  174. package/src/ai/ai.test.ts +433 -0
  175. package/src/ai/ai.ts +84 -0
  176. package/src/ai/bot.ts +122 -0
  177. package/src/ai/mcts-bot.ts +331 -0
  178. package/src/ai/random-bot.ts +20 -0
  179. package/src/client/client.test.ts +993 -0
  180. package/src/client/client.ts +588 -0
  181. package/src/client/debug/Debug.svelte +239 -0
  182. package/src/client/debug/Menu.svelte +65 -0
  183. package/src/client/debug/ai/AI.svelte +215 -0
  184. package/src/client/debug/ai/Options.svelte +48 -0
  185. package/src/client/debug/info/Info.svelte +22 -0
  186. package/src/client/debug/info/Item.svelte +24 -0
  187. package/src/client/debug/log/Log.svelte +157 -0
  188. package/src/client/debug/log/LogEvent.svelte +149 -0
  189. package/src/client/debug/log/LogMetadata.svelte +7 -0
  190. package/src/client/debug/log/PhaseMarker.svelte +27 -0
  191. package/src/client/debug/log/TurnMarker.svelte +23 -0
  192. package/src/client/debug/main/ClientSwitcher.svelte +59 -0
  193. package/src/client/debug/main/Controls.svelte +58 -0
  194. package/src/client/debug/main/Hotkey.svelte +84 -0
  195. package/src/client/debug/main/InteractiveFunction.svelte +85 -0
  196. package/src/client/debug/main/Main.svelte +121 -0
  197. package/src/client/debug/main/Move.svelte +68 -0
  198. package/src/client/debug/main/PlayerInfo.svelte +70 -0
  199. package/src/client/debug/mcts/Action.svelte +22 -0
  200. package/src/client/debug/mcts/MCTS.svelte +78 -0
  201. package/src/client/debug/mcts/Table.svelte +98 -0
  202. package/src/client/debug/tests/JSONTree.mock.svelte +3 -0
  203. package/src/client/debug/tests/debug.test.ts +183 -0
  204. package/src/client/debug/utils/shortcuts.js +50 -0
  205. package/src/client/debug/utils/shortcuts.test.js +49 -0
  206. package/src/client/manager.ts +177 -0
  207. package/src/client/react-native.js +136 -0
  208. package/src/client/react-native.test.js +229 -0
  209. package/src/client/react.ssr.test.tsx +24 -0
  210. package/src/client/react.test.tsx +213 -0
  211. package/src/client/react.tsx +192 -0
  212. package/src/client/transport/dummy.ts +19 -0
  213. package/src/client/transport/local.test.ts +353 -0
  214. package/src/client/transport/local.ts +230 -0
  215. package/src/client/transport/socketio.test.ts +328 -0
  216. package/src/client/transport/socketio.ts +210 -0
  217. package/src/client/transport/transport.test.ts +27 -0
  218. package/src/client/transport/transport.ts +95 -0
  219. package/src/core/action-creators.ts +159 -0
  220. package/src/core/action-types.ts +18 -0
  221. package/src/core/backwards-compatibility.ts +23 -0
  222. package/src/core/constants.ts +6 -0
  223. package/src/core/errors.ts +35 -0
  224. package/src/core/flow.test.ts +2433 -0
  225. package/src/core/flow.ts +897 -0
  226. package/src/core/game-methods.ts +9 -0
  227. package/src/core/game.test.ts +286 -0
  228. package/src/core/game.ts +114 -0
  229. package/src/core/initialize.ts +77 -0
  230. package/src/core/logger.test.js +90 -0
  231. package/src/core/logger.ts +18 -0
  232. package/src/core/player-view.test.ts +50 -0
  233. package/src/core/player-view.ts +39 -0
  234. package/src/core/reducer.test.ts +991 -0
  235. package/src/core/reducer.ts +532 -0
  236. package/src/core/turn-order.test.ts +1123 -0
  237. package/src/core/turn-order.ts +473 -0
  238. package/src/lobby/client.test.ts +385 -0
  239. package/src/lobby/client.ts +358 -0
  240. package/src/lobby/connection.test.ts +207 -0
  241. package/src/lobby/connection.ts +162 -0
  242. package/src/lobby/create-match-form.tsx +122 -0
  243. package/src/lobby/login-form.tsx +75 -0
  244. package/src/lobby/match-instance.tsx +135 -0
  245. package/src/lobby/react.ssr.test.tsx +22 -0
  246. package/src/lobby/react.test.tsx +594 -0
  247. package/src/lobby/react.tsx +402 -0
  248. package/src/master/filter-player-view.test.ts +381 -0
  249. package/src/master/filter-player-view.ts +102 -0
  250. package/src/master/master.test.ts +1068 -0
  251. package/src/master/master.ts +492 -0
  252. package/src/plugins/events/events.test.ts +108 -0
  253. package/src/plugins/events/events.ts +209 -0
  254. package/src/plugins/main.test.ts +411 -0
  255. package/src/plugins/main.ts +314 -0
  256. package/src/plugins/plugin-events.ts +40 -0
  257. package/src/plugins/plugin-immer.test.ts +86 -0
  258. package/src/plugins/plugin-immer.ts +37 -0
  259. package/src/plugins/plugin-log.test.ts +37 -0
  260. package/src/plugins/plugin-log.ts +40 -0
  261. package/src/plugins/plugin-player.test.ts +172 -0
  262. package/src/plugins/plugin-player.ts +100 -0
  263. package/src/plugins/plugin-random.ts +40 -0
  264. package/src/plugins/plugin-serializable.test.ts +40 -0
  265. package/src/plugins/plugin-serializable.ts +55 -0
  266. package/src/plugins/random/random.alea.ts +109 -0
  267. package/src/plugins/random/random.test.ts +167 -0
  268. package/src/plugins/random/random.ts +198 -0
  269. package/src/server/api.test.ts +1699 -0
  270. package/src/server/api.ts +527 -0
  271. package/src/server/auth.test.ts +275 -0
  272. package/src/server/auth.ts +89 -0
  273. package/src/server/cors.test.ts +121 -0
  274. package/src/server/cors.ts +7 -0
  275. package/src/server/db/base.ts +296 -0
  276. package/src/server/db/flatfile.test.ts +221 -0
  277. package/src/server/db/flatfile.ts +228 -0
  278. package/src/server/db/index.test.ts +8 -0
  279. package/src/server/db/index.ts +12 -0
  280. package/src/server/db/inmemory.test.ts +143 -0
  281. package/src/server/db/inmemory.ts +143 -0
  282. package/src/server/db/localstorage.test.ts +73 -0
  283. package/src/server/db/localstorage.ts +44 -0
  284. package/src/server/index.test.ts +265 -0
  285. package/src/server/index.ts +175 -0
  286. package/src/server/transport/pubsub/generic-pub-sub.ts +11 -0
  287. package/src/server/transport/pubsub/in-memory-pub-sub.test.ts +47 -0
  288. package/src/server/transport/pubsub/in-memory-pub-sub.ts +28 -0
  289. package/src/server/transport/socketio-simultaneous.test.ts +603 -0
  290. package/src/server/transport/socketio.test.ts +303 -0
  291. package/src/server/transport/socketio.ts +279 -0
  292. package/src/server/util.ts +85 -0
  293. package/src/testing/mock-random.test.ts +45 -0
  294. package/src/testing/mock-random.ts +27 -0
  295. package/src/types.ts +511 -0
  296. package/testing/package.json +7 -0
@@ -0,0 +1,522 @@
1
+ import { nanoid } from 'nanoid/non-secure';
2
+ import { D as Debug } from './Debug-0141fe2d.js';
3
+ import { applyMiddleware, compose, createStore } from 'redux';
4
+ import { A as ActionCreators, r as reset, u as undo, a as redo, s as sync, P as PlayerView, S as SYNC, U as UPDATE, b as PATCH, R as RESET, c as REDO, d as UNDO, G as GAME_EVENT, M as MAKE_MOVE, e as STRIP_TRANSIENTS, p as patch, f as update } from './turn-order-376d315e.js';
5
+ import { P as ProcessGameConfig, C as CreateGameReducer, T as TransientHandlingMiddleware } from './reducer-c46da7e5.js';
6
+ import { I as InitializeGame } from './initialize-11d626ca.js';
7
+ import { T as Transport } from './transport-ce07b771.js';
8
+
9
+ /**
10
+ * This class doesn’t do anything, but simplifies the client class by providing
11
+ * dummy functions to call, so we don’t need to mock them in the client.
12
+ */
13
+ class DummyImpl extends Transport {
14
+ connect() { }
15
+ disconnect() { }
16
+ sendAction() { }
17
+ sendChatMessage() { }
18
+ requestSync() { }
19
+ updateCredentials() { }
20
+ updateMatchID() { }
21
+ updatePlayerID() { }
22
+ }
23
+ const DummyTransport = (opts) => new DummyImpl(opts);
24
+
25
+ /**
26
+ * Class to manage boardgame.io clients and limit debug panel rendering.
27
+ */
28
+ class ClientManager {
29
+ constructor() {
30
+ this.debugPanel = null;
31
+ this.currentClient = null;
32
+ this.clients = new Map();
33
+ this.subscribers = new Map();
34
+ }
35
+ /**
36
+ * Register a client with the client manager.
37
+ */
38
+ register(client) {
39
+ // Add client to clients map.
40
+ this.clients.set(client, client);
41
+ // Mount debug for this client (no-op if another debug is already mounted).
42
+ this.mountDebug(client);
43
+ this.notifySubscribers();
44
+ }
45
+ /**
46
+ * Unregister a client from the client manager.
47
+ */
48
+ unregister(client) {
49
+ // Remove client from clients map.
50
+ this.clients.delete(client);
51
+ if (this.currentClient === client) {
52
+ // If the removed client owned the debug panel, unmount it.
53
+ this.unmountDebug();
54
+ // Mount debug panel for next available client.
55
+ for (const [client] of this.clients) {
56
+ if (this.debugPanel)
57
+ break;
58
+ this.mountDebug(client);
59
+ }
60
+ }
61
+ this.notifySubscribers();
62
+ }
63
+ /**
64
+ * Subscribe to the client manager state.
65
+ * Calls the passed callback each time the current client changes or a client
66
+ * registers/unregisters.
67
+ * Returns a function to unsubscribe from the state updates.
68
+ */
69
+ subscribe(callback) {
70
+ const id = Symbol();
71
+ this.subscribers.set(id, callback);
72
+ callback(this.getState());
73
+ return () => {
74
+ this.subscribers.delete(id);
75
+ };
76
+ }
77
+ /**
78
+ * Switch to a client with a matching playerID.
79
+ */
80
+ switchPlayerID(playerID) {
81
+ // For multiplayer clients, try switching control to a different client
82
+ // that is using the same transport layer.
83
+ if (this.currentClient.multiplayer) {
84
+ for (const [client] of this.clients) {
85
+ if (client.playerID === playerID &&
86
+ client.debugOpt !== false &&
87
+ client.multiplayer === this.currentClient.multiplayer) {
88
+ this.switchToClient(client);
89
+ return;
90
+ }
91
+ }
92
+ }
93
+ // If no client matches, update the playerID for the current client.
94
+ this.currentClient.updatePlayerID(playerID);
95
+ this.notifySubscribers();
96
+ }
97
+ /**
98
+ * Set the passed client as the active client for debugging.
99
+ */
100
+ switchToClient(client) {
101
+ if (client === this.currentClient)
102
+ return;
103
+ this.unmountDebug();
104
+ this.mountDebug(client);
105
+ this.notifySubscribers();
106
+ }
107
+ /**
108
+ * Notify all subscribers of changes to the client manager state.
109
+ */
110
+ notifySubscribers() {
111
+ const arg = this.getState();
112
+ this.subscribers.forEach((cb) => {
113
+ cb(arg);
114
+ });
115
+ }
116
+ /**
117
+ * Get the client manager state.
118
+ */
119
+ getState() {
120
+ return {
121
+ client: this.currentClient,
122
+ debuggableClients: this.getDebuggableClients(),
123
+ };
124
+ }
125
+ /**
126
+ * Get an array of the registered clients that haven’t disabled the debug panel.
127
+ */
128
+ getDebuggableClients() {
129
+ return [...this.clients.values()].filter((client) => client.debugOpt !== false);
130
+ }
131
+ /**
132
+ * Mount the debug panel using the passed client.
133
+ */
134
+ mountDebug(client) {
135
+ if (client.debugOpt === false ||
136
+ this.debugPanel !== null ||
137
+ typeof document === 'undefined') {
138
+ return;
139
+ }
140
+ let DebugImpl;
141
+ let target = document.body;
142
+ if (process.env.NODE_ENV !== 'production') {
143
+ DebugImpl = Debug;
144
+ }
145
+ if (client.debugOpt && client.debugOpt !== true) {
146
+ DebugImpl = client.debugOpt.impl || DebugImpl;
147
+ target = client.debugOpt.target || target;
148
+ }
149
+ if (DebugImpl) {
150
+ this.currentClient = client;
151
+ this.debugPanel = new DebugImpl({
152
+ target,
153
+ props: { clientManager: this },
154
+ });
155
+ }
156
+ }
157
+ /**
158
+ * Unmount the debug panel.
159
+ */
160
+ unmountDebug() {
161
+ this.debugPanel.$destroy();
162
+ this.debugPanel = null;
163
+ this.currentClient = null;
164
+ }
165
+ }
166
+
167
+ /*
168
+ * Copyright 2017 The boardgame.io Authors
169
+ *
170
+ * Use of this source code is governed by a MIT-style
171
+ * license that can be found in the LICENSE file or at
172
+ * https://opensource.org/licenses/MIT.
173
+ */
174
+ /**
175
+ * Global client manager instance that all clients register with.
176
+ */
177
+ const GlobalClientManager = new ClientManager();
178
+ /**
179
+ * Standardise the passed playerID, using currentPlayer if appropriate.
180
+ */
181
+ function assumedPlayerID(playerID, store, multiplayer) {
182
+ // In singleplayer mode, if the client does not have a playerID
183
+ // associated with it, we attach the currentPlayer as playerID.
184
+ if (!multiplayer && (playerID === null || playerID === undefined)) {
185
+ const state = store.getState();
186
+ playerID = state.ctx.currentPlayer;
187
+ }
188
+ return playerID;
189
+ }
190
+ /**
191
+ * createDispatchers
192
+ *
193
+ * Create action dispatcher wrappers with bound playerID and credentials
194
+ */
195
+ function createDispatchers(storeActionType, innerActionNames, store, playerID, credentials, multiplayer) {
196
+ const dispatchers = {};
197
+ for (const name of innerActionNames) {
198
+ dispatchers[name] = (...args) => {
199
+ const action = ActionCreators[storeActionType](name, args, assumedPlayerID(playerID, store, multiplayer), credentials);
200
+ store.dispatch(action);
201
+ };
202
+ }
203
+ return dispatchers;
204
+ }
205
+ // Creates a set of dispatchers to make moves.
206
+ const createMoveDispatchers = createDispatchers.bind(null, 'makeMove');
207
+ // Creates a set of dispatchers to dispatch game flow events.
208
+ const createEventDispatchers = createDispatchers.bind(null, 'gameEvent');
209
+ // Creates a set of dispatchers to dispatch actions to plugins.
210
+ const createPluginDispatchers = createDispatchers.bind(null, 'plugin');
211
+ /**
212
+ * Implementation of Client (see below).
213
+ */
214
+ class _ClientImpl {
215
+ constructor({ game, debug, numPlayers, multiplayer, matchID: matchID, playerID, credentials, enhancer, }) {
216
+ this.game = ProcessGameConfig(game);
217
+ this.playerID = playerID;
218
+ this.matchID = matchID || 'default';
219
+ this.credentials = credentials;
220
+ this.multiplayer = multiplayer;
221
+ this.debugOpt = debug;
222
+ this.manager = GlobalClientManager;
223
+ this.gameStateOverride = null;
224
+ this.subscribers = {};
225
+ this._running = false;
226
+ this.reducer = CreateGameReducer({
227
+ game: this.game,
228
+ isClient: multiplayer !== undefined,
229
+ });
230
+ this.initialState = null;
231
+ if (!multiplayer) {
232
+ this.initialState = InitializeGame({ game: this.game, numPlayers });
233
+ }
234
+ this.reset = () => {
235
+ this.store.dispatch(reset(this.initialState));
236
+ };
237
+ this.undo = () => {
238
+ const undo$1 = undo(assumedPlayerID(this.playerID, this.store, this.multiplayer), this.credentials);
239
+ this.store.dispatch(undo$1);
240
+ };
241
+ this.redo = () => {
242
+ const redo$1 = redo(assumedPlayerID(this.playerID, this.store, this.multiplayer), this.credentials);
243
+ this.store.dispatch(redo$1);
244
+ };
245
+ this.log = [];
246
+ /**
247
+ * Middleware that manages the log object.
248
+ * Reducers generate deltalogs, which are log events
249
+ * that are the result of application of a single action.
250
+ * The master may also send back a deltalog or the entire
251
+ * log depending on the type of request.
252
+ * The middleware below takes care of all these cases while
253
+ * managing the log object.
254
+ */
255
+ const LogMiddleware = (store) => (next) => (action) => {
256
+ const result = next(action);
257
+ const state = store.getState();
258
+ switch (action.type) {
259
+ case MAKE_MOVE:
260
+ case GAME_EVENT:
261
+ case UNDO:
262
+ case REDO: {
263
+ const deltalog = state.deltalog;
264
+ this.log = [...this.log, ...deltalog];
265
+ break;
266
+ }
267
+ case RESET: {
268
+ this.log = [];
269
+ break;
270
+ }
271
+ case PATCH:
272
+ case UPDATE: {
273
+ let id = -1;
274
+ if (this.log.length > 0) {
275
+ id = this.log[this.log.length - 1]._stateID;
276
+ }
277
+ let deltalog = action.deltalog || [];
278
+ // Filter out actions that are already present
279
+ // in the current log. This may occur when the
280
+ // client adds an entry to the log followed by
281
+ // the update from the master here.
282
+ deltalog = deltalog.filter((l) => l._stateID > id);
283
+ this.log = [...this.log, ...deltalog];
284
+ break;
285
+ }
286
+ case SYNC: {
287
+ this.initialState = action.initialState;
288
+ this.log = action.log || [];
289
+ break;
290
+ }
291
+ }
292
+ return result;
293
+ };
294
+ /**
295
+ * Middleware that intercepts actions and sends them to the master,
296
+ * which keeps the authoritative version of the state.
297
+ */
298
+ const TransportMiddleware = (store) => (next) => (action) => {
299
+ const baseState = store.getState();
300
+ const result = next(action);
301
+ if (!('clientOnly' in action) &&
302
+ action.type !== STRIP_TRANSIENTS) {
303
+ this.transport.sendAction(baseState, action);
304
+ }
305
+ return result;
306
+ };
307
+ /**
308
+ * Middleware that intercepts actions and invokes the subscription callback.
309
+ */
310
+ const SubscriptionMiddleware = () => (next) => (action) => {
311
+ const result = next(action);
312
+ this.notifySubscribers();
313
+ return result;
314
+ };
315
+ const middleware = applyMiddleware(TransientHandlingMiddleware, SubscriptionMiddleware, TransportMiddleware, LogMiddleware);
316
+ enhancer =
317
+ enhancer !== undefined ? compose(middleware, enhancer) : middleware;
318
+ this.store = createStore(this.reducer, this.initialState, enhancer);
319
+ if (!multiplayer)
320
+ multiplayer = DummyTransport;
321
+ this.transport = multiplayer({
322
+ transportDataCallback: (data) => this.receiveTransportData(data),
323
+ gameKey: game,
324
+ game: this.game,
325
+ matchID,
326
+ playerID,
327
+ credentials,
328
+ gameName: this.game.name,
329
+ numPlayers,
330
+ });
331
+ this.createDispatchers();
332
+ this.chatMessages = [];
333
+ this.sendChatMessage = (payload) => {
334
+ this.transport.sendChatMessage(this.matchID, {
335
+ id: nanoid(7),
336
+ sender: this.playerID,
337
+ payload: payload,
338
+ });
339
+ };
340
+ }
341
+ /** Handle incoming match data from a multiplayer transport. */
342
+ receiveMatchData(matchData) {
343
+ this.matchData = matchData;
344
+ this.notifySubscribers();
345
+ }
346
+ /** Handle an incoming chat message from a multiplayer transport. */
347
+ receiveChatMessage(message) {
348
+ this.chatMessages = [...this.chatMessages, message];
349
+ this.notifySubscribers();
350
+ }
351
+ /** Handle all incoming updates from a multiplayer transport. */
352
+ receiveTransportData(data) {
353
+ const [matchID] = data.args;
354
+ if (matchID !== this.matchID)
355
+ return;
356
+ switch (data.type) {
357
+ case 'sync': {
358
+ const [, syncInfo] = data.args;
359
+ const action = sync(syncInfo);
360
+ this.receiveMatchData(syncInfo.filteredMetadata);
361
+ this.store.dispatch(action);
362
+ break;
363
+ }
364
+ case 'update': {
365
+ const [, state, deltalog] = data.args;
366
+ const currentState = this.store.getState();
367
+ if (state._stateID >= currentState._stateID) {
368
+ const action = update(state, deltalog);
369
+ this.store.dispatch(action);
370
+ }
371
+ break;
372
+ }
373
+ case 'patch': {
374
+ const [, prevStateID, stateID, patch$1, deltalog] = data.args;
375
+ const currentStateID = this.store.getState()._stateID;
376
+ if (prevStateID !== currentStateID)
377
+ break;
378
+ const action = patch(prevStateID, stateID, patch$1, deltalog);
379
+ this.store.dispatch(action);
380
+ // Emit sync if patch apply failed.
381
+ if (this.store.getState()._stateID === currentStateID) {
382
+ this.transport.requestSync();
383
+ }
384
+ break;
385
+ }
386
+ case 'matchData': {
387
+ const [, matchData] = data.args;
388
+ this.receiveMatchData(matchData);
389
+ break;
390
+ }
391
+ case 'chat': {
392
+ const [, chatMessage] = data.args;
393
+ this.receiveChatMessage(chatMessage);
394
+ break;
395
+ }
396
+ }
397
+ }
398
+ notifySubscribers() {
399
+ Object.values(this.subscribers).forEach((fn) => fn(this.getState()));
400
+ }
401
+ overrideGameState(state) {
402
+ this.gameStateOverride = state;
403
+ this.notifySubscribers();
404
+ }
405
+ start() {
406
+ this.transport.connect();
407
+ this._running = true;
408
+ this.manager.register(this);
409
+ }
410
+ stop() {
411
+ this.transport.disconnect();
412
+ this._running = false;
413
+ this.manager.unregister(this);
414
+ }
415
+ subscribe(fn) {
416
+ const id = Object.keys(this.subscribers).length;
417
+ this.subscribers[id] = fn;
418
+ this.transport.subscribeToConnectionStatus(() => this.notifySubscribers());
419
+ if (this._running || !this.multiplayer) {
420
+ fn(this.getState());
421
+ }
422
+ // Return a handle that allows the caller to unsubscribe.
423
+ return () => {
424
+ delete this.subscribers[id];
425
+ };
426
+ }
427
+ getInitialState() {
428
+ return this.initialState;
429
+ }
430
+ getState() {
431
+ let state = this.store.getState();
432
+ if (this.gameStateOverride !== null) {
433
+ state = this.gameStateOverride;
434
+ }
435
+ // This is the state before a sync with the game master.
436
+ if (state === null) {
437
+ return state;
438
+ }
439
+ // isActive.
440
+ let isActive = true;
441
+ const isPlayerActive = this.game.flow.isPlayerActive(state.G, state.ctx, this.playerID);
442
+ if (this.multiplayer && !isPlayerActive) {
443
+ isActive = false;
444
+ }
445
+ if (!this.multiplayer &&
446
+ this.playerID !== null &&
447
+ this.playerID !== undefined &&
448
+ !isPlayerActive) {
449
+ isActive = false;
450
+ }
451
+ if (state.ctx.gameover !== undefined) {
452
+ isActive = false;
453
+ }
454
+ // Secrets are normally stripped on the server,
455
+ // but we also strip them here so that game developers
456
+ // can see their effects while prototyping.
457
+ // Do not strip again if this is a multiplayer game
458
+ // since the server has already stripped secret info. (issue #818)
459
+ if (!this.multiplayer) {
460
+ state = {
461
+ ...state,
462
+ G: this.game.playerView({
463
+ G: state.G,
464
+ ctx: state.ctx,
465
+ playerID: this.playerID,
466
+ }),
467
+ plugins: PlayerView(state, this),
468
+ };
469
+ }
470
+ // Combine into return value.
471
+ return {
472
+ ...state,
473
+ log: this.log,
474
+ isActive,
475
+ isConnected: this.transport.isConnected,
476
+ };
477
+ }
478
+ createDispatchers() {
479
+ this.moves = createMoveDispatchers(this.game.moveNames, this.store, this.playerID, this.credentials, this.multiplayer);
480
+ this.events = createEventDispatchers(this.game.flow.enabledEventNames, this.store, this.playerID, this.credentials, this.multiplayer);
481
+ this.plugins = createPluginDispatchers(this.game.pluginNames, this.store, this.playerID, this.credentials, this.multiplayer);
482
+ }
483
+ updatePlayerID(playerID) {
484
+ this.playerID = playerID;
485
+ this.createDispatchers();
486
+ this.transport.updatePlayerID(playerID);
487
+ this.notifySubscribers();
488
+ }
489
+ updateMatchID(matchID) {
490
+ this.matchID = matchID;
491
+ this.createDispatchers();
492
+ this.transport.updateMatchID(matchID);
493
+ this.notifySubscribers();
494
+ }
495
+ updateCredentials(credentials) {
496
+ this.credentials = credentials;
497
+ this.createDispatchers();
498
+ this.transport.updateCredentials(credentials);
499
+ this.notifySubscribers();
500
+ }
501
+ }
502
+ /**
503
+ * Client
504
+ *
505
+ * boardgame.io JS client.
506
+ *
507
+ * @param {...object} game - The return value of `Game`.
508
+ * @param {...object} numPlayers - The number of players.
509
+ * @param {...object} multiplayer - Set to a falsy value or a transportFactory, e.g., SocketIO()
510
+ * @param {...object} matchID - The matchID that you want to connect to.
511
+ * @param {...object} playerID - The playerID associated with this client.
512
+ * @param {...string} credentials - The authentication credentials associated with this client.
513
+ *
514
+ * Returns:
515
+ * A JS object that provides an API to interact with the
516
+ * game by dispatching moves and events.
517
+ */
518
+ function Client(opts) {
519
+ return new _ClientImpl(opts);
520
+ }
521
+
522
+ export { Client as C };