@pretty-chitty/core 1.1.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.
- package/LICENSE.md +51 -0
- package/README.md +152 -0
- package/dist/0e0a96423fd742218c61.woff2 +0 -0
- package/dist/1e28c9f184923aacc181.woff +0 -0
- package/dist/37f3b2ddcbe588b2aaa5.jpg +0 -0
- package/dist/3f0fb9058a03e14ad2fa.jpg +0 -0
- package/dist/4482e08504d544757971.woff2 +0 -0
- package/dist/5212361bfd059a27e2da.woff2 +0 -0
- package/dist/699b459f21e39ca4b8df.woff2 +0 -0
- package/dist/7e339dfbea59fe54f2e3.png +0 -0
- package/dist/a3e6d4ebd8f859f0f1dc.woff +0 -0
- package/dist/b8b0d3bc0d26444e4a5a.woff2 +0 -0
- package/dist/bce9a6fcc5b3da9a086a.woff +0 -0
- package/dist/components/ActionLogDisplay.d.ts +4 -0
- package/dist/components/ActionLogDisplay.d.ts.map +1 -0
- package/dist/components/ActionLogDisplay.js +144 -0
- package/dist/components/ActionLogDisplay.js.map +1 -0
- package/dist/components/ActionLogHistory.d.ts +6 -0
- package/dist/components/ActionLogHistory.d.ts.map +1 -0
- package/dist/components/ActionLogHistory.js +81 -0
- package/dist/components/ActionLogHistory.js.map +1 -0
- package/dist/components/ActionLogHistoryDisplay.d.ts +2 -0
- package/dist/components/ActionLogHistoryDisplay.d.ts.map +1 -0
- package/dist/components/ActionLogHistoryDisplay.js +17 -0
- package/dist/components/ActionLogHistoryDisplay.js.map +1 -0
- package/dist/components/ActionLogSidebar.d.ts +2 -0
- package/dist/components/ActionLogSidebar.d.ts.map +1 -0
- package/dist/components/ActionLogSidebar.js +9 -0
- package/dist/components/ActionLogSidebar.js.map +1 -0
- package/dist/components/BottomBar.d.ts +2 -0
- package/dist/components/BottomBar.d.ts.map +1 -0
- package/dist/components/BottomBar.js +33 -0
- package/dist/components/BottomBar.js.map +1 -0
- package/dist/components/BottomBarBreak.d.ts +2 -0
- package/dist/components/BottomBarBreak.d.ts.map +1 -0
- package/dist/components/BottomBarBreak.js +8 -0
- package/dist/components/BottomBarBreak.js.map +1 -0
- package/dist/components/BottomBarButton.d.ts +16 -0
- package/dist/components/BottomBarButton.d.ts.map +1 -0
- package/dist/components/BottomBarButton.js +123 -0
- package/dist/components/BottomBarButton.js.map +1 -0
- package/dist/components/CanvasLibraryViewer.d.ts +8 -0
- package/dist/components/CanvasLibraryViewer.d.ts.map +1 -0
- package/dist/components/CanvasLibraryViewer.js +29 -0
- package/dist/components/CanvasLibraryViewer.js.map +1 -0
- package/dist/components/ChitLibraryViewer.d.ts +8 -0
- package/dist/components/ChitLibraryViewer.d.ts.map +1 -0
- package/dist/components/ChitLibraryViewer.js +101 -0
- package/dist/components/ChitLibraryViewer.js.map +1 -0
- package/dist/components/ClientTrustMatchViewer.d.ts +11 -0
- package/dist/components/ClientTrustMatchViewer.d.ts.map +1 -0
- package/dist/components/ClientTrustMatchViewer.js +53 -0
- package/dist/components/ClientTrustMatchViewer.js.map +1 -0
- package/dist/components/ContextGalleryDisplay.d.ts +4 -0
- package/dist/components/ContextGalleryDisplay.d.ts.map +1 -0
- package/dist/components/ContextGalleryDisplay.js +49 -0
- package/dist/components/ContextGalleryDisplay.js.map +1 -0
- package/dist/components/GalleryDisplay.d.ts +2 -0
- package/dist/components/GalleryDisplay.d.ts.map +1 -0
- package/dist/components/GalleryDisplay.js +42 -0
- package/dist/components/GalleryDisplay.js.map +1 -0
- package/dist/components/GalleryPlayground.d.ts +14 -0
- package/dist/components/GalleryPlayground.d.ts.map +1 -0
- package/dist/components/GalleryPlayground.js +36 -0
- package/dist/components/GalleryPlayground.js.map +1 -0
- package/dist/components/GalleryViewer.d.ts +48 -0
- package/dist/components/GalleryViewer.d.ts.map +1 -0
- package/dist/components/GalleryViewer.js +567 -0
- package/dist/components/GalleryViewer.js.map +1 -0
- package/dist/components/GameDesigner.d.ts +5 -0
- package/dist/components/GameDesigner.d.ts.map +1 -0
- package/dist/components/GameDesigner.js +14 -0
- package/dist/components/GameDesigner.js.map +1 -0
- package/dist/components/GameDialog.d.ts +7 -0
- package/dist/components/GameDialog.d.ts.map +1 -0
- package/dist/components/GameDialog.js +24 -0
- package/dist/components/GameDialog.js.map +1 -0
- package/dist/components/GameModalBackdrop.d.ts +10 -0
- package/dist/components/GameModalBackdrop.d.ts.map +1 -0
- package/dist/components/GameModalBackdrop.js +33 -0
- package/dist/components/GameModalBackdrop.js.map +1 -0
- package/dist/components/GameModalDialog.d.ts +11 -0
- package/dist/components/GameModalDialog.d.ts.map +1 -0
- package/dist/components/GameModalDialog.js +42 -0
- package/dist/components/GameModalDialog.js.map +1 -0
- package/dist/components/LiveButton.d.ts +4 -0
- package/dist/components/LiveButton.d.ts.map +1 -0
- package/dist/components/LiveButton.js +17 -0
- package/dist/components/LiveButton.js.map +1 -0
- package/dist/components/MatchEndDisplay.d.ts +2 -0
- package/dist/components/MatchEndDisplay.d.ts.map +1 -0
- package/dist/components/MatchEndDisplay.js +67 -0
- package/dist/components/MatchEndDisplay.js.map +1 -0
- package/dist/components/MatchViewer.d.ts +5 -0
- package/dist/components/MatchViewer.d.ts.map +1 -0
- package/dist/components/MatchViewer.js +59 -0
- package/dist/components/MatchViewer.js.map +1 -0
- package/dist/components/ObjectWithPropsEditor.d.ts +5 -0
- package/dist/components/ObjectWithPropsEditor.d.ts.map +1 -0
- package/dist/components/ObjectWithPropsEditor.js +88 -0
- package/dist/components/ObjectWithPropsEditor.js.map +1 -0
- package/dist/components/Panel/MultiPanel.d.ts +13 -0
- package/dist/components/Panel/MultiPanel.d.ts.map +1 -0
- package/dist/components/Panel/MultiPanel.js +196 -0
- package/dist/components/Panel/MultiPanel.js.map +1 -0
- package/dist/components/Panel/PanelContents.d.ts +27 -0
- package/dist/components/Panel/PanelContents.d.ts.map +1 -0
- package/dist/components/Panel/PanelContents.js +202 -0
- package/dist/components/Panel/PanelContents.js.map +1 -0
- package/dist/components/Panel/PanelTabStack.d.ts +9 -0
- package/dist/components/Panel/PanelTabStack.d.ts.map +1 -0
- package/dist/components/Panel/PanelTabStack.js +56 -0
- package/dist/components/Panel/PanelTabStack.js.map +1 -0
- package/dist/components/Panel/SinglePanel.d.ts +13 -0
- package/dist/components/Panel/SinglePanel.d.ts.map +1 -0
- package/dist/components/Panel/SinglePanel.js +44 -0
- package/dist/components/Panel/SinglePanel.js.map +1 -0
- package/dist/components/Panel/ViewerWrapper.d.ts +17 -0
- package/dist/components/Panel/ViewerWrapper.d.ts.map +1 -0
- package/dist/components/Panel/ViewerWrapper.js +70 -0
- package/dist/components/Panel/ViewerWrapper.js.map +1 -0
- package/dist/components/Panel/ViewerZoomControls.d.ts +8 -0
- package/dist/components/Panel/ViewerZoomControls.d.ts.map +1 -0
- package/dist/components/Panel/ViewerZoomControls.js +152 -0
- package/dist/components/Panel/ViewerZoomControls.js.map +1 -0
- package/dist/components/Panel/util.d.ts +3 -0
- package/dist/components/Panel/util.d.ts.map +1 -0
- package/dist/components/Panel/util.js +5 -0
- package/dist/components/Panel/util.js.map +1 -0
- package/dist/components/PanelSpark.d.ts +7 -0
- package/dist/components/PanelSpark.d.ts.map +1 -0
- package/dist/components/PanelSpark.js +84 -0
- package/dist/components/PanelSpark.js.map +1 -0
- package/dist/components/PersistentCanvas.d.ts +12 -0
- package/dist/components/PersistentCanvas.d.ts.map +1 -0
- package/dist/components/PersistentCanvas.js +44 -0
- package/dist/components/PersistentCanvas.js.map +1 -0
- package/dist/components/PlayerImage.d.ts +9 -0
- package/dist/components/PlayerImage.d.ts.map +1 -0
- package/dist/components/PlayerImage.js +21 -0
- package/dist/components/PlayerImage.js.map +1 -0
- package/dist/components/Playground.d.ts +9 -0
- package/dist/components/Playground.d.ts.map +1 -0
- package/dist/components/Playground.js +129 -0
- package/dist/components/Playground.js.map +1 -0
- package/dist/components/PromptControls.d.ts +4 -0
- package/dist/components/PromptControls.d.ts.map +1 -0
- package/dist/components/PromptControls.js +87 -0
- package/dist/components/PromptControls.js.map +1 -0
- package/dist/components/SelectableItemAndStage.d.ts +8 -0
- package/dist/components/SelectableItemAndStage.d.ts.map +1 -0
- package/dist/components/SelectableItemAndStage.js +16 -0
- package/dist/components/SelectableItemAndStage.js.map +1 -0
- package/dist/components/SettingsDisplay.d.ts +2 -0
- package/dist/components/SettingsDisplay.d.ts.map +1 -0
- package/dist/components/SettingsDisplay.js +62 -0
- package/dist/components/SettingsDisplay.js.map +1 -0
- package/dist/components/SparkLineChart.d.ts +21 -0
- package/dist/components/SparkLineChart.d.ts.map +1 -0
- package/dist/components/SparkLineChart.js +143 -0
- package/dist/components/SparkLineChart.js.map +1 -0
- package/dist/components/StageAndEditor.d.ts +5 -0
- package/dist/components/StageAndEditor.d.ts.map +1 -0
- package/dist/components/StageAndEditor.js +12 -0
- package/dist/components/StageAndEditor.js.map +1 -0
- package/dist/components/TimeControlBar.d.ts +5 -0
- package/dist/components/TimeControlBar.d.ts.map +1 -0
- package/dist/components/TimeControlBar.js +38 -0
- package/dist/components/TimeControlBar.js.map +1 -0
- package/dist/components/TokenizedMessage.d.ts +13 -0
- package/dist/components/TokenizedMessage.d.ts.map +1 -0
- package/dist/components/TokenizedMessage.js +102 -0
- package/dist/components/TokenizedMessage.js.map +1 -0
- package/dist/components/TopBar.d.ts +4 -0
- package/dist/components/TopBar.d.ts.map +1 -0
- package/dist/components/TopBar.js +47 -0
- package/dist/components/TopBar.js.map +1 -0
- package/dist/components/TopBarDropdown.d.ts +6 -0
- package/dist/components/TopBarDropdown.d.ts.map +1 -0
- package/dist/components/TopBarDropdown.js +69 -0
- package/dist/components/TopBarDropdown.js.map +1 -0
- package/dist/components/TopBarPlayers.d.ts +2 -0
- package/dist/components/TopBarPlayers.d.ts.map +1 -0
- package/dist/components/TopBarPlayers.js +70 -0
- package/dist/components/TopBarPlayers.js.map +1 -0
- package/dist/components/UpdatingCanvasImage.d.ts +7 -0
- package/dist/components/UpdatingCanvasImage.d.ts.map +1 -0
- package/dist/components/UpdatingCanvasImage.js +22 -0
- package/dist/components/UpdatingCanvasImage.js.map +1 -0
- package/dist/components/UpdatingCanvasViewer.d.ts +7 -0
- package/dist/components/UpdatingCanvasViewer.d.ts.map +1 -0
- package/dist/components/UpdatingCanvasViewer.js +50 -0
- package/dist/components/UpdatingCanvasViewer.js.map +1 -0
- package/dist/components/Viewer.d.ts +16 -0
- package/dist/components/Viewer.d.ts.map +1 -0
- package/dist/components/Viewer.js +289 -0
- package/dist/components/Viewer.js.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -0
- package/dist/e085acb5e467d8e85d21.woff +0 -0
- package/dist/e65dff62134b8879e792.woff +0 -0
- package/dist/game/Chit.d.ts +64 -0
- package/dist/game/Chit.d.ts.map +1 -0
- package/dist/game/Chit.js +524 -0
- package/dist/game/Chit.js.map +1 -0
- package/dist/game/ClientTimeState.d.ts +16 -0
- package/dist/game/ClientTimeState.d.ts.map +1 -0
- package/dist/game/ClientTimeState.js +38 -0
- package/dist/game/ClientTimeState.js.map +1 -0
- package/dist/game/ClockDetails.d.ts +9 -0
- package/dist/game/ClockDetails.d.ts.map +1 -0
- package/dist/game/ClockDetails.js +19 -0
- package/dist/game/ClockDetails.js.map +1 -0
- package/dist/game/Connection.d.ts +26 -0
- package/dist/game/Connection.d.ts.map +1 -0
- package/dist/game/Connection.js +99 -0
- package/dist/game/Connection.js.map +1 -0
- package/dist/game/ConnectionObject.d.ts +7 -0
- package/dist/game/ConnectionObject.d.ts.map +1 -0
- package/dist/game/ConnectionObject.js +16 -0
- package/dist/game/ConnectionObject.js.map +1 -0
- package/dist/game/ConnectionTransport.d.ts +17 -0
- package/dist/game/ConnectionTransport.d.ts.map +1 -0
- package/dist/game/ConnectionTransport.js +39 -0
- package/dist/game/ConnectionTransport.js.map +1 -0
- package/dist/game/DropdownChit.d.ts +7 -0
- package/dist/game/DropdownChit.d.ts.map +1 -0
- package/dist/game/DropdownChit.js +29 -0
- package/dist/game/DropdownChit.js.map +1 -0
- package/dist/game/GalleryItemChitChildrenSource.d.ts +12 -0
- package/dist/game/GalleryItemChitChildrenSource.d.ts.map +1 -0
- package/dist/game/GalleryItemChitChildrenSource.js +25 -0
- package/dist/game/GalleryItemChitChildrenSource.js.map +1 -0
- package/dist/game/GalleryItemRawSource.d.ts +9 -0
- package/dist/game/GalleryItemRawSource.d.ts.map +1 -0
- package/dist/game/GalleryItemRawSource.js +13 -0
- package/dist/game/GalleryItemRawSource.js.map +1 -0
- package/dist/game/Game.d.ts +51 -0
- package/dist/game/Game.d.ts.map +1 -0
- package/dist/game/Game.js +2 -0
- package/dist/game/Game.js.map +1 -0
- package/dist/game/GameBagChit.d.ts +16 -0
- package/dist/game/GameBagChit.d.ts.map +1 -0
- package/dist/game/GameBagChit.js +51 -0
- package/dist/game/GameBagChit.js.map +1 -0
- package/dist/game/GameButton.d.ts +30 -0
- package/dist/game/GameButton.d.ts.map +1 -0
- package/dist/game/GameButton.js +115 -0
- package/dist/game/GameButton.js.map +1 -0
- package/dist/game/GameDeckChit.d.ts +23 -0
- package/dist/game/GameDeckChit.d.ts.map +1 -0
- package/dist/game/GameDeckChit.js +79 -0
- package/dist/game/GameDeckChit.js.map +1 -0
- package/dist/game/GameTheme.d.ts +75 -0
- package/dist/game/GameTheme.d.ts.map +1 -0
- package/dist/game/GameTheme.js +103 -0
- package/dist/game/GameTheme.js.map +1 -0
- package/dist/game/Match.d.ts +34 -0
- package/dist/game/Match.d.ts.map +1 -0
- package/dist/game/Match.js +151 -0
- package/dist/game/Match.js.map +1 -0
- package/dist/game/MatchConnection.d.ts +8 -0
- package/dist/game/MatchConnection.d.ts.map +1 -0
- package/dist/game/MatchConnection.js +6 -0
- package/dist/game/MatchConnection.js.map +1 -0
- package/dist/game/MatchStorage.d.ts +17 -0
- package/dist/game/MatchStorage.d.ts.map +1 -0
- package/dist/game/MatchStorage.js +32 -0
- package/dist/game/MatchStorage.js.map +1 -0
- package/dist/game/ModalState.d.ts +9 -0
- package/dist/game/ModalState.d.ts.map +1 -0
- package/dist/game/ModalState.js +27 -0
- package/dist/game/ModalState.js.map +1 -0
- package/dist/game/OrderedOutlet.d.ts +50 -0
- package/dist/game/OrderedOutlet.d.ts.map +1 -0
- package/dist/game/OrderedOutlet.js +164 -0
- package/dist/game/OrderedOutlet.js.map +1 -0
- package/dist/game/Pick.d.ts +26 -0
- package/dist/game/Pick.d.ts.map +1 -0
- package/dist/game/Pick.js +239 -0
- package/dist/game/Pick.js.map +1 -0
- package/dist/game/PlayerChit.d.ts +16 -0
- package/dist/game/PlayerChit.d.ts.map +1 -0
- package/dist/game/PlayerChit.js +56 -0
- package/dist/game/PlayerChit.js.map +1 -0
- package/dist/game/PlayerInfo.d.ts +12 -0
- package/dist/game/PlayerInfo.d.ts.map +1 -0
- package/dist/game/PlayerInfo.js +20 -0
- package/dist/game/PlayerInfo.js.map +1 -0
- package/dist/game/PlayerPromptStatusChit.d.ts +5 -0
- package/dist/game/PlayerPromptStatusChit.d.ts.map +1 -0
- package/dist/game/PlayerPromptStatusChit.js +35 -0
- package/dist/game/PlayerPromptStatusChit.js.map +1 -0
- package/dist/game/Prompt.d.ts +94 -0
- package/dist/game/Prompt.d.ts.map +1 -0
- package/dist/game/Prompt.js +229 -0
- package/dist/game/Prompt.js.map +1 -0
- package/dist/game/RootChit.d.ts +15 -0
- package/dist/game/RootChit.d.ts.map +1 -0
- package/dist/game/RootChit.js +62 -0
- package/dist/game/RootChit.js.map +1 -0
- package/dist/game/SparkChit.d.ts +27 -0
- package/dist/game/SparkChit.d.ts.map +1 -0
- package/dist/game/SparkChit.js +97 -0
- package/dist/game/SparkChit.js.map +1 -0
- package/dist/game/StaticChitTypeRegistry.d.ts +5 -0
- package/dist/game/StaticChitTypeRegistry.d.ts.map +1 -0
- package/dist/game/StaticChitTypeRegistry.js +3 -0
- package/dist/game/StaticChitTypeRegistry.js.map +1 -0
- package/dist/game/Turn.d.ts +169 -0
- package/dist/game/Turn.d.ts.map +1 -0
- package/dist/game/Turn.js +1031 -0
- package/dist/game/Turn.js.map +1 -0
- package/dist/game/TurnState.d.ts +30 -0
- package/dist/game/TurnState.d.ts.map +1 -0
- package/dist/game/TurnState.js +170 -0
- package/dist/game/TurnState.js.map +1 -0
- package/dist/game/clientTransport/ClientPrompts.d.ts +23 -0
- package/dist/game/clientTransport/ClientPrompts.d.ts.map +1 -0
- package/dist/game/clientTransport/ClientPrompts.js +85 -0
- package/dist/game/clientTransport/ClientPrompts.js.map +1 -0
- package/dist/game/clientTransport/ClientStatus.d.ts +19 -0
- package/dist/game/clientTransport/ClientStatus.d.ts.map +1 -0
- package/dist/game/clientTransport/ClientStatus.js +25 -0
- package/dist/game/clientTransport/ClientStatus.js.map +1 -0
- package/dist/game/clientTransport/ClientTime.d.ts +42 -0
- package/dist/game/clientTransport/ClientTime.d.ts.map +1 -0
- package/dist/game/clientTransport/ClientTime.js +197 -0
- package/dist/game/clientTransport/ClientTime.js.map +1 -0
- package/dist/game/index.d.ts +1 -0
- package/dist/game/index.d.ts.map +1 -0
- package/dist/game/index.js +2 -0
- package/dist/game/index.js.map +1 -0
- package/dist/game/serverTransport/ServerPrompts.d.ts +17 -0
- package/dist/game/serverTransport/ServerPrompts.d.ts.map +1 -0
- package/dist/game/serverTransport/ServerPrompts.js +51 -0
- package/dist/game/serverTransport/ServerPrompts.js.map +1 -0
- package/dist/game/serverTransport/ServerStatus.d.ts +12 -0
- package/dist/game/serverTransport/ServerStatus.d.ts.map +1 -0
- package/dist/game/serverTransport/ServerStatus.js +16 -0
- package/dist/game/serverTransport/ServerStatus.js.map +1 -0
- package/dist/game/serverTransport/ServerTime.d.ts +39 -0
- package/dist/game/serverTransport/ServerTime.d.ts.map +1 -0
- package/dist/game/serverTransport/ServerTime.js +57 -0
- package/dist/game/serverTransport/ServerTime.js.map +1 -0
- package/dist/hooks/useChits.d.ts +4 -0
- package/dist/hooks/useChits.d.ts.map +1 -0
- package/dist/hooks/useChits.js +24 -0
- package/dist/hooks/useChits.js.map +1 -0
- package/dist/hooks/useConnection.d.ts +8 -0
- package/dist/hooks/useConnection.d.ts.map +1 -0
- package/dist/hooks/useConnection.js +14 -0
- package/dist/hooks/useConnection.js.map +1 -0
- package/dist/hooks/useEventChannelState.d.ts +4 -0
- package/dist/hooks/useEventChannelState.d.ts.map +1 -0
- package/dist/hooks/useEventChannelState.js +25 -0
- package/dist/hooks/useEventChannelState.js.map +1 -0
- package/dist/hooks/useGame.d.ts +8 -0
- package/dist/hooks/useGame.d.ts.map +1 -0
- package/dist/hooks/useGame.js +14 -0
- package/dist/hooks/useGame.js.map +1 -0
- package/dist/hooks/useGameTheme.d.ts +8 -0
- package/dist/hooks/useGameTheme.d.ts.map +1 -0
- package/dist/hooks/useGameTheme.js +11 -0
- package/dist/hooks/useGameTheme.js.map +1 -0
- package/dist/hooks/useModalState.d.ts +7 -0
- package/dist/hooks/useModalState.d.ts.map +1 -0
- package/dist/hooks/useModalState.js +12 -0
- package/dist/hooks/useModalState.js.map +1 -0
- package/dist/hooks/usePanelPositioning.d.ts +22 -0
- package/dist/hooks/usePanelPositioning.d.ts.map +1 -0
- package/dist/hooks/usePanelPositioning.js +10 -0
- package/dist/hooks/usePanelPositioning.js.map +1 -0
- package/dist/hooks/usePanelScale.d.ts +7 -0
- package/dist/hooks/usePanelScale.d.ts.map +1 -0
- package/dist/hooks/usePanelScale.js +22 -0
- package/dist/hooks/usePanelScale.js.map +1 -0
- package/dist/hooks/usePanelStates.d.ts +9 -0
- package/dist/hooks/usePanelStates.d.ts.map +1 -0
- package/dist/hooks/usePanelStates.js +19 -0
- package/dist/hooks/usePanelStates.js.map +1 -0
- package/dist/hooks/usePlayer.d.ts +7 -0
- package/dist/hooks/usePlayer.d.ts.map +1 -0
- package/dist/hooks/usePlayer.js +14 -0
- package/dist/hooks/usePlayer.js.map +1 -0
- package/dist/hooks/useSmartDebouncedState.d.ts +27 -0
- package/dist/hooks/useSmartDebouncedState.d.ts.map +1 -0
- package/dist/hooks/useSmartDebouncedState.js +109 -0
- package/dist/hooks/useSmartDebouncedState.js.map +1 -0
- package/dist/hooks/useTimeController.d.ts +22 -0
- package/dist/hooks/useTimeController.d.ts.map +1 -0
- package/dist/hooks/useTimeController.js +89 -0
- package/dist/hooks/useTimeController.js.map +1 -0
- package/dist/hooks/useTokenMap.d.ts +5 -0
- package/dist/hooks/useTokenMap.d.ts.map +1 -0
- package/dist/hooks/useTokenMap.js +16 -0
- package/dist/hooks/useTokenMap.js.map +1 -0
- package/dist/hooks/useWebGlRenderer.d.ts +34 -0
- package/dist/hooks/useWebGlRenderer.d.ts.map +1 -0
- package/dist/hooks/useWebGlRenderer.js +167 -0
- package/dist/hooks/useWebGlRenderer.js.map +1 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.html +12 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/pretty-chitty.js +190767 -0
- package/dist/pretty-chitty.js.map +1 -0
- package/dist/rendering/CameraSpec.d.ts +22 -0
- package/dist/rendering/CameraSpec.d.ts.map +1 -0
- package/dist/rendering/CameraSpec.js +25 -0
- package/dist/rendering/CameraSpec.js.map +1 -0
- package/dist/rendering/CameraWrapperPerspective.d.ts +44 -0
- package/dist/rendering/CameraWrapperPerspective.d.ts.map +1 -0
- package/dist/rendering/CameraWrapperPerspective.js +481 -0
- package/dist/rendering/CameraWrapperPerspective.js.map +1 -0
- package/dist/rendering/ChitGalleryItemInstance.d.ts +31 -0
- package/dist/rendering/ChitGalleryItemInstance.d.ts.map +1 -0
- package/dist/rendering/ChitGalleryItemInstance.js +75 -0
- package/dist/rendering/ChitGalleryItemInstance.js.map +1 -0
- package/dist/rendering/ChitRenderInstance.d.ts +104 -0
- package/dist/rendering/ChitRenderInstance.d.ts.map +1 -0
- package/dist/rendering/ChitRenderInstance.js +902 -0
- package/dist/rendering/ChitRenderInstance.js.map +1 -0
- package/dist/rendering/ChitRenderSpec.d.ts +80 -0
- package/dist/rendering/ChitRenderSpec.d.ts.map +1 -0
- package/dist/rendering/ChitRenderSpec.js +152 -0
- package/dist/rendering/ChitRenderSpec.js.map +1 -0
- package/dist/rendering/HighlightSpec.d.ts +6 -0
- package/dist/rendering/HighlightSpec.d.ts.map +1 -0
- package/dist/rendering/HighlightSpec.js +6 -0
- package/dist/rendering/HighlightSpec.js.map +1 -0
- package/dist/rendering/LightSpec.d.ts +17 -0
- package/dist/rendering/LightSpec.d.ts.map +1 -0
- package/dist/rendering/LightSpec.js +37 -0
- package/dist/rendering/LightSpec.js.map +1 -0
- package/dist/rendering/LightWrapper.d.ts +19 -0
- package/dist/rendering/LightWrapper.d.ts.map +1 -0
- package/dist/rendering/LightWrapper.js +114 -0
- package/dist/rendering/LightWrapper.js.map +1 -0
- package/dist/rendering/RootChitRenderInstance.d.ts +81 -0
- package/dist/rendering/RootChitRenderInstance.d.ts.map +1 -0
- package/dist/rendering/RootChitRenderInstance.js +372 -0
- package/dist/rendering/RootChitRenderInstance.js.map +1 -0
- package/dist/rendering/Splay.d.ts +23 -0
- package/dist/rendering/Splay.d.ts.map +1 -0
- package/dist/rendering/Splay.js +89 -0
- package/dist/rendering/Splay.js.map +1 -0
- package/dist/rendering/SplayCounter.d.ts +19 -0
- package/dist/rendering/SplayCounter.d.ts.map +1 -0
- package/dist/rendering/SplayCounter.js +18 -0
- package/dist/rendering/SplayCounter.js.map +1 -0
- package/dist/rendering/TextureReferenceCounter.d.ts +12 -0
- package/dist/rendering/TextureReferenceCounter.d.ts.map +1 -0
- package/dist/rendering/TextureReferenceCounter.js +76 -0
- package/dist/rendering/TextureReferenceCounter.js.map +1 -0
- package/dist/rendering/index.d.ts +1 -0
- package/dist/rendering/index.d.ts.map +1 -0
- package/dist/rendering/index.js +2 -0
- package/dist/rendering/index.js.map +1 -0
- package/dist/rendering/outline/DepthVisualizationPass.d.ts +12 -0
- package/dist/rendering/outline/DepthVisualizationPass.d.ts.map +1 -0
- package/dist/rendering/outline/DepthVisualizationPass.js +93 -0
- package/dist/rendering/outline/DepthVisualizationPass.js.map +1 -0
- package/dist/rendering/outline/EffectComposer.d.ts +24 -0
- package/dist/rendering/outline/EffectComposer.d.ts.map +1 -0
- package/dist/rendering/outline/EffectComposer.js +118 -0
- package/dist/rendering/outline/EffectComposer.js.map +1 -0
- package/dist/rendering/outline/FullScreenQuad.d.ts +12 -0
- package/dist/rendering/outline/FullScreenQuad.d.ts.map +1 -0
- package/dist/rendering/outline/FullScreenQuad.js +21 -0
- package/dist/rendering/outline/FullScreenQuad.js.map +1 -0
- package/dist/rendering/outline/IDBasedOutlinePass.d.ts +49 -0
- package/dist/rendering/outline/IDBasedOutlinePass.d.ts.map +1 -0
- package/dist/rendering/outline/IDBasedOutlinePass.js +597 -0
- package/dist/rendering/outline/IDBasedOutlinePass.js.map +1 -0
- package/dist/rendering/outline/OutputPass.d.ts +13 -0
- package/dist/rendering/outline/OutputPass.d.ts.map +1 -0
- package/dist/rendering/outline/OutputPass.js +57 -0
- package/dist/rendering/outline/OutputPass.js.map +1 -0
- package/dist/rendering/outline/RenderPass.d.ts +13 -0
- package/dist/rendering/outline/RenderPass.d.ts.map +1 -0
- package/dist/rendering/outline/RenderPass.js +54 -0
- package/dist/rendering/outline/RenderPass.js.map +1 -0
- package/dist/rendering/outline/SceneWrapper.d.ts +39 -0
- package/dist/rendering/outline/SceneWrapper.d.ts.map +1 -0
- package/dist/rendering/outline/SceneWrapper.js +522 -0
- package/dist/rendering/outline/SceneWrapper.js.map +1 -0
- package/dist/rendering/outline/ShaderPass.d.ts +12 -0
- package/dist/rendering/outline/ShaderPass.d.ts.map +1 -0
- package/dist/rendering/outline/ShaderPass.js +43 -0
- package/dist/rendering/outline/ShaderPass.js.map +1 -0
- package/dist/rendering/outline/index.d.ts +8 -0
- package/dist/rendering/outline/index.d.ts.map +1 -0
- package/dist/rendering/outline/index.js +8 -0
- package/dist/rendering/outline/index.js.map +1 -0
- package/dist/rendering/outline/passes/DebugIDMappingPass.d.ts +20 -0
- package/dist/rendering/outline/passes/DebugIDMappingPass.d.ts.map +1 -0
- package/dist/rendering/outline/passes/DebugIDMappingPass.js +131 -0
- package/dist/rendering/outline/passes/DebugIDMappingPass.js.map +1 -0
- package/dist/rendering/outline/passes/DepthOcclusionPass.d.ts +24 -0
- package/dist/rendering/outline/passes/DepthOcclusionPass.d.ts.map +1 -0
- package/dist/rendering/outline/passes/DepthOcclusionPass.js +95 -0
- package/dist/rendering/outline/passes/DepthOcclusionPass.js.map +1 -0
- package/dist/rendering/outline/passes/InterMeshEdgeDetectionPass.d.ts +32 -0
- package/dist/rendering/outline/passes/InterMeshEdgeDetectionPass.d.ts.map +1 -0
- package/dist/rendering/outline/passes/InterMeshEdgeDetectionPass.js +208 -0
- package/dist/rendering/outline/passes/InterMeshEdgeDetectionPass.js.map +1 -0
- package/dist/rendering/outline/shaders.d.ts +20 -0
- package/dist/rendering/outline/shaders.d.ts.map +1 -0
- package/dist/rendering/outline/shaders.js +103 -0
- package/dist/rendering/outline/shaders.js.map +1 -0
- package/dist/rendering/outline/types.d.ts +14 -0
- package/dist/rendering/outline/types.d.ts.map +1 -0
- package/dist/rendering/outline/types.js +16 -0
- package/dist/rendering/outline/types.js.map +1 -0
- package/dist/utilities/Annotations.d.ts +60 -0
- package/dist/utilities/Annotations.d.ts.map +1 -0
- package/dist/utilities/Annotations.js +171 -0
- package/dist/utilities/Annotations.js.map +1 -0
- package/dist/utilities/BaseTable.d.ts +8 -0
- package/dist/utilities/BaseTable.d.ts.map +1 -0
- package/dist/utilities/BaseTable.js +35 -0
- package/dist/utilities/BaseTable.js.map +1 -0
- package/dist/utilities/BboxUtils.d.ts +3 -0
- package/dist/utilities/BboxUtils.d.ts.map +1 -0
- package/dist/utilities/BboxUtils.js +19 -0
- package/dist/utilities/BboxUtils.js.map +1 -0
- package/dist/utilities/CanvasStack/CanvasOperations.d.ts +140 -0
- package/dist/utilities/CanvasStack/CanvasOperations.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/CanvasOperations.js +403 -0
- package/dist/utilities/CanvasStack/CanvasOperations.js.map +1 -0
- package/dist/utilities/CanvasStack/CanvasStack.d.ts +42 -0
- package/dist/utilities/CanvasStack/CanvasStack.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/CanvasStack.js +128 -0
- package/dist/utilities/CanvasStack/CanvasStack.js.map +1 -0
- package/dist/utilities/CanvasStack/IconCanvas.d.ts +10 -0
- package/dist/utilities/CanvasStack/IconCanvas.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/IconCanvas.js +15 -0
- package/dist/utilities/CanvasStack/IconCanvas.js.map +1 -0
- package/dist/utilities/CanvasStack/ImageCache.d.ts +8 -0
- package/dist/utilities/CanvasStack/ImageCache.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/ImageCache.js +29 -0
- package/dist/utilities/CanvasStack/ImageCache.js.map +1 -0
- package/dist/utilities/CanvasStack/ImageColorOverlayer.d.ts +2 -0
- package/dist/utilities/CanvasStack/ImageColorOverlayer.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/ImageColorOverlayer.js +31 -0
- package/dist/utilities/CanvasStack/ImageColorOverlayer.js.map +1 -0
- package/dist/utilities/CanvasStack/PlayerCanvas.d.ts +10 -0
- package/dist/utilities/CanvasStack/PlayerCanvas.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/PlayerCanvas.js +15 -0
- package/dist/utilities/CanvasStack/PlayerCanvas.js.map +1 -0
- package/dist/utilities/CanvasStack/ReactCanvas.d.ts +133 -0
- package/dist/utilities/CanvasStack/ReactCanvas.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/ReactCanvas.js +161 -0
- package/dist/utilities/CanvasStack/ReactCanvas.js.map +1 -0
- package/dist/utilities/CanvasStack/RichTextRenderer.d.ts +63 -0
- package/dist/utilities/CanvasStack/RichTextRenderer.d.ts.map +1 -0
- package/dist/utilities/CanvasStack/RichTextRenderer.js +523 -0
- package/dist/utilities/CanvasStack/RichTextRenderer.js.map +1 -0
- package/dist/utilities/CardMesh.d.ts +17 -0
- package/dist/utilities/CardMesh.d.ts.map +1 -0
- package/dist/utilities/CardMesh.js +44 -0
- package/dist/utilities/CardMesh.js.map +1 -0
- package/dist/utilities/Dice.d.ts +24 -0
- package/dist/utilities/Dice.d.ts.map +1 -0
- package/dist/utilities/Dice.js +148 -0
- package/dist/utilities/Dice.js.map +1 -0
- package/dist/utilities/EventChannel.d.ts +13 -0
- package/dist/utilities/EventChannel.d.ts.map +1 -0
- package/dist/utilities/EventChannel.js +47 -0
- package/dist/utilities/EventChannel.js.map +1 -0
- package/dist/utilities/GalleryItemConversion.d.ts +4 -0
- package/dist/utilities/GalleryItemConversion.d.ts.map +1 -0
- package/dist/utilities/GalleryItemConversion.js +28 -0
- package/dist/utilities/GalleryItemConversion.js.map +1 -0
- package/dist/utilities/IUpdatingCanvas.d.ts +19 -0
- package/dist/utilities/IUpdatingCanvas.d.ts.map +1 -0
- package/dist/utilities/IUpdatingCanvas.js +2 -0
- package/dist/utilities/IUpdatingCanvas.js.map +1 -0
- package/dist/utilities/LayoutHelper.d.ts +34 -0
- package/dist/utilities/LayoutHelper.d.ts.map +1 -0
- package/dist/utilities/LayoutHelper.js +451 -0
- package/dist/utilities/LayoutHelper.js.map +1 -0
- package/dist/utilities/ObjectWithProps.d.ts +5 -0
- package/dist/utilities/ObjectWithProps.d.ts.map +1 -0
- package/dist/utilities/ObjectWithProps.js +65 -0
- package/dist/utilities/ObjectWithProps.js.map +1 -0
- package/dist/utilities/OutlineCanvas.d.ts +12 -0
- package/dist/utilities/OutlineCanvas.d.ts.map +1 -0
- package/dist/utilities/OutlineCanvas.js +31 -0
- package/dist/utilities/OutlineCanvas.js.map +1 -0
- package/dist/utilities/OutlineGeometry.d.ts +3 -0
- package/dist/utilities/OutlineGeometry.d.ts.map +1 -0
- package/dist/utilities/OutlineGeometry.js +57 -0
- package/dist/utilities/OutlineGeometry.js.map +1 -0
- package/dist/utilities/ParameterizedCanvas.d.ts +13 -0
- package/dist/utilities/ParameterizedCanvas.d.ts.map +1 -0
- package/dist/utilities/ParameterizedCanvas.js +85 -0
- package/dist/utilities/ParameterizedCanvas.js.map +1 -0
- package/dist/utilities/RequestSharedAnimationFrame.d.ts +2 -0
- package/dist/utilities/RequestSharedAnimationFrame.d.ts.map +1 -0
- package/dist/utilities/RequestSharedAnimationFrame.js +16 -0
- package/dist/utilities/RequestSharedAnimationFrame.js.map +1 -0
- package/dist/utilities/StaticImage.d.ts +19 -0
- package/dist/utilities/StaticImage.d.ts.map +1 -0
- package/dist/utilities/StaticImage.js +38 -0
- package/dist/utilities/StaticImage.js.map +1 -0
- package/dist/utilities/SvgExtruder.d.ts +20 -0
- package/dist/utilities/SvgExtruder.d.ts.map +1 -0
- package/dist/utilities/SvgExtruder.js +238 -0
- package/dist/utilities/SvgExtruder.js.map +1 -0
- package/dist/utilities/ThreeDisposer.d.ts +11 -0
- package/dist/utilities/ThreeDisposer.d.ts.map +1 -0
- package/dist/utilities/ThreeDisposer.js +53 -0
- package/dist/utilities/ThreeDisposer.js.map +1 -0
- package/dist/utilities/zIndex.d.ts +14 -0
- package/dist/utilities/zIndex.d.ts.map +1 -0
- package/dist/utilities/zIndex.js +14 -0
- package/dist/utilities/zIndex.js.map +1 -0
- package/package.json +138 -0
- package/src/library/assets/checker.svg +4 -0
- package/src/library/assets/cutout.svg +22 -0
- package/src/library/components/ActionLogDisplay.tsx +183 -0
- package/src/library/components/ActionLogHistory.tsx +127 -0
- package/src/library/components/ActionLogHistoryDisplay.tsx +21 -0
- package/src/library/components/ActionLogSidebar.tsx +17 -0
- package/src/library/components/BottomBar.tsx +78 -0
- package/src/library/components/BottomBarBreak.tsx +12 -0
- package/src/library/components/BottomBarButton.tsx +181 -0
- package/src/library/components/CanvasLibraryViewer.tsx +86 -0
- package/src/library/components/ChitLibraryViewer.tsx +168 -0
- package/src/library/components/ClientTrustMatchViewer.tsx +83 -0
- package/src/library/components/ContextGalleryDisplay.tsx +72 -0
- package/src/library/components/GalleryDisplay.tsx +57 -0
- package/src/library/components/GalleryPlayground.tsx +50 -0
- package/src/library/components/GalleryViewer.tsx +773 -0
- package/src/library/components/GameDesigner.tsx +39 -0
- package/src/library/components/GameDialog.tsx +43 -0
- package/src/library/components/GameModalBackdrop.tsx +47 -0
- package/src/library/components/GameModalDialog.tsx +77 -0
- package/src/library/components/LiveButton.tsx +26 -0
- package/src/library/components/MatchEndDisplay.tsx +120 -0
- package/src/library/components/MatchViewer.tsx +111 -0
- package/src/library/components/ObjectWithPropsEditor.tsx +169 -0
- package/src/library/components/Panel/MultiPanel.tsx +276 -0
- package/src/library/components/Panel/PanelContents.tsx +359 -0
- package/src/library/components/Panel/PanelTabStack.tsx +103 -0
- package/src/library/components/Panel/SinglePanel.tsx +75 -0
- package/src/library/components/Panel/ViewerWrapper.tsx +131 -0
- package/src/library/components/Panel/ViewerZoomControls.tsx +216 -0
- package/src/library/components/Panel/util.ts +7 -0
- package/src/library/components/PanelSpark.tsx +112 -0
- package/src/library/components/PersistentCanvas.tsx +81 -0
- package/src/library/components/PlayerImage.tsx +40 -0
- package/src/library/components/Playground.tsx +285 -0
- package/src/library/components/PromptControls.tsx +132 -0
- package/src/library/components/SelectableItemAndStage.tsx +49 -0
- package/src/library/components/SettingsDisplay.tsx +142 -0
- package/src/library/components/SparkLineChart.tsx +307 -0
- package/src/library/components/StageAndEditor.tsx +28 -0
- package/src/library/components/TimeControlBar.tsx +71 -0
- package/src/library/components/TokenizedMessage.tsx +206 -0
- package/src/library/components/TopBar.tsx +90 -0
- package/src/library/components/TopBarDropdown.tsx +94 -0
- package/src/library/components/TopBarPlayers.tsx +163 -0
- package/src/library/components/UpdatingCanvasImage.tsx +25 -0
- package/src/library/components/UpdatingCanvasViewer.tsx +62 -0
- package/src/library/components/Viewer.tsx +360 -0
- package/src/library/components/index.ts +0 -0
- package/src/library/game/Chit.test.ts +66 -0
- package/src/library/game/Chit.ts +575 -0
- package/src/library/game/ClientTimeState.ts +42 -0
- package/src/library/game/ClockDetails.ts +24 -0
- package/src/library/game/Connection.test.ts +50 -0
- package/src/library/game/Connection.ts +122 -0
- package/src/library/game/ConnectionObject.ts +13 -0
- package/src/library/game/ConnectionTransport.ts +52 -0
- package/src/library/game/DropdownChit.tsx +17 -0
- package/src/library/game/GalleryItemChitChildrenSource.ts +31 -0
- package/src/library/game/GalleryItemRawSource.ts +15 -0
- package/src/library/game/Game.ts +55 -0
- package/src/library/game/GameBagChit.ts +42 -0
- package/src/library/game/GameButton.ts +127 -0
- package/src/library/game/GameDeckChit.ts +77 -0
- package/src/library/game/GameTheme.ts +122 -0
- package/src/library/game/Match.ts +187 -0
- package/src/library/game/MatchConnection.ts +5 -0
- package/src/library/game/MatchStorage.ts +51 -0
- package/src/library/game/ModalState.ts +29 -0
- package/src/library/game/OrderedOutlet.ts +198 -0
- package/src/library/game/Pick.ts +314 -0
- package/src/library/game/PlayerChit.ts +43 -0
- package/src/library/game/PlayerInfo.ts +30 -0
- package/src/library/game/PlayerPromptStatusChit.ts +20 -0
- package/src/library/game/Prompt.ts +292 -0
- package/src/library/game/RootChit.ts +54 -0
- package/src/library/game/SparkChit.ts +97 -0
- package/src/library/game/StaticChitTypeRegistry.ts +3 -0
- package/src/library/game/Turn.test.ts +611 -0
- package/src/library/game/Turn.ts +1249 -0
- package/src/library/game/TurnState.ts +187 -0
- package/src/library/game/clientTransport/ClientPrompts.ts +102 -0
- package/src/library/game/clientTransport/ClientStatus.ts +36 -0
- package/src/library/game/clientTransport/ClientTime.ts +256 -0
- package/src/library/game/index.ts +0 -0
- package/src/library/game/serverTransport/ServerPrompts.ts +76 -0
- package/src/library/game/serverTransport/ServerStatus.ts +31 -0
- package/src/library/game/serverTransport/ServerTime.ts +74 -0
- package/src/library/hooks/useChits.ts +32 -0
- package/src/library/hooks/useConnection.tsx +16 -0
- package/src/library/hooks/useEventChannelState.ts +33 -0
- package/src/library/hooks/useGame.tsx +16 -0
- package/src/library/hooks/useGameTheme.tsx +12 -0
- package/src/library/hooks/useModalState.tsx +13 -0
- package/src/library/hooks/usePanelPositioning.tsx +31 -0
- package/src/library/hooks/usePanelScale.tsx +23 -0
- package/src/library/hooks/usePanelStates.ts +30 -0
- package/src/library/hooks/usePlayer.tsx +15 -0
- package/src/library/hooks/useSmartDebouncedState.ts +161 -0
- package/src/library/hooks/useTimeController.tsx +108 -0
- package/src/library/hooks/useTokenMap.ts +20 -0
- package/src/library/hooks/useWebGlRenderer.tsx +227 -0
- package/src/library/index.ts +116 -0
- package/src/library/rendering/CameraSpec.ts +25 -0
- package/src/library/rendering/CameraWrapperPerspective.ts +612 -0
- package/src/library/rendering/ChitGalleryItemInstance.ts +108 -0
- package/src/library/rendering/ChitRenderInstance.ts +1141 -0
- package/src/library/rendering/ChitRenderSpec.ts +213 -0
- package/src/library/rendering/HighlightSpec.ts +5 -0
- package/src/library/rendering/LightSpec.ts +41 -0
- package/src/library/rendering/LightWrapper.ts +152 -0
- package/src/library/rendering/RootChitRenderInstance.ts +460 -0
- package/src/library/rendering/Splay.ts +118 -0
- package/src/library/rendering/SplayCounter.tsx +37 -0
- package/src/library/rendering/TextureReferenceCounter.ts +86 -0
- package/src/library/rendering/index.ts +0 -0
- package/src/library/rendering/outline/DepthVisualizationPass.ts +117 -0
- package/src/library/rendering/outline/EffectComposer.ts +187 -0
- package/src/library/rendering/outline/FullScreenQuad.ts +32 -0
- package/src/library/rendering/outline/IDBasedOutlinePass.ts +741 -0
- package/src/library/rendering/outline/OutputPass.ts +88 -0
- package/src/library/rendering/outline/RenderPass.ts +72 -0
- package/src/library/rendering/outline/SceneWrapper.ts +617 -0
- package/src/library/rendering/outline/ShaderPass.ts +50 -0
- package/src/library/rendering/outline/index.ts +8 -0
- package/src/library/rendering/outline/passes/DebugIDMappingPass.ts +154 -0
- package/src/library/rendering/outline/passes/DepthOcclusionPass.ts +106 -0
- package/src/library/rendering/outline/passes/InterMeshEdgeDetectionPass.ts +244 -0
- package/src/library/rendering/outline/shaders.ts +110 -0
- package/src/library/rendering/outline/types.ts +25 -0
- package/src/library/utilities/Annotations.ts +188 -0
- package/src/library/utilities/BaseTable.tsx +58 -0
- package/src/library/utilities/BboxUtils.ts +23 -0
- package/src/library/utilities/CanvasStack/CanvasOperations.tsx +630 -0
- package/src/library/utilities/CanvasStack/CanvasStack.ts +191 -0
- package/src/library/utilities/CanvasStack/IconCanvas.tsx +17 -0
- package/src/library/utilities/CanvasStack/ImageCache.ts +38 -0
- package/src/library/utilities/CanvasStack/ImageColorOverlayer.ts +36 -0
- package/src/library/utilities/CanvasStack/PlayerCanvas.tsx +17 -0
- package/src/library/utilities/CanvasStack/ReactCanvas.tsx +293 -0
- package/src/library/utilities/CanvasStack/RichTextRenderer.ts +719 -0
- package/src/library/utilities/CardMesh.ts +55 -0
- package/src/library/utilities/Dice.tsx +183 -0
- package/src/library/utilities/EventChannel.ts +52 -0
- package/src/library/utilities/GalleryItemConversion.ts +30 -0
- package/src/library/utilities/IUpdatingCanvas.ts +14 -0
- package/src/library/utilities/LayoutHelper.ts +586 -0
- package/src/library/utilities/ObjectWithProps.ts +52 -0
- package/src/library/utilities/OutlineCanvas.tsx +45 -0
- package/src/library/utilities/OutlineGeometry.ts +69 -0
- package/src/library/utilities/ParameterizedCanvas.ts +78 -0
- package/src/library/utilities/RequestSharedAnimationFrame.ts +16 -0
- package/src/library/utilities/StaticImage.tsx +58 -0
- package/src/library/utilities/SvgExtruder.ts +330 -0
- package/src/library/utilities/ThreeDisposer.ts +66 -0
- package/src/library/utilities/zIndex.ts +15 -0
|
@@ -0,0 +1,1249 @@
|
|
|
1
|
+
import nextTick from "next-tick";
|
|
2
|
+
import { Chit } from "./Chit";
|
|
3
|
+
import { Match } from "./Match";
|
|
4
|
+
import { NoValidMovesPrompt, PickPrompt, Prompt, SelectPrompt } from "./Prompt";
|
|
5
|
+
import { PromptResponse, RngResponse, TurnState } from "./TurnState";
|
|
6
|
+
import { ButtonPick, Pick } from "./Pick";
|
|
7
|
+
import { Confirm, GameButton } from "./GameButton";
|
|
8
|
+
import { PlayerChit } from "./PlayerChit";
|
|
9
|
+
import { RootChit } from "./RootChit";
|
|
10
|
+
import { ClockDetails } from "./ClockDetails";
|
|
11
|
+
|
|
12
|
+
type LogMessageSerializationResponse = {
|
|
13
|
+
message: string;
|
|
14
|
+
clock: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type ChitSerializationResponse = {
|
|
18
|
+
chits: ChitStateLookup;
|
|
19
|
+
clockDetails: ClockDetails;
|
|
20
|
+
log?: LogMessageSerializationResponse;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type ChitHistoryItem = {
|
|
24
|
+
clock: number;
|
|
25
|
+
state: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type ChitHistoryResponse = {
|
|
29
|
+
[id: string]: ChitHistoryItem[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type ValidPick = undefined | false | Pick | Pick[] | ButtonPick | ButtonPick[] | GameButton | GameButton[];
|
|
33
|
+
export type Picks = ValidPick | ValidPick[];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* A `Turn` is the heart of pretty-chitty. It represents multiple actions or sequences of events from a
|
|
38
|
+
* single player (or possibly not player).
|
|
39
|
+
*
|
|
40
|
+
* The core of a `Turn` is the async `fn` provided. This `fn` will run all of this logic for that turn,
|
|
41
|
+
* prompt the user for actions, take random number draws and possibly create one or more sub-turns.
|
|
42
|
+
*
|
|
43
|
+
* The general pattern will look something like this:
|
|
44
|
+
*
|
|
45
|
+
* ```
|
|
46
|
+
* setup.createTurn([rootChit, playerChit], playerChit, async (turn) => {
|
|
47
|
+
*
|
|
48
|
+
* // take a random number
|
|
49
|
+
* const randomDraw = await turn.rng();
|
|
50
|
+
*
|
|
51
|
+
* // ask the turn's player to make a decision.
|
|
52
|
+
* await turn.pick([Chit.pick([chit1,chit2], async chosenChit => {
|
|
53
|
+
* // do something with chosen chit
|
|
54
|
+
* })]);
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* There are a couple of VERY important details here:
|
|
59
|
+
*
|
|
60
|
+
* 1) Your turn implemention should persist no state itself.
|
|
61
|
+
* 2) Your turn is going to "lock" one or more chits. Those chits will only be editable by this turn (until the turn is done or a sub-turn briefly locks those same chits)
|
|
62
|
+
* 3) If a user needs to "undo" something, it will automatically reset all of the locked chits to their original locked state and re-evaluate the turn from its beginning to easily handle a single "step back".
|
|
63
|
+
* 4) As a result, all random numbers need to go through this turn's rng() so they are persisted correctly.
|
|
64
|
+
* 5) All state should be either ephemeral or stored on the chits themselves. Remember that your turn's function may re-evaluate at any point!
|
|
65
|
+
* 6) It will automatically handle prompting a user for confirmation before drawing a random number OR before changing the active player.
|
|
66
|
+
*
|
|
67
|
+
* @group Core Game Elements
|
|
68
|
+
*/
|
|
69
|
+
export class Turn<T, P extends PlayerChit, R extends RootChit<P>> {
|
|
70
|
+
private pass = 0;
|
|
71
|
+
private clockSteps: ClockStep[] = [];
|
|
72
|
+
private decisionIndex = 0; // decision points that can be potentially rolled back
|
|
73
|
+
|
|
74
|
+
/** @internal */
|
|
75
|
+
public unresolvedPrompt?: Prompt;
|
|
76
|
+
|
|
77
|
+
/** @internal */
|
|
78
|
+
public completed = false;
|
|
79
|
+
|
|
80
|
+
/** @internal */
|
|
81
|
+
public activeSubTurns: Turn<any, P, R>[] = [];
|
|
82
|
+
|
|
83
|
+
/** @internal */
|
|
84
|
+
public destroyed = false;
|
|
85
|
+
|
|
86
|
+
/** @internal */
|
|
87
|
+
public paused = Promise.resolve();
|
|
88
|
+
|
|
89
|
+
private newChitCounter: { [type: string]: number } = {};
|
|
90
|
+
private chitLookup: ChitLookup = {};
|
|
91
|
+
private lockedChitStates: ChitStateLookup = {};
|
|
92
|
+
private lastChitStates: ChitStateLookup = {};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Locates a chit by its ID. If not found, will throw.
|
|
96
|
+
* @param id
|
|
97
|
+
* @returns the found chit
|
|
98
|
+
* @throws If the chit is missing
|
|
99
|
+
* @internal
|
|
100
|
+
*/
|
|
101
|
+
public readonly findChit: (id: string) => Chit = (id: string) => {
|
|
102
|
+
// store as an arrow fn so it can be passed as a fn reference and retain 'this'
|
|
103
|
+
const result = this.chitLookup[id];
|
|
104
|
+
if (!result) {
|
|
105
|
+
if (this.parent) {
|
|
106
|
+
return this.parent.findChit(id);
|
|
107
|
+
}
|
|
108
|
+
throw new Error("Cannot find chit");
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The root chit instance of the game. All chits in the game have this chit somewhere in its hierarchy
|
|
115
|
+
*/
|
|
116
|
+
public get rootChit(): R {
|
|
117
|
+
return this.findChit("root") as R;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private _playerIds!: string[];
|
|
121
|
+
|
|
122
|
+
constructor(
|
|
123
|
+
public id: string,
|
|
124
|
+
/** @internal */
|
|
125
|
+
public match: Match<P, R>,
|
|
126
|
+
/** @internal */
|
|
127
|
+
public state: TurnState,
|
|
128
|
+
/** @internal */
|
|
129
|
+
public fn: (turn: Turn<T, P, R>) => Promise<T>,
|
|
130
|
+
/** @internal */
|
|
131
|
+
private chitsToLock: Chit[],
|
|
132
|
+
public player?: P,
|
|
133
|
+
/** @internal */
|
|
134
|
+
private parent?: Turn<any, P, R>,
|
|
135
|
+
) {
|
|
136
|
+
if (chitsToLock.find((chit) => !chit.id)) {
|
|
137
|
+
throw new Error("Cannot lock a chit without an id");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// store our chit lookup plus the initial states of all of those chits
|
|
141
|
+
// so if we have to reset, we can just restore those states
|
|
142
|
+
Chit.walk(chitsToLock, (c) => {
|
|
143
|
+
if (!c.id) {
|
|
144
|
+
throw new Error("Cannot lock a chit without an id");
|
|
145
|
+
}
|
|
146
|
+
c.lock(this);
|
|
147
|
+
this.chitLookup[c.id] = c;
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// this has to be done after we capture and lock the chits, but we need player ids so we can properly serialize
|
|
151
|
+
// chits
|
|
152
|
+
this._playerIds = this.rootChit.players.map((p) => {
|
|
153
|
+
if (!p.id) {
|
|
154
|
+
throw new Error("Cannot create turns for players without IDs");
|
|
155
|
+
}
|
|
156
|
+
return p.id;
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// now serialize all chits in their "locked" state
|
|
160
|
+
Object.values(this.chitLookup).forEach((c) => {
|
|
161
|
+
if (!c.id) {
|
|
162
|
+
throw new Error("Cannot serialize a chit without an id");
|
|
163
|
+
}
|
|
164
|
+
this.lastChitStates[c.id] = this.lockedChitStates[c.id] = c.serialize(this._playerIds);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Generates a random number from 0 to 1. This number will persisted in state and will be consistent if the
|
|
170
|
+
* turn needs to be re-run. Drawing a random number prevents normal resets.
|
|
171
|
+
*
|
|
172
|
+
* If the player can perform a reset, this will confirm with them first.
|
|
173
|
+
*
|
|
174
|
+
* @returns A number from 0-1
|
|
175
|
+
*/
|
|
176
|
+
async rng(message = "confirm draw or roll") {
|
|
177
|
+
await this.possiblyConfirm(message);
|
|
178
|
+
const result = this.state.getOrCreateRng(this.decisionIndex);
|
|
179
|
+
this.decisionIndex++;
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Generates a series of random numbers from 0 to 1. This is a helper method to help batch up a lot of random draws
|
|
185
|
+
* since each rng() call must be awaited.
|
|
186
|
+
* @param count
|
|
187
|
+
* @returns A parameterless function that will return the next random number in the list. If you try to select too many random numbers, that method will throw.
|
|
188
|
+
*/
|
|
189
|
+
async takeRng(count: number, message = "confirm draw or roll"): Promise<() => number> {
|
|
190
|
+
await this.possiblyConfirm(message);
|
|
191
|
+
const results: number[] = [];
|
|
192
|
+
for (let i = 0; i < count; i++) {
|
|
193
|
+
results.push(this.state.getOrCreateRng(this.decisionIndex));
|
|
194
|
+
this.decisionIndex++;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let counter = 0;
|
|
198
|
+
return () => {
|
|
199
|
+
if (counter >= results.length) {
|
|
200
|
+
throw new Error("RNG take out of bounds");
|
|
201
|
+
}
|
|
202
|
+
return results[counter++];
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Add a game log message to the last flush step
|
|
208
|
+
* @param message
|
|
209
|
+
*/
|
|
210
|
+
log(message: string) {
|
|
211
|
+
let step = this.clockSteps[this.clockSteps.length - 1];
|
|
212
|
+
if (!step || !(step instanceof FlushClockStep) || (step as FlushClockStep).log !== undefined) {
|
|
213
|
+
// flushing any changes while there are active subturns makes timelines *VERY* difficult
|
|
214
|
+
if (this.activeSubTurns.length) {
|
|
215
|
+
throw new Error("Cannot flush while subturns are active");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.flush(true);
|
|
219
|
+
step = this.clockSteps[this.clockSteps.length - 1];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const flushStep = step as FlushClockStep;
|
|
223
|
+
flushStep.log = message;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Append a game log message to the last flush step that has a game log message
|
|
228
|
+
* @param message
|
|
229
|
+
* @returns
|
|
230
|
+
*/
|
|
231
|
+
amendLog(message: string | ((previous: string) => string)) {
|
|
232
|
+
const lastSubTurnIndex = this.clockSteps.findLastIndex((step) => step instanceof SubTurnsClockStep);
|
|
233
|
+
const lastIndex = this.clockSteps.findLastIndex(
|
|
234
|
+
(step, index) => index > lastSubTurnIndex && step instanceof FlushClockStep && step.log,
|
|
235
|
+
);
|
|
236
|
+
if (lastIndex < 0) {
|
|
237
|
+
if (message instanceof Function) {
|
|
238
|
+
message = message("");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
this.log(message);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const step = this.clockSteps[lastIndex] as FlushClockStep;
|
|
246
|
+
if (message instanceof Function) {
|
|
247
|
+
message = message(step.log!);
|
|
248
|
+
}
|
|
249
|
+
step.log = message;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Scan all of the chits managed by this turn. If any of them have changed, group them together into a
|
|
254
|
+
* "ClockStep". If any new chits appear, then add them to our lookup. If any chits are deleted (orphaned),
|
|
255
|
+
* then we have to identify those as well.
|
|
256
|
+
*/
|
|
257
|
+
flush(force = false) {
|
|
258
|
+
const seenIds = new Set<string>();
|
|
259
|
+
const newStates: ChitStateLookup = {};
|
|
260
|
+
let sawChange = force;
|
|
261
|
+
|
|
262
|
+
// first ensure they all are locked and all have ids
|
|
263
|
+
const chitsToAddIdsTo: Chit[] = [];
|
|
264
|
+
Chit.walk(this.chitsToLock, (c) => {
|
|
265
|
+
if (!c.id) {
|
|
266
|
+
chitsToAddIdsTo.push(c);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
chitsToAddIdsTo.sort((a, b) => a.createdOrder - b.createdOrder);
|
|
271
|
+
chitsToAddIdsTo.forEach((c) => {
|
|
272
|
+
const type = c.chitTypeName();
|
|
273
|
+
const counter = (this.newChitCounter[type] || 0) + 1;
|
|
274
|
+
this.newChitCounter[type] = counter;
|
|
275
|
+
c.id = `${this.id}.${type}.${counter}`;
|
|
276
|
+
c.lock(this);
|
|
277
|
+
|
|
278
|
+
const existing = this.chitLookup[c.id];
|
|
279
|
+
this.chitLookup[c.id] = c; // it's possible that this is kicking out an "old" version of this chit from a previous pass
|
|
280
|
+
if (existing) {
|
|
281
|
+
existing.removeFromParent(); // do not want to leave stray references to this cloned chit around!
|
|
282
|
+
existing.unlock(this);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// now (once per chit) we serialize the state if it changed
|
|
287
|
+
Chit.walk(this.chitsToLock, (c) => {
|
|
288
|
+
if (!c.id) {
|
|
289
|
+
throw new Error("Should not be possible unless Chit.walk is misbehaving");
|
|
290
|
+
}
|
|
291
|
+
if (!seenIds.has(c.id)) {
|
|
292
|
+
seenIds.add(c.id);
|
|
293
|
+
const serialized = c.serialize(this._playerIds);
|
|
294
|
+
const lastState = this.lastChitStates[c.id];
|
|
295
|
+
if (serialized !== lastState) {
|
|
296
|
+
this.lastChitStates[c.id] = newStates[c.id] = serialized;
|
|
297
|
+
sawChange = true;
|
|
298
|
+
} else {
|
|
299
|
+
newStates[c.id] = serialized;
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
return false; // already saw this - no need to keep digging into children
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// find any chits that we previously serialized that we no longer see
|
|
307
|
+
// these should be marked as deleted now
|
|
308
|
+
const chitsToDelete = Object.keys(this.lastChitStates)
|
|
309
|
+
.filter((id) => !seenIds.has(id) && this.lastChitStates[id] !== Chit.deletedIfSerialized())
|
|
310
|
+
.map((id) => this.findChit(id));
|
|
311
|
+
|
|
312
|
+
// make sure any missing items that were previously also missing are still deleted
|
|
313
|
+
Object.keys(this.lastChitStates)
|
|
314
|
+
.filter((id) => !seenIds.has(id) && this.lastChitStates[id] == Chit.deletedIfSerialized())
|
|
315
|
+
.forEach((id) => {
|
|
316
|
+
newStates[id] = Chit.deletedIfSerialized();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// find all chits without parents - all of their descendants are safe to be purged
|
|
320
|
+
chitsToDelete
|
|
321
|
+
.filter((chit) => !chit.parent)
|
|
322
|
+
.forEach((chit) => {
|
|
323
|
+
if (chit.id) {
|
|
324
|
+
sawChange = true;
|
|
325
|
+
chit.unlock(this);
|
|
326
|
+
newStates[chit.id] = Chit.deletedIfSerialized();
|
|
327
|
+
// do not store this new state in lastChitStates, but rather delete this record from it altogether
|
|
328
|
+
chit.walk((c) => {
|
|
329
|
+
if (c.id) {
|
|
330
|
+
seenIds.add(c.id);
|
|
331
|
+
this.lastChitStates[c.id] = Chit.deletedIfSerialized();
|
|
332
|
+
newStates[c.id] = Chit.deletedIfSerialized();
|
|
333
|
+
chit.unlock(this);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// any chits remaining that we haven't seen are bad news - they have likely been reparented to some other Turn, which
|
|
340
|
+
// is against the rules. They need to remain under this turns control.
|
|
341
|
+
if (chitsToDelete.find((c) => c.id && !seenIds.has(c.id))) {
|
|
342
|
+
throw new Error("Chit has been reparented to another Turn which will corrupt control");
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (sawChange) {
|
|
346
|
+
// flushing any changes while there are active subturns makes timelines *VERY* difficult
|
|
347
|
+
if (this.activeSubTurns.length) {
|
|
348
|
+
throw new Error("Cannot flush while subturns are active");
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
this.clockSteps.push(new FlushClockStep(this.clock, newStates));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Creates a sub-turn. This is useful for a few reasons:
|
|
357
|
+
* 1) It is the only way to change game control flow from our current player to a different player
|
|
358
|
+
* 2) It creates a new "reset" point for backing out turns
|
|
359
|
+
*
|
|
360
|
+
* It takes an async function which it will execute. For simplicity, the result of that function will be the result of
|
|
361
|
+
* this function.
|
|
362
|
+
*
|
|
363
|
+
* It is okay to have multiple turns going at once, but there are some rules:
|
|
364
|
+
* 1) If there is an ongoing sub turn that hasn't resolved, you cannot prompt or change chits in this turn.
|
|
365
|
+
* 2) There is only one ongoing subturn allowed per player.
|
|
366
|
+
*
|
|
367
|
+
* @param chits The chits to lock. These are the only chits that will be allowed to be modified by this turn. If there are never any concurrent turns, this can safely be the root chit (although there maybe minor performance implications)
|
|
368
|
+
* @param player The player who will be prompted for choices during this turn.
|
|
369
|
+
* @param cb The async function that will be the logic of this turn. The function takes a new turn instance
|
|
370
|
+
* @returns Whatever the final result of cb() is
|
|
371
|
+
*/
|
|
372
|
+
public async createTurn<A>(chits: Chit[], player: P, cb: (turn: Turn<A, P, R>) => Promise<A>): Promise<A> {
|
|
373
|
+
if (this.unresolvedPrompt) {
|
|
374
|
+
throw new Error("Still awaiting a prompt result");
|
|
375
|
+
}
|
|
376
|
+
if (this.destroyed) {
|
|
377
|
+
throw new DestroyError(); // do not create more turns if we are destroyed!
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
await this.checkPause();
|
|
381
|
+
|
|
382
|
+
this.flush();
|
|
383
|
+
|
|
384
|
+
if (player.playerId && player.playerId !== this.player?.playerId) {
|
|
385
|
+
await this.possiblyConfirm("confirm switching active player");
|
|
386
|
+
this.flush();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (player) {
|
|
390
|
+
chits = chits.concat(player);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (player && this.activeSubTurns.find((subTurn) => subTurn.player === player)) {
|
|
394
|
+
throw new Error("Only one sub-turn can be active at a time per player");
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const id = `${this.id}.t${this.decisionIndex}`;
|
|
398
|
+
const s = this.state.getOrCreateTurnState(this.decisionIndex);
|
|
399
|
+
s.playerId = player?.playerId;
|
|
400
|
+
s.id = id;
|
|
401
|
+
Chit.walk(chits, (chit) => chit.unlock(this));
|
|
402
|
+
const turn = new Turn<A, P, R>(id, this.match, s, cb, chits, player, this);
|
|
403
|
+
|
|
404
|
+
this.decisionIndex++;
|
|
405
|
+
|
|
406
|
+
if (this.activeSubTurns.length === 0) {
|
|
407
|
+
this.clockSteps.push(new SubTurnsClockStep(this.clock, [turn]));
|
|
408
|
+
} else {
|
|
409
|
+
const lastStep = this.clockSteps[this.clockSteps.length - 1];
|
|
410
|
+
if (!(lastStep instanceof SubTurnsClockStep)) {
|
|
411
|
+
throw new Error("Unexpected clocksteps stage");
|
|
412
|
+
}
|
|
413
|
+
lastStep.turns.push(turn);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
this.activeSubTurns.push(turn);
|
|
417
|
+
|
|
418
|
+
//make sure flow goes to next tick
|
|
419
|
+
await new Promise((resolve) => nextTick(() => resolve(true)));
|
|
420
|
+
|
|
421
|
+
await this.checkPause();
|
|
422
|
+
|
|
423
|
+
const result = await turn.execute();
|
|
424
|
+
|
|
425
|
+
await this.checkPause();
|
|
426
|
+
|
|
427
|
+
this.activeSubTurns = this.activeSubTurns.filter((t) => t !== turn);
|
|
428
|
+
|
|
429
|
+
Object.values(turn.chitLookup).forEach((chit) => {
|
|
430
|
+
if (chit.id) {
|
|
431
|
+
chit.lock(this);
|
|
432
|
+
this.chitLookup[chit.id] = chit;
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
this.lastChitStates = { ...this.lastChitStates, ...turn.lastChitStates };
|
|
437
|
+
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
public async runParallelTurns<A>(
|
|
442
|
+
players: P[],
|
|
443
|
+
chits: (p: P) => Chit[],
|
|
444
|
+
action: (p: P, turn: Turn<A, P, R>) => Promise<A>,
|
|
445
|
+
): Promise<A[]> {
|
|
446
|
+
// the whole point of this function is so we can mark all players as having a prompt waiting for them
|
|
447
|
+
players.forEach((player) => (player.promptStatus.latestPromptMessage = "Waiting for turn to complete"));
|
|
448
|
+
|
|
449
|
+
const turns = players.map((player) =>
|
|
450
|
+
this.createTurn(chits(player), player, (turn: Turn<A, P, R>) => action(player, turn)),
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
return await Promise.all(turns);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Basic selection prompt. All chits will appear as "selected" on the respective client.
|
|
458
|
+
* Upon clicking one, the prompt will resolve itself.
|
|
459
|
+
*
|
|
460
|
+
* @param chits The list of chits that can be selected from
|
|
461
|
+
* @returns The chit that the player selected
|
|
462
|
+
*/
|
|
463
|
+
public async select(chits: Chit[]): Promise<Chit> {
|
|
464
|
+
if (chits.length === 1) {
|
|
465
|
+
return chits[0];
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const prompt = new SelectPrompt();
|
|
469
|
+
prompt.chits = chits;
|
|
470
|
+
|
|
471
|
+
this.prepareForPrompt(prompt);
|
|
472
|
+
|
|
473
|
+
// make sure all of these chits are locked by us - otherwise someone has made a mistake.
|
|
474
|
+
chits.forEach((chit) => chit.confirmLock(this));
|
|
475
|
+
|
|
476
|
+
await this.waitForPromptResolution(prompt);
|
|
477
|
+
if (!prompt.selectedChit) {
|
|
478
|
+
throw new Error("Prompt should have selected chit response");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return prompt.selectedChit;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* If a player has gotten themselves into a corner - i.e. no valid moves - this prompt will
|
|
486
|
+
* simply inform them of that and allow them to undo.
|
|
487
|
+
* @param message
|
|
488
|
+
* @param help
|
|
489
|
+
*/
|
|
490
|
+
public async noValidMoves(message?: string, help?: string) {
|
|
491
|
+
const prompt = new NoValidMovesPrompt();
|
|
492
|
+
if (message) {
|
|
493
|
+
prompt.message = message;
|
|
494
|
+
}
|
|
495
|
+
if (help) {
|
|
496
|
+
prompt.help = help;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
this.prepareForPrompt(prompt);
|
|
500
|
+
|
|
501
|
+
await this.waitForPromptResolution(prompt);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* More complex selection prompt. Useful in Typescript when you want to handle a response to multiple
|
|
506
|
+
* types of chits. This will allow a different typed callback per set of chits. This also allows
|
|
507
|
+
* the insertion of "buttons"
|
|
508
|
+
* @param message (optional) The message to show describing the prompt in a few words
|
|
509
|
+
* @param help (optional) A detailed help message to show
|
|
510
|
+
* @param picks An array of "picks" - each of which can have its own typesafe callback
|
|
511
|
+
*/
|
|
512
|
+
public async pick(message?: string | Picks, help?: string | Picks, picks?: Picks) {
|
|
513
|
+
if (typeof message !== "string") {
|
|
514
|
+
picks = message;
|
|
515
|
+
message = undefined;
|
|
516
|
+
help = undefined;
|
|
517
|
+
}
|
|
518
|
+
if (help !== undefined && typeof help !== "string") {
|
|
519
|
+
picks = help;
|
|
520
|
+
help = undefined;
|
|
521
|
+
}
|
|
522
|
+
if (picks === undefined) {
|
|
523
|
+
throw new Error("No PIcks");
|
|
524
|
+
}
|
|
525
|
+
if (!Array.isArray(picks)) {
|
|
526
|
+
picks = [picks];
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const prompt = new PickPrompt();
|
|
530
|
+
prompt.setMessageAndHelp(message, help);
|
|
531
|
+
|
|
532
|
+
const flatPicks = [...picks]
|
|
533
|
+
.flat()
|
|
534
|
+
.map((o) => {
|
|
535
|
+
if (!o) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
if (o instanceof Pick) {
|
|
539
|
+
return o;
|
|
540
|
+
}
|
|
541
|
+
if (o instanceof GameButton) {
|
|
542
|
+
return GameButton.pick(o);
|
|
543
|
+
}
|
|
544
|
+
throw new Error("Invalid type");
|
|
545
|
+
})
|
|
546
|
+
.filter((a) => a && a.numberOfChoices() > 0) as Pick[];
|
|
547
|
+
|
|
548
|
+
prompt.picks = flatPicks;
|
|
549
|
+
|
|
550
|
+
if (flatPicks.length === 0) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const autoresolved = await prompt.autoResolve();
|
|
555
|
+
|
|
556
|
+
if (!autoresolved) {
|
|
557
|
+
this.prepareForPrompt(prompt);
|
|
558
|
+
|
|
559
|
+
// make sure all of these chits are locked by us - otherwise someone has made a mistake.
|
|
560
|
+
flatPicks.forEach((pick) => pick.confirmLock(this));
|
|
561
|
+
|
|
562
|
+
await this.waitForPromptResolution(prompt);
|
|
563
|
+
|
|
564
|
+
await prompt.finished();
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/** @internal */
|
|
569
|
+
public rerun(turn: Turn<any, P, R>) {
|
|
570
|
+
this.activeSubTurns.forEach((t) => t.rerun(turn));
|
|
571
|
+
if (this.unresolvedPrompt) {
|
|
572
|
+
this.unresolvedPrompt.shouldRerun = turn;
|
|
573
|
+
this.unresolvedPrompt.resolve({});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/** @internal */
|
|
578
|
+
async possiblyConfirm(action: string): Promise<void> {
|
|
579
|
+
if (this.state.hasUserMadeChoiceSinceUserContextChangedOrRng(this.decisionIndex - 1)) {
|
|
580
|
+
const c = new Confirm(() => {});
|
|
581
|
+
c.message = action;
|
|
582
|
+
await this.pick([c]);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/** @internal */
|
|
587
|
+
private nextSavedStateToProcess?: TurnState;
|
|
588
|
+
|
|
589
|
+
private isProcessingSavedState = false;
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* This is only useful at the 'root' turn level, really.
|
|
593
|
+
* @internal
|
|
594
|
+
*/
|
|
595
|
+
public async processNewSavedState(state: TurnState) {
|
|
596
|
+
if (this.isProcessingSavedState) {
|
|
597
|
+
this.nextSavedStateToProcess = state;
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
try {
|
|
602
|
+
this.isProcessingSavedState = true;
|
|
603
|
+
this.pause();
|
|
604
|
+
|
|
605
|
+
// defer to next tick on starting
|
|
606
|
+
await new Promise<void>((resolve) => nextTick(() => resolve()));
|
|
607
|
+
|
|
608
|
+
const instructions = this.handleNewSavedState(state);
|
|
609
|
+
|
|
610
|
+
this.propagateNewState(state);
|
|
611
|
+
|
|
612
|
+
for (const instruction of instructions) {
|
|
613
|
+
if (instruction.type === "reset") {
|
|
614
|
+
this.state = state;
|
|
615
|
+
instruction.turn.rerun(instruction.turn);
|
|
616
|
+
} else if (instruction.type === "prompt") {
|
|
617
|
+
await new Promise<void>((resolve, reject) =>
|
|
618
|
+
nextTick(() => {
|
|
619
|
+
if (instruction.turn.unresolvedPrompt !== instruction.prompt) {
|
|
620
|
+
reject("waiting on incorrect prompt");
|
|
621
|
+
}
|
|
622
|
+
instruction.prompt.resolve(instruction.response);
|
|
623
|
+
resolve();
|
|
624
|
+
}),
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// always defer to next tick again when resuming
|
|
630
|
+
await new Promise<void>((resolve) => nextTick(() => resolve()));
|
|
631
|
+
} finally {
|
|
632
|
+
this.unpause();
|
|
633
|
+
this.isProcessingSavedState = false;
|
|
634
|
+
|
|
635
|
+
if (this.nextSavedStateToProcess) {
|
|
636
|
+
const newState = this.nextSavedStateToProcess;
|
|
637
|
+
this.nextSavedStateToProcess = undefined;
|
|
638
|
+
this.processNewSavedState(newState);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/** @internal */
|
|
644
|
+
public propagateNewState(state: TurnState) {
|
|
645
|
+
this.state = state;
|
|
646
|
+
|
|
647
|
+
this.activeSubTurns.forEach((t) => {
|
|
648
|
+
const newState = state.decisions.find((decision) => decision.type === "turn" && decision.id === t.id);
|
|
649
|
+
if (newState) {
|
|
650
|
+
t.propagateNewState(newState as TurnState);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/** @internal */
|
|
656
|
+
public handleNewSavedState(state: TurnState): SavedStateProcessingInstructions[] {
|
|
657
|
+
const oldState = this.state;
|
|
658
|
+
|
|
659
|
+
// if we have decisions that the state we are loading does NOT have yet
|
|
660
|
+
// then we have to reset and rerun this turn
|
|
661
|
+
if (oldState.decisions.length > state.decisions.length) {
|
|
662
|
+
return [{ turn: this, type: "reset" }];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// confirm all of the choices are the same
|
|
666
|
+
const result: SavedStateProcessingInstructions[] = [];
|
|
667
|
+
for (let i = 0; i < oldState.decisions.length; i++) {
|
|
668
|
+
const oldDecision = oldState.decisions[i];
|
|
669
|
+
const newDecision = state.decisions[i];
|
|
670
|
+
|
|
671
|
+
if (oldDecision.type !== newDecision.type) {
|
|
672
|
+
return [{ turn: this, type: "reset" }];
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
//
|
|
676
|
+
// This is just wrong. the only time we don't have to do a full reset is if the last step is a turn that isn't
|
|
677
|
+
// resolved yet. that turn can update itself, but leaving turn 2 alone
|
|
678
|
+
//
|
|
679
|
+
|
|
680
|
+
if (oldDecision.type === "rng") {
|
|
681
|
+
if ((oldDecision as RngResponse).value !== (newDecision as RngResponse).value) {
|
|
682
|
+
return [{ turn: this, type: "reset" }];
|
|
683
|
+
}
|
|
684
|
+
} else if (oldDecision.type === "prompt") {
|
|
685
|
+
const oldResponse = oldDecision as PromptResponse;
|
|
686
|
+
const newResponse = newDecision as PromptResponse;
|
|
687
|
+
|
|
688
|
+
// special case: if we are looking at a prompt we were waiting on previously
|
|
689
|
+
// we can now resolve it!
|
|
690
|
+
if (
|
|
691
|
+
i === oldState.decisions.length - 1 &&
|
|
692
|
+
oldResponse.response === undefined &&
|
|
693
|
+
newResponse.response !== undefined
|
|
694
|
+
) {
|
|
695
|
+
if (!this.unresolvedPrompt) {
|
|
696
|
+
return [{ turn: this, type: "reset" }]; // something has gone wrong if we have a response and are not waiting on a response
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
result.push({
|
|
700
|
+
type: "prompt",
|
|
701
|
+
turn: this,
|
|
702
|
+
prompt: this.unresolvedPrompt,
|
|
703
|
+
response: newResponse.response,
|
|
704
|
+
});
|
|
705
|
+
} else if (JSON.stringify(oldResponse.response) !== JSON.stringify(newResponse.response)) {
|
|
706
|
+
return [{ turn: this, type: "reset" }];
|
|
707
|
+
}
|
|
708
|
+
} else if (oldDecision.type === "turn") {
|
|
709
|
+
const oldTurnState = oldDecision as TurnState;
|
|
710
|
+
const newTurnState = newDecision as TurnState;
|
|
711
|
+
|
|
712
|
+
// if this turn isn't finished, then let that turn try to resolve the new state
|
|
713
|
+
const foundTurn = this.activeSubTurns.find((t) => t.id === newTurnState.id);
|
|
714
|
+
if (foundTurn) {
|
|
715
|
+
const subTurnChanges = foundTurn.handleNewSavedState(newTurnState);
|
|
716
|
+
subTurnChanges.forEach((r) => result.push(r));
|
|
717
|
+
} else if (JSON.stringify(oldTurnState.decisions) !== JSON.stringify(newTurnState.decisions)) {
|
|
718
|
+
return [{ turn: this, type: "reset" }];
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return result;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
private findIndexOfLastFlushStepBefore(clock: number): number {
|
|
726
|
+
for (let j = this.clockSteps.length - 1; j >= 0; j--) {
|
|
727
|
+
if (this.clockSteps[j] instanceof FlushClockStep && this.clockSteps[j].startClock < clock) {
|
|
728
|
+
return j;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return 0;
|
|
732
|
+
}
|
|
733
|
+
private findIndexOfLastFlushStepWithLogMessageBefore(clock: number): number {
|
|
734
|
+
for (let j = this.clockSteps.length - 1; j >= 0; j--) {
|
|
735
|
+
if (
|
|
736
|
+
this.clockSteps[j] instanceof FlushClockStep &&
|
|
737
|
+
this.clockSteps[j].startClock < clock &&
|
|
738
|
+
(this.clockSteps[j] as FlushClockStep).log
|
|
739
|
+
) {
|
|
740
|
+
return j;
|
|
741
|
+
}
|
|
742
|
+
if (this.clockSteps[j].startClock < clock && this.clockSteps[j] instanceof SubTurnsClockStep) {
|
|
743
|
+
// logs cannot be inside subturns
|
|
744
|
+
break;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
return -1;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/** @internal */
|
|
751
|
+
chitsHistory(playerId: string, ids: string[]): ChitHistoryResponse {
|
|
752
|
+
const result: ChitHistoryResponse = {};
|
|
753
|
+
|
|
754
|
+
const appendLog = (id: string, clock: number, state: string) => {
|
|
755
|
+
if (!state) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
result[id] = result[id] ?? [];
|
|
759
|
+
if (result[id][result[id].length - 1]?.state !== state) {
|
|
760
|
+
result[id].push({
|
|
761
|
+
clock,
|
|
762
|
+
state,
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
this.clockSteps.forEach((step) => {
|
|
768
|
+
if (step instanceof FlushClockStep) {
|
|
769
|
+
ids.forEach((id) => appendLog(id, step.startClock, step.state[id]));
|
|
770
|
+
} else if (step instanceof SubTurnsClockStep) {
|
|
771
|
+
for (const turn of step.visibleTurns(playerId)) {
|
|
772
|
+
const turnResponse = turn.chitsHistory(playerId, ids);
|
|
773
|
+
Object.entries(turnResponse).forEach(([id, value]) => {
|
|
774
|
+
value.forEach((v) => {
|
|
775
|
+
appendLog(id, step.startClock + v.clock, v.state);
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
return result;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/** @internal */
|
|
785
|
+
serialize(playerId: string, clock: number): ChitSerializationResponse {
|
|
786
|
+
clock = Math.max(0, Math.min(clock, this.playerVisibleClockTime(playerId)));
|
|
787
|
+
|
|
788
|
+
let chits = {};
|
|
789
|
+
let resultingClock = -1;
|
|
790
|
+
|
|
791
|
+
// going forwards
|
|
792
|
+
let index = this.findIndexOfLastFlushStepBefore(clock);
|
|
793
|
+
const lastLogIndex = this.findIndexOfLastFlushStepWithLogMessageBefore(clock);
|
|
794
|
+
|
|
795
|
+
// set up logs
|
|
796
|
+
let log: LogMessageSerializationResponse | undefined;
|
|
797
|
+
if (lastLogIndex >= 0) {
|
|
798
|
+
const messageStep = this.clockSteps[lastLogIndex] as FlushClockStep;
|
|
799
|
+
log = {
|
|
800
|
+
message: messageStep.log!,
|
|
801
|
+
clock: messageStep.startClock,
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
let subTurns: { [turnId: string]: ClockDetails } | undefined = undefined;
|
|
805
|
+
|
|
806
|
+
// eslint-disable-next-line no-constant-condition
|
|
807
|
+
while (true) {
|
|
808
|
+
const clockStep = this.clockSteps[index];
|
|
809
|
+
index++;
|
|
810
|
+
if (!clockStep) {
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (clockStep.startClock >= clock) {
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
if (clockStep instanceof FlushClockStep) {
|
|
819
|
+
subTurns = undefined;
|
|
820
|
+
chits = { ...clockStep.state };
|
|
821
|
+
resultingClock = clockStep.endClock();
|
|
822
|
+
} else if (clockStep instanceof SubTurnsClockStep) {
|
|
823
|
+
subTurns = {};
|
|
824
|
+
resultingClock = clockStep.startClock;
|
|
825
|
+
let remainingClocksToSpend = clock - clockStep.startClock;
|
|
826
|
+
for (const turn of clockStep.visibleTurns(playerId)) {
|
|
827
|
+
const time = Math.max(remainingClocksToSpend, 0);
|
|
828
|
+
if (time <= 0) {
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// we are going forward so we never want to have a turn go backwards. ever.
|
|
833
|
+
const serialized = turn.serialize(playerId, time);
|
|
834
|
+
Object.assign(chits, serialized.chits);
|
|
835
|
+
|
|
836
|
+
resultingClock += serialized.clockDetails.clock;
|
|
837
|
+
remainingClocksToSpend -= serialized.clockDetails.clock;
|
|
838
|
+
subTurns[turn.id] = serialized.clockDetails;
|
|
839
|
+
if (serialized.log) {
|
|
840
|
+
log = serialized.log;
|
|
841
|
+
log.clock += clockStep.startClock;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
return {
|
|
848
|
+
log,
|
|
849
|
+
chits,
|
|
850
|
+
clockDetails: {
|
|
851
|
+
pass: this.pass,
|
|
852
|
+
clock: resultingClock === -1 ? clock : resultingClock,
|
|
853
|
+
subTurns,
|
|
854
|
+
},
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/** @internal */
|
|
859
|
+
gameLog(playerId: string): LogMessageSerializationResponse[] {
|
|
860
|
+
return this.clockSteps
|
|
861
|
+
.map((step) => {
|
|
862
|
+
if (step instanceof FlushClockStep && step.log) {
|
|
863
|
+
return { message: step.log, clock: step.startClock };
|
|
864
|
+
} else if (step instanceof SubTurnsClockStep) {
|
|
865
|
+
let offset = step.startClock;
|
|
866
|
+
|
|
867
|
+
return step
|
|
868
|
+
.visibleTurns(playerId)
|
|
869
|
+
.map((turn) => {
|
|
870
|
+
const logs = turn.gameLog(playerId).map((l) => {
|
|
871
|
+
l.clock += offset;
|
|
872
|
+
return l;
|
|
873
|
+
});
|
|
874
|
+
offset += turn.clockDetails(playerId).clock;
|
|
875
|
+
return logs;
|
|
876
|
+
})
|
|
877
|
+
.flat();
|
|
878
|
+
}
|
|
879
|
+
})
|
|
880
|
+
.flat()
|
|
881
|
+
.filter((d) => d) as LogMessageSerializationResponse[];
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/*
|
|
885
|
+
* Internal helper function to prep a Prompt for prompting
|
|
886
|
+
*/
|
|
887
|
+
private prepareForPrompt<A extends Prompt>(prompt: A): A {
|
|
888
|
+
if (this.unresolvedPrompt) {
|
|
889
|
+
throw new Error("Already awaiting a prompt result");
|
|
890
|
+
}
|
|
891
|
+
if (!this.player) {
|
|
892
|
+
throw new Error("No player attached to turn");
|
|
893
|
+
}
|
|
894
|
+
if (this.activeSubTurns.length) {
|
|
895
|
+
throw new Error("Prompts are not allowed while subturns are not resolved");
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
prompt.findChit = this.findChit;
|
|
899
|
+
prompt.id = `${this.id} prompt ${this.decisionIndex}`;
|
|
900
|
+
prompt.clock = this.clock;
|
|
901
|
+
prompt.canReset = this.state.hasUserMadeChoiceSinceUserContextChangedOrRng(this.decisionIndex - 1);
|
|
902
|
+
this.player.promptStatus.latestPromptMessage = prompt.message;
|
|
903
|
+
if (!this.player.promptStatus.latestPromptMessage.length) {
|
|
904
|
+
this.player.promptStatus.latestPromptMessage = "No prompt set";
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
this.flush();
|
|
908
|
+
|
|
909
|
+
return prompt;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/*
|
|
913
|
+
* Internal helper function to handle safely awaiting a prompt's response
|
|
914
|
+
*/
|
|
915
|
+
private async waitForPromptResolution(prompt: Prompt) {
|
|
916
|
+
if (!this.player) {
|
|
917
|
+
throw new Error("Must have player specified");
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
await this.checkPause();
|
|
921
|
+
const resolution = this.state.getOrCreatePromptResponse(this.decisionIndex);
|
|
922
|
+
await this.checkPause(); // state could have gotten funky here? if we have a resolution already? maybe not so bad?
|
|
923
|
+
|
|
924
|
+
if (resolution.response !== undefined) {
|
|
925
|
+
await new Promise((resolve) => nextTick(() => resolve(true))); // defer to next tick to make sure replay works identically
|
|
926
|
+
prompt.resolve(resolution.response);
|
|
927
|
+
} else {
|
|
928
|
+
if (this.player.promptStatus.latestPrompt.value) {
|
|
929
|
+
throw new Error("Player can only have prompt out at a time");
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
this.unresolvedPrompt = prompt;
|
|
933
|
+
this.player.promptStatus.latestPrompt.value = prompt;
|
|
934
|
+
|
|
935
|
+
// weird anti-pattern which will actually wait for a resolution to the prompt and return flow here.
|
|
936
|
+
let succeeded = false;
|
|
937
|
+
await new Promise((resolve) =>
|
|
938
|
+
prompt.onResolve((success: boolean) => {
|
|
939
|
+
succeeded = success;
|
|
940
|
+
resolve(undefined);
|
|
941
|
+
}),
|
|
942
|
+
);
|
|
943
|
+
|
|
944
|
+
if (prompt.shouldRerun) {
|
|
945
|
+
throw new RerunError(prompt.shouldRerun);
|
|
946
|
+
}
|
|
947
|
+
if (prompt.shouldReset) {
|
|
948
|
+
throw new RollBackError();
|
|
949
|
+
}
|
|
950
|
+
if (prompt.shouldStepBack) {
|
|
951
|
+
throw new StepBackError();
|
|
952
|
+
}
|
|
953
|
+
if (!succeeded) {
|
|
954
|
+
this.player.promptStatus.latestPrompt.value = undefined;
|
|
955
|
+
this.unresolvedPrompt = undefined;
|
|
956
|
+
// throw new Error("Unknown error");
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
this.player.promptStatus.latestPrompt.value = undefined;
|
|
961
|
+
resolution.response = prompt.response;
|
|
962
|
+
this.unresolvedPrompt = undefined;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// it is possible our state got reset out from under us and the response we have (which is a pointer)
|
|
966
|
+
// to an object -- MAY be writing to the OLD state
|
|
967
|
+
this.state.setOrCreatePromptResponse(this.decisionIndex, resolution);
|
|
968
|
+
|
|
969
|
+
this.player.promptStatus.latestPromptResponseTime = this.absoluteClock(this.player.id);
|
|
970
|
+
this.player.promptStatus.latestPromptMessage = undefined;
|
|
971
|
+
this.decisionIndex++;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/*
|
|
975
|
+
* The main runtime. Will attempt to run `fn` until it succeeds. Each time it has to loop back,
|
|
976
|
+
* it will reset chit's states to where they should be.
|
|
977
|
+
*/
|
|
978
|
+
async execute() {
|
|
979
|
+
// eslint-disable-next-line no-constant-condition
|
|
980
|
+
while (true) {
|
|
981
|
+
try {
|
|
982
|
+
await this.checkPause();
|
|
983
|
+
|
|
984
|
+
// actually execute this fn
|
|
985
|
+
const result = await this.fn(this);
|
|
986
|
+
|
|
987
|
+
if (this.player && this.player !== this.parent?.player) {
|
|
988
|
+
await this.possiblyConfirm("confirm turn end");
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
this.cleanUp();
|
|
992
|
+
return result;
|
|
993
|
+
} catch (error) {
|
|
994
|
+
if (error instanceof RerunError) {
|
|
995
|
+
if ((error as RerunError).turn === this) {
|
|
996
|
+
this.restartExecution();
|
|
997
|
+
continue;
|
|
998
|
+
}
|
|
999
|
+
throw error;
|
|
1000
|
+
}
|
|
1001
|
+
if (error instanceof StepBackError) {
|
|
1002
|
+
// bubble it up to parent if we can
|
|
1003
|
+
if (this.decisionIndex === 0 && this.parent?.player === this.player) {
|
|
1004
|
+
throw error;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
this.state.stepBack(); // once to clear the current prompt
|
|
1008
|
+
this.state.stepBack(); // and again to clear what was before
|
|
1009
|
+
this.restartExecution();
|
|
1010
|
+
continue;
|
|
1011
|
+
} else if (error instanceof RollBackError) {
|
|
1012
|
+
this.state.fullStepBack();
|
|
1013
|
+
this.restartExecution();
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
this.destroy();
|
|
1017
|
+
throw error;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/** @internal */
|
|
1023
|
+
_paused?: () => void;
|
|
1024
|
+
|
|
1025
|
+
/** @internal */
|
|
1026
|
+
pause() {
|
|
1027
|
+
if (this._paused) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
this.paused = new Promise((resolve) => {
|
|
1032
|
+
this._paused = resolve;
|
|
1033
|
+
});
|
|
1034
|
+
this.activeSubTurns.forEach((turn) => turn.pause());
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
/** @internal */
|
|
1038
|
+
async unpause() {
|
|
1039
|
+
if (this._paused) {
|
|
1040
|
+
this._paused();
|
|
1041
|
+
this._paused = undefined;
|
|
1042
|
+
}
|
|
1043
|
+
this.activeSubTurns.forEach((turn) => turn.unpause());
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/** @internal */
|
|
1047
|
+
async checkPause() {
|
|
1048
|
+
await this.paused;
|
|
1049
|
+
if (this.destroyed) {
|
|
1050
|
+
throw new DestroyError();
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/** @internal */
|
|
1055
|
+
destroy() {
|
|
1056
|
+
if (this.destroyed) {
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
this.destroyed = true;
|
|
1061
|
+
this.activeSubTurns.forEach((turn) => turn.destroy());
|
|
1062
|
+
Object.values(this.chitLookup).forEach((chit) => chit.unlock(this));
|
|
1063
|
+
if (this.unresolvedPrompt && this.player) {
|
|
1064
|
+
this.player.promptStatus.latestPrompt.value = undefined;
|
|
1065
|
+
this.unresolvedPrompt.destroy();
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/** @internal */
|
|
1070
|
+
fixPass() {
|
|
1071
|
+
this.pass = Date.now();
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
private cleanUp() {
|
|
1075
|
+
if (this.player) {
|
|
1076
|
+
this.player.promptStatus.latestPromptMessage = undefined;
|
|
1077
|
+
}
|
|
1078
|
+
this.completed = true;
|
|
1079
|
+
this.flush();
|
|
1080
|
+
Object.values(this.chitLookup).forEach((chit) => chit.unlock(this));
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/** @internal */
|
|
1084
|
+
get lastClockStep(): ClockStep | undefined {
|
|
1085
|
+
return this.clockSteps[this.clockSteps.length - 1];
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/** @internal */
|
|
1089
|
+
get clock() {
|
|
1090
|
+
return this.lastClockStep?.endClock() ?? 0;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/** @internal */
|
|
1094
|
+
playerVisibleClockTime(playerId?: string) {
|
|
1095
|
+
return this.lastClockStep?.endClock(playerId) ?? 0;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/** @internal */
|
|
1099
|
+
absoluteClock(playerId?: string): number {
|
|
1100
|
+
return this.parent?.absoluteClock(playerId) ?? this.clockDetails(playerId).clock;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
/** @internal */
|
|
1104
|
+
clockDetails(playerId?: string): ClockDetails {
|
|
1105
|
+
const result: ClockDetails = {
|
|
1106
|
+
clock: this.playerVisibleClockTime(playerId),
|
|
1107
|
+
pass: this.pass,
|
|
1108
|
+
};
|
|
1109
|
+
const visibleActiveTurns =
|
|
1110
|
+
this.lastClockStep instanceof SubTurnsClockStep ? this.lastClockStep.visibleTurns(playerId) : [];
|
|
1111
|
+
if (visibleActiveTurns.length > 0) {
|
|
1112
|
+
result.subTurns = {};
|
|
1113
|
+
|
|
1114
|
+
for (const turn of visibleActiveTurns) {
|
|
1115
|
+
result.subTurns[turn.id] = turn.clockDetails(playerId);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return result;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
private restartExecution() {
|
|
1122
|
+
this.activeSubTurns.forEach((t) => t.destroy());
|
|
1123
|
+
|
|
1124
|
+
const chits = Object.values(this.chitLookup).filter((chit) => chit.id);
|
|
1125
|
+
|
|
1126
|
+
chits.forEach((chit) => chit.beginDeserializing());
|
|
1127
|
+
|
|
1128
|
+
chits.forEach((chit) => {
|
|
1129
|
+
chit.lock(this);
|
|
1130
|
+
const lockedState = this.lockedChitStates[chit.id ?? ""];
|
|
1131
|
+
|
|
1132
|
+
if (lockedState) {
|
|
1133
|
+
chit.deserialize(lockedState, this.findChit);
|
|
1134
|
+
} else {
|
|
1135
|
+
chit.removeFromParent(); // effectively "deletes" it. In practice, the `fn` will recreate a new chit which will have the new ID, which replaces this one.
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
chits.forEach((chit) => chit.doneDeserializing());
|
|
1140
|
+
|
|
1141
|
+
if (this.player) {
|
|
1142
|
+
this.player.promptStatus.latestPrompt.value = undefined;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
this.chitLookup = {};
|
|
1146
|
+
Chit.walk(this.chitsToLock, (c) => {
|
|
1147
|
+
if (c.id) {
|
|
1148
|
+
this.chitLookup[c.id] = c;
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
|
|
1152
|
+
this.lastChitStates = { ...this.lockedChitStates }; // reset our known chit states
|
|
1153
|
+
this.clockSteps = [];
|
|
1154
|
+
this.decisionIndex = 0;
|
|
1155
|
+
this.newChitCounter = {};
|
|
1156
|
+
this.unresolvedPrompt = undefined;
|
|
1157
|
+
this.activeSubTurns = [];
|
|
1158
|
+
this.pass++;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
//
|
|
1163
|
+
// Helper classes - maybe will move to separate file if needed?
|
|
1164
|
+
//
|
|
1165
|
+
|
|
1166
|
+
type ChitLookup = { [id: string]: Chit };
|
|
1167
|
+
type ChitStateLookup = { [id: string]: string };
|
|
1168
|
+
|
|
1169
|
+
abstract class ClockStep {
|
|
1170
|
+
abstract get startClock(): number;
|
|
1171
|
+
abstract endClock(playerId?: string): number;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
class SubTurnsClockStep<P extends PlayerChit, R extends RootChit<P>> extends ClockStep {
|
|
1175
|
+
visibleTurns(playerId?: string) {
|
|
1176
|
+
if (this.turns.length === 1 || playerId === undefined) {
|
|
1177
|
+
return this.turns;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
const myTurn = this.turns.find((turn) => turn.player?.id === playerId);
|
|
1181
|
+
if (myTurn && !myTurn?.completed) {
|
|
1182
|
+
return [myTurn];
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
if (myTurn?.completed) {
|
|
1186
|
+
return [myTurn, ...this.turns.filter((turn) => turn !== myTurn)];
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
const completedTurns = this.turns.filter((turn) => turn.completed);
|
|
1190
|
+
if (completedTurns.length === this.turns.length) {
|
|
1191
|
+
return completedTurns;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
return [];
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
endClock(playerId?: string): number {
|
|
1198
|
+
return (
|
|
1199
|
+
this.startClock +
|
|
1200
|
+
this.visibleTurns(playerId).reduce((sum, turn) => sum + turn.playerVisibleClockTime(playerId), 0)
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
constructor(
|
|
1205
|
+
public startClock: number,
|
|
1206
|
+
public turns: Turn<any, P, R>[],
|
|
1207
|
+
) {
|
|
1208
|
+
super();
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
class FlushClockStep extends ClockStep {
|
|
1213
|
+
public log?: string;
|
|
1214
|
+
public endClock() {
|
|
1215
|
+
return this.startClock + 1;
|
|
1216
|
+
}
|
|
1217
|
+
constructor(
|
|
1218
|
+
public startClock: number,
|
|
1219
|
+
public state: ChitStateLookup,
|
|
1220
|
+
) {
|
|
1221
|
+
super();
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
export class StepBackError extends Error {}
|
|
1226
|
+
export class RollBackError extends Error {}
|
|
1227
|
+
export class DestroyError extends Error {}
|
|
1228
|
+
export class RerunError extends Error {
|
|
1229
|
+
constructor(public turn: Turn<any, any, any>) {
|
|
1230
|
+
super();
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
export class MismatchError extends Error {
|
|
1234
|
+
constructor() {
|
|
1235
|
+
super("Mismatch");
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
type SavedStateProcessingInstructions =
|
|
1240
|
+
| {
|
|
1241
|
+
type: "reset";
|
|
1242
|
+
turn: Turn<any, any, any>;
|
|
1243
|
+
}
|
|
1244
|
+
| {
|
|
1245
|
+
type: "prompt";
|
|
1246
|
+
turn: Turn<any, any, any>;
|
|
1247
|
+
prompt: Prompt;
|
|
1248
|
+
response: any;
|
|
1249
|
+
};
|