@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,318 @@
1
+ import { P as ProcessGameConfig, C as CreateGameReducer, T as TransientHandlingMiddleware, I as IsLongFormMove } from './reducer-c46da7e5.js';
2
+ import { g as error, d as UNDO, c as REDO, M as MAKE_MOVE } from './turn-order-376d315e.js';
3
+ import { applyMiddleware, createStore } from 'redux';
4
+ import { i as isSynchronous, c as createMatch } from './util-b6147cef.js';
5
+
6
+ /*
7
+ * Copyright 2018 The boardgame.io Authors
8
+ *
9
+ * Use of this source code is governed by a MIT-style
10
+ * license that can be found in the LICENSE file or at
11
+ * https://opensource.org/licenses/MIT.
12
+ */
13
+ /**
14
+ * Filter match data to get a player metadata object with credentials stripped.
15
+ */
16
+ const filterMatchData = (matchData) => Object.values(matchData.players).map((player) => {
17
+ const { credentials, ...filteredData } = player;
18
+ return filteredData;
19
+ });
20
+ /**
21
+ * Remove player credentials from action payload
22
+ */
23
+ const stripCredentialsFromAction = (action) => {
24
+ const { credentials, ...payload } = action.payload;
25
+ return { ...action, payload };
26
+ };
27
+ /**
28
+ * Master
29
+ *
30
+ * Class that runs the game and maintains the authoritative state.
31
+ * It uses the transportAPI to communicate with clients and the
32
+ * storageAPI to communicate with the database.
33
+ */
34
+ class Master {
35
+ constructor(game, storageAPI, transportAPI, auth) {
36
+ this.game = ProcessGameConfig(game);
37
+ this.storageAPI = storageAPI;
38
+ this.transportAPI = transportAPI;
39
+ this.subscribeCallback = () => { };
40
+ this.auth = auth;
41
+ }
42
+ subscribe(fn) {
43
+ this.subscribeCallback = fn;
44
+ }
45
+ /**
46
+ * Called on each move / event made by the client.
47
+ * Computes the new value of the game state and returns it
48
+ * along with a deltalog.
49
+ */
50
+ async onUpdate(credAction, stateID, matchID, playerID) {
51
+ if (!credAction || !credAction.payload) {
52
+ return { error: 'missing action or action payload' };
53
+ }
54
+ let metadata;
55
+ if (isSynchronous(this.storageAPI)) {
56
+ ({ metadata } = this.storageAPI.fetch(matchID, { metadata: true }));
57
+ }
58
+ else {
59
+ ({ metadata } = await this.storageAPI.fetch(matchID, { metadata: true }));
60
+ }
61
+ if (this.auth) {
62
+ const isAuthentic = await this.auth.authenticateCredentials({
63
+ playerID,
64
+ credentials: credAction.payload.credentials,
65
+ metadata,
66
+ });
67
+ if (!isAuthentic) {
68
+ return { error: 'unauthorized action' };
69
+ }
70
+ }
71
+ const action = stripCredentialsFromAction(credAction);
72
+ const key = matchID;
73
+ let state;
74
+ if (isSynchronous(this.storageAPI)) {
75
+ ({ state } = this.storageAPI.fetch(key, { state: true }));
76
+ }
77
+ else {
78
+ ({ state } = await this.storageAPI.fetch(key, { state: true }));
79
+ }
80
+ if (state === undefined) {
81
+ error(`game not found, matchID=[${key}]`);
82
+ return { error: 'game not found' };
83
+ }
84
+ if (state.ctx.gameover !== undefined) {
85
+ error(`game over - matchID=[${key}] - playerID=[${playerID}]` +
86
+ ` - action[${action.payload.type}]`);
87
+ return;
88
+ }
89
+ const reducer = CreateGameReducer({
90
+ game: this.game,
91
+ });
92
+ const middleware = applyMiddleware(TransientHandlingMiddleware);
93
+ const store = createStore(reducer, state, middleware);
94
+ // Only allow UNDO / REDO if there is exactly one player
95
+ // that can make moves right now and the person doing the
96
+ // action is that player.
97
+ if (action.type == UNDO || action.type == REDO) {
98
+ const hasActivePlayers = state.ctx.activePlayers !== null;
99
+ const isCurrentPlayer = state.ctx.currentPlayer === playerID;
100
+ if (
101
+ // If activePlayers is empty, non-current players can’t undo.
102
+ (!hasActivePlayers && !isCurrentPlayer) ||
103
+ // If player is not active or multiple players are active, can’t undo.
104
+ (hasActivePlayers &&
105
+ (state.ctx.activePlayers[playerID] === undefined ||
106
+ Object.keys(state.ctx.activePlayers).length > 1))) {
107
+ error(`playerID=[${playerID}] cannot undo / redo right now`);
108
+ return;
109
+ }
110
+ }
111
+ // Check whether the player is active.
112
+ if (!this.game.flow.isPlayerActive(state.G, state.ctx, playerID)) {
113
+ error(`player not active - playerID=[${playerID}]` +
114
+ ` - action[${action.payload.type}]`);
115
+ return;
116
+ }
117
+ // Get move for further checks
118
+ const move = action.type == MAKE_MOVE
119
+ ? this.game.flow.getMove(state.ctx, action.payload.type, playerID)
120
+ : null;
121
+ // Check whether the player is allowed to make the move.
122
+ if (action.type == MAKE_MOVE && !move) {
123
+ error(`move not processed - canPlayerMakeMove=false - playerID=[${playerID}]` +
124
+ ` - action[${action.payload.type}]`);
125
+ return;
126
+ }
127
+ // Check if action's stateID is different than store's stateID
128
+ // and if move does not have ignoreStaleStateID truthy.
129
+ if (state._stateID !== stateID &&
130
+ !(move && IsLongFormMove(move) && move.ignoreStaleStateID)) {
131
+ error(`invalid stateID, was=[${stateID}], expected=[${state._stateID}]` +
132
+ ` - playerID=[${playerID}] - action[${action.payload.type}]`);
133
+ return;
134
+ }
135
+ const prevState = store.getState();
136
+ // Update server's version of the store.
137
+ store.dispatch(action);
138
+ state = store.getState();
139
+ this.subscribeCallback({
140
+ state,
141
+ action,
142
+ matchID,
143
+ });
144
+ if (this.game.deltaState) {
145
+ this.transportAPI.sendAll({
146
+ type: 'patch',
147
+ args: [matchID, stateID, prevState, state],
148
+ });
149
+ }
150
+ else {
151
+ this.transportAPI.sendAll({
152
+ type: 'update',
153
+ args: [matchID, state],
154
+ });
155
+ }
156
+ const { deltalog, ...stateWithoutDeltalog } = state;
157
+ let newMetadata;
158
+ if (metadata &&
159
+ (metadata.gameover === undefined || metadata.gameover === null)) {
160
+ newMetadata = {
161
+ ...metadata,
162
+ updatedAt: Date.now(),
163
+ };
164
+ if (state.ctx.gameover !== undefined) {
165
+ newMetadata.gameover = state.ctx.gameover;
166
+ }
167
+ }
168
+ if (isSynchronous(this.storageAPI)) {
169
+ this.storageAPI.setState(key, stateWithoutDeltalog, deltalog);
170
+ if (newMetadata)
171
+ this.storageAPI.setMetadata(key, newMetadata);
172
+ }
173
+ else {
174
+ const writes = [
175
+ this.storageAPI.setState(key, stateWithoutDeltalog, deltalog),
176
+ ];
177
+ if (newMetadata) {
178
+ writes.push(this.storageAPI.setMetadata(key, newMetadata));
179
+ }
180
+ await Promise.all(writes);
181
+ }
182
+ }
183
+ /**
184
+ * Called when the client connects / reconnects.
185
+ * Returns the latest game state and the entire log.
186
+ */
187
+ async onSync(matchID, playerID, credentials, numPlayers = 2) {
188
+ const key = matchID;
189
+ const fetchOpts = {
190
+ state: true,
191
+ metadata: true,
192
+ log: true,
193
+ initialState: true,
194
+ };
195
+ const fetchResult = isSynchronous(this.storageAPI)
196
+ ? this.storageAPI.fetch(key, fetchOpts)
197
+ : await this.storageAPI.fetch(key, fetchOpts);
198
+ let { state, initialState, log, metadata } = fetchResult;
199
+ if (this.auth && playerID !== undefined && playerID !== null) {
200
+ const isAuthentic = await this.auth.authenticateCredentials({
201
+ playerID,
202
+ credentials,
203
+ metadata,
204
+ });
205
+ if (!isAuthentic) {
206
+ return { error: 'unauthorized' };
207
+ }
208
+ }
209
+ // If the game doesn't exist, then create one on demand.
210
+ // TODO: Move this out of the sync call.
211
+ if (state === undefined) {
212
+ const match = createMatch({
213
+ game: this.game,
214
+ unlisted: true,
215
+ numPlayers,
216
+ setupData: undefined,
217
+ });
218
+ if ('setupDataError' in match) {
219
+ return { error: 'game requires setupData' };
220
+ }
221
+ initialState = state = match.initialState;
222
+ metadata = match.metadata;
223
+ this.subscribeCallback({ state, matchID });
224
+ if (isSynchronous(this.storageAPI)) {
225
+ this.storageAPI.createMatch(key, { initialState, metadata });
226
+ }
227
+ else {
228
+ await this.storageAPI.createMatch(key, { initialState, metadata });
229
+ }
230
+ }
231
+ const filteredMetadata = metadata ? filterMatchData(metadata) : undefined;
232
+ const syncInfo = {
233
+ state,
234
+ log,
235
+ filteredMetadata,
236
+ initialState,
237
+ };
238
+ this.transportAPI.send({
239
+ playerID,
240
+ type: 'sync',
241
+ args: [matchID, syncInfo],
242
+ });
243
+ return;
244
+ }
245
+ /**
246
+ * Called when a client connects or disconnects.
247
+ * Updates and sends out metadata to reflect the player’s connection status.
248
+ */
249
+ async onConnectionChange(matchID, playerID, credentials, connected) {
250
+ const key = matchID;
251
+ // Ignore changes for clients without a playerID, e.g. spectators.
252
+ if (playerID === undefined || playerID === null) {
253
+ return;
254
+ }
255
+ let metadata;
256
+ if (isSynchronous(this.storageAPI)) {
257
+ ({ metadata } = this.storageAPI.fetch(key, { metadata: true }));
258
+ }
259
+ else {
260
+ ({ metadata } = await this.storageAPI.fetch(key, { metadata: true }));
261
+ }
262
+ if (metadata === undefined) {
263
+ error(`metadata not found for matchID=[${key}]`);
264
+ return { error: 'metadata not found' };
265
+ }
266
+ if (metadata.players[playerID] === undefined) {
267
+ error(`Player not in the match, matchID=[${key}] playerID=[${playerID}]`);
268
+ return { error: 'player not in the match' };
269
+ }
270
+ if (this.auth) {
271
+ const isAuthentic = await this.auth.authenticateCredentials({
272
+ playerID,
273
+ credentials,
274
+ metadata,
275
+ });
276
+ if (!isAuthentic) {
277
+ return { error: 'unauthorized' };
278
+ }
279
+ }
280
+ metadata.players[playerID].isConnected = connected;
281
+ const filteredMetadata = filterMatchData(metadata);
282
+ this.transportAPI.sendAll({
283
+ type: 'matchData',
284
+ args: [matchID, filteredMetadata],
285
+ });
286
+ if (isSynchronous(this.storageAPI)) {
287
+ this.storageAPI.setMetadata(key, metadata);
288
+ }
289
+ else {
290
+ await this.storageAPI.setMetadata(key, metadata);
291
+ }
292
+ }
293
+ async onChatMessage(matchID, chatMessage, credentials) {
294
+ const key = matchID;
295
+ if (this.auth) {
296
+ const { metadata } = await this.storageAPI.fetch(key, {
297
+ metadata: true,
298
+ });
299
+ if (!(chatMessage && typeof chatMessage.sender === 'string')) {
300
+ return { error: 'unauthorized' };
301
+ }
302
+ const isAuthentic = await this.auth.authenticateCredentials({
303
+ playerID: chatMessage.sender,
304
+ credentials,
305
+ metadata,
306
+ });
307
+ if (!isAuthentic) {
308
+ return { error: 'unauthorized' };
309
+ }
310
+ }
311
+ this.transportAPI.sendAll({
312
+ type: 'chat',
313
+ args: [matchID, chatMessage],
314
+ });
315
+ }
316
+ }
317
+
318
+ export { Master as M };
@@ -0,0 +1,10 @@
1
+ export { M as Master } from './master-fa8f2e43.js';
2
+ import './reducer-c46da7e5.js';
3
+ import './turn-order-376d315e.js';
4
+ import 'immer';
5
+ import './plugin-random-087f861e.js';
6
+ import 'lodash.isplainobject';
7
+ import 'rfc6902';
8
+ import 'redux';
9
+ import './util-b6147cef.js';
10
+ import './initialize-11d626ca.js';
@@ -0,0 +1,14 @@
1
+ export { L as Local, S as SocketIO } from './socketio-c22ffa65.js';
2
+ import './util-b6147cef.js';
3
+ import './initialize-11d626ca.js';
4
+ import './reducer-c46da7e5.js';
5
+ import './turn-order-376d315e.js';
6
+ import 'immer';
7
+ import './plugin-random-087f861e.js';
8
+ import 'lodash.isplainobject';
9
+ import 'rfc6902';
10
+ import './master-fa8f2e43.js';
11
+ import 'redux';
12
+ import './transport-ce07b771.js';
13
+ import './filter-player-view-2c6cc96f.js';
14
+ import 'socket.io-client';
@@ -0,0 +1,226 @@
1
+ // Inlined version of Alea from https://github.com/davidbau/seedrandom.
2
+ // Converted to Typescript October 2020.
3
+ class Alea {
4
+ constructor(seed) {
5
+ const mash = Mash();
6
+ // Apply the seeding algorithm from Baagoe.
7
+ this.c = 1;
8
+ this.s0 = mash(' ');
9
+ this.s1 = mash(' ');
10
+ this.s2 = mash(' ');
11
+ this.s0 -= mash(seed);
12
+ if (this.s0 < 0) {
13
+ this.s0 += 1;
14
+ }
15
+ this.s1 -= mash(seed);
16
+ if (this.s1 < 0) {
17
+ this.s1 += 1;
18
+ }
19
+ this.s2 -= mash(seed);
20
+ if (this.s2 < 0) {
21
+ this.s2 += 1;
22
+ }
23
+ }
24
+ next() {
25
+ const t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32
26
+ this.s0 = this.s1;
27
+ this.s1 = this.s2;
28
+ return (this.s2 = t - (this.c = Math.trunc(t)));
29
+ }
30
+ }
31
+ function Mash() {
32
+ let n = 0xefc8249d;
33
+ const mash = function (data) {
34
+ const str = data.toString();
35
+ for (let i = 0; i < str.length; i++) {
36
+ n += str.charCodeAt(i);
37
+ let h = 0.02519603282416938 * n;
38
+ n = h >>> 0;
39
+ h -= n;
40
+ h *= n;
41
+ n = h >>> 0;
42
+ h -= n;
43
+ n += h * 0x100000000; // 2^32
44
+ }
45
+ return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
46
+ };
47
+ return mash;
48
+ }
49
+ function copy(f, t) {
50
+ t.c = f.c;
51
+ t.s0 = f.s0;
52
+ t.s1 = f.s1;
53
+ t.s2 = f.s2;
54
+ return t;
55
+ }
56
+ function alea(seed, state) {
57
+ const xg = new Alea(seed);
58
+ const prng = xg.next.bind(xg);
59
+ if (state)
60
+ copy(state, xg);
61
+ prng.state = () => copy(xg, {});
62
+ return prng;
63
+ }
64
+
65
+ /*
66
+ * Copyright 2017 The boardgame.io Authors
67
+ *
68
+ * Use of this source code is governed by a MIT-style
69
+ * license that can be found in the LICENSE file or at
70
+ * https://opensource.org/licenses/MIT.
71
+ */
72
+ /**
73
+ * Random
74
+ *
75
+ * Calls that require a pseudorandom number generator.
76
+ * Uses a seed from ctx, and also persists the PRNG
77
+ * state in ctx so that moves can stay pure.
78
+ */
79
+ class Random {
80
+ /**
81
+ * constructor
82
+ * @param {object} ctx - The ctx object to initialize from.
83
+ */
84
+ constructor(state) {
85
+ // If we are on the client, the seed is not present.
86
+ // Just use a temporary seed to execute the move without
87
+ // crashing it. The move state itself is discarded,
88
+ // so the actual value doesn't matter.
89
+ this.state = state || { seed: '0' };
90
+ this.used = false;
91
+ }
92
+ /**
93
+ * Generates a new seed from the current date / time.
94
+ */
95
+ static seed() {
96
+ return Date.now().toString(36).slice(-10);
97
+ }
98
+ isUsed() {
99
+ return this.used;
100
+ }
101
+ getState() {
102
+ return this.state;
103
+ }
104
+ /**
105
+ * Generate a random number.
106
+ */
107
+ _random() {
108
+ this.used = true;
109
+ const R = this.state;
110
+ const seed = R.prngstate ? '' : R.seed;
111
+ const rand = alea(seed, R.prngstate);
112
+ const number = rand();
113
+ this.state = {
114
+ ...R,
115
+ prngstate: rand.state(),
116
+ };
117
+ return number;
118
+ }
119
+ api() {
120
+ const random = this._random.bind(this);
121
+ const SpotValue = {
122
+ D4: 4,
123
+ D6: 6,
124
+ D8: 8,
125
+ D10: 10,
126
+ D12: 12,
127
+ D20: 20,
128
+ };
129
+ // Generate functions for predefined dice values D4 - D20.
130
+ const predefined = {};
131
+ for (const key in SpotValue) {
132
+ const spotvalue = SpotValue[key];
133
+ predefined[key] = (diceCount) => {
134
+ return diceCount === undefined
135
+ ? Math.floor(random() * spotvalue) + 1
136
+ : Array.from({ length: diceCount }).map(() => Math.floor(random() * spotvalue) + 1);
137
+ };
138
+ }
139
+ function Die(spotvalue = 6, diceCount) {
140
+ return diceCount === undefined
141
+ ? Math.floor(random() * spotvalue) + 1
142
+ : Array.from({ length: diceCount }).map(() => Math.floor(random() * spotvalue) + 1);
143
+ }
144
+ return {
145
+ /**
146
+ * Similar to Die below, but with fixed spot values.
147
+ * Supports passing a diceCount
148
+ * if not defined, defaults to 1 and returns the value directly.
149
+ * if defined, returns an array containing the random dice values.
150
+ *
151
+ * D4: (diceCount) => value
152
+ * D6: (diceCount) => value
153
+ * D8: (diceCount) => value
154
+ * D10: (diceCount) => value
155
+ * D12: (diceCount) => value
156
+ * D20: (diceCount) => value
157
+ */
158
+ ...predefined,
159
+ /**
160
+ * Roll a die of specified spot value.
161
+ *
162
+ * @param {number} spotvalue - The die dimension (default: 6).
163
+ * @param {number} diceCount - number of dice to throw.
164
+ * if not defined, defaults to 1 and returns the value directly.
165
+ * if defined, returns an array containing the random dice values.
166
+ */
167
+ Die,
168
+ /**
169
+ * Generate a random number between 0 and 1.
170
+ */
171
+ Number: () => {
172
+ return random();
173
+ },
174
+ /**
175
+ * Shuffle an array.
176
+ *
177
+ * @param {Array} deck - The array to shuffle. Does not mutate
178
+ * the input, but returns the shuffled array.
179
+ */
180
+ Shuffle: (deck) => {
181
+ const clone = [...deck];
182
+ let sourceIndex = deck.length;
183
+ let destinationIndex = 0;
184
+ const shuffled = Array.from({ length: sourceIndex });
185
+ while (sourceIndex) {
186
+ const randomIndex = Math.trunc(sourceIndex * random());
187
+ shuffled[destinationIndex++] = clone[randomIndex];
188
+ clone[randomIndex] = clone[--sourceIndex];
189
+ }
190
+ return shuffled;
191
+ },
192
+ _private: this,
193
+ };
194
+ }
195
+ }
196
+
197
+ /*
198
+ * Copyright 2018 The boardgame.io Authors
199
+ *
200
+ * Use of this source code is governed by a MIT-style
201
+ * license that can be found in the LICENSE file or at
202
+ * https://opensource.org/licenses/MIT.
203
+ */
204
+ const RandomPlugin = {
205
+ name: 'random',
206
+ noClient: ({ api }) => {
207
+ return api._private.isUsed();
208
+ },
209
+ flush: ({ api }) => {
210
+ return api._private.getState();
211
+ },
212
+ api: ({ data }) => {
213
+ const random = new Random(data);
214
+ return random.api();
215
+ },
216
+ setup: ({ game }) => {
217
+ let { seed } = game;
218
+ if (seed === undefined) {
219
+ seed = Random.seed();
220
+ }
221
+ return { seed };
222
+ },
223
+ playerView: () => undefined,
224
+ };
225
+
226
+ export { RandomPlugin as R, alea as a };
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright 2018 The boardgame.io Authors
3
+ *
4
+ * Use of this source code is governed by a MIT-style
5
+ * license that can be found in the LICENSE file or at
6
+ * https://opensource.org/licenses/MIT.
7
+ */
8
+ /**
9
+ * Plugin that maintains state for each player in G.players.
10
+ * During a turn, G.player will contain the object for the current player.
11
+ * In two player games, G.opponent will contain the object for the other player.
12
+ *
13
+ * @param {function} initPlayerState - Function of type (playerID) => playerState.
14
+ */
15
+ const PlayerPlugin = ({ setup, playerView, } = {}) => ({
16
+ name: 'player',
17
+ flush: ({ api }) => {
18
+ return { players: api.state };
19
+ },
20
+ api: ({ ctx, data }) => {
21
+ const state = data.players;
22
+ const get = () => {
23
+ return data.players[ctx.currentPlayer];
24
+ };
25
+ const set = (value) => {
26
+ return (state[ctx.currentPlayer] = value);
27
+ };
28
+ const result = { state, get, set };
29
+ if (ctx.numPlayers === 2) {
30
+ const other = ctx.currentPlayer === '0' ? '1' : '0';
31
+ const get = () => {
32
+ return data.players[other];
33
+ };
34
+ const set = (value) => {
35
+ return (state[other] = value);
36
+ };
37
+ result.opponent = { get, set };
38
+ }
39
+ return result;
40
+ },
41
+ setup: ({ ctx }) => {
42
+ const players = {};
43
+ for (let i = 0; i < ctx.numPlayers; i++) {
44
+ let playerState = {};
45
+ if (setup !== undefined) {
46
+ playerState = setup(i + '');
47
+ }
48
+ players[i + ''] = playerState;
49
+ }
50
+ return { players };
51
+ },
52
+ playerView: ({ data, playerID }) => playerView ? { players: playerView(data.players, playerID) } : data,
53
+ });
54
+
55
+ export { PlayerPlugin as PluginPlayer };