@@ -5,25 +5,18 @@ import encodeGameActionResponse from '@deities/apollo/actions/encodeGameActionRe
5
5
import {
6
6
decodeEffects ,
7
7
Effects ,
8
- EncodedEffects ,
9
8
encodeEffects ,
10
9
} from '@deities/apollo/Effects.tsx' ;
11
10
import {
12
11
decodeActionResponse ,
13
12
encodeAction ,
14
- EncodedActionResponse ,
15
13
} from '@deities/apollo/EncodedActions.tsx' ;
16
14
import { decodeGameState } from '@deities/apollo/GameState.tsx' ;
17
15
import { computeVisibleEndTurnActionResponse } from '@deities/apollo/lib/computeVisibleActions.tsx' ;
18
16
import decodeGameActionResponse from '@deities/apollo/lib/decodeGameActionResponse.tsx' ;
19
17
import dropLabelsFromActionResponse from '@deities/apollo/lib/dropLabelsFromActionResponse.tsx' ;
20
18
import dropLabelsFromGameState from '@deities/apollo/lib/dropLabelsFromGameState.tsx' ;
21
- import {
22
- EncodedGameState ,
23
- GameActionResponse ,
24
- GameState ,
25
- } from '@deities/apollo/Types.tsx' ;
26
- import { PlainMap } from '@deities/athena/map/PlainMap.tsx' ;
19
+ import { GameActionResponse , GameState } from '@deities/apollo/Types.tsx' ;
27
20
import MapData from '@deities/athena/MapData.tsx' ;
28
21
import { getHiddenLabels } from '@deities/athena/WinConditions.tsx' ;
29
22
import onGameEnd from '@deities/hermes/game/onGameEnd.tsx' ;
@@ -32,17 +25,27 @@ import toClientGame, {
32
25
} from '@deities/hermes/game/toClientGame.tsx' ;
33
26
import { useCallback } from 'react' ;
34
27
import gameActionWorker from '../workers/gameAction.tsx?worker' ;
35
-
36
- type ClientGameAction = [
37
- actionResponse : EncodedActionResponse ,
38
- map : PlainMap ,
39
- gameState : EncodedGameState ,
40
- effects : EncodedEffects ,
41
- ] ;
28
+ import {
29
+ ClientGameActionRequest ,
30
+ ClientGameActionResponse ,
31
+ } from '../workers/Types.tsx' ;
42
32
43
33
const ActionError = ( action : Action ) =>
44
34
new Error ( `Map: Error executing remote '${ action . type } ' action.` ) ;
45
35
36
+ let worker : Worker | null = null ;
37
+ const getWorker = ( ) => {
38
+ if ( worker ) {
39
+ return worker ;
40
+ }
41
+ worker = new gameActionWorker ( ) ;
42
+ worker . onerror = ( ) => {
43
+ worker ?. terminate ( ) ;
44
+ worker = null ;
45
+ } ;
46
+ return worker ;
47
+ } ;
48
+
46
49
export default function useClientGameAction (
47
50
game : ClientGame | null ,
48
51
setGame : ( game : ClientGame ) => void ,
@@ -69,27 +72,36 @@ export default function useClientGameAction(
69
72
}
70
73
71
74
try {
72
- const worker = new gameActionWorker ( ) ;
75
+ const message : ClientGameActionRequest = [
76
+ map . toJSON ( ) ,
77
+ encodeEffects ( game . effects ) ,
78
+ encodeAction ( action ) ,
79
+ mutateAction ,
80
+ ] ;
81
+
73
82
const [
74
83
encodedActionResponse ,
75
84
plainMap ,
76
85
encodedGameState ,
77
86
encodedEffects ,
78
- ] = await new Promise < ClientGameAction > ( ( resolve ) => {
79
- worker . postMessage ( [
80
- map . toJSON ( ) ,
81
- encodeEffects ( game . effects ) ,
82
- encodeAction ( action ) ,
83
- mutateAction ,
84
- ] ) ;
85
- worker . onmessage = ( event : MessageEvent < ClientGameAction > ) =>
86
- resolve ( event . data ) ;
87
+ ] = await new Promise < ClientGameActionResponse > ( ( resolve , reject ) => {
88
+ const { port1, port2 } = new MessageChannel ( ) ;
89
+ port1 . onmessage = (
90
+ event : MessageEvent < ClientGameActionResponse | null > ,
91
+ ) => {
92
+ if ( event . data ) {
93
+ resolve ( event . data ) ;
94
+ } else {
95
+ reject ( ) ;
96
+ }
97
+ } ;
98
+ port1 . onmessageerror = reject ;
99
+ getWorker ( ) . postMessage ( message , [ port2 ] ) ;
87
100
} ) ;
88
-
89
101
actionResponse = decodeActionResponse ( encodedActionResponse ) ;
90
102
initialActiveMap = MapData . fromObject ( plainMap ) ;
91
103
gameState = decodeGameState ( encodedGameState ) ;
92
- newEffects = decodeEffects ( encodedEffects ) ;
104
+ newEffects = encodedEffects ? decodeEffects ( encodedEffects ) : null ;
93
105
} catch ( error ) {
94
106
throw process . env . NODE_ENV === 'development'
95
107
? error
0 commit comments