@dreamboard-games/sdk 0.2.0 → 0.2.1-alpha.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/dist/{ThemeProvider-fy0_QzgO.d.ts → ThemeProvider-BBMVT3KG.d.ts} +1 -1
- package/dist/attributes-BeRyboMS.d.ts +279 -0
- package/dist/browser-interaction.d.ts +708 -0
- package/dist/browser-interaction.js +106 -0
- package/dist/browser-interaction.js.map +1 -0
- package/dist/{bundle-TIZcw8LB.d.ts → bundle-CDd5FKeD.d.ts} +3 -1
- package/dist/{chunk-U5C6BONG.js → chunk-326PGVAA.js} +2 -2
- package/dist/{chunk-VFTAA4WO.js → chunk-MKXPVOUT.js} +4 -2
- package/dist/chunk-MKXPVOUT.js.map +1 -0
- package/dist/{chunk-GKKBPPSW.js → chunk-MZNVHMJ5.js} +4 -4
- package/dist/{chunk-KAELH4KC.js → chunk-NKCRKGR2.js} +2 -2
- package/dist/{chunk-WN74KVNY.js → chunk-PEI3FIL2.js} +2 -2
- package/dist/chunk-PEI3FIL2.js.map +1 -0
- package/dist/chunk-QLG6VEMW.js +1691 -0
- package/dist/chunk-QLG6VEMW.js.map +1 -0
- package/dist/{chunk-WYPQ3GG5.js → chunk-WG4JQL3S.js} +4 -1
- package/dist/{chunk-WYPQ3GG5.js.map → chunk-WG4JQL3S.js.map} +1 -1
- package/dist/{chunk-7YAHLYBR.js → chunk-XV6D3ET4.js} +8 -4
- package/dist/{chunk-7YAHLYBR.js.map → chunk-XV6D3ET4.js.map} +1 -1
- package/dist/{chunk-TDSWKVZ4.js → chunk-ZABVH7AO.js} +1236 -17
- package/dist/chunk-ZABVH7AO.js.map +1 -0
- package/dist/{components-D5ZRE2Hl.d.ts → components-BoiVSYqx.d.ts} +1 -1
- package/dist/generated/runtime/primitives.d.ts +5 -4
- package/dist/generated/runtime/primitives.js +4 -3
- package/dist/generated/runtime-api.d.ts +1 -1
- package/dist/generated/runtime.d.ts +5 -4
- package/dist/generated/runtime.js +7 -6
- package/dist/generated/workspace-contract.d.ts +5 -4
- package/dist/generated/workspace-contract.js +6 -5
- package/dist/{hex-board-view-D_07hO6O.d.ts → hex-board-view-1iAyJRFn.d.ts} +1 -0
- package/dist/index.js +1 -1
- package/dist/infrastructure/reducer-bundle-abi.d.ts +113 -113
- package/dist/infrastructure/reducer-bundle-abi.js +1 -1
- package/dist/package-set.d.ts +2 -2
- package/dist/package-set.js +1 -1
- package/dist/reducer.d.ts +1 -1
- package/dist/reducer.js +305 -12
- package/dist/reducer.js.map +1 -1
- package/dist/runtime/primitives.d.ts +6 -5
- package/dist/runtime/primitives.js +4 -3
- package/dist/runtime/workspace-contract.d.ts +6 -5
- package/dist/runtime/workspace-contract.js +6 -5
- package/dist/{runtime-api-DWxvTr-O.d.ts → runtime-api-CPLm_XDG.d.ts} +6 -0
- package/dist/runtime.d.ts +5 -4
- package/dist/runtime.js +6 -5
- package/dist/testing.d.ts +2 -2
- package/dist/ui/components.d.ts +2 -2
- package/dist/ui/components.js +1 -1
- package/dist/{ui-contract-iQfTtUSL.d.ts → ui-contract-rzKBwOLC.d.ts} +5 -3
- package/dist/ui.d.ts +5 -5
- package/dist/ui.js +2 -2
- package/package.json +15 -9
- package/src/browser-interaction/attributes.ts +211 -0
- package/src/browser-interaction/canonical.ts +77 -0
- package/src/browser-interaction/constants.ts +77 -0
- package/src/browser-interaction/effects.ts +176 -0
- package/src/browser-interaction/index.ts +111 -0
- package/src/browser-interaction/normalize.ts +997 -0
- package/src/browser-interaction/registry.ts +70 -0
- package/src/browser-interaction/resolve.ts +596 -0
- package/src/browser-interaction/schemas.ts +152 -0
- package/src/browser-interaction/types.ts +304 -0
- package/src/browser-interaction.ts +1 -0
- package/src/generated/reducer-contract/wire.ts +1 -1
- package/src/generated/reducer-contract/zod.ts +3 -1
- package/src/package-set.ts +1 -1
- package/src/reducer/bundle/ingress-bundle.ts +1 -1
- package/src/reducer/bundle/trusted/interaction-types.ts +3 -0
- package/src/reducer/bundle/trusted/projection-builder.ts +337 -13
- package/src/reducer/ingress/input-codec.ts +1 -1
- package/src/reducer/ingress/session-codec.ts +1 -1
- package/src/runtime-internal/components/InteractionForm.tsx +345 -7
- package/src/runtime-internal/components/PluginRuntime.tsx +2 -0
- package/src/runtime-internal/components/board/target-layer.ts +2 -0
- package/src/runtime-internal/context/PluginStateContext.tsx +41 -0
- package/src/runtime-internal/hooks/useBoardInteractions.ts +73 -11
- package/src/runtime-internal/primitives/board.tsx +71 -0
- package/src/runtime-internal/primitives/interaction.tsx +160 -1
- package/src/runtime-internal/types/plugin-state.ts +6 -0
- package/src/runtime-internal/utils/browser-interaction-effects.ts +240 -0
- package/src/runtime-internal/utils/interaction-draft-digest.ts +252 -0
- package/src/runtime-internal/utils/semantic-projection-digest.ts +407 -0
- package/src/ui/components/board/HexGrid.tsx +3 -0
- package/src/ui/components/board/target-layer.ts +1 -0
- package/dist/chunk-TDSWKVZ4.js.map +0 -1
- package/dist/chunk-VFTAA4WO.js.map +0 -1
- package/dist/chunk-WN74KVNY.js.map +0 -1
- /package/dist/{chunk-U5C6BONG.js.map → chunk-326PGVAA.js.map} +0 -0
- /package/dist/{chunk-GKKBPPSW.js.map → chunk-MZNVHMJ5.js.map} +0 -0
- /package/dist/{chunk-KAELH4KC.js.map → chunk-NKCRKGR2.js.map} +0 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GameplaySnapshot,
|
|
3
|
+
InteractionDescriptor,
|
|
4
|
+
InteractionInputDescriptor,
|
|
5
|
+
PluginStateSnapshot,
|
|
6
|
+
} from "../types/plugin-state.js";
|
|
7
|
+
|
|
8
|
+
type JsonValue =
|
|
9
|
+
| null
|
|
10
|
+
| boolean
|
|
11
|
+
| number
|
|
12
|
+
| string
|
|
13
|
+
| JsonValue[]
|
|
14
|
+
| { [key: string]: JsonValue };
|
|
15
|
+
|
|
16
|
+
type CanonicalJson = JsonValue;
|
|
17
|
+
|
|
18
|
+
export const AUTHORIZED_SEAT_PROJECTION_DIGEST_VERSION =
|
|
19
|
+
"authorized-seat-projection@2";
|
|
20
|
+
|
|
21
|
+
export function semanticProjectionDigestForState(
|
|
22
|
+
state: PluginStateSnapshot,
|
|
23
|
+
): string | null {
|
|
24
|
+
const actorPlayerId = state.session.controllingPlayerId;
|
|
25
|
+
if (!actorPlayerId) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const seatOrder = state.lobby?.seats.map((seat) => seat.playerId) ?? [];
|
|
29
|
+
if (!seatOrder.includes(actorPlayerId)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return hashJson(semanticSeatProjection(state, state.gameplay, seatOrder));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function semanticSeatProjection(
|
|
36
|
+
state: PluginStateSnapshot,
|
|
37
|
+
gameplay: GameplaySnapshot,
|
|
38
|
+
seatOrder: readonly string[],
|
|
39
|
+
): CanonicalJson {
|
|
40
|
+
const playerToSeat = new Map(
|
|
41
|
+
seatOrder.map((playerId, index) => [playerId, index] as const),
|
|
42
|
+
);
|
|
43
|
+
const actorPlayerId = state.session.controllingPlayerId;
|
|
44
|
+
const actorSeat = actorPlayerId ? playerToSeat.get(actorPlayerId) : undefined;
|
|
45
|
+
if (actorSeat === undefined) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`authorized projection player ${actorPlayerId ?? "__none__"} is not present in seat order`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
digestVersion: AUTHORIZED_SEAT_PROJECTION_DIGEST_VERSION,
|
|
53
|
+
actorSeat,
|
|
54
|
+
currentStage: gameplay.currentStage ?? null,
|
|
55
|
+
stageSeats: gameplay.activePlayers.map((playerId) =>
|
|
56
|
+
canonicalizeSeatReference(playerId, playerToSeat),
|
|
57
|
+
),
|
|
58
|
+
view: canonicalizeSemanticProjectionValue(state.view, playerToSeat),
|
|
59
|
+
zones: canonicalizeSemanticProjectionValue(gameplay.zones ?? {}, playerToSeat),
|
|
60
|
+
availableInteractions: gameplay.availableInteractions.map((descriptor) =>
|
|
61
|
+
semanticInteractionDescriptor(descriptor, playerToSeat),
|
|
62
|
+
),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function semanticInteractionDescriptor(
|
|
67
|
+
descriptor: InteractionDescriptor,
|
|
68
|
+
playerToSeat: ReadonlyMap<string, number>,
|
|
69
|
+
): CanonicalJson {
|
|
70
|
+
const inputs = descriptor.inputs.map((input) =>
|
|
71
|
+
semanticInteractionInput(input, playerToSeat),
|
|
72
|
+
);
|
|
73
|
+
const { defaults, defaultProvenance } = collectDefaults(descriptor.inputs);
|
|
74
|
+
return {
|
|
75
|
+
interactionKey: descriptor.interactionKey,
|
|
76
|
+
interactionId: descriptor.interactionId,
|
|
77
|
+
stableIdentity: canonicalizeSemanticProjectionValue(
|
|
78
|
+
`${descriptor.interactionKey}:${descriptor.interactionId}`,
|
|
79
|
+
playerToSeat,
|
|
80
|
+
),
|
|
81
|
+
kind: descriptor.kind,
|
|
82
|
+
surface:
|
|
83
|
+
descriptor.zoneId ??
|
|
84
|
+
descriptor.zoneIds?.find((zoneId) => typeof zoneId === "string") ??
|
|
85
|
+
null,
|
|
86
|
+
commitMode:
|
|
87
|
+
descriptor.commit.mode === "autoWhenReady" ? "autoWhenReady" : "manual",
|
|
88
|
+
status: descriptor.availability.status ?? null,
|
|
89
|
+
available: descriptor.availability.status === "available",
|
|
90
|
+
inputs,
|
|
91
|
+
defaults: canonicalizeSemanticProjectionValue(defaults, playerToSeat),
|
|
92
|
+
defaultProvenance,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function semanticInteractionInput(
|
|
97
|
+
input: InteractionInputDescriptor,
|
|
98
|
+
playerToSeat: ReadonlyMap<string, number>,
|
|
99
|
+
): CanonicalJson {
|
|
100
|
+
const domain = asRecord(input.domain);
|
|
101
|
+
const selection = asRecord(domain.selection);
|
|
102
|
+
return {
|
|
103
|
+
key: input.key,
|
|
104
|
+
kind: input.kind,
|
|
105
|
+
domain: canonicalizeSemanticProjectionValue(input.domain, playerToSeat),
|
|
106
|
+
defaultValue:
|
|
107
|
+
input.defaultValue === undefined
|
|
108
|
+
? null
|
|
109
|
+
: canonicalizeSemanticProjectionValue(input.defaultValue, playerToSeat),
|
|
110
|
+
defaultProvenance: input.defaultValue === undefined ? null : "input",
|
|
111
|
+
selectionMode: stringField(selection, "mode"),
|
|
112
|
+
min: numberField(domain),
|
|
113
|
+
max: numberField(domain, "max"),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function collectDefaults(inputs: readonly InteractionInputDescriptor[]): {
|
|
118
|
+
defaults: Record<string, JsonValue>;
|
|
119
|
+
defaultProvenance: Record<string, "input">;
|
|
120
|
+
} {
|
|
121
|
+
const defaults: Record<string, JsonValue> = {};
|
|
122
|
+
const defaultProvenance: Record<string, "input"> = {};
|
|
123
|
+
for (const input of inputs) {
|
|
124
|
+
if (input.defaultValue !== undefined) {
|
|
125
|
+
defaults[input.key] = toCanonicalJson(input.defaultValue) as JsonValue;
|
|
126
|
+
defaultProvenance[input.key] = "input";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { defaults, defaultProvenance };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function canonicalizeSemanticProjectionValue(
|
|
133
|
+
value: unknown,
|
|
134
|
+
playerToSeat: ReadonlyMap<string, number>,
|
|
135
|
+
): CanonicalJson {
|
|
136
|
+
if (
|
|
137
|
+
value === null ||
|
|
138
|
+
typeof value === "boolean" ||
|
|
139
|
+
typeof value === "number"
|
|
140
|
+
) {
|
|
141
|
+
return toCanonicalJson(value);
|
|
142
|
+
}
|
|
143
|
+
if (typeof value === "string") {
|
|
144
|
+
return canonicalizeSeatReference(value, playerToSeat);
|
|
145
|
+
}
|
|
146
|
+
if (Array.isArray(value)) {
|
|
147
|
+
return value.map((item) =>
|
|
148
|
+
canonicalizeSemanticProjectionValue(item, playerToSeat),
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
if (isRecord(value)) {
|
|
152
|
+
return Object.fromEntries(
|
|
153
|
+
Object.entries(value)
|
|
154
|
+
.filter(
|
|
155
|
+
([key, item]) =>
|
|
156
|
+
item !== undefined &&
|
|
157
|
+
!SEMANTIC_PROJECTION_TRANSPORT_FIELDS.has(key),
|
|
158
|
+
)
|
|
159
|
+
.map(([key, item]) => [
|
|
160
|
+
canonicalizeObjectKey(key, playerToSeat),
|
|
161
|
+
canonicalizeSemanticProjectionProperty(key, item, playerToSeat),
|
|
162
|
+
]),
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function canonicalizeSemanticProjectionProperty(
|
|
169
|
+
key: string,
|
|
170
|
+
value: unknown,
|
|
171
|
+
playerToSeat: ReadonlyMap<string, number>,
|
|
172
|
+
): CanonicalJson {
|
|
173
|
+
const canonicalValue = canonicalizeSemanticProjectionValue(value, playerToSeat);
|
|
174
|
+
if (
|
|
175
|
+
(key === "eligibleTargets" || key === "dependentCases") &&
|
|
176
|
+
Array.isArray(canonicalValue)
|
|
177
|
+
) {
|
|
178
|
+
return [...canonicalValue].sort((left, right) =>
|
|
179
|
+
compareJson(canonicalJson(left), canonicalJson(right)),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
return canonicalValue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function canonicalizeSeatReference(
|
|
186
|
+
value: string,
|
|
187
|
+
playerToSeat: ReadonlyMap<string, number>,
|
|
188
|
+
): CanonicalJson {
|
|
189
|
+
const seat = playerToSeat.get(value);
|
|
190
|
+
return seat === undefined ? value : { $seat: seat };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function canonicalizeObjectKey(
|
|
194
|
+
key: string,
|
|
195
|
+
playerToSeat: ReadonlyMap<string, number>,
|
|
196
|
+
): string {
|
|
197
|
+
const seat = playerToSeat.get(key);
|
|
198
|
+
return seat === undefined ? key : `$seat:${seat}`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const SEMANTIC_PROJECTION_TRANSPORT_FIELDS = new Set([
|
|
202
|
+
"availableInteractionRefs",
|
|
203
|
+
"board",
|
|
204
|
+
"cursor",
|
|
205
|
+
"etag",
|
|
206
|
+
"hydratedAt",
|
|
207
|
+
"hydrationCursor",
|
|
208
|
+
"hydrationSequence",
|
|
209
|
+
"interactionRef",
|
|
210
|
+
"interactionRefs",
|
|
211
|
+
"lastEventId",
|
|
212
|
+
"receivedAt",
|
|
213
|
+
"sequence",
|
|
214
|
+
"serverTime",
|
|
215
|
+
"snapshotVersion",
|
|
216
|
+
"transportSequence",
|
|
217
|
+
"transportVersion",
|
|
218
|
+
"updatedAt",
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
function toCanonicalJson(value: unknown): CanonicalJson {
|
|
222
|
+
if (
|
|
223
|
+
value === null ||
|
|
224
|
+
typeof value === "boolean" ||
|
|
225
|
+
typeof value === "string"
|
|
226
|
+
) {
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
if (typeof value === "number") {
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
232
|
+
if (Array.isArray(value)) {
|
|
233
|
+
return value.map((item) => toCanonicalJson(item));
|
|
234
|
+
}
|
|
235
|
+
if (isRecord(value)) {
|
|
236
|
+
return Object.fromEntries(
|
|
237
|
+
Object.entries(value)
|
|
238
|
+
.filter(([, item]) => item !== undefined)
|
|
239
|
+
.map(([key, item]) => [key, toCanonicalJson(item)]),
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function hashJson(value: CanonicalJson): string {
|
|
246
|
+
return `sha256:${sha256Hex(canonicalJson(value))}`;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function canonicalJson(value: CanonicalJson): string {
|
|
250
|
+
return JSON.stringify(canonicalizeJson(value));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function canonicalizeJson(value: CanonicalJson): CanonicalJson {
|
|
254
|
+
if (
|
|
255
|
+
value === null ||
|
|
256
|
+
typeof value === "boolean" ||
|
|
257
|
+
typeof value === "string"
|
|
258
|
+
) {
|
|
259
|
+
return value;
|
|
260
|
+
}
|
|
261
|
+
if (typeof value === "number") {
|
|
262
|
+
if (!Number.isFinite(value)) {
|
|
263
|
+
throw new Error("canonical JSON contains a non-finite number");
|
|
264
|
+
}
|
|
265
|
+
return value;
|
|
266
|
+
}
|
|
267
|
+
if (Array.isArray(value)) {
|
|
268
|
+
return value.map((item) => canonicalizeJson(item));
|
|
269
|
+
}
|
|
270
|
+
return Object.fromEntries(
|
|
271
|
+
Object.entries(value)
|
|
272
|
+
.sort(([left], [right]) => compareJson(left, right))
|
|
273
|
+
.map(([key, item]) => [key, canonicalizeJson(item)]),
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function compareJson(left: string, right: string): number {
|
|
278
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
282
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function asRecord(value: unknown): Record<string, unknown> {
|
|
286
|
+
return isRecord(value) ? value : {};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function stringField(record: Record<string, unknown>, key: string): string | null {
|
|
290
|
+
const value = record[key];
|
|
291
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function numberField(
|
|
295
|
+
record: Record<string, unknown>,
|
|
296
|
+
key = "min",
|
|
297
|
+
): number | null {
|
|
298
|
+
const value = record[key];
|
|
299
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const SHA256_K = [
|
|
303
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
|
304
|
+
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
305
|
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
|
306
|
+
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
307
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
|
308
|
+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
309
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
|
310
|
+
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
311
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
|
312
|
+
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
313
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
314
|
+
];
|
|
315
|
+
|
|
316
|
+
function sha256Hex(input: string): string {
|
|
317
|
+
const bytes = utf8Bytes(input);
|
|
318
|
+
const bitLength = bytes.length * 8;
|
|
319
|
+
bytes.push(0x80);
|
|
320
|
+
while (bytes.length % 64 !== 56) {
|
|
321
|
+
bytes.push(0);
|
|
322
|
+
}
|
|
323
|
+
for (let shift = 56; shift >= 0; shift -= 8) {
|
|
324
|
+
bytes.push(Math.floor(bitLength / 2 ** shift) & 0xff);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
let h0 = 0x6a09e667;
|
|
328
|
+
let h1 = 0xbb67ae85;
|
|
329
|
+
let h2 = 0x3c6ef372;
|
|
330
|
+
let h3 = 0xa54ff53a;
|
|
331
|
+
let h4 = 0x510e527f;
|
|
332
|
+
let h5 = 0x9b05688c;
|
|
333
|
+
let h6 = 0x1f83d9ab;
|
|
334
|
+
let h7 = 0x5be0cd19;
|
|
335
|
+
const words = new Array<number>(64);
|
|
336
|
+
|
|
337
|
+
for (let offset = 0; offset < bytes.length; offset += 64) {
|
|
338
|
+
for (let index = 0; index < 16; index += 1) {
|
|
339
|
+
const base = offset + index * 4;
|
|
340
|
+
words[index] =
|
|
341
|
+
((bytes[base]! << 24) |
|
|
342
|
+
(bytes[base + 1]! << 16) |
|
|
343
|
+
(bytes[base + 2]! << 8) |
|
|
344
|
+
bytes[base + 3]!) >>>
|
|
345
|
+
0;
|
|
346
|
+
}
|
|
347
|
+
for (let index = 16; index < 64; index += 1) {
|
|
348
|
+
const s0 =
|
|
349
|
+
rotateRight(words[index - 15]!, 7) ^
|
|
350
|
+
rotateRight(words[index - 15]!, 18) ^
|
|
351
|
+
(words[index - 15]! >>> 3);
|
|
352
|
+
const s1 =
|
|
353
|
+
rotateRight(words[index - 2]!, 17) ^
|
|
354
|
+
rotateRight(words[index - 2]!, 19) ^
|
|
355
|
+
(words[index - 2]! >>> 10);
|
|
356
|
+
words[index] =
|
|
357
|
+
(words[index - 16]! + s0 + words[index - 7]! + s1) >>> 0;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
let a = h0;
|
|
361
|
+
let b = h1;
|
|
362
|
+
let c = h2;
|
|
363
|
+
let d = h3;
|
|
364
|
+
let e = h4;
|
|
365
|
+
let f = h5;
|
|
366
|
+
let g = h6;
|
|
367
|
+
let h = h7;
|
|
368
|
+
|
|
369
|
+
for (let index = 0; index < 64; index += 1) {
|
|
370
|
+
const s1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
|
|
371
|
+
const ch = (e & f) ^ (~e & g);
|
|
372
|
+
const temp1 = (h + s1 + ch + SHA256_K[index]! + words[index]!) >>> 0;
|
|
373
|
+
const s0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
|
|
374
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
375
|
+
const temp2 = (s0 + maj) >>> 0;
|
|
376
|
+
h = g;
|
|
377
|
+
g = f;
|
|
378
|
+
f = e;
|
|
379
|
+
e = (d + temp1) >>> 0;
|
|
380
|
+
d = c;
|
|
381
|
+
c = b;
|
|
382
|
+
b = a;
|
|
383
|
+
a = (temp1 + temp2) >>> 0;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
h0 = (h0 + a) >>> 0;
|
|
387
|
+
h1 = (h1 + b) >>> 0;
|
|
388
|
+
h2 = (h2 + c) >>> 0;
|
|
389
|
+
h3 = (h3 + d) >>> 0;
|
|
390
|
+
h4 = (h4 + e) >>> 0;
|
|
391
|
+
h5 = (h5 + f) >>> 0;
|
|
392
|
+
h6 = (h6 + g) >>> 0;
|
|
393
|
+
h7 = (h7 + h) >>> 0;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return [h0, h1, h2, h3, h4, h5, h6, h7]
|
|
397
|
+
.map((value) => value.toString(16).padStart(8, "0"))
|
|
398
|
+
.join("");
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function rotateRight(value: number, bits: number): number {
|
|
402
|
+
return (value >>> bits) | (value << (32 - bits));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function utf8Bytes(input: string): number[] {
|
|
406
|
+
return Array.from(new TextEncoder().encode(input));
|
|
407
|
+
}
|
|
@@ -1041,6 +1041,7 @@ function HexGridImpl(
|
|
|
1041
1041
|
return (
|
|
1042
1042
|
<g
|
|
1043
1043
|
key={space.id}
|
|
1044
|
+
{...state.browserAttributes}
|
|
1044
1045
|
transform={`translate(${pos.x}, ${pos.y})`}
|
|
1045
1046
|
role={isSelectable ? "button" : undefined}
|
|
1046
1047
|
className={clsx(isSelectable && "cursor-pointer")}
|
|
@@ -1140,6 +1141,7 @@ function HexGridImpl(
|
|
|
1140
1141
|
return (
|
|
1141
1142
|
<g
|
|
1142
1143
|
key={edge.id}
|
|
1144
|
+
{...state.browserAttributes}
|
|
1143
1145
|
role={isSelectable ? "button" : undefined}
|
|
1144
1146
|
className={clsx(isSelectable && "cursor-pointer")}
|
|
1145
1147
|
onPointerEnter={() => setHoveredEdgeId(edge.id)}
|
|
@@ -1215,6 +1217,7 @@ function HexGridImpl(
|
|
|
1215
1217
|
return (
|
|
1216
1218
|
<g
|
|
1217
1219
|
key={vertex.id}
|
|
1220
|
+
{...state.browserAttributes}
|
|
1218
1221
|
role={isSelectable ? "button" : undefined}
|
|
1219
1222
|
className={clsx(isSelectable && "cursor-pointer")}
|
|
1220
1223
|
onPointerEnter={() => setHoveredVertexId(vertex.id)}
|