tangled
alpha
login
or
join now
eldridge.cam
/
cartography
0
fork
atom
Trading card city builder game?
0
fork
atom
overview
issues
pulls
pipelines
update client side to match latest websocket updates
eldridge.cam
1 month ago
0dcc0a35
008a37ce
verified
This commit was signed with the committer's
known signature
.
eldridge.cam
SSH Key Fingerprint:
SHA256:MAgO4sya2MgvdgUjSGKAO0lQ9X2HQp1Jb+x/Tpeeims=
0/0
Waiting for spindle ...
+49
-31
4 changed files
expand all
collapse all
unified
split
app
src
lib
appserver
socket
SocketV1.svelte.ts
SocketV1Protocol.ts
routes
(socket)
play
components
FieldView.svelte
PlayPage.svelte
+21
-7
app/src/lib/appserver/socket/SocketV1.svelte.ts
···
5
5
import Value from "typebox/value";
6
6
import {
7
7
Account,
8
8
-
GameState,
8
8
+
DeckState,
9
9
+
FieldState,
9
10
Request,
10
11
RequestMessage,
11
12
ResponseMessage,
···
100
101
});
101
102
}
102
103
103
103
-
$watchField(data: { id: number }, subscriber: (gameState: GameState | undefined) => void) {
104
104
-
let gameState: GameState | undefined = undefined;
104
104
+
$watchField(data: { id: number }, subscriber: (fieldState: FieldState | undefined) => void) {
105
105
+
let fieldState: FieldState | undefined = undefined;
105
106
this.#sendMessage({ type: "WatchField", data: data.id }).$subscribe((response) => {
106
107
if (response.type === "PutFieldState") {
107
107
-
gameState = response.data;
108
108
-
} else if (response.type === "PatchFieldState") {
108
108
+
fieldState = response.data;
109
109
+
} else if (response.type === "PatchState") {
110
110
+
const patches = response.data;
111
111
+
fieldState = jsonpatch.apply(fieldState, patches);
112
112
+
}
113
113
+
subscriber(fieldState);
114
114
+
});
115
115
+
}
116
116
+
117
117
+
$watchDeck(subscriber: (deckState: DeckState | undefined) => void) {
118
118
+
let deckState: DeckState | undefined = undefined;
119
119
+
this.#sendMessage({ type: "WatchDeck" }).$subscribe((response) => {
120
120
+
if (response.type === "PutDeckState") {
121
121
+
deckState = response.data;
122
122
+
} else if (response.type === "PatchState") {
109
123
const patches = response.data;
110
110
-
gameState = jsonpatch.apply(gameState, patches);
124
124
+
deckState = jsonpatch.apply(deckState, patches);
111
125
}
112
112
-
subscriber(gameState);
126
126
+
subscriber(deckState);
113
127
});
114
128
}
115
129
+20
-16
app/src/lib/appserver/socket/SocketV1Protocol.ts
···
94
94
export const FieldCitizen = Type.Object({ id: CitizenId, x: Type.Integer(), y: Type.Integer() });
95
95
export type FieldCitizen = StaticDecode<typeof FieldCitizen>;
96
96
97
97
-
export const GameStateField = Type.Object({
97
97
+
export const FieldState = Type.Object({
98
98
tiles: Type.Array(FieldTile),
99
99
citizens: Type.Array(FieldCitizen),
100
100
});
101
101
-
export type GameStateField = StaticDecode<typeof GameStateField>;
101
101
+
export type FieldState = StaticDecode<typeof FieldState>;
102
102
103
103
-
export const GameState = Type.Object({
104
104
-
deck: Type.Object({
105
105
-
tiles: Type.Array(Tile),
106
106
-
citizens: Type.Array(Citizen),
107
107
-
}),
108
108
-
field: GameStateField,
103
103
+
export const DeckState = Type.Object({
104
104
+
tiles: Type.Array(Tile),
105
105
+
citizens: Type.Array(Citizen),
109
106
});
110
110
-
export type GameState = StaticDecode<typeof GameState>;
107
107
+
export type DeckState = StaticDecode<typeof DeckState>;
111
108
112
109
export const Authenticate = Type.Object({
113
110
type: Type.Literal("Authenticate"),
114
111
data: Type.String(),
115
112
});
116
113
export type Authenticate = StaticDecode<typeof Authenticate>;
114
114
+
115
115
+
export const WatchDeck = Type.Object({ type: Type.Literal("WatchDeck") });
116
116
+
export type WatchDeck = StaticDecode<typeof WatchDeck>;
117
117
118
118
export const WatchField = Type.Object({ type: Type.Literal("WatchField"), data: Type.Integer() });
119
119
export type WatchField = StaticDecode<typeof WatchField>;
···
127
127
});
128
128
export type DebugAddCard = StaticDecode<typeof DebugAddCard>;
129
129
130
130
-
export const Request = Type.Union([Authenticate, WatchField, Unsubscribe, DebugAddCard]);
130
130
+
export const Request = Type.Union([Authenticate, WatchDeck, WatchField, Unsubscribe, DebugAddCard]);
131
131
export type Request = StaticDecode<typeof Request>;
132
132
133
133
export const Authenticated = Type.Object({ type: Type.Literal("Authenticated"), data: Account });
134
134
export type Authenticated = StaticDecode<typeof Authenticated>;
135
135
136
136
-
export const PutFieldState = Type.Object({ type: Type.Literal("PutFieldState"), data: GameState });
136
136
+
export const PutFieldState = Type.Object({ type: Type.Literal("PutFieldState"), data: FieldState });
137
137
export type PutFieldState = StaticDecode<typeof PutFieldState>;
138
138
139
139
-
export const PatchFieldState = Type.Object({
140
140
-
type: Type.Literal("PatchFieldState"),
139
139
+
export const PutDeckState = Type.Object({ type: Type.Literal("PutDeckState"), data: DeckState });
140
140
+
export type PutDeckState = StaticDecode<typeof PutDeckState>;
141
141
+
142
142
+
export const PatchState = Type.Object({
143
143
+
type: Type.Literal("PatchState"),
141
144
data: Type.Array(JsonPatch),
142
145
});
143
143
-
export type PatchFieldState = StaticDecode<typeof PatchFieldState>;
146
146
+
export type PatchState = StaticDecode<typeof PatchState>;
144
147
145
145
-
export const Response = Type.Union([Authenticated, PutFieldState, PatchFieldState]);
148
148
+
export const Response = Type.Union([Authenticated, PutFieldState, PutDeckState, PatchState]);
146
149
export type Response = StaticDecode<typeof Response>;
147
150
148
151
export type Once<T> = Branded<"Once", T>;
···
153
156
154
157
export interface SocketV1Protocol {
155
158
Authenticate: Once<Authenticated>;
156
156
-
WatchField: Stream<PutFieldState | PatchFieldState>;
159
159
+
WatchDeck: Stream<PutDeckState | PatchState>;
160
160
+
WatchField: Stream<PutFieldState | PatchState>;
157
161
Unsubscribe: never;
158
162
}
159
163
+3
-3
app/src/routes/(socket)/play/components/FieldView.svelte
···
1
1
<script lang="ts">
2
2
-
import { FieldTile, GameState, TileId } from "$lib/appserver/socket/SocketV1Protocol";
2
2
+
import { FieldTile, FieldState, TileId } from "$lib/appserver/socket/SocketV1Protocol";
3
3
import DragTile from "$lib/components/DragTile.svelte";
4
4
5
5
type RuntimeTile = FieldTile | { id: TileId; x: number | undefined; y: number | undefined };
6
6
7
7
-
const { gameState }: { gameState: GameState } = $props();
7
7
+
const { fieldState }: { fieldState: FieldState } = $props();
8
8
9
9
const uncommittedTiles: { id: TileId; x: number | undefined; y: number | undefined }[] = $state(
10
10
[],
11
11
);
12
12
-
const fieldTiles = $derived<RuntimeTile[]>([...gameState.field.tiles, ...uncommittedTiles]);
12
12
+
const fieldTiles = $derived<RuntimeTile[]>([...fieldState.tiles, ...uncommittedTiles]);
13
13
</script>
14
14
15
15
{#each fieldTiles as fieldTile (fieldTile.id)}
+5
-5
app/src/routes/(socket)/play/components/PlayPage.svelte
···
1
1
<script lang="ts">
2
2
-
import type { GameState } from "$lib/appserver/socket/SocketV1Protocol";
2
2
+
import type { FieldState } from "$lib/appserver/socket/SocketV1Protocol";
3
3
import { getSocket } from "$lib/appserver/provideSocket.svelte";
4
4
import DragTile from "$lib/components/DragTile.svelte";
5
5
import DragWindow from "$lib/components/DragWindow.svelte";
···
12
12
const fields = createListFields(() => "foxfriends");
13
13
14
14
let fieldId: number | undefined = $state();
15
15
-
let gameState: GameState | undefined = $state();
15
15
+
let fieldState: FieldState | undefined = $state();
16
16
17
17
$effect(() => {
18
18
if (fieldId) {
19
19
-
socket.$watchField({ id: fieldId }, (state) => (gameState = state));
19
19
+
socket.$watchField({ id: fieldId }, (state) => (fieldState = state));
20
20
}
21
21
});
22
22
</script>
···
45
45
{:else}
46
46
<div>Loading</div>
47
47
{/if}
48
48
-
{:else if gameState}
49
49
-
<FieldView {gameState} />
48
48
+
{:else if fieldState}
49
49
+
<FieldView {fieldState} />
50
50
{:else}
51
51
<div>Loading</div>
52
52
{/if}