@roster-lock/types 1.0.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/LICENSE.md +11 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/v1/draft/index.js +3 -0
- package/dist/v1/draft/index.js.map +1 -0
- package/dist/v1/index.js +24 -0
- package/dist/v1/index.js.map +1 -0
- package/dist/v1/lock/engine.js +3 -0
- package/dist/v1/lock/engine.js.map +1 -0
- package/dist/v1/lock/index.js +21 -0
- package/dist/v1/lock/index.js.map +1 -0
- package/dist/v1/lock/piece-meta.js +3 -0
- package/dist/v1/lock/piece-meta.js.map +1 -0
- package/dist/v1/lock/roster.js +3 -0
- package/dist/v1/lock/roster.js.map +1 -0
- package/dist/v1/lock/selection/index.js +18 -0
- package/dist/v1/lock/selection/index.js.map +1 -0
- package/dist/v1/lock/selection/meta.js +3 -0
- package/dist/v1/lock/selection/meta.js.map +1 -0
- package/dist/v1/lock/selection/script.js +3 -0
- package/dist/v1/lock/selection/script.js.map +1 -0
- package/dist/v1/lock/selection/selection-types/game-controlled.js +3 -0
- package/dist/v1/lock/selection/selection-types/game-controlled.js.map +1 -0
- package/dist/v1/lock/selection/selection-types/normal.js +3 -0
- package/dist/v1/lock/selection/selection-types/normal.js.map +1 -0
- package/dist/v1/lock/selection/selection-types/preselected.js +3 -0
- package/dist/v1/lock/selection/selection-types/preselected.js.map +1 -0
- package/dist/v1/lock/selection/selection-types/unselectable.js +3 -0
- package/dist/v1/lock/selection/selection-types/unselectable.js.map +1 -0
- package/dist/v1/metadata.js +3 -0
- package/dist/v1/metadata.js.map +1 -0
- package/dist/v1/relay/index.js +3 -0
- package/dist/v1/relay/index.js.map +1 -0
- package/dist/v1/request/index.js +20 -0
- package/dist/v1/request/index.js.map +1 -0
- package/dist/v1/request/input/agent-to-relay.js +3 -0
- package/dist/v1/request/input/agent-to-relay.js.map +1 -0
- package/dist/v1/request/input/client-to-agent.js +3 -0
- package/dist/v1/request/input/client-to-agent.js.map +1 -0
- package/dist/v1/request/input/index.js +20 -0
- package/dist/v1/request/input/index.js.map +1 -0
- package/dist/v1/request/input/user-to-client.js +3 -0
- package/dist/v1/request/input/user-to-client.js.map +1 -0
- package/dist/v1/request/output/download-event.js +14 -0
- package/dist/v1/request/output/download-event.js.map +1 -0
- package/dist/v1/request/output/index.js +18 -0
- package/dist/v1/request/output/index.js.map +1 -0
- package/dist/v1/request/shared.js +3 -0
- package/dist/v1/request/shared.js.map +1 -0
- package/dist/v1/runtime/download/Archive.js +3 -0
- package/dist/v1/runtime/download/Archive.js.map +1 -0
- package/dist/v1/runtime/download/Decompressor.js +3 -0
- package/dist/v1/runtime/download/Decompressor.js.map +1 -0
- package/dist/v1/runtime/download/Protocol.js +3 -0
- package/dist/v1/runtime/download/Protocol.js.map +1 -0
- package/dist/v1/runtime/download/index.js +21 -0
- package/dist/v1/runtime/download/index.js.map +1 -0
- package/dist/v1/runtime/download/types.js +3 -0
- package/dist/v1/runtime/download/types.js.map +1 -0
- package/dist/v1/runtime/index.js +20 -0
- package/dist/v1/runtime/index.js.map +1 -0
- package/dist/v1/runtime/piece-selection-sort/index.js +3 -0
- package/dist/v1/runtime/piece-selection-sort/index.js.map +1 -0
- package/dist/v1/runtime/unstrusted-script/index.js +18 -0
- package/dist/v1/runtime/unstrusted-script/index.js.map +1 -0
- package/dist/v1/runtime/unstrusted-script/purpose-input.js +3 -0
- package/dist/v1/runtime/unstrusted-script/purpose-input.js.map +1 -0
- package/dist/v1/shared.js +3 -0
- package/dist/v1/shared.js.map +1 -0
- package/package.json +25 -0
- package/src/index.ts +2 -0
- package/src/v1/draft/index.ts +32 -0
- package/src/v1/index.ts +8 -0
- package/src/v1/lock/engine.ts +40 -0
- package/src/v1/lock/index.ts +24 -0
- package/src/v1/lock/piece-meta.ts +9 -0
- package/src/v1/lock/roster.ts +27 -0
- package/src/v1/lock/selection/index.ts +34 -0
- package/src/v1/lock/selection/meta.ts +17 -0
- package/src/v1/lock/selection/script.ts +56 -0
- package/src/v1/lock/selection/selection-types/game-controlled.ts +9 -0
- package/src/v1/lock/selection/selection-types/normal.ts +32 -0
- package/src/v1/lock/selection/selection-types/preselected.ts +12 -0
- package/src/v1/lock/selection/selection-types/unselectable.ts +3 -0
- package/src/v1/metadata.ts +10 -0
- package/src/v1/relay/index.ts +19 -0
- package/src/v1/request/index.ts +4 -0
- package/src/v1/request/input/agent-to-relay.ts +6 -0
- package/src/v1/request/input/client-to-agent.ts +19 -0
- package/src/v1/request/input/index.ts +4 -0
- package/src/v1/request/input/user-to-client.ts +21 -0
- package/src/v1/request/output/download-event.ts +49 -0
- package/src/v1/request/output/index.ts +34 -0
- package/src/v1/request/shared.ts +13 -0
- package/src/v1/runtime/download/Archive.ts +13 -0
- package/src/v1/runtime/download/Decompressor.ts +6 -0
- package/src/v1/runtime/download/Protocol.ts +15 -0
- package/src/v1/runtime/download/index.ts +5 -0
- package/src/v1/runtime/download/types.ts +18 -0
- package/src/v1/runtime/index.ts +4 -0
- package/src/v1/runtime/piece-selection-sort/index.ts +34 -0
- package/src/v1/runtime/unstrusted-script/index.ts +59 -0
- package/src/v1/runtime/unstrusted-script/purpose-input.ts +34 -0
- package/src/v1/shared.ts +14 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RosterLockIdentity } from "../shared";
|
|
2
|
+
import { RosterLockEngineConfig } from "./engine";
|
|
3
|
+
import { RosterLockPiece } from "./roster";
|
|
4
|
+
import { RosterLockSelectionConfig } from "./selection";
|
|
5
|
+
import { RosterLockPieceMeta } from "./piece-meta";
|
|
6
|
+
|
|
7
|
+
export * from "./engine";
|
|
8
|
+
export * from "./roster";
|
|
9
|
+
export * from "./selection";
|
|
10
|
+
export * from "./piece-meta";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export type RosterLockV1Config = {
|
|
14
|
+
configIdentity: RosterLockIdentity<"lock", 1>,
|
|
15
|
+
|
|
16
|
+
author: string,
|
|
17
|
+
title: string,
|
|
18
|
+
version: string,
|
|
19
|
+
engine: RosterLockEngineConfig,
|
|
20
|
+
rosters: Record<string, Array<RosterLockPiece>>,
|
|
21
|
+
selection: RosterLockSelectionConfig,
|
|
22
|
+
pieceMeta: RosterLockPieceMeta,
|
|
23
|
+
}
|
|
24
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PieceType } from "../shared";
|
|
2
|
+
import { JSONShallowObject, SelectionPieceMeta } from "./selection/meta";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Custom fields (tier, difficulty, tags, etc) that selection configs can validate against
|
|
6
|
+
and merge algorithms/scripts can read via PIECE_META.get(). Kept out of the selection
|
|
7
|
+
config itself so the same selection config can be reused across different rosters.
|
|
8
|
+
*/
|
|
9
|
+
export type RosterLockPieceMeta = Record<PieceType, SelectionPieceMeta<JSONShallowObject>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import { PieceId, Sha256 } from "../shared";
|
|
3
|
+
|
|
4
|
+
type URLType = string;
|
|
5
|
+
type DownloadableSource = string;
|
|
6
|
+
|
|
7
|
+
export type RosterLockPiece = {
|
|
8
|
+
id: PieceId,
|
|
9
|
+
version: {
|
|
10
|
+
logic: Sha256,
|
|
11
|
+
media: Sha256,
|
|
12
|
+
docs: Sha256,
|
|
13
|
+
},
|
|
14
|
+
humanInfo: {
|
|
15
|
+
name: string,
|
|
16
|
+
author: string,
|
|
17
|
+
url: URLType,
|
|
18
|
+
image?: URLType,
|
|
19
|
+
}
|
|
20
|
+
downloadSources: Array<DownloadableSource>,
|
|
21
|
+
pathVariables: Record<string, string>,
|
|
22
|
+
requiredPieces: Record<string, {
|
|
23
|
+
expected: Array<PieceId>,
|
|
24
|
+
selectable: boolean,
|
|
25
|
+
}>,
|
|
26
|
+
};
|
|
27
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import { PieceType } from "../../shared";
|
|
3
|
+
import { UntrustedScriptRef } from "./script";
|
|
4
|
+
import { SelectionGameControlledConfig } from "./selection-types/game-controlled";
|
|
5
|
+
import { SelectionNormalConfig, UserSelectionValidation } from "./selection-types/normal";
|
|
6
|
+
import { SelectionPreselectedConfig } from "./selection-types/preselected";
|
|
7
|
+
import { SelectionUnselectableConfig } from "./selection-types/unselectable";
|
|
8
|
+
|
|
9
|
+
export * from "./meta";
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
SelectionPreselectedConfig,
|
|
13
|
+
SelectionGameControlledConfig,
|
|
14
|
+
SelectionNormalConfig,
|
|
15
|
+
SelectionUnselectableConfig,
|
|
16
|
+
UserSelectionValidation,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { UntrustedScriptRef };
|
|
20
|
+
|
|
21
|
+
export type RosterLockSelectionConfig = {
|
|
22
|
+
piece: Record<PieceType, (
|
|
23
|
+
| SelectionGameControlledConfig
|
|
24
|
+
| SelectionNormalConfig
|
|
25
|
+
| SelectionPreselectedConfig
|
|
26
|
+
| SelectionUnselectableConfig
|
|
27
|
+
)>,
|
|
28
|
+
|
|
29
|
+
globalValidation: Array<UntrustedScriptRef>
|
|
30
|
+
|
|
31
|
+
scriptDictionary: Record<string, { content: string, }>
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PieceId } from "../../shared";
|
|
2
|
+
|
|
3
|
+
export type JSONShallowObject = Record<string, (
|
|
4
|
+
| string | number | boolean
|
|
5
|
+
| Array<string> | Array<number> | Array<boolean>
|
|
6
|
+
)>;
|
|
7
|
+
|
|
8
|
+
type SimpleSchemaType = (
|
|
9
|
+
| "boolean" | "number" | "string"
|
|
10
|
+
| "boolean[]" | "number[]" | "string[]"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
export type SelectionPieceMeta<Config extends JSONShallowObject> = {
|
|
14
|
+
schema: Record<string, SimpleSchemaType>,
|
|
15
|
+
defaultMeta: Config,
|
|
16
|
+
values: Record<PieceId, Partial<Config>>,
|
|
17
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Global Variables accessible to the script
|
|
3
|
+
|
|
4
|
+
// This is psuedo random number generator based on seeds from all players during the commit/reveal step
|
|
5
|
+
// It returns a float between 0 and 1
|
|
6
|
+
RANDOM()
|
|
7
|
+
|
|
8
|
+
// This is a map of all the piece meta
|
|
9
|
+
// Normally only includes the current piece type and any "on demand" piece types that are required by the current piece type
|
|
10
|
+
// for globalValidation it includes all piece types after merging
|
|
11
|
+
// This is a getter as it will merge default meta with a piece's custom meta
|
|
12
|
+
PIECE_META.get(pieceType: string, pieceId: string): Meta
|
|
13
|
+
|
|
14
|
+
// The pieces available to be selected
|
|
15
|
+
// Normally only includes the current piece type and any "on demand" piece types that are required by the current piece type
|
|
16
|
+
// for globalValidation it includes all piece types after merging
|
|
17
|
+
PIECES_AVAILABLE: {
|
|
18
|
+
[pieceType: string]: Array<PieceId>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type SelectedPiece = {
|
|
22
|
+
// The id of the piece
|
|
23
|
+
id: pieceId,
|
|
24
|
+
// Whether the piece was selected or required by the piece config
|
|
25
|
+
selected: "selected" | "required",
|
|
26
|
+
// The "on demand" pieces that are required by this piece
|
|
27
|
+
// Includes both the selected and the pieces defined in the piece's config
|
|
28
|
+
required: Record<pieceType, Array<SelectedPiece>>,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// The pieces selected by the current player - only available during individual validation
|
|
33
|
+
PLAYER_SELECTION: Array<SelectedPiece>
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// The pieces selected by each player - only available during merge algorithms
|
|
37
|
+
EACH_PLAYER_SELECTION: {
|
|
38
|
+
[userId: string]: Array<SelectedPiece>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The final merged selection - only available during globalValidation
|
|
42
|
+
FINAL_SELECTION: {
|
|
43
|
+
// depending on the pieceType, it's either a list of pieces or a list of pieces per player
|
|
44
|
+
[pieceType: string]: Array<SelectedPiece> | Record<userId, Array<SelectedPiece>>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
*/
|
|
48
|
+
type RelativePath = string;
|
|
49
|
+
export type UntrustedScriptRef = (
|
|
50
|
+
// I'm thinking a "published" config will be a tarball of all necessary files
|
|
51
|
+
// This allows users to write scripts in their preferred editor then add them as necessary
|
|
52
|
+
| {
|
|
53
|
+
src: RelativePath,
|
|
54
|
+
method?: string,
|
|
55
|
+
}
|
|
56
|
+
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// The game will handle the selection however it wants
|
|
4
|
+
// The selection should be sent along side the match lock config when creating a room
|
|
5
|
+
|
|
6
|
+
// Room will handle the selection as if it were a "preselected" config
|
|
7
|
+
export type SelectionGameControlledConfig = {
|
|
8
|
+
type: "game-controlled",
|
|
9
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { UntrustedScriptRef } from "../script";
|
|
2
|
+
import { PieceId, Count } from "../../../shared";
|
|
3
|
+
|
|
4
|
+
export type UserSelectionValidation = {
|
|
5
|
+
count: Count,
|
|
6
|
+
unique: boolean,
|
|
7
|
+
banList: Array<PieceId>,
|
|
8
|
+
customValidation: Array<UntrustedScriptRef>
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export type SelectionNormalConfig = {
|
|
13
|
+
type: "normal",
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
The validation is used to validate the current user's and other player's choices
|
|
17
|
+
The validation does not validate the final choices after the merge algorithm is run
|
|
18
|
+
*/
|
|
19
|
+
validation: UserSelectionValidation,
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
A merge algorithm takes in each player's choices and returns a new set of choices
|
|
23
|
+
If the pieceType is "personal", the merge algorithm is expected to return a set of choices per player
|
|
24
|
+
If the pieceType is "shared", the merge algorithm is expected to return a single set of choices
|
|
25
|
+
- the mergeAlgorithm is mandatory for "shared" pieces
|
|
26
|
+
If the pieceType is "on demand", the merge algorithm is not allowed
|
|
27
|
+
|
|
28
|
+
We validate the return type of the algorithm to ensure it matches the pieceType
|
|
29
|
+
*/
|
|
30
|
+
mergeAlgorithm?: UntrustedScriptRef
|
|
31
|
+
};
|
|
32
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
// Can select pieces as a part of the config
|
|
3
|
+
// This is useful if players just want to play a specific stage without the chance of another being chosen
|
|
4
|
+
// Final Destination Fox only
|
|
5
|
+
|
|
6
|
+
import { SelectedPiece } from "../../../request/shared";
|
|
7
|
+
|
|
8
|
+
// When selecting personal pieces, the array will be applied to all players
|
|
9
|
+
export type SelectionPreselectedConfig = {
|
|
10
|
+
type: "preselected",
|
|
11
|
+
pieces: Array<SelectedPiece>
|
|
12
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
import { RosterLockPiece } from "./lock/roster";
|
|
3
|
+
import { RosterLockIdentity } from "./shared";
|
|
4
|
+
|
|
5
|
+
export type RosterLockV1PieceInfo = (
|
|
6
|
+
& {
|
|
7
|
+
configIdentity: RosterLockIdentity<"piece-info", 1>
|
|
8
|
+
}
|
|
9
|
+
& Pick<RosterLockPiece, "humanInfo" | "downloadSources" | "pathVariables">
|
|
10
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
// Room Creation
|
|
3
|
+
export type RoomConfig = {
|
|
4
|
+
matchmakerId: string;
|
|
5
|
+
coordinatorId: string;
|
|
6
|
+
roomId: string;
|
|
7
|
+
rosterConfigHash: string;
|
|
8
|
+
machines: RoomMachine[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type RoomMachine = {
|
|
12
|
+
machineId: string;
|
|
13
|
+
publicKey: string;
|
|
14
|
+
displayName: string;
|
|
15
|
+
// How many local players this machine is bringing to the room, declared to
|
|
16
|
+
// the matchmaker at queue time - match-agent validates each machine's
|
|
17
|
+
// submitted selections against this count.
|
|
18
|
+
playerCount: number;
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { RosterLockV1Config } from "../../lock";
|
|
2
|
+
|
|
3
|
+
import { UserSelection } from "../shared";
|
|
4
|
+
|
|
5
|
+
export type RosterLockV1SyncDLRequestClientToAgent = {
|
|
6
|
+
relay: {
|
|
7
|
+
url: string,
|
|
8
|
+
roomId: string,
|
|
9
|
+
},
|
|
10
|
+
machine: {
|
|
11
|
+
timestamp: number,
|
|
12
|
+
publicKey: string,
|
|
13
|
+
signature: string,
|
|
14
|
+
},
|
|
15
|
+
rosterConfig: RosterLockV1Config,
|
|
16
|
+
// Keyed by local player index on this machine (0-based) - a machine with
|
|
17
|
+
// multiple local players (e.g. 2 controllers) submits one entry per player.
|
|
18
|
+
playerSelections: Record<number, UserSelection>,
|
|
19
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RosterLockV1Config } from "../../lock";
|
|
2
|
+
|
|
3
|
+
import { UserSelection } from "../shared";
|
|
4
|
+
|
|
5
|
+
export type RosterLockV1SyncDLRequestUserToClient = {
|
|
6
|
+
version: 1,
|
|
7
|
+
relay: {
|
|
8
|
+
url: string,
|
|
9
|
+
roomId: string,
|
|
10
|
+
},
|
|
11
|
+
machine: {
|
|
12
|
+
machineId: string;
|
|
13
|
+
keys: {
|
|
14
|
+
publicKey: string,
|
|
15
|
+
privateKey: string,
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
rosterConfig: RosterLockV1Config,
|
|
19
|
+
// Keyed by local player index on this machine (0-based).
|
|
20
|
+
playerSelections: Record<number, UserSelection>,
|
|
21
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
export enum ROSTERLOCK_DOWNLOAD_STATE {
|
|
3
|
+
downloadStart = "download-start",
|
|
4
|
+
downloadProgress = "download-progress",
|
|
5
|
+
downloadValidation = "download-validation",
|
|
6
|
+
downloadFinished = "download-finished",
|
|
7
|
+
downloadFailure = "download-failure",
|
|
8
|
+
|
|
9
|
+
downloadAllComplete = "download-all-complete",
|
|
10
|
+
downloadFullFailure = "download-full-fail",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type RosterLockDownloadUpdate = (
|
|
14
|
+
| {
|
|
15
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadStart,
|
|
16
|
+
pieceType: string,
|
|
17
|
+
pieceVersions: { logic: string, media: string },
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadProgress,
|
|
21
|
+
pieceType: string,
|
|
22
|
+
pieceVersions: { logic: string, media: string },
|
|
23
|
+
progress: number,
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadValidation,
|
|
27
|
+
pieceType: string,
|
|
28
|
+
pieceVersions: { logic: string, media: string },
|
|
29
|
+
}
|
|
30
|
+
| {
|
|
31
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadFinished,
|
|
32
|
+
pieceType: string,
|
|
33
|
+
pieceVersions: { logic: string, media: string },
|
|
34
|
+
}
|
|
35
|
+
| {
|
|
36
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadFailure,
|
|
37
|
+
pieceType: string,
|
|
38
|
+
pieceVersions: { logic: string, media: string },
|
|
39
|
+
error: string,
|
|
40
|
+
}
|
|
41
|
+
| {
|
|
42
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadAllComplete,
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
type: ROSTERLOCK_DOWNLOAD_STATE.downloadFullFailure,
|
|
46
|
+
error: string,
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import { PlayerId, PieceType, PieceId } from "../../shared";
|
|
3
|
+
import { SelectedPiece } from "../shared";
|
|
4
|
+
|
|
5
|
+
export * from "./download-event";
|
|
6
|
+
|
|
7
|
+
export type SharedSelection = {
|
|
8
|
+
type: "shared",
|
|
9
|
+
value: Array<SelectedPiece>,
|
|
10
|
+
};
|
|
11
|
+
export type PersonalSelection = {
|
|
12
|
+
type: "personal",
|
|
13
|
+
value: Record<PlayerId, Array<SelectedPiece>>,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type FinalSelection = Record<PieceType, (
|
|
17
|
+
| SharedSelection
|
|
18
|
+
| PersonalSelection
|
|
19
|
+
)>;
|
|
20
|
+
|
|
21
|
+
export type DownloadResult = {
|
|
22
|
+
pieceType: PieceType,
|
|
23
|
+
pieceId: PieceId,
|
|
24
|
+
pieceVersions: { logic: string, media: string },
|
|
25
|
+
folder: string,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type DownloadResultsMap = Record<PieceType, Record<PieceId, DownloadResult>>;
|
|
29
|
+
|
|
30
|
+
export type RosterLockV1SyncDLResult = {
|
|
31
|
+
finalSelection: FinalSelection,
|
|
32
|
+
downloadResults: DownloadResultsMap,
|
|
33
|
+
}
|
|
34
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PieceId, PieceType } from "../shared";
|
|
2
|
+
|
|
3
|
+
export type SelectedPiece = {
|
|
4
|
+
id: PieceId,
|
|
5
|
+
// selected: "selected" | "required",
|
|
6
|
+
required: Record<PieceType, {
|
|
7
|
+
mandatory: Array<SelectedPiece>,
|
|
8
|
+
selectable: Array<SelectedPiece>
|
|
9
|
+
}>
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export type UserSelection = Record<PieceType, Array<SelectedPiece>>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export type ArchiveFile = {
|
|
4
|
+
path: string,
|
|
5
|
+
contents: AsyncIterable<Uint8Array>
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type ArchiveHandler = {
|
|
9
|
+
name: string;
|
|
10
|
+
extensions: Array<string>,
|
|
11
|
+
extractFiles: (input: AsyncIterable<Uint8Array>)=>AsyncIterable<ArchiveFile>;
|
|
12
|
+
};
|
|
13
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import { ProcessHandlers } from "./types";
|
|
3
|
+
|
|
4
|
+
export type ProtocolHandler = {
|
|
5
|
+
name: string,
|
|
6
|
+
validateURL: (url: string)=>boolean
|
|
7
|
+
download: (
|
|
8
|
+
url: string,
|
|
9
|
+
folderDestination: string,
|
|
10
|
+
processHandlers: ProcessHandlers
|
|
11
|
+
) => Promise<{
|
|
12
|
+
finishPromise: Promise<any>,
|
|
13
|
+
metaData?: any
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Decompressor } from "./Decompressor";
|
|
2
|
+
import { ArchiveHandler } from "./Archive";
|
|
3
|
+
|
|
4
|
+
export type Processors = {
|
|
5
|
+
decompressors: Array<Decompressor>;
|
|
6
|
+
archiveHandler: ArchiveHandler;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type ProcessHandlers = {
|
|
10
|
+
onProgress?: (progress: number, total?: number) => void;
|
|
11
|
+
abortSignal: AbortSignal;
|
|
12
|
+
getProcessors: (pathname: string) => Processors;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type FileSignature = {
|
|
16
|
+
offset: number;
|
|
17
|
+
bytes: number[];
|
|
18
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import { RosterLockV1Config } from "../../lock";
|
|
3
|
+
import { PieceType, PlayerId, LogicId } from "../../shared";
|
|
4
|
+
import { UserSelection } from "../../request";
|
|
5
|
+
|
|
6
|
+
export type SortPiecesArg = {
|
|
7
|
+
lockConfig: RosterLockV1Config,
|
|
8
|
+
pieceType: PieceType,
|
|
9
|
+
dataDir: string,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type HandleFullSelectionArg = {
|
|
13
|
+
lockConfig: RosterLockV1Config,
|
|
14
|
+
// In case we only want to save local selections
|
|
15
|
+
localUsers: Array<PlayerId>,
|
|
16
|
+
// User Selections have all users
|
|
17
|
+
userSelections: Record<PlayerId, UserSelection>,
|
|
18
|
+
dataDir: string,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type HandleGameCompleteArg = HandleFullSelectionArg & {
|
|
22
|
+
winners: Array<PlayerId>,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type PieceSelectionSortPlugin = {
|
|
26
|
+
name: string,
|
|
27
|
+
publicInfo: {
|
|
28
|
+
title: string,
|
|
29
|
+
description: string,
|
|
30
|
+
},
|
|
31
|
+
sortPieces: (arg: SortPiecesArg) => Promise<Array<LogicId>>,
|
|
32
|
+
handleFullSelection: (arg: HandleFullSelectionArg) => Promise<void>,
|
|
33
|
+
handleGameComplete: (arg: HandleGameCompleteArg) => Promise<void>,
|
|
34
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { RosterLockV1Config, UntrustedScriptRef } from "../../lock";
|
|
2
|
+
import { ScriptPurposeInput } from "./purpose-input";
|
|
3
|
+
export * from "./purpose-input";
|
|
4
|
+
|
|
5
|
+
export type ScriptStarter = {
|
|
6
|
+
config: RosterLockV1Config,
|
|
7
|
+
randomSeeds: string[],
|
|
8
|
+
purpose: ScriptPurposeInput,
|
|
9
|
+
entryScript: UntrustedScriptRef
|
|
10
|
+
debugLog?: Array<string>,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export type ScriptGlobals<ScriptModule> = {
|
|
15
|
+
randomFloat: ()=>number,
|
|
16
|
+
randomInt: (min: number, max: number)=>number,
|
|
17
|
+
shuffleIndexes: (length: number, startOffset?: number)=>Array<number>,
|
|
18
|
+
getPieceMeta: (pieceType: string, pieceId: string)=>any,
|
|
19
|
+
getAvailablePieces: (pieceType: string)=>Array<string>,
|
|
20
|
+
requireScript: (path: string, runCode: (newPath: string, content: string)=>Promise<ScriptModule>)=>Promise<ScriptModule>,
|
|
21
|
+
log: (...args: any)=>void
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export type ScriptRunner<ScriptModule> = (
|
|
26
|
+
globals: ScriptGlobals<ScriptModule>,
|
|
27
|
+
input: ScriptPurposeInput,
|
|
28
|
+
script: string,
|
|
29
|
+
initialMethod: string
|
|
30
|
+
)=>Promise<unknown>;
|
|
31
|
+
|
|
32
|
+
export type UntrustedScript<ScriptModule> = {
|
|
33
|
+
name: string,
|
|
34
|
+
extensions: Array<string>,
|
|
35
|
+
directoryFile: Array<string>,
|
|
36
|
+
runScript: ScriptRunner<ScriptModule>,
|
|
37
|
+
exportConfig: (config: any)=>ScriptModule
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type UntrustedConfig = {
|
|
41
|
+
name: string,
|
|
42
|
+
extensions: Array<string>,
|
|
43
|
+
runConfig: (configString: string)=>Promise<unknown>
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type ScriptStackFrame = {
|
|
47
|
+
filename: string | null,
|
|
48
|
+
line: number | null,
|
|
49
|
+
name: string | null,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type NormalizedScriptError = {
|
|
53
|
+
type: "UntrustedScriptError"
|
|
54
|
+
message: string,
|
|
55
|
+
filename: string | null,
|
|
56
|
+
line: number | null,
|
|
57
|
+
column: number | null,
|
|
58
|
+
stack: ScriptStackFrame[] | null,
|
|
59
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import { PlayerId, PieceType } from "../../shared";
|
|
3
|
+
import { SelectedPiece } from "../../request";
|
|
4
|
+
|
|
5
|
+
export type PieceUserValidationInput = {
|
|
6
|
+
type: "piece-user-validation",
|
|
7
|
+
pieceType: string,
|
|
8
|
+
userId: string,
|
|
9
|
+
input: Array<SelectedPiece>,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type PieceMergeInput = {
|
|
13
|
+
type: "piece-merge",
|
|
14
|
+
pieceType: string,
|
|
15
|
+
users: Array<PlayerId>,
|
|
16
|
+
input: Record<PlayerId, Array<SelectedPiece>>,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type GlobalValidationInput = {
|
|
20
|
+
type: "global-validation",
|
|
21
|
+
pieceTypes: Array<string>,
|
|
22
|
+
users: Array<PlayerId>,
|
|
23
|
+
input: Record<PieceType, (
|
|
24
|
+
| Record<PlayerId, Array<SelectedPiece>>
|
|
25
|
+
| Array<SelectedPiece>
|
|
26
|
+
)> ,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
export type ScriptPurposeInput = (
|
|
31
|
+
| PieceUserValidationInput
|
|
32
|
+
| PieceMergeInput
|
|
33
|
+
| GlobalValidationInput
|
|
34
|
+
);
|
package/src/v1/shared.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
export type PlayerId = string;
|
|
3
|
+
export type PieceType = string;
|
|
4
|
+
export type PieceId = string;
|
|
5
|
+
// RosterLockPiece["version"]["logic"] - the piece's real identity. A media/docs
|
|
6
|
+
// update keeps the same LogicId; a logic update is a wholly new one.
|
|
7
|
+
export type LogicId = string;
|
|
8
|
+
export type Sha256 = string;
|
|
9
|
+
|
|
10
|
+
export type RosterLockIdentity<P extends string, V extends number> = {
|
|
11
|
+
namespace: "roster-lock", purpose: P, version: V
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type Count = number | "*" | [number, number | "*"];
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "nodenext",
|
|
5
|
+
"moduleResolution": "nodenext",
|
|
6
|
+
"types": [],
|
|
7
|
+
"lib": ["es2022", "dom"],
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"rootDir": "./src",
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"strict": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"removeComments": true,
|
|
15
|
+
"noImplicitAny": true
|
|
16
|
+
},
|
|
17
|
+
"files": ["src/index.ts"],
|
|
18
|
+
"include": ["./typings", "./types", "**/*.test.ts"],
|
|
19
|
+
"exclude": ["node_modules", "**/*.spec.ts"]
|
|
20
|
+
}
|