@gamepark/react-client 6.38.5 → 7.0.0-beta.2

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 (317) hide show
  1. package/dist/Actions/ActionFailed.d.ts +6 -6
  2. package/dist/Actions/ActionFailed.js +4 -8
  3. package/dist/Actions/ActionFailed.js.map +1 -1
  4. package/dist/Actions/AnimationComplete.d.ts +6 -6
  5. package/dist/Actions/AnimationComplete.js +4 -8
  6. package/dist/Actions/AnimationComplete.js.map +1 -1
  7. package/dist/Actions/AnimationPaused.d.ts +6 -6
  8. package/dist/Actions/AnimationPaused.js +4 -8
  9. package/dist/Actions/AnimationPaused.js.map +1 -1
  10. package/dist/Actions/AnimationStart.d.ts +5 -5
  11. package/dist/Actions/AnimationStart.js +1 -4
  12. package/dist/Actions/AnimationStart.js.map +1 -1
  13. package/dist/Actions/ClearFailures.d.ts +1 -5
  14. package/dist/Actions/ClearFailures.js +3 -9
  15. package/dist/Actions/ClearFailures.js.map +1 -1
  16. package/dist/Actions/GameNotificationsReceived.d.ts +8 -10
  17. package/dist/Actions/GameNotificationsReceived.js +2 -9
  18. package/dist/Actions/GameNotificationsReceived.js.map +1 -1
  19. package/dist/Actions/GameOver.d.ts +16 -16
  20. package/dist/Actions/GameOver.js +4 -8
  21. package/dist/Actions/GameOver.js.map +1 -1
  22. package/dist/Actions/GameStateLoaded.d.ts +16 -16
  23. package/dist/Actions/GameStateLoaded.js +7 -20
  24. package/dist/Actions/GameStateLoaded.js.map +1 -1
  25. package/dist/Actions/MovePlayed.d.ts +11 -11
  26. package/dist/Actions/MovePlayed.js +3 -2
  27. package/dist/Actions/MovePlayed.js.map +1 -1
  28. package/dist/Actions/MoveUndone.d.ts +7 -7
  29. package/dist/Actions/MoveUndone.js +4 -9
  30. package/dist/Actions/MoveUndone.js.map +1 -1
  31. package/dist/Actions/PlayerQuit.d.ts +5 -11
  32. package/dist/Actions/PlayerQuit.js +2 -19
  33. package/dist/Actions/PlayerQuit.js.map +1 -1
  34. package/dist/Actions/SetAnimationsSpeed.d.ts +1 -6
  35. package/dist/Actions/SetAnimationsSpeed.js +3 -9
  36. package/dist/Actions/SetAnimationsSpeed.js.map +1 -1
  37. package/dist/Actions/giveUp.d.ts +1 -0
  38. package/dist/Actions/giveUp.js +3 -0
  39. package/dist/Actions/giveUp.js.map +1 -0
  40. package/dist/Actions/index.d.ts +7 -12
  41. package/dist/Actions/index.js +7 -28
  42. package/dist/Actions/index.js.map +1 -1
  43. package/dist/Actions/loadGameState.d.ts +14 -0
  44. package/dist/Actions/loadGameState.js +3 -0
  45. package/dist/Actions/loadGameState.js.map +1 -0
  46. package/dist/Actions/playMove.d.ts +10 -0
  47. package/dist/Actions/playMove.js +3 -0
  48. package/dist/Actions/playMove.js.map +1 -0
  49. package/dist/Actions/receiveNotifications.d.ts +8 -0
  50. package/dist/Actions/receiveNotifications.js +3 -0
  51. package/dist/Actions/receiveNotifications.js.map +1 -0
  52. package/dist/Actions/removePlayer.d.ts +5 -0
  53. package/dist/Actions/removePlayer.js +3 -0
  54. package/dist/Actions/removePlayer.js.map +1 -0
  55. package/dist/Actions/reportFailure.d.ts +1 -0
  56. package/dist/Actions/reportFailure.js +3 -0
  57. package/dist/Actions/reportFailure.js.map +1 -0
  58. package/dist/Actions/setGameOver.d.ts +2 -0
  59. package/dist/Actions/setGameOver.js +3 -0
  60. package/dist/Actions/setGameOver.js.map +1 -0
  61. package/dist/Actions/startAnimation.d.ts +1 -0
  62. package/dist/Actions/startAnimation.js +3 -0
  63. package/dist/Actions/startAnimation.js.map +1 -0
  64. package/dist/Actions/undoMove.d.ts +5 -0
  65. package/dist/Actions/undoMove.js +4 -0
  66. package/dist/Actions/undoMove.js.map +1 -0
  67. package/dist/Chat/ChatChannel.d.ts +5 -5
  68. package/dist/Chat/ChatChannel.js +1 -2
  69. package/dist/Chat/Message.d.ts +6 -6
  70. package/dist/Chat/Message.js +1 -2
  71. package/dist/Chat/index.d.ts +2 -2
  72. package/dist/Chat/index.js +2 -18
  73. package/dist/Chat/index.js.map +1 -1
  74. package/dist/Deckbuilding/Deck.d.ts +5 -5
  75. package/dist/Deckbuilding/Deck.js +1 -2
  76. package/dist/Deckbuilding/index.d.ts +4 -4
  77. package/dist/Deckbuilding/index.js +4 -24
  78. package/dist/Deckbuilding/index.js.map +1 -1
  79. package/dist/Deckbuilding/useDeleteDeck.d.ts +5 -2
  80. package/dist/Deckbuilding/useDeleteDeck.js +9 -15
  81. package/dist/Deckbuilding/useDeleteDeck.js.map +1 -1
  82. package/dist/Deckbuilding/useMyDecks.d.ts +3 -2
  83. package/dist/Deckbuilding/useMyDecks.js +8 -14
  84. package/dist/Deckbuilding/useMyDecks.js.map +1 -1
  85. package/dist/Deckbuilding/useSaveDeck.d.ts +5 -2
  86. package/dist/Deckbuilding/useSaveDeck.js +9 -15
  87. package/dist/Deckbuilding/useSaveDeck.js.map +1 -1
  88. package/dist/EjectPlayer/EjectPlayer.d.ts +1 -6
  89. package/dist/EjectPlayer/EjectPlayer.js +2 -8
  90. package/dist/EjectPlayer/EjectPlayer.js.map +1 -1
  91. package/dist/EjectPlayer/index.d.ts +1 -1
  92. package/dist/EjectPlayer/index.js +1 -17
  93. package/dist/EjectPlayer/index.js.map +1 -1
  94. package/dist/Failure/Failure.d.ts +6 -6
  95. package/dist/Failure/Failure.js +6 -9
  96. package/dist/Failure/Failure.js.map +1 -1
  97. package/dist/Failure/index.d.ts +1 -1
  98. package/dist/Failure/index.js +1 -17
  99. package/dist/Failure/index.js.map +1 -1
  100. package/dist/GiveUp/GiveUp.d.ts +7 -7
  101. package/dist/GiveUp/GiveUp.js +2 -5
  102. package/dist/GiveUp/GiveUp.js.map +1 -1
  103. package/dist/GiveUp/index.d.ts +1 -1
  104. package/dist/GiveUp/index.js +1 -17
  105. package/dist/GiveUp/index.js.map +1 -1
  106. package/dist/Hooks/index.d.ts +5 -5
  107. package/dist/Hooks/index.js +5 -21
  108. package/dist/Hooks/index.js.map +1 -1
  109. package/dist/Hooks/useChatMessages.d.ts +7 -12
  110. package/dist/Hooks/useChatMessages.js +44 -51
  111. package/dist/Hooks/useChatMessages.js.map +1 -1
  112. package/dist/Hooks/useMessageAuthor.d.ts +4 -4
  113. package/dist/Hooks/useMessageAuthor.js +13 -18
  114. package/dist/Hooks/useMessageAuthor.js.map +1 -1
  115. package/dist/Hooks/useOptions.d.ts +2 -2
  116. package/dist/Hooks/useOptions.js +4 -8
  117. package/dist/Hooks/useOptions.js.map +1 -1
  118. package/dist/Hooks/useRematch.d.ts +7 -7
  119. package/dist/Hooks/useRematch.js +18 -19
  120. package/dist/Hooks/useRematch.js.map +1 -1
  121. package/dist/Hooks/useSendMessage.d.ts +4 -1
  122. package/dist/Hooks/useSendMessage.js +6 -14
  123. package/dist/Hooks/useSendMessage.js.map +1 -1
  124. package/dist/Log/StartLiveLog.d.ts +1 -4
  125. package/dist/Log/StartLiveLog.js +3 -5
  126. package/dist/Log/StartLiveLog.js.map +1 -1
  127. package/dist/Log/StopLiveLog.d.ts +2 -5
  128. package/dist/Log/StopLiveLog.js +6 -9
  129. package/dist/Log/StopLiveLog.js.map +1 -1
  130. package/dist/Log/index.d.ts +4 -4
  131. package/dist/Log/index.js +4 -20
  132. package/dist/Log/index.js.map +1 -1
  133. package/dist/Log/useLogControls.d.ts +7 -7
  134. package/dist/Log/useLogControls.js +18 -22
  135. package/dist/Log/useLogControls.js.map +1 -1
  136. package/dist/PlayerTime/PlayerTime.d.ts +11 -11
  137. package/dist/PlayerTime/PlayerTime.js +1 -2
  138. package/dist/PlayerTime/index.d.ts +1 -1
  139. package/dist/PlayerTime/index.js +1 -17
  140. package/dist/PlayerTime/index.js.map +1 -1
  141. package/dist/Rematch/RematchQueries.d.ts +19 -19
  142. package/dist/Rematch/RematchQueries.js +23 -13
  143. package/dist/Rematch/RematchQueries.js.map +1 -1
  144. package/dist/Rematch/index.d.ts +1 -1
  145. package/dist/Rematch/index.js +1 -17
  146. package/dist/Rematch/index.js.map +1 -1
  147. package/dist/Sound/MuteSounds.d.ts +2 -5
  148. package/dist/Sound/MuteSounds.js +7 -10
  149. package/dist/Sound/MuteSounds.js.map +1 -1
  150. package/dist/Sound/UnmuteSounds.d.ts +1 -4
  151. package/dist/Sound/UnmuteSounds.js +3 -5
  152. package/dist/Sound/UnmuteSounds.js.map +1 -1
  153. package/dist/Sound/index.d.ts +3 -3
  154. package/dist/Sound/index.js +3 -19
  155. package/dist/Sound/index.js.map +1 -1
  156. package/dist/Sound/useSoundControls.d.ts +7 -7
  157. package/dist/Sound/useSoundControls.js +18 -22
  158. package/dist/Sound/useSoundControls.js.map +1 -1
  159. package/dist/Store/DisplayedAction.d.ts +15 -15
  160. package/dist/Store/DisplayedAction.js +12 -19
  161. package/dist/Store/DisplayedAction.js.map +1 -1
  162. package/dist/Store/GamePageState.d.ts +27 -28
  163. package/dist/Store/GamePageState.js +1 -2
  164. package/dist/Store/PlayedMove.d.ts +5 -5
  165. package/dist/Store/PlayedMove.js +1 -2
  166. package/dist/Store/endAnimation.d.ts +1 -0
  167. package/dist/Store/endAnimation.js +3 -0
  168. package/dist/Store/endAnimation.js.map +1 -0
  169. package/dist/Store/gameMiddleware.d.ts +4 -4
  170. package/dist/Store/gameMiddleware.js +34 -41
  171. package/dist/Store/gameMiddleware.js.map +1 -1
  172. package/dist/Store/gameReducer.d.ts +14 -20
  173. package/dist/Store/gameReducer.js +462 -525
  174. package/dist/Store/gameReducer.js.map +1 -1
  175. package/dist/Store/index.d.ts +4 -3
  176. package/dist/Store/index.js +4 -19
  177. package/dist/Store/index.js.map +1 -1
  178. package/dist/Store/localMovePreviewMiddleware.d.ts +4 -4
  179. package/dist/Store/localMovePreviewMiddleware.js +19 -18
  180. package/dist/Store/localMovePreviewMiddleware.js.map +1 -1
  181. package/dist/Store/store.d.ts +13 -0
  182. package/dist/Store/store.js +27 -0
  183. package/dist/Store/store.js.map +1 -0
  184. package/dist/Tutorial/PlayTutorialMoves.d.ts +1 -9
  185. package/dist/Tutorial/PlayTutorialMoves.js +2 -6
  186. package/dist/Tutorial/PlayTutorialMoves.js.map +1 -1
  187. package/dist/Tutorial/Tutorial.d.ts +5 -5
  188. package/dist/Tutorial/Tutorial.js +1 -2
  189. package/dist/Tutorial/TutorialDescription.d.ts +7 -7
  190. package/dist/Tutorial/TutorialDescription.js +1 -2
  191. package/dist/Tutorial/index.d.ts +4 -4
  192. package/dist/Tutorial/index.js +4 -20
  193. package/dist/Tutorial/index.js.map +1 -1
  194. package/dist/Tutorial/useTutorial.d.ts +2 -2
  195. package/dist/Tutorial/useTutorial.js +12 -22
  196. package/dist/Tutorial/useTutorial.js.map +1 -1
  197. package/dist/Types/GameAI.d.ts +1 -1
  198. package/dist/Types/GameAI.js +1 -2
  199. package/dist/Types/GameData.d.ts +18 -18
  200. package/dist/Types/GameData.js +1 -2
  201. package/dist/Types/GameMessage.d.ts +8 -8
  202. package/dist/Types/GameMessage.js +1 -2
  203. package/dist/Types/GameMode.d.ts +6 -6
  204. package/dist/Types/GameMode.js +7 -10
  205. package/dist/Types/GameMode.js.map +1 -1
  206. package/dist/Types/GameNotification.d.ts +6 -6
  207. package/dist/Types/GameNotification.js +1 -2
  208. package/dist/Types/GameOptions.d.ts +9 -9
  209. package/dist/Types/GameOptions.js +5 -8
  210. package/dist/Types/GameOptions.js.map +1 -1
  211. package/dist/Types/MovePlayedNotification.d.ts +9 -9
  212. package/dist/Types/MovePlayedNotification.js +6 -12
  213. package/dist/Types/MovePlayedNotification.js.map +1 -1
  214. package/dist/Types/MoveUndoneNotification.d.ts +8 -8
  215. package/dist/Types/MoveUndoneNotification.js +6 -12
  216. package/dist/Types/MoveUndoneNotification.js.map +1 -1
  217. package/dist/Types/Player.d.ts +13 -13
  218. package/dist/Types/Player.js +1 -2
  219. package/dist/Types/PlayerQuitReason.d.ts +4 -4
  220. package/dist/Types/PlayerQuitReason.js +5 -8
  221. package/dist/Types/PlayerQuitReason.js.map +1 -1
  222. package/dist/Types/ProxyGameData.d.ts +13 -13
  223. package/dist/Types/ProxyGameData.js +1 -2
  224. package/dist/Types/Tournament.d.ts +4 -4
  225. package/dist/Types/Tournament.js +1 -2
  226. package/dist/Types/index.d.ts +12 -12
  227. package/dist/Types/index.js +12 -28
  228. package/dist/Types/index.js.map +1 -1
  229. package/dist/User/User.d.ts +6 -6
  230. package/dist/User/User.js +1 -2
  231. package/dist/User/index.d.ts +2 -2
  232. package/dist/User/index.js +2 -18
  233. package/dist/User/index.js.map +1 -1
  234. package/dist/User/useMe.d.ts +4 -4
  235. package/dist/User/useMe.js +10 -21
  236. package/dist/User/useMe.js.map +1 -1
  237. package/dist/animations/Animation.d.ts +6 -6
  238. package/dist/animations/Animation.js +1 -2
  239. package/dist/animations/AnimationContext.d.ts +8 -8
  240. package/dist/animations/AnimationContext.js +1 -2
  241. package/dist/animations/AnimationState.d.ts +6 -6
  242. package/dist/animations/AnimationState.js +1 -2
  243. package/dist/animations/AnimationStep.d.ts +6 -6
  244. package/dist/animations/AnimationStep.js +7 -10
  245. package/dist/animations/AnimationStep.js.map +1 -1
  246. package/dist/animations/Animations.d.ts +8 -8
  247. package/dist/animations/Animations.js +15 -22
  248. package/dist/animations/Animations.js.map +1 -1
  249. package/dist/animations/AnimationsListener.d.ts +6 -0
  250. package/dist/animations/AnimationsListener.js +54 -0
  251. package/dist/animations/AnimationsListener.js.map +1 -0
  252. package/dist/animations/AnimationsListenerCreator.d.ts +2 -4
  253. package/dist/animations/AnimationsListenerCreator.js +40 -50
  254. package/dist/animations/AnimationsListenerCreator.js.map +1 -1
  255. package/dist/animations/animationMiddleware.d.ts +4 -0
  256. package/dist/animations/animationMiddleware.js +50 -0
  257. package/dist/animations/animationMiddleware.js.map +1 -0
  258. package/dist/animations/index.d.ts +5 -6
  259. package/dist/animations/index.js +5 -22
  260. package/dist/animations/index.js.map +1 -1
  261. package/dist/api/Client/GameClientAPI.d.ts +24 -24
  262. package/dist/api/Client/GameClientAPI.js +116 -165
  263. package/dist/api/Client/GameClientAPI.js.map +1 -1
  264. package/dist/api/Client/GameNotificationsListener.d.ts +5 -5
  265. package/dist/api/Client/GameNotificationsListener.js +62 -113
  266. package/dist/api/Client/GameNotificationsListener.js.map +1 -1
  267. package/dist/api/Client/RemoteGameLoader.d.ts +4 -5
  268. package/dist/api/Client/RemoteGameLoader.js +66 -62
  269. package/dist/api/Client/RemoteGameLoader.js.map +1 -1
  270. package/dist/api/Client/RemoteGameProvider.d.ts +7 -7
  271. package/dist/api/Client/RemoteGameProvider.js +19 -70
  272. package/dist/api/Client/RemoteGameProvider.js.map +1 -1
  273. package/dist/api/Client/apollo-client.d.ts +2 -2
  274. package/dist/api/Client/apollo-client.js +40 -58
  275. package/dist/api/Client/apollo-client.js.map +1 -1
  276. package/dist/api/Client/index.d.ts +4 -3
  277. package/dist/api/Client/index.js +4 -19
  278. package/dist/api/Client/index.js.map +1 -1
  279. package/dist/api/Client/pusher.d.ts +2 -0
  280. package/dist/api/Client/pusher.js +9 -0
  281. package/dist/api/Client/pusher.js.map +1 -0
  282. package/dist/api/GameAPI.d.ts +10 -10
  283. package/dist/api/GameAPI.js +1 -2
  284. package/dist/api/Local/ConsoleTools.d.ts +25 -25
  285. package/dist/api/Local/ConsoleTools.js +78 -86
  286. package/dist/api/Local/ConsoleTools.js.map +1 -1
  287. package/dist/api/Local/GameLocalAPI.d.ts +44 -44
  288. package/dist/api/Local/GameLocalAPI.js +442 -540
  289. package/dist/api/Local/GameLocalAPI.js.map +1 -1
  290. package/dist/api/Local/LocalGameProvider.d.ts +15 -15
  291. package/dist/api/Local/LocalGameProvider.js +18 -58
  292. package/dist/api/Local/LocalGameProvider.js.map +1 -1
  293. package/dist/api/Local/index.d.ts +1 -1
  294. package/dist/api/Local/index.js +1 -17
  295. package/dist/api/Local/index.js.map +1 -1
  296. package/dist/api/index.d.ts +2 -2
  297. package/dist/api/index.js +2 -18
  298. package/dist/api/index.js.map +1 -1
  299. package/dist/index.d.ts +16 -18
  300. package/dist/index.js +16 -36
  301. package/dist/index.js.map +1 -1
  302. package/dist/util/ArrayUtil.d.ts +2 -2
  303. package/dist/util/ArrayUtil.js +16 -21
  304. package/dist/util/ArrayUtil.js.map +1 -1
  305. package/package.json +66 -65
  306. package/dist/Actions/ActionType.d.ts +0 -3
  307. package/dist/Actions/ActionType.js +0 -8
  308. package/dist/Actions/ActionType.js.map +0 -1
  309. package/dist/Scoring/ScoringDescription.d.ts +0 -8
  310. package/dist/Scoring/ScoringDescription.js +0 -3
  311. package/dist/Scoring/ScoringDescription.js.map +0 -1
  312. package/dist/Scoring/index.d.ts +0 -1
  313. package/dist/Scoring/index.js +0 -18
  314. package/dist/Scoring/index.js.map +0 -1
  315. package/dist/util/TimeUtil.d.ts +0 -2
  316. package/dist/util/TimeUtil.js +0 -27
  317. package/dist/util/TimeUtil.js.map +0 -1
@@ -1,526 +1,463 @@
1
- "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- var desc = Object.getOwnPropertyDescriptor(m, k);
16
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
- desc = { enumerable: true, get: function() { return m[k]; } };
18
- }
19
- Object.defineProperty(o, k2, desc);
20
- }) : (function(o, m, k, k2) {
21
- if (k2 === undefined) k2 = k;
22
- o[k2] = m[k];
23
- }));
24
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
- Object.defineProperty(o, "default", { enumerable: true, value: v });
26
- }) : function(o, v) {
27
- o["default"] = v;
28
- });
29
- var __importStar = (this && this.__importStar) || function (mod) {
30
- if (mod && mod.__esModule) return mod;
31
- var result = {};
32
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
- __setModuleDefault(result, mod);
34
- return result;
35
- };
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
- Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.replayAction = exports.replayActions = exports.getGameAfterAnimations = exports.gameReducer = void 0;
41
- var rules_api_1 = require("@gamepark/rules-api");
42
- var assert_1 = __importDefault(require("assert"));
43
- var immer_1 = __importStar(require("immer"));
44
- var isEqual_1 = __importDefault(require("lodash/isEqual"));
45
- var uniqueId_1 = __importDefault(require("lodash/uniqueId"));
46
- var Actions_1 = require("../Actions");
47
- var PlayerQuit_1 = require("../Actions/PlayerQuit");
48
- var animations_1 = require("../animations");
49
- var Failure_1 = require("../Failure");
50
- var GiveUp_1 = require("../GiveUp");
51
- var Log_1 = require("../Log");
52
- var Sound_1 = require("../Sound");
53
- var Types_1 = require("../Types");
54
- var ArrayUtil_1 = require("../util/ArrayUtil");
55
- var DisplayedAction_1 = require("./DisplayedAction");
56
- function gameReducer(context) {
57
- var _a;
58
- var GameRules = context.Rules;
59
- var animations = (_a = context.animations) !== null && _a !== void 0 ? _a : new animations_1.Animations();
60
- var initialState = {
61
- players: [], pendingNotifications: [], nextNotificationIndex: 0, legalMoves: [], failures: [],
62
- animationIncrement: 0, animationsSpeed: 1, animationPaused: false,
63
- soundsMuted: (0, Sound_1.soundsMuted)(), clientTimeDelta: 0, liveLogStopped: false
64
- };
65
- return function (state, event) {
66
- if (state === void 0) { state = initialState; }
67
- switch (event.type) {
68
- case Actions_1.GAME_STATE_LOADED:
69
- return (0, immer_1.default)(state, function (draft) {
70
- if (event.serverTime) {
71
- draft.clientTimeDelta = approximateTimeDelta(event.serverTime, draft.clientTimeDelta);
72
- }
73
- draft.players = event.players;
74
- draft.options = event.options;
75
- draft.playerId = event.playerId;
76
- draft.state = event.state;
77
- if (event.playerId !== undefined) {
78
- draft.legalMoves = (0, immer_1.castDraft)(new GameRules(event.state).getLegalMoves(event.playerId));
79
- }
80
- draft.setup = event.setup;
81
- draft.gameOver = !!event.endDate;
82
- draft.gameMode = event.mode;
83
- draft.tournament = event.tournament;
84
- draft.nextNotificationIndex = event.notifications.length;
85
- if (!event.endDate) {
86
- draft.client = { player: event.playerId };
87
- }
88
- setActionsFromPastNotifications(draft, event.notifications);
89
- });
90
- case Actions_1.GAME_NOTIFICATIONS_RECEIVED:
91
- return (0, immer_1.default)(state, function (draft) {
92
- if (event.serverTime) {
93
- draft.clientTimeDelta = approximateTimeDelta(event.serverTime, draft.clientTimeDelta);
94
- }
95
- draft.players.forEach(function (player) {
96
- var _a;
97
- var newPlayerTime = (_a = event.players.find(function (p) { return p.id === player.id; })) === null || _a === void 0 ? void 0 : _a.time;
98
- player.time = newPlayerTime || player.time;
99
- });
100
- if (event.notificationsIndex == 0 && !draft.actions) {
101
- setActionsFromPastNotifications(draft, event.notifications);
102
- }
103
- for (var i = Math.max(draft.nextNotificationIndex - event.notificationsIndex, 0); i < event.notifications.length; i++) {
104
- draft.pendingNotifications.push(__assign(__assign({}, event.notifications[i]), { index: i + event.notificationsIndex }));
105
- }
106
- draft.pendingNotifications.sort(function (n1, n2) { return n1.index - n2.index; });
107
- if (draft.state) {
108
- applyPendingNotifications(draft);
109
- }
110
- });
111
- case Actions_1.ActionType.MOVE_PLAYED:
112
- return (0, immer_1.default)(state, function (draft) {
113
- var _a;
114
- if (!draft.state)
115
- throw new Error('Cannot play move before game state is loaded');
116
- if (!draft.actions)
117
- throw new Error('Cannot play move before game history is loaded');
118
- var transient = event.transient;
119
- var local = (_a = event.local) !== null && _a !== void 0 ? _a : transient;
120
- if (state.playerId === undefined && !local)
121
- throw new Error('Spectators cannot play');
122
- var action = {
123
- id: 'local-' + (0, uniqueId_1.default)(),
124
- playerId: state.playerId,
125
- move: event.move,
126
- consequences: [],
127
- played: 0,
128
- pending: !local,
129
- local: local,
130
- transient: transient
131
- };
132
- var rules = getGameAfterAnimations(draft, GameRules);
133
- var isUnpredictable = function (move) { return (0, rules_api_1.hasUnpredictableMoves)(rules) && rules.isUnpredictableMove(move, action.playerId); };
134
- if (!local && (event.delayed || isUnpredictable(event.move))) {
135
- action.delayed = true;
136
- }
137
- else {
138
- action.consequences = [];
139
- var pendingMoves_1 = rules.play(JSON.parse(JSON.stringify(event.move)), { local: local, transient: transient });
140
- (0, rules_api_1.loopWithFuse)(function () {
141
- var move = pendingMoves_1.shift();
142
- if (!move || isUnpredictable(move))
143
- return false;
144
- action.consequences.push(move);
145
- pendingMoves_1.unshift.apply(pendingMoves_1, rules.play(JSON.parse(JSON.stringify(move)), { local: local, transient: transient }));
146
- return true;
147
- }, { errorFn: function () { return new Error("Infinite loop detected while applying move consequences: ".concat(JSON.stringify(action), ")")); } });
148
- if (event.skipAnimation) {
149
- playNextMove(action, draft);
150
- }
151
- else {
152
- animatePlayedAction(action, draft);
153
- }
154
- }
155
- if (!transient || action.animation) {
156
- draft.actions.push(action);
157
- }
158
- });
159
- case Actions_1.MOVE_UNDONE:
160
- return (0, immer_1.default)(state, function (draft) {
161
- if (!state.actions || !draft.actions || !state.setup || !state.state) {
162
- return console.error('Cannot undo before actions history is loaded');
163
- }
164
- var action = (0, ArrayUtil_1.findLastItem)(draft.actions, function (action) { return action.id === event.actionId; });
165
- if (!action)
166
- return console.error("Could not find action to undo with this id: ".concat(event.actionId));
167
- if (!action.local && state.playerId === undefined) {
168
- return console.error('Spectators cannot undo moves');
169
- }
170
- action.cancelled = true;
171
- if (!action.local) {
172
- action.cancelPending = true;
173
- }
174
- if (!action.local && (event.delayed || !new GameRules(state.state, state.client).isTurnToPlay(state.playerId))) {
175
- action.delayed = true;
176
- }
177
- else {
178
- animateUndoneAction(action, draft);
179
- }
180
- });
181
- case Actions_1.ACTION_FAILED:
182
- return (0, immer_1.default)(state, function (draft) {
183
- if (draft.actions) {
184
- switch (event.reason) {
185
- case Failure_1.Failure.UNDO_FORBIDDEN:
186
- for (var _i = 0, _a = draft.actions; _i < _a.length; _i++) {
187
- var action = _a[_i];
188
- if (action.cancelPending) {
189
- action.cancelled = false;
190
- action.cancelPending = false;
191
- }
192
- }
193
- break;
194
- default:
195
- draft.actions = draft.actions.filter(function (action) { return !action.pending; });
196
- var rules = new GameRules(JSON.parse(JSON.stringify(draft.setup)), state.client);
197
- replayActions(rules, draft.actions, state.state);
198
- draft.state = rules.game;
199
- }
200
- }
201
- draft.failures.push(event.reason);
202
- });
203
- case Actions_1.CLEAR_FAILURES:
204
- return (0, immer_1.default)(state, function (draft) {
205
- draft.failures = [];
206
- });
207
- case Actions_1.ANIMATION_START:
208
- return (0, immer_1.default)(state, function (draft) {
209
- if (!draft.actions)
210
- return;
211
- var action = draft.actions.find(function (action) { return action.id === event.actionId; });
212
- if (action) {
213
- animateAction(action, draft);
214
- }
215
- });
216
- case Actions_1.ANIMATION_COMPLETE:
217
- return (0, immer_1.default)(state, function (draft) {
218
- var _a;
219
- if (draft.actions) {
220
- var action = draft.actions.find(function (action) { var _a; return ((_a = action.animation) === null || _a === void 0 ? void 0 : _a.id) === event.animationId; });
221
- if (!action) {
222
- return console.error('ANIMATION_COMPLETE event received but not animation found with provided id');
223
- }
224
- var step = (_a = action.animation) === null || _a === void 0 ? void 0 : _a.step;
225
- if (action.transient) {
226
- draft.actions.splice(draft.actions.indexOf(action), 1);
227
- }
228
- else {
229
- delete action.animation;
230
- }
231
- if (step === animations_1.AnimationStep.BEFORE_MOVE) {
232
- playNextMove(action, draft);
233
- }
234
- else if (step === animations_1.AnimationStep.BEFORE_UNDO) {
235
- undoNextMove(action, draft);
236
- }
237
- else {
238
- refreshLegalMoves(draft);
239
- }
240
- }
241
- });
242
- case Actions_1.ANIMATION_PAUSED:
243
- return (0, immer_1.default)(state, function (draft) {
244
- draft.animationPaused = event.pause;
245
- });
246
- case Actions_1.SET_ANIMATIONS_SPEED:
247
- return __assign(__assign({}, state), { animationsSpeed: event.speed });
248
- case GiveUp_1.GIVE_UP:
249
- return __assign(__assign({}, state), { playerId: undefined });
250
- case Sound_1.MUTE_SOUNDS:
251
- return __assign(__assign({}, state), { soundsMuted: true });
252
- case Sound_1.UNMUTE_SOUNDS:
253
- return __assign(__assign({}, state), { soundsMuted: false });
254
- case Log_1.START_LIVE_LOG:
255
- return __assign(__assign({}, state), { liveLogStopped: false });
256
- case Log_1.STOP_LIVE_LOG:
257
- return __assign(__assign({}, state), { liveLogStopped: true });
258
- case PlayerQuit_1.PLAYER_QUIT:
259
- return (0, immer_1.default)(state, function (draft) {
260
- var player = draft.players.find(function (p) { return p.id === event.playerId; });
261
- if (player) {
262
- player.quit = true;
263
- player.quitReason = event.reason;
264
- }
265
- if (draft.playerId === event.playerId) {
266
- delete draft.playerId;
267
- }
268
- });
269
- case Actions_1.GAME_OVER:
270
- return __assign(__assign({}, state), { gameOver: true, players: state.players.map(function (player) {
271
- var _a;
272
- var p = event.players.find(function (p) { return p.id === player.id; });
273
- if (!p)
274
- return player;
275
- else
276
- return (__assign(__assign({}, player), { time: (_a = p.time) !== null && _a !== void 0 ? _a : player.time, gamePointsDelta: p.gamePointsDelta, tournamentPoints: p.tournamentPoints }));
277
- }) });
278
- }
279
- return state;
280
- };
281
- function playNextMove(action, draft) {
282
- var consequenceIndex = action.played === 0 ? undefined : action.played - 1;
283
- var move = consequenceIndex === undefined ? action.move : action.consequences[consequenceIndex];
284
- var rules = new GameRules(draft.state, draft.client);
285
- rules.play(JSON.parse(JSON.stringify(move)), { local: action.local, transient: action.transient });
286
- action.played++;
287
- if (!action.local && !action.transient && !action.pending) {
288
- draft.playedMoves.push({ actionId: action.id, move: move, consequenceIndex: consequenceIndex });
289
- }
290
- animatePlayedAction(action, draft, animations_1.AnimationStep.AFTER_MOVE);
291
- }
292
- function undoNextMove(action, draft) {
293
- var rules = new GameRules(JSON.parse(JSON.stringify(draft.setup)), draft.client);
294
- action.played--;
295
- var actionsPlayed = draft.actions.filter(function (action) { return action.played > 0; })
296
- .map(function (action) { return (__assign(__assign({}, action), { consequences: action.consequences.slice(0, action.played - 1) })); });
297
- replayActions(rules, actionsPlayed, draft.state);
298
- draft.state = rules.game;
299
- animateUndoneAction(action, draft, animations_1.AnimationStep.AFTER_UNDO);
300
- }
301
- function setActionsFromPastNotifications(draft, notifications) {
302
- var _a;
303
- draft.actions = [];
304
- draft.playedMoves = [];
305
- var _loop_1 = function (i) {
306
- var notification = notifications[i];
307
- if ((0, Types_1.isMovePlayedNotification)(notification)) {
308
- var action = {
309
- id: (_a = notification.actionId) !== null && _a !== void 0 ? _a : undefined,
310
- playerId: notification.playerId, move: notification.moveView,
311
- consequences: notification.consequences,
312
- played: 1 + notification.consequences.length
313
- };
314
- draft.actions.push(action);
315
- draft.playedMoves.push({ actionId: action.id, move: action.move });
316
- for (var consequenceIndex = 0; consequenceIndex < action.consequences.length; consequenceIndex++) {
317
- var consequence = action.consequences[consequenceIndex];
318
- draft.playedMoves.push({ actionId: action.id, move: consequence, consequenceIndex: consequenceIndex });
319
- }
320
- }
321
- else if ((0, Types_1.isMoveUndoneNotification)(notification)) {
322
- var index = notification.actionId ? (0, ArrayUtil_1.findLastIndex)(draft.actions, function (action) { return action.id === notification.actionId; }) : notification.moveUndone;
323
- if (index !== -1) {
324
- draft.actions.splice(index, 1);
325
- }
326
- draft.playedMoves = draft.playedMoves.filter(function (playedMove) { return playedMove.actionId !== notification.actionId; });
327
- }
328
- };
329
- for (var i = 0; i < draft.nextNotificationIndex; i++) {
330
- _loop_1(i);
331
- }
332
- }
333
- function applyPendingNotifications(draft) {
334
- if (!draft.actions) {
335
- return;
336
- }
337
- while (draft.pendingNotifications.length && draft.pendingNotifications[0].index <= draft.nextNotificationIndex) {
338
- var notification = draft.pendingNotifications.shift();
339
- if (notification.index < draft.nextNotificationIndex) {
340
- console.info('A notification was received twice: ' + JSON.stringify(notification));
341
- }
342
- else {
343
- draft.nextNotificationIndex++;
344
- applyNotification(draft, notification);
345
- }
346
- }
347
- }
348
- function applyNotification(draft, notification) {
349
- if ((0, Types_1.isMovePlayedNotification)(notification)) {
350
- applyMovePlayedNotification(draft, notification);
351
- }
352
- else if ((0, Types_1.isMoveUndoneNotification)(notification)) {
353
- applyMoveUndoneNotification(draft, notification);
354
- }
355
- }
356
- function applyMovePlayedNotification(draft, notification) {
357
- var _a;
358
- var _b, _c;
359
- (0, assert_1.default)(draft.actions !== undefined, 'Cannot apply a notification before action history is loaded');
360
- var action;
361
- if (notification.playerId == draft.playerId) {
362
- action = draft.actions.find(function (action) { return action.pending && action.playerId == notification.playerId; });
363
- }
364
- if (action) {
365
- action.id = (_b = notification.actionId) !== null && _b !== void 0 ? _b : undefined;
366
- action.pending = false;
367
- if (action.delayed) {
368
- action.move = notification.moveView;
369
- action.consequences = notification.consequences;
370
- delete action.delayed;
371
- }
372
- else {
373
- if (action.played !== 0) {
374
- draft.playedMoves.push({ actionId: action.id, move: action.move });
375
- for (var consequenceIndex = 0; consequenceIndex < action.played - 1; consequenceIndex++) {
376
- var consequence = action.consequences[consequenceIndex];
377
- draft.playedMoves.push({ actionId: action.id, move: consequence, consequenceIndex: consequenceIndex });
378
- }
379
- }
380
- if (!(0, isEqual_1.default)(JSON.parse(JSON.stringify(action.move)), JSON.parse(JSON.stringify(notification.moveView)))) {
381
- var rules = new GameRules(draft.state);
382
- if ((0, rules_api_1.hasUnpredictableMoves)(rules) && rules.canIgnoreServerDifference
383
- && rules.canIgnoreServerDifference(action.move, notification.moveView)) {
384
- action.move = notification.moveView;
385
- }
386
- else {
387
- console.error('An action was played and executed immediately:', JSON.parse(JSON.stringify(action.move)), ', but the notifications does not contain the same data:', JSON.parse(JSON.stringify(notification.moveView)), '(use the "delayed" parameter to postpone execution if the outcome cannot be anticipated).');
388
- }
389
- }
390
- if (action.consequences.length > notification.consequences.length) {
391
- console.error('The server returned less consequences that what was played locally:', action.consequences, notification.consequences);
392
- }
393
- else {
394
- for (var i = 0; i < action.consequences.length; i++) {
395
- if (!(0, isEqual_1.default)(JSON.parse(JSON.stringify(action.consequences[i])), JSON.parse(JSON.stringify(notification.consequences[i])))) {
396
- var rules = new GameRules(draft.state);
397
- if ((0, rules_api_1.hasUnpredictableMoves)(rules) && rules.canIgnoreServerDifference
398
- && rules.canIgnoreServerDifference(action.consequences[i], notification.consequences[i])) {
399
- action.consequences[i] = notification.consequences[i];
400
- }
401
- else {
402
- console.error("Consequence #".concat(i, " was played on the client, but the server returned a different consequence:"), JSON.parse(JSON.stringify(action.consequences[i])), notification.consequences[i]);
403
- }
404
- }
405
- }
406
- (_a = action.consequences).push.apply(_a, notification.consequences.slice(action.consequences.length));
407
- }
408
- }
409
- }
410
- else {
411
- draft.actions.splice((0, ArrayUtil_1.findLastIndex)(draft.actions, function (action) { return !action.pending; }) + 1, 0, {
412
- id: (_c = notification.actionId) !== null && _c !== void 0 ? _c : undefined,
413
- playerId: notification.playerId,
414
- move: notification.moveView,
415
- consequences: notification.consequences,
416
- played: 0
417
- });
418
- }
419
- }
420
- function applyMoveUndoneNotification(draft, notification) {
421
- (0, assert_1.default)(draft.actions !== undefined, 'Cannot apply a notification before action history is loaded');
422
- var index = (0, ArrayUtil_1.findLastIndex)(draft.actions, function (action) { return action.id === notification.actionId; });
423
- if (index === -1)
424
- return console.error("Received move undone notification, but action ".concat(notification.actionId, " is unknown"));
425
- var cancelledAction = draft.actions[index];
426
- if (!cancelledAction.played && !cancelledAction.animation) {
427
- draft.actions.splice(index, 1);
428
- }
429
- else {
430
- cancelledAction.cancelled = true;
431
- delete cancelledAction.cancelPending;
432
- delete cancelledAction.delayed;
433
- }
434
- draft.playedMoves = draft.playedMoves.filter(function (move) { return move.actionId !== notification.actionId; });
435
- }
436
- function animateAction(action, draft) {
437
- if (!action.cancelled) {
438
- animatePlayedAction(action, draft);
439
- }
440
- else {
441
- animateUndoneAction(action, draft);
442
- }
443
- }
444
- function animatePlayedAction(action, draft, step) {
445
- if (step === void 0) { step = animations_1.AnimationStep.BEFORE_MOVE; }
446
- if (action.activePlayers === undefined) {
447
- var rules_1 = new GameRules(draft.state, draft.client);
448
- action.activePlayers = draft.players.map(function (p) { return p.id; }).filter(function (p) { return rules_1.isTurnToPlay(p); });
449
- }
450
- var move = (0, DisplayedAction_1.getAnimatedMove)(action, step);
451
- var duration = animations.getDuration(move, getAnimationContext(action, draft, step)) / draft.animationsSpeed;
452
- if (duration > 0) {
453
- action.animation = { id: draft.animationIncrement++, duration: duration, step: step };
454
- }
455
- else if (step === animations_1.AnimationStep.BEFORE_MOVE) {
456
- playNextMove(action, draft);
457
- }
458
- else if (action.played <= action.consequences.length && !draft.animationPaused) {
459
- animatePlayedAction(action, draft);
460
- }
461
- else {
462
- refreshLegalMoves(draft);
463
- }
464
- }
465
- function refreshLegalMoves(draft) {
466
- if (draft.playerId !== undefined) {
467
- var rules = new GameRules(draft.state, draft.client);
468
- draft.legalMoves = (0, immer_1.castDraft)(rules.getLegalMoves(draft.playerId));
469
- }
470
- }
471
- function animateUndoneAction(action, draft, step) {
472
- if (step === void 0) { step = animations_1.AnimationStep.BEFORE_UNDO; }
473
- var move = (0, DisplayedAction_1.getAnimatedMove)(action, step);
474
- var duration = animations.getDuration(move, getAnimationContext(action, draft, step)) / draft.animationsSpeed;
475
- if (duration > 0) {
476
- action.animation = { id: draft.animationIncrement++, duration: duration, step: step };
477
- }
478
- else if (step === animations_1.AnimationStep.BEFORE_UNDO) {
479
- undoNextMove(action, draft);
480
- }
481
- else if (action.played > 0) {
482
- animateUndoneAction(action, draft);
483
- }
484
- else {
485
- refreshLegalMoves(draft);
486
- if (!action.cancelPending) {
487
- draft.actions.splice(draft.actions.indexOf(action), 1);
488
- }
489
- }
490
- }
491
- function getAnimationContext(action, draft, step) {
492
- return __assign(__assign({}, context), { action: action, game: draft.state, playerId: draft.playerId, step: step });
493
- }
494
- }
495
- exports.gameReducer = gameReducer;
496
- function getGameAfterAnimations(state, Rules) {
497
- if (!state.actions || !state.setup) {
498
- throw new Error('Cannot play move before game history is loaded');
499
- }
500
- if (state.actions.some(function (action) { return action.animation || action.cancelled; })) {
501
- var rules_2 = new Rules(JSON.parse(JSON.stringify(state.setup)), state.client);
502
- var actionsToReplay = state.actions.filter(function (action) { return !action.delayed && !action.cancelled; });
503
- actionsToReplay.forEach(function (action) { return replayAction(rules_2, action); });
504
- return rules_2;
505
- }
506
- else {
507
- return new Rules(JSON.parse(JSON.stringify(state.state)), { player: state.playerId });
508
- }
509
- }
510
- exports.getGameAfterAnimations = getGameAfterAnimations;
511
- var estimatedLatency = 100;
512
- function approximateTimeDelta(serverTime, clientTimeDelta) {
513
- return Math.min(serverTime + estimatedLatency - new Date().getTime(), clientTimeDelta || Infinity);
514
- }
515
- function replayActions(rules, actions, previousState) {
516
- actions.forEach(function (action) { return replayAction(rules, action); });
517
- if ((0, rules_api_1.hasUndo)(rules) && rules.restoreTransientState)
518
- rules.restoreTransientState(previousState);
519
- }
520
- exports.replayActions = replayActions;
521
- function replayAction(rules, action) {
522
- rules.play(JSON.parse(JSON.stringify(action.move)), { local: action.local, transient: action.transient });
523
- action.consequences.forEach(function (move) { return rules.play(JSON.parse(JSON.stringify(move)), { local: action.local, transient: action.transient }); });
524
- }
525
- exports.replayAction = replayAction;
1
+ import { hasUndo, hasUnpredictableMoves, loopWithFuse } from '@gamepark/rules-api';
2
+ import { createReducer } from '@reduxjs/toolkit';
3
+ import assert from 'assert';
4
+ import { isEqual, merge } from 'es-toolkit';
5
+ import { uniqueId } from 'es-toolkit/compat';
6
+ import { castDraft } from 'immer';
7
+ import { clearFailures, giveUp, playMove, receiveNotifications, setAnimationsSpeed, setGameOver, undoMove } from '../Actions';
8
+ import { loadGameState } from '../Actions/loadGameState';
9
+ import { removePlayer } from '../Actions/removePlayer';
10
+ import { reportFailure } from '../Actions/reportFailure';
11
+ import { startAnimation } from '../Actions/startAnimation';
12
+ import { Animations, AnimationStep } from '../animations';
13
+ import { Failure } from '../Failure';
14
+ import { startLiveLog, stopLiveLog } from '../Log';
15
+ import { muteSounds, soundsMuted, unmuteSounds } from '../Sound';
16
+ import { isMovePlayedNotification, isMoveUndoneNotification } from '../Types';
17
+ import { findLastIndex, findLastItem } from '../util/ArrayUtil';
18
+ import { getAnimatedMove } from './DisplayedAction';
19
+ import { endAnimation } from './endAnimation';
20
+ export function gameReducer(context) {
21
+ const GameRules = context?.Rules;
22
+ const animations = context?.animations ?? new Animations();
23
+ const initialState = {
24
+ players: [], pendingNotifications: [], nextNotificationIndex: 0, legalMoves: [], failures: [],
25
+ animationIncrement: 0, animationsSpeed: 1,
26
+ soundsMuted: soundsMuted(), clientTimeDelta: 0, liveLogStopped: false
27
+ };
28
+ return createReducer(initialState, (builder) => {
29
+ builder.addCase(loadGameState, (draft, { payload }) => {
30
+ if (payload.serverTime) {
31
+ draft.clientTimeDelta = approximateTimeDelta(payload.serverTime, draft.clientTimeDelta);
32
+ }
33
+ draft.players = payload.players;
34
+ draft.options = payload.options;
35
+ draft.playerId = payload.playerId;
36
+ draft.state = payload.state;
37
+ if (payload.playerId !== undefined) {
38
+ draft.legalMoves = castDraft(new GameRules(payload.state).getLegalMoves(payload.playerId));
39
+ }
40
+ draft.setup = payload.setup;
41
+ draft.gameOver = !!payload.endDate;
42
+ draft.gameMode = payload.mode;
43
+ draft.tournament = payload.tournament;
44
+ draft.nextNotificationIndex = payload.notifications.length;
45
+ if (!payload.endDate) {
46
+ draft.client = { player: payload.playerId };
47
+ }
48
+ setActionsFromPastNotifications(draft, payload.notifications);
49
+ });
50
+ builder.addCase(receiveNotifications, (draft, { payload }) => {
51
+ if (payload.serverTime) {
52
+ draft.clientTimeDelta = approximateTimeDelta(payload.serverTime, draft.clientTimeDelta);
53
+ }
54
+ for (const player of draft.players) {
55
+ const newPlayerTime = payload.players.find(p => p.id === player.id)?.time;
56
+ player.time = newPlayerTime ?? player.time;
57
+ }
58
+ if (payload.notificationsIndex == 0 && !draft.actions) {
59
+ setActionsFromPastNotifications(draft, payload.notifications);
60
+ }
61
+ for (let i = Math.max(draft.nextNotificationIndex - payload.notificationsIndex, 0); i < payload.notifications.length; i++) {
62
+ draft.pendingNotifications.push({ ...payload.notifications[i], index: i + payload.notificationsIndex });
63
+ }
64
+ draft.pendingNotifications.sort((n1, n2) => n1.index - n2.index);
65
+ if (draft.state) {
66
+ applyPendingNotifications(draft);
67
+ }
68
+ });
69
+ builder.addCase(playMove, (draft, { payload: { move, options } }) => {
70
+ if (!draft.state)
71
+ throw new Error('Cannot play move before game state is loaded');
72
+ if (!draft.actions)
73
+ throw new Error('Cannot play move before game history is loaded');
74
+ const transient = options?.transient;
75
+ const local = options?.local ?? transient;
76
+ if (draft.playerId === undefined && !local)
77
+ throw new Error('Spectators cannot play');
78
+ const action = {
79
+ id: 'local-' + uniqueId(),
80
+ playerId: draft.playerId,
81
+ move,
82
+ consequences: [],
83
+ played: 0,
84
+ pending: !local,
85
+ local,
86
+ transient
87
+ };
88
+ const rules = getGameAfterAnimations(draft, GameRules);
89
+ const isUnpredictable = (move) => hasUnpredictableMoves(rules) && rules.isUnpredictableMove(move, action.playerId);
90
+ if (!local && (options?.delayed || isUnpredictable(move))) {
91
+ action.delayed = true;
92
+ }
93
+ else {
94
+ action.consequences = [];
95
+ const pendingMoves = rules.play(JSON.parse(JSON.stringify(move)), { local, transient });
96
+ loopWithFuse(() => {
97
+ const move = pendingMoves.shift();
98
+ if (!move || isUnpredictable(move))
99
+ return false;
100
+ action.consequences.push(move);
101
+ pendingMoves.unshift(...rules.play(JSON.parse(JSON.stringify(move)), { local, transient }));
102
+ return true;
103
+ }, { errorFn: () => new Error(`Infinite loop detected while applying move consequences: ${JSON.stringify(action)})`) });
104
+ if (options?.skipAnimation) {
105
+ playNextMove(action, draft);
106
+ }
107
+ else {
108
+ animatePlayedAction(action, draft);
109
+ }
110
+ }
111
+ if (!transient || action.animation) {
112
+ draft.actions.push(action);
113
+ }
114
+ });
115
+ builder.addCase(undoMove, (draft, { payload: { actionId, delayed } }) => {
116
+ if (!draft.actions || !draft.setup || !draft.state) {
117
+ return console.error('Cannot undo before actions history is loaded');
118
+ }
119
+ const action = findLastItem(draft.actions, action => action.id === actionId);
120
+ if (!action)
121
+ return console.error(`Could not find action to undo with this id: ${actionId}`);
122
+ if (!action.local && draft.playerId === undefined) {
123
+ return console.error('Spectators cannot undo moves');
124
+ }
125
+ action.cancelled = true;
126
+ if (!action.local) {
127
+ action.cancelPending = true;
128
+ }
129
+ if (!action.local && (delayed || !new GameRules(draft.state, draft.client).isTurnToPlay(draft.playerId))) {
130
+ action.delayed = true;
131
+ }
132
+ else {
133
+ animateUndoneAction(action, draft);
134
+ }
135
+ });
136
+ builder.addCase(reportFailure, (draft, { payload: reason }) => {
137
+ if (draft.actions) {
138
+ switch (reason) {
139
+ case Failure.UNDO_FORBIDDEN:
140
+ for (const action of draft.actions) {
141
+ if (action.cancelPending) {
142
+ action.cancelled = false;
143
+ action.cancelPending = false;
144
+ }
145
+ }
146
+ break;
147
+ default:
148
+ draft.actions = draft.actions.filter(action => !action.pending);
149
+ const rules = new GameRules(JSON.parse(JSON.stringify(draft.setup)), draft.client);
150
+ replayActions(rules, draft.actions, draft.state);
151
+ draft.state = rules.game;
152
+ }
153
+ }
154
+ draft.failures.push(reason);
155
+ });
156
+ builder.addCase(clearFailures, (draft) => {
157
+ draft.failures = [];
158
+ });
159
+ builder.addCase(startAnimation, (draft, { payload: actionId }) => {
160
+ if (!draft.actions)
161
+ return;
162
+ const action = draft.actions.find(action => action.id === actionId);
163
+ if (action) {
164
+ animateAction(action, draft);
165
+ }
166
+ });
167
+ builder.addCase(endAnimation, (draft, { payload: animationId }) => {
168
+ if (draft.actions) {
169
+ const action = draft.actions.find(action => action.animation?.id === animationId);
170
+ if (!action) {
171
+ return console.error('endAnimation action received but not animation found with provided id');
172
+ }
173
+ const step = action.animation?.step;
174
+ if (action.transient) {
175
+ draft.actions.splice(draft.actions.indexOf(action), 1);
176
+ }
177
+ else {
178
+ delete action.animation;
179
+ }
180
+ if (step === AnimationStep.BEFORE_MOVE) {
181
+ playNextMove(action, draft);
182
+ }
183
+ else if (step === AnimationStep.BEFORE_UNDO) {
184
+ undoNextMove(action, draft);
185
+ }
186
+ else {
187
+ refreshLegalMoves(draft);
188
+ }
189
+ }
190
+ });
191
+ builder.addCase(setAnimationsSpeed, (draft, { payload: speed }) => {
192
+ draft.animationsSpeed = speed;
193
+ });
194
+ builder.addCase(giveUp, (draft) => {
195
+ draft.playerId = undefined;
196
+ });
197
+ builder.addCase(muteSounds, (draft) => {
198
+ draft.soundsMuted = true;
199
+ });
200
+ builder.addCase(unmuteSounds, (draft) => {
201
+ draft.soundsMuted = false;
202
+ });
203
+ builder.addCase(startLiveLog, (draft) => {
204
+ draft.liveLogStopped = false;
205
+ });
206
+ builder.addCase(stopLiveLog, (draft) => {
207
+ draft.liveLogStopped = true;
208
+ });
209
+ builder.addCase(removePlayer, (draft, { payload: { playerId, reason } }) => {
210
+ const player = draft.players.find(p => p.id === playerId);
211
+ if (player) {
212
+ player.quit = true;
213
+ player.quitReason = reason;
214
+ }
215
+ if (draft.playerId === playerId) {
216
+ delete draft.playerId;
217
+ }
218
+ });
219
+ builder.addCase(setGameOver, (draft, { payload: players }) => {
220
+ draft.gameOver = true;
221
+ for (const player of draft.players) {
222
+ const newPlayerData = players.find(p => p.id === player.id) ?? {};
223
+ merge(player, newPlayerData);
224
+ }
225
+ });
226
+ });
227
+ function playNextMove(action, draft) {
228
+ const consequenceIndex = action.played === 0 ? undefined : action.played - 1;
229
+ const move = consequenceIndex === undefined ? action.move : action.consequences[consequenceIndex];
230
+ const rules = new GameRules(draft.state, draft.client);
231
+ rules.play(JSON.parse(JSON.stringify(move)), { local: action.local, transient: action.transient });
232
+ action.played++;
233
+ if (!action.local && !action.transient && !action.pending) {
234
+ draft.playedMoves.push({ actionId: action.id, move, consequenceIndex });
235
+ }
236
+ animatePlayedAction(action, draft, AnimationStep.AFTER_MOVE);
237
+ }
238
+ function undoNextMove(action, draft) {
239
+ const rules = new GameRules(JSON.parse(JSON.stringify(draft.setup)), draft.client);
240
+ action.played--;
241
+ const actionsPlayed = draft.actions.filter(action => action.played > 0)
242
+ .map(action => ({
243
+ ...action,
244
+ consequences: action.consequences.slice(0, action.played - 1)
245
+ }));
246
+ replayActions(rules, actionsPlayed, draft.state);
247
+ draft.state = rules.game;
248
+ animateUndoneAction(action, draft, AnimationStep.AFTER_UNDO);
249
+ }
250
+ function setActionsFromPastNotifications(draft, notifications) {
251
+ draft.actions = [];
252
+ draft.playedMoves = [];
253
+ for (let i = 0; i < draft.nextNotificationIndex; i++) {
254
+ const notification = notifications[i];
255
+ if (isMovePlayedNotification(notification)) {
256
+ const action = {
257
+ id: notification.actionId ?? undefined,
258
+ playerId: notification.playerId, move: notification.moveView,
259
+ consequences: notification.consequences,
260
+ played: 1 + notification.consequences.length
261
+ };
262
+ draft.actions.push(action);
263
+ draft.playedMoves.push({ actionId: action.id, move: action.move });
264
+ for (let consequenceIndex = 0; consequenceIndex < action.consequences.length; consequenceIndex++) {
265
+ const consequence = action.consequences[consequenceIndex];
266
+ draft.playedMoves.push({ actionId: action.id, move: consequence, consequenceIndex });
267
+ }
268
+ }
269
+ else if (isMoveUndoneNotification(notification)) {
270
+ const index = notification.actionId ? findLastIndex(draft.actions, action => action.id === notification.actionId) : notification.moveUndone;
271
+ if (index !== -1) {
272
+ draft.actions.splice(index, 1);
273
+ }
274
+ draft.playedMoves = draft.playedMoves.filter((playedMove) => playedMove.actionId !== notification.actionId);
275
+ }
276
+ }
277
+ }
278
+ function applyPendingNotifications(draft) {
279
+ if (!draft.actions) {
280
+ return;
281
+ }
282
+ while (draft.pendingNotifications.length && draft.pendingNotifications[0].index <= draft.nextNotificationIndex) {
283
+ const notification = draft.pendingNotifications.shift();
284
+ if (notification.index < draft.nextNotificationIndex) {
285
+ console.info('A notification was received twice: ' + JSON.stringify(notification));
286
+ }
287
+ else {
288
+ draft.nextNotificationIndex++;
289
+ applyNotification(draft, notification);
290
+ }
291
+ }
292
+ }
293
+ function applyNotification(draft, notification) {
294
+ if (isMovePlayedNotification(notification)) {
295
+ applyMovePlayedNotification(draft, notification);
296
+ }
297
+ else if (isMoveUndoneNotification(notification)) {
298
+ applyMoveUndoneNotification(draft, notification);
299
+ }
300
+ }
301
+ function applyMovePlayedNotification(draft, notification) {
302
+ assert(draft.actions !== undefined, 'Cannot apply a notification before action history is loaded');
303
+ let action;
304
+ if (notification.playerId === draft.playerId) {
305
+ action = draft.actions.find(action => action.pending && action.playerId == notification.playerId);
306
+ }
307
+ if (action) {
308
+ action.id = notification.actionId ?? undefined;
309
+ action.pending = false;
310
+ if (action.delayed) {
311
+ action.move = notification.moveView;
312
+ action.consequences = notification.consequences;
313
+ delete action.delayed;
314
+ }
315
+ else {
316
+ if (action.played !== 0) {
317
+ draft.playedMoves.push({ actionId: action.id, move: action.move });
318
+ for (let consequenceIndex = 0; consequenceIndex < action.played - 1; consequenceIndex++) {
319
+ const consequence = action.consequences[consequenceIndex];
320
+ draft.playedMoves.push({ actionId: action.id, move: consequence, consequenceIndex });
321
+ }
322
+ }
323
+ if (!isEqual(JSON.parse(JSON.stringify(action.move)), JSON.parse(JSON.stringify(notification.moveView)))) {
324
+ const rules = new GameRules(draft.state);
325
+ if (hasUnpredictableMoves(rules) && rules.canIgnoreServerDifference
326
+ && rules.canIgnoreServerDifference(action.move, notification.moveView)) {
327
+ action.move = notification.moveView;
328
+ }
329
+ else {
330
+ console.error('An action was played and executed immediately:', JSON.parse(JSON.stringify(action.move)), ', but the notifications does not contain the same data:', JSON.parse(JSON.stringify(notification.moveView)), '(use the "delayed" parameter to postpone execution if the outcome cannot be anticipated).');
331
+ }
332
+ }
333
+ if (action.consequences.length > notification.consequences.length) {
334
+ console.error('The server returned less consequences that what was played locally:', action.consequences, notification.consequences);
335
+ }
336
+ else {
337
+ for (let i = 0; i < action.consequences.length; i++) {
338
+ if (!isEqual(JSON.parse(JSON.stringify(action.consequences[i])), JSON.parse(JSON.stringify(notification.consequences[i])))) {
339
+ const rules = new GameRules(draft.state);
340
+ if (hasUnpredictableMoves(rules) && rules.canIgnoreServerDifference
341
+ && rules.canIgnoreServerDifference(action.consequences[i], notification.consequences[i])) {
342
+ action.consequences[i] = notification.consequences[i];
343
+ }
344
+ else {
345
+ console.error(`Consequence #${i} was played on the client, but the server returned a different consequence:`, JSON.parse(JSON.stringify(action.consequences[i])), notification.consequences[i]);
346
+ }
347
+ }
348
+ }
349
+ action.consequences.push(...notification.consequences.slice(action.consequences.length));
350
+ }
351
+ }
352
+ }
353
+ else {
354
+ draft.actions.splice(findLastIndex(draft.actions, action => !action.pending) + 1, 0, {
355
+ id: notification.actionId ?? undefined,
356
+ playerId: notification.playerId,
357
+ move: notification.moveView,
358
+ consequences: notification.consequences,
359
+ played: 0
360
+ });
361
+ }
362
+ }
363
+ function applyMoveUndoneNotification(draft, notification) {
364
+ assert(draft.actions !== undefined, 'Cannot apply a notification before action history is loaded');
365
+ const index = findLastIndex(draft.actions, action => action.id === notification.actionId);
366
+ if (index === -1)
367
+ return console.error(`Received move undone notification, but action ${notification.actionId} is unknown`);
368
+ const cancelledAction = draft.actions[index];
369
+ if (!cancelledAction.played && !cancelledAction.animation) {
370
+ draft.actions.splice(index, 1);
371
+ }
372
+ else {
373
+ cancelledAction.cancelled = true;
374
+ delete cancelledAction.cancelPending;
375
+ delete cancelledAction.delayed;
376
+ }
377
+ draft.playedMoves = draft.playedMoves.filter((move) => move.actionId !== notification.actionId);
378
+ }
379
+ function animateAction(action, draft) {
380
+ if (!action.cancelled) {
381
+ animatePlayedAction(action, draft);
382
+ }
383
+ else {
384
+ animateUndoneAction(action, draft);
385
+ }
386
+ }
387
+ function animatePlayedAction(action, draft, step = AnimationStep.BEFORE_MOVE) {
388
+ if (action.activePlayers === undefined) {
389
+ const rules = new GameRules(draft.state, draft.client);
390
+ action.activePlayers = draft.players.map(p => p.id).filter(p => rules.isTurnToPlay(p));
391
+ }
392
+ const move = getAnimatedMove(action, step);
393
+ const duration = animations.getDuration(move, getAnimationContext(action, draft, step)) / draft.animationsSpeed;
394
+ if (duration > 0) {
395
+ action.animation = { id: draft.animationIncrement++, duration, step };
396
+ }
397
+ else if (step === AnimationStep.BEFORE_MOVE) {
398
+ playNextMove(action, draft);
399
+ }
400
+ else if (action.played <= action.consequences.length) {
401
+ animatePlayedAction(action, draft);
402
+ }
403
+ else {
404
+ refreshLegalMoves(draft);
405
+ }
406
+ }
407
+ function refreshLegalMoves(draft) {
408
+ if (draft.playerId !== undefined) {
409
+ const rules = new GameRules(draft.state, draft.client);
410
+ draft.legalMoves = castDraft(rules.getLegalMoves(draft.playerId));
411
+ }
412
+ }
413
+ function animateUndoneAction(action, draft, step = AnimationStep.BEFORE_UNDO) {
414
+ const move = getAnimatedMove(action, step);
415
+ const duration = animations.getDuration(move, getAnimationContext(action, draft, step)) / draft.animationsSpeed;
416
+ if (duration > 0) {
417
+ action.animation = { id: draft.animationIncrement++, duration, step };
418
+ }
419
+ else if (step === AnimationStep.BEFORE_UNDO) {
420
+ undoNextMove(action, draft);
421
+ }
422
+ else if (action.played > 0) {
423
+ animateUndoneAction(action, draft);
424
+ }
425
+ else {
426
+ refreshLegalMoves(draft);
427
+ if (!action.cancelPending) {
428
+ draft.actions.splice(draft.actions.indexOf(action), 1);
429
+ }
430
+ }
431
+ }
432
+ function getAnimationContext(action, draft, step) {
433
+ return { ...context, action: action, game: draft.state, playerId: draft.playerId, step };
434
+ }
435
+ }
436
+ export function getGameAfterAnimations(state, Rules) {
437
+ if (!state.actions || !state.setup) {
438
+ throw new Error('Cannot play move before game history is loaded');
439
+ }
440
+ if (state.actions.some(action => action.animation || action.cancelled)) {
441
+ const rules = new Rules(JSON.parse(JSON.stringify(state.setup)), state.client);
442
+ const actionsToReplay = state.actions.filter(action => !action.delayed && !action.cancelled);
443
+ actionsToReplay.forEach(action => replayAction(rules, action));
444
+ return rules;
445
+ }
446
+ else {
447
+ return new Rules(JSON.parse(JSON.stringify(state.state)), { player: state.playerId });
448
+ }
449
+ }
450
+ const estimatedLatency = 100;
451
+ function approximateTimeDelta(serverTime, clientTimeDelta) {
452
+ return Math.min(serverTime + estimatedLatency - new Date().getTime(), clientTimeDelta || Infinity);
453
+ }
454
+ export function replayActions(rules, actions, previousState) {
455
+ actions.forEach(action => replayAction(rules, action));
456
+ if (hasUndo(rules) && rules.restoreTransientState)
457
+ rules.restoreTransientState(previousState);
458
+ }
459
+ export function replayAction(rules, action) {
460
+ rules.play(JSON.parse(JSON.stringify(action.move)), { local: action.local, transient: action.transient });
461
+ action.consequences.forEach(move => rules.play(JSON.parse(JSON.stringify(move)), { local: action.local, transient: action.transient }));
462
+ }
526
463
  //# sourceMappingURL=gameReducer.js.map