@couch-kit/host 1.5.1 → 1.6.0
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/lib/action-recorder.d.ts +43 -0
- package/lib/action-recorder.d.ts.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/action-recorder.ts +114 -0
- package/src/index.tsx +1 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { IAction, IGameState } from "@couch-kit/core";
|
|
2
|
+
/**
|
|
3
|
+
* A recorded action with timing metadata.
|
|
4
|
+
*/
|
|
5
|
+
export interface RecordedAction<A extends IAction = IAction> {
|
|
6
|
+
action: A;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A complete recording of a game session.
|
|
11
|
+
*/
|
|
12
|
+
export interface ActionRecording<S extends IGameState = IGameState, A extends IAction = IAction> {
|
|
13
|
+
initialState: S;
|
|
14
|
+
actions: RecordedAction<A>[];
|
|
15
|
+
startTimestamp: number;
|
|
16
|
+
endTimestamp?: number;
|
|
17
|
+
metadata?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Return type of useActionRecorder.
|
|
21
|
+
*/
|
|
22
|
+
export interface ActionRecorderControls<S extends IGameState = IGameState, A extends IAction = IAction> {
|
|
23
|
+
/** Whether recording is currently active */
|
|
24
|
+
isRecording: boolean;
|
|
25
|
+
/** Number of actions recorded so far */
|
|
26
|
+
recordedCount: number;
|
|
27
|
+
/** Start recording actions. Captures current state as initial state. */
|
|
28
|
+
startRecording: (currentState: S, metadata?: Record<string, unknown>) => void;
|
|
29
|
+
/** Stop recording and return the recording */
|
|
30
|
+
stopRecording: () => ActionRecording<S, A> | null;
|
|
31
|
+
/** Record a single action (call this when dispatching) */
|
|
32
|
+
recordAction: (action: A) => void;
|
|
33
|
+
/** Export the current recording as JSON string */
|
|
34
|
+
exportRecording: () => string | null;
|
|
35
|
+
/** Discard the current recording */
|
|
36
|
+
discardRecording: () => void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Hook that enables recording of game actions for later replay.
|
|
40
|
+
* Used on the host side to capture game sessions.
|
|
41
|
+
*/
|
|
42
|
+
export declare function useActionRecorder<S extends IGameState = IGameState, A extends IAction = IAction>(): ActionRecorderControls<S, A>;
|
|
43
|
+
//# sourceMappingURL=action-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-recorder.d.ts","sourceRoot":"","sources":["../src/action-recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IACzD,MAAM,EAAE,CAAC,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAC9B,CAAC,SAAS,UAAU,GAAG,UAAU,EACjC,CAAC,SAAS,OAAO,GAAG,OAAO;IAE3B,YAAY,EAAE,CAAC,CAAC;IAChB,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CACrC,CAAC,SAAS,UAAU,GAAG,UAAU,EACjC,CAAC,SAAS,OAAO,GAAG,OAAO;IAE3B,4CAA4C;IAC5C,WAAW,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,cAAc,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC9E,8CAA8C;IAC9C,aAAa,EAAE,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IAClD,0DAA0D;IAC1D,YAAY,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAClC,kDAAkD;IAClD,eAAe,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACrC,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,SAAS,UAAU,GAAG,UAAU,EACjC,CAAC,SAAS,OAAO,GAAG,OAAO,KACxB,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CA0DhC"}
|
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@couch-kit/host",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": true
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"prepublishOnly": "bun run build"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@couch-kit/core": "0.
|
|
58
|
+
"@couch-kit/core": "0.8.0",
|
|
59
59
|
"buffer": "^6.0.3",
|
|
60
60
|
"js-sha1": "^0.7.0",
|
|
61
61
|
"react-native-nitro-http-server": "^1.5.4"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
import type { IAction, IGameState } from "@couch-kit/core";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A recorded action with timing metadata.
|
|
6
|
+
*/
|
|
7
|
+
export interface RecordedAction<A extends IAction = IAction> {
|
|
8
|
+
action: A;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A complete recording of a game session.
|
|
14
|
+
*/
|
|
15
|
+
export interface ActionRecording<
|
|
16
|
+
S extends IGameState = IGameState,
|
|
17
|
+
A extends IAction = IAction,
|
|
18
|
+
> {
|
|
19
|
+
initialState: S;
|
|
20
|
+
actions: RecordedAction<A>[];
|
|
21
|
+
startTimestamp: number;
|
|
22
|
+
endTimestamp?: number;
|
|
23
|
+
metadata?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Return type of useActionRecorder.
|
|
28
|
+
*/
|
|
29
|
+
export interface ActionRecorderControls<
|
|
30
|
+
S extends IGameState = IGameState,
|
|
31
|
+
A extends IAction = IAction,
|
|
32
|
+
> {
|
|
33
|
+
/** Whether recording is currently active */
|
|
34
|
+
isRecording: boolean;
|
|
35
|
+
/** Number of actions recorded so far */
|
|
36
|
+
recordedCount: number;
|
|
37
|
+
/** Start recording actions. Captures current state as initial state. */
|
|
38
|
+
startRecording: (currentState: S, metadata?: Record<string, unknown>) => void;
|
|
39
|
+
/** Stop recording and return the recording */
|
|
40
|
+
stopRecording: () => ActionRecording<S, A> | null;
|
|
41
|
+
/** Record a single action (call this when dispatching) */
|
|
42
|
+
recordAction: (action: A) => void;
|
|
43
|
+
/** Export the current recording as JSON string */
|
|
44
|
+
exportRecording: () => string | null;
|
|
45
|
+
/** Discard the current recording */
|
|
46
|
+
discardRecording: () => void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Hook that enables recording of game actions for later replay.
|
|
51
|
+
* Used on the host side to capture game sessions.
|
|
52
|
+
*/
|
|
53
|
+
export function useActionRecorder<
|
|
54
|
+
S extends IGameState = IGameState,
|
|
55
|
+
A extends IAction = IAction,
|
|
56
|
+
>(): ActionRecorderControls<S, A> {
|
|
57
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
58
|
+
const [recordedCount, setRecordedCount] = useState(0);
|
|
59
|
+
const recordingRef = useRef<ActionRecording<S, A> | null>(null);
|
|
60
|
+
|
|
61
|
+
const startRecording = useCallback(
|
|
62
|
+
(currentState: S, metadata?: Record<string, unknown>) => {
|
|
63
|
+
recordingRef.current = {
|
|
64
|
+
initialState: currentState,
|
|
65
|
+
actions: [],
|
|
66
|
+
startTimestamp: Date.now(),
|
|
67
|
+
metadata,
|
|
68
|
+
};
|
|
69
|
+
setIsRecording(true);
|
|
70
|
+
setRecordedCount(0);
|
|
71
|
+
},
|
|
72
|
+
[],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const stopRecording = useCallback((): ActionRecording<S, A> | null => {
|
|
76
|
+
if (!recordingRef.current) return null;
|
|
77
|
+
|
|
78
|
+
recordingRef.current.endTimestamp = Date.now();
|
|
79
|
+
const recording = recordingRef.current;
|
|
80
|
+
setIsRecording(false);
|
|
81
|
+
return recording;
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
const recordAction = useCallback((action: A) => {
|
|
85
|
+
if (!recordingRef.current) return;
|
|
86
|
+
|
|
87
|
+
recordingRef.current.actions.push({
|
|
88
|
+
action,
|
|
89
|
+
timestamp: Date.now(),
|
|
90
|
+
});
|
|
91
|
+
setRecordedCount((c) => c + 1);
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
const exportRecording = useCallback((): string | null => {
|
|
95
|
+
if (!recordingRef.current) return null;
|
|
96
|
+
return JSON.stringify(recordingRef.current, null, 2);
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
99
|
+
const discardRecording = useCallback(() => {
|
|
100
|
+
recordingRef.current = null;
|
|
101
|
+
setIsRecording(false);
|
|
102
|
+
setRecordedCount(0);
|
|
103
|
+
}, []);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
isRecording,
|
|
107
|
+
recordedCount,
|
|
108
|
+
startRecording,
|
|
109
|
+
stopRecording,
|
|
110
|
+
recordAction,
|
|
111
|
+
exportRecording,
|
|
112
|
+
discardRecording,
|
|
113
|
+
};
|
|
114
|
+
}
|
package/src/index.tsx
CHANGED