@crowdedkingdoms/crowdyjs 8.7.0 → 8.8.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/MIGRATION.md +42 -0
- package/README.md +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/kit/decks.d.ts +33 -1
- package/dist/kit/decks.d.ts.map +1 -1
- package/dist/kit/decks.js +49 -1
- package/dist/kit/director.d.ts +88 -0
- package/dist/kit/director.d.ts.map +1 -0
- package/dist/kit/director.js +86 -0
- package/dist/kit/economy.d.ts +46 -1
- package/dist/kit/economy.d.ts.map +1 -1
- package/dist/kit/economy.js +63 -1
- package/dist/kit/index.d.ts +6 -2
- package/dist/kit/index.d.ts.map +1 -1
- package/dist/kit/index.js +6 -2
- package/dist/kit/instances.d.ts +52 -0
- package/dist/kit/instances.d.ts.map +1 -0
- package/dist/kit/instances.js +60 -0
- package/dist/kit/kit.d.ts +16 -0
- package/dist/kit/kit.d.ts.map +1 -1
- package/dist/kit/kit.js +12 -4
- package/dist/kit/leaderboards.d.ts +21 -1
- package/dist/kit/leaderboards.d.ts.map +1 -1
- package/dist/kit/leaderboards.js +40 -1
- package/dist/kit/matches.d.ts +33 -1
- package/dist/kit/matches.d.ts.map +1 -1
- package/dist/kit/matches.js +56 -1
- package/dist/kit/matchmaking.d.ts +57 -0
- package/dist/kit/matchmaking.d.ts.map +1 -0
- package/dist/kit/matchmaking.js +59 -0
- package/dist/kit/minigames.d.ts +30 -0
- package/dist/kit/minigames.d.ts.map +1 -0
- package/dist/kit/minigames.js +38 -0
- package/dist/kit/quests.d.ts +57 -0
- package/dist/kit/quests.d.ts.map +1 -1
- package/dist/kit/quests.js +72 -0
- package/dist/kit/wire.d.ts +37 -0
- package/dist/kit/wire.d.ts.map +1 -1
- package/dist/kit/wire.js +50 -0
- package/package.json +1 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Scalars } from '../generated/graphql.js';
|
|
2
|
+
import type { EngineDetector } from './engine.js';
|
|
3
|
+
/** Options for {@link MatchmakingKit}. */
|
|
4
|
+
export interface MatchmakingKitOptions {
|
|
5
|
+
/** The matchmaking module name. Defaults to `'matchmaking'`. */
|
|
6
|
+
moduleName?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Your queue status: where you are queued and any live proposal. */
|
|
9
|
+
export interface KitQueueStatus {
|
|
10
|
+
queuedIn: string | null;
|
|
11
|
+
proposal: {
|
|
12
|
+
proposalId: string;
|
|
13
|
+
mode: string;
|
|
14
|
+
players: string[];
|
|
15
|
+
accepted: string[];
|
|
16
|
+
handedOff: boolean;
|
|
17
|
+
} | null;
|
|
18
|
+
queueDepth: number;
|
|
19
|
+
rating: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Runtime helpers for the matchmaking engine (Wave 2): rating-bucketed
|
|
23
|
+
* queues with widening windows, party blocks, and accept-gated proposals
|
|
24
|
+
* that hand off to the match layer over compute events. After everyone
|
|
25
|
+
* accepts, resolve the created match with `kit.matches.findByProposal`.
|
|
26
|
+
*
|
|
27
|
+
* Obtained via `client.kit(appId).matchmaking`.
|
|
28
|
+
*/
|
|
29
|
+
export declare class MatchmakingKit {
|
|
30
|
+
private readonly engines;
|
|
31
|
+
private readonly moduleName;
|
|
32
|
+
constructor(_appId: Scalars['BigInt']['input'], engines: EngineDetector, options?: MatchmakingKitOptions);
|
|
33
|
+
/** Is the matchmaking engine deployed + enabled (cached per session)? */
|
|
34
|
+
engineAvailable(): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Join a queue (optionally with a party block that must match together,
|
|
37
|
+
* and an explicit rating for games that keep rating on the progression
|
|
38
|
+
* layer).
|
|
39
|
+
*/
|
|
40
|
+
queueJoin(input?: {
|
|
41
|
+
mode?: string;
|
|
42
|
+
rating?: number;
|
|
43
|
+
party?: string[];
|
|
44
|
+
}): Promise<Record<string, unknown>>;
|
|
45
|
+
/** Leave your queue (all modes, or one with `mode`). */
|
|
46
|
+
queueLeave(mode?: string): Promise<Record<string, unknown>>;
|
|
47
|
+
/** Your queue/proposal status. */
|
|
48
|
+
queueStatus(mode?: string): Promise<KitQueueStatus>;
|
|
49
|
+
/** Accept a proposal; when everyone has, the match handoff fires. */
|
|
50
|
+
accept(proposalId: string): Promise<Record<string, unknown>>;
|
|
51
|
+
/** Report the decided result (Elo-lite rating update + proposal close). */
|
|
52
|
+
reportResult(proposalId: string, winnerUserId: string): Promise<Record<string, unknown>>;
|
|
53
|
+
/** Engine totals (queues/proposals/rated players). */
|
|
54
|
+
status(): Promise<Record<string, unknown>>;
|
|
55
|
+
private invoke;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=matchmaking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchmaking.d.ts","sourceRoot":"","sources":["../../src/kit/matchmaking.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;KACpB,GAAG,IAAI,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,qBAAa,cAAc;IAKvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAGlC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjB,OAAO,EAAE,cAAc,EACxC,OAAO,GAAE,qBAA0B;IAKrC,yEAAyE;IACzE,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC;;;;OAIG;IACG,SAAS,CAAC,KAAK,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO;IAIhF,wDAAwD;IAClD,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM;IAI9B,kCAAkC;IAC5B,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAUzD,qEAAqE;IAC/D,MAAM,CAAC,UAAU,EAAE,MAAM;IAI/B,2EAA2E;IACrE,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAI3D,sDAAsD;IAChD,MAAM;YAIE,MAAM;CAOrB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime helpers for the matchmaking engine (Wave 2): rating-bucketed
|
|
3
|
+
* queues with widening windows, party blocks, and accept-gated proposals
|
|
4
|
+
* that hand off to the match layer over compute events. After everyone
|
|
5
|
+
* accepts, resolve the created match with `kit.matches.findByProposal`.
|
|
6
|
+
*
|
|
7
|
+
* Obtained via `client.kit(appId).matchmaking`.
|
|
8
|
+
*/
|
|
9
|
+
export class MatchmakingKit {
|
|
10
|
+
constructor(_appId, engines, options = {}) {
|
|
11
|
+
this.engines = engines;
|
|
12
|
+
this.moduleName = options.moduleName ?? 'matchmaking';
|
|
13
|
+
}
|
|
14
|
+
/** Is the matchmaking engine deployed + enabled (cached per session)? */
|
|
15
|
+
engineAvailable() {
|
|
16
|
+
return this.engines.has(this.moduleName);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Join a queue (optionally with a party block that must match together,
|
|
20
|
+
* and an explicit rating for games that keep rating on the progression
|
|
21
|
+
* layer).
|
|
22
|
+
*/
|
|
23
|
+
async queueJoin(input = {}) {
|
|
24
|
+
return this.invoke('queue_join', input);
|
|
25
|
+
}
|
|
26
|
+
/** Leave your queue (all modes, or one with `mode`). */
|
|
27
|
+
async queueLeave(mode) {
|
|
28
|
+
return this.invoke('queue_leave', mode ? { mode } : {});
|
|
29
|
+
}
|
|
30
|
+
/** Your queue/proposal status. */
|
|
31
|
+
async queueStatus(mode) {
|
|
32
|
+
const body = await this.invoke('queue_status', mode ? { mode } : {});
|
|
33
|
+
return {
|
|
34
|
+
queuedIn: body.queuedIn != null ? String(body.queuedIn) : null,
|
|
35
|
+
proposal: body.proposal ?? null,
|
|
36
|
+
queueDepth: Number(body.queueDepth ?? 0),
|
|
37
|
+
rating: Number(body.rating ?? 0),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Accept a proposal; when everyone has, the match handoff fires. */
|
|
41
|
+
async accept(proposalId) {
|
|
42
|
+
return this.invoke('accept', { proposalId });
|
|
43
|
+
}
|
|
44
|
+
/** Report the decided result (Elo-lite rating update + proposal close). */
|
|
45
|
+
async reportResult(proposalId, winnerUserId) {
|
|
46
|
+
return this.invoke('report_result', { proposalId, winnerUserId });
|
|
47
|
+
}
|
|
48
|
+
/** Engine totals (queues/proposals/rated players). */
|
|
49
|
+
async status() {
|
|
50
|
+
return this.invoke('status', {});
|
|
51
|
+
}
|
|
52
|
+
async invoke(exportName, params) {
|
|
53
|
+
const result = await this.engines.invoke(this.moduleName, exportName, params);
|
|
54
|
+
if (!result.success) {
|
|
55
|
+
throw new Error(`matchmaking.${exportName} failed: ${result.reason ?? 'unknown'}`);
|
|
56
|
+
}
|
|
57
|
+
return result.body;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Scalars } from '../generated/graphql.js';
|
|
2
|
+
import type { EngineDetector, EngineInvokeResult } from './engine.js';
|
|
3
|
+
/** Options for {@link MinigamesKit}. */
|
|
4
|
+
export interface MinigamesKitOptions {
|
|
5
|
+
/** Default module when calls omit one (e.g. your scaffolded game). */
|
|
6
|
+
defaultModuleName?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A thin invoke wrapper for invoke-loop minigames (the Wave 2 `minigame`
|
|
10
|
+
* scaffold pattern): synchronous `play` RPCs with server-bound caller
|
|
11
|
+
* identity, server-held secrets, and per-caller records. Every method
|
|
12
|
+
* resolves the engine envelope — denials come back as
|
|
13
|
+
* `{success: false, reason}` rather than throwing.
|
|
14
|
+
*
|
|
15
|
+
* Obtained via `client.kit(appId).minigames`.
|
|
16
|
+
*/
|
|
17
|
+
export declare class MinigamesKit {
|
|
18
|
+
private readonly engines;
|
|
19
|
+
private readonly defaultModuleName?;
|
|
20
|
+
constructor(_appId: Scalars['BigInt']['input'], engines: EngineDetector, options?: MinigamesKitOptions);
|
|
21
|
+
/** Is a minigame module deployed + enabled (cached per session)? */
|
|
22
|
+
engineAvailable(moduleName?: string): Promise<boolean>;
|
|
23
|
+
/** One round: invoke the game's `play` export with your move. */
|
|
24
|
+
play(params: Record<string, unknown>, moduleName?: string): Promise<EngineInvokeResult>;
|
|
25
|
+
/** Your per-caller record. */
|
|
26
|
+
record(moduleName?: string): Promise<EngineInvokeResult>;
|
|
27
|
+
/** Any other export the game defines (typed result envelope). */
|
|
28
|
+
invoke(exportName: string, params?: Record<string, unknown>, moduleName?: string): Promise<EngineInvokeResult>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=minigames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minigames.d.ts","sourceRoot":"","sources":["../../src/kit/minigames.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtE,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,qBAAa,YAAY;IAKrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAS;gBAG1C,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjB,OAAO,EAAE,cAAc,EACxC,OAAO,GAAE,mBAAwB;IAKnC,oEAAoE;IACpE,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMtD,iEAAiE;IAC3D,IAAI,CACR,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAI9B,8BAA8B;IACxB,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAI9D,iEAAiE;IAC3D,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC;CAO/B"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A thin invoke wrapper for invoke-loop minigames (the Wave 2 `minigame`
|
|
3
|
+
* scaffold pattern): synchronous `play` RPCs with server-bound caller
|
|
4
|
+
* identity, server-held secrets, and per-caller records. Every method
|
|
5
|
+
* resolves the engine envelope — denials come back as
|
|
6
|
+
* `{success: false, reason}` rather than throwing.
|
|
7
|
+
*
|
|
8
|
+
* Obtained via `client.kit(appId).minigames`.
|
|
9
|
+
*/
|
|
10
|
+
export class MinigamesKit {
|
|
11
|
+
constructor(_appId, engines, options = {}) {
|
|
12
|
+
this.engines = engines;
|
|
13
|
+
this.defaultModuleName = options.defaultModuleName;
|
|
14
|
+
}
|
|
15
|
+
/** Is a minigame module deployed + enabled (cached per session)? */
|
|
16
|
+
engineAvailable(moduleName) {
|
|
17
|
+
const name = moduleName ?? this.defaultModuleName;
|
|
18
|
+
if (!name)
|
|
19
|
+
return Promise.resolve(false);
|
|
20
|
+
return this.engines.has(name);
|
|
21
|
+
}
|
|
22
|
+
/** One round: invoke the game's `play` export with your move. */
|
|
23
|
+
async play(params, moduleName) {
|
|
24
|
+
return this.invoke('play', params, moduleName);
|
|
25
|
+
}
|
|
26
|
+
/** Your per-caller record. */
|
|
27
|
+
async record(moduleName) {
|
|
28
|
+
return this.invoke('record', {}, moduleName);
|
|
29
|
+
}
|
|
30
|
+
/** Any other export the game defines (typed result envelope). */
|
|
31
|
+
async invoke(exportName, params = {}, moduleName) {
|
|
32
|
+
const name = moduleName ?? this.defaultModuleName;
|
|
33
|
+
if (!name) {
|
|
34
|
+
return { success: false, reason: 'no minigame module configured', body: {} };
|
|
35
|
+
}
|
|
36
|
+
return this.engines.invoke(name, exportName, params);
|
|
37
|
+
}
|
|
38
|
+
}
|
package/dist/kit/quests.d.ts
CHANGED
|
@@ -87,6 +87,63 @@ export declare class QuestsKit {
|
|
|
87
87
|
}>;
|
|
88
88
|
/** List a player's quest progress rows. */
|
|
89
89
|
mine(ownerUserId: Scalars['BigInt']['input']): Promise<KitQuestProgress[]>;
|
|
90
|
+
/**
|
|
91
|
+
* STUDIO (admin) — define an ordered tutorial chain as quest defs. Steps
|
|
92
|
+
* are plain quests whose `questId` encodes the chain + index
|
|
93
|
+
* (`"<chain>:<i>"`), so no new server surface is involved: the sequencing
|
|
94
|
+
* is a read-side convention enforced by {@link tutorial} /
|
|
95
|
+
* {@link acceptNextTutorialStep} (a step is `locked` until every earlier
|
|
96
|
+
* step completes).
|
|
97
|
+
*/
|
|
98
|
+
defineTutorial(input: {
|
|
99
|
+
/** Chain id (one app can ship several tutorials). Defaults to `'ftue'`. */
|
|
100
|
+
chain?: string;
|
|
101
|
+
steps: Array<{
|
|
102
|
+
displayName: string;
|
|
103
|
+
targetCount?: number;
|
|
104
|
+
rewardItemId?: string;
|
|
105
|
+
rewardQty?: number;
|
|
106
|
+
rewardGold?: number;
|
|
107
|
+
}>;
|
|
108
|
+
}): Promise<{
|
|
109
|
+
__typename?: "GmContainer";
|
|
110
|
+
containerId: string;
|
|
111
|
+
appId: string;
|
|
112
|
+
sessionId: string | null;
|
|
113
|
+
typeName: string;
|
|
114
|
+
displayName: string;
|
|
115
|
+
description: string | null;
|
|
116
|
+
ownerUserId: string | null;
|
|
117
|
+
metadataJson: string;
|
|
118
|
+
}[]>;
|
|
119
|
+
/** One tutorial step joined with the player's progress. */
|
|
120
|
+
/**
|
|
121
|
+
* A player's view of a tutorial chain: steps in order, each `locked`
|
|
122
|
+
* (an earlier step is incomplete), `active` (the first incomplete step),
|
|
123
|
+
* or `complete`. The client shows/drives only the `active` step; the
|
|
124
|
+
* trusted advance authority is unchanged (players still cannot complete
|
|
125
|
+
* their own quests).
|
|
126
|
+
*/
|
|
127
|
+
tutorial(ownerUserId: Scalars['BigInt']['input'], chain?: string): Promise<Array<{
|
|
128
|
+
stepIndex: number;
|
|
129
|
+
def: KitQuestDef;
|
|
130
|
+
progress: KitQuestProgress | null;
|
|
131
|
+
status: 'locked' | 'active' | 'complete';
|
|
132
|
+
}>>;
|
|
133
|
+
/**
|
|
134
|
+
* Ensure the player's ACTIVE tutorial step has a progress row (accepting
|
|
135
|
+
* it when missing) and return the step. Returns null when the chain is
|
|
136
|
+
* complete. Calling this for a locked step is impossible by construction —
|
|
137
|
+
* it always targets the first incomplete step.
|
|
138
|
+
*/
|
|
139
|
+
acceptNextTutorialStep(ownerUserId: Scalars['BigInt']['input'], chain?: string, options?: {
|
|
140
|
+
sessionId?: string;
|
|
141
|
+
}): Promise<{
|
|
142
|
+
stepIndex: number;
|
|
143
|
+
def: KitQuestDef;
|
|
144
|
+
progress: KitQuestProgress | null;
|
|
145
|
+
status: "locked" | "active" | "complete";
|
|
146
|
+
} | null>;
|
|
90
147
|
/** Read one progress row. */
|
|
91
148
|
state(progressId: string): Promise<KitQuestProgress>;
|
|
92
149
|
/**
|
package/dist/kit/quests.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quests.d.ts","sourceRoot":"","sources":["../../src/kit/quests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,qBAAa,SAAS;IAIlB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;gBAGjB,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,gBAAqB;IAKhC,iEAAiE;IAC3D,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IA2BvC,uEAAuE;IACjE,WAAW,CAAC,KAAK,EAAE;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;KAClC;;;;;;;;;;;IAkCD;;;OAGG;IACG,MAAM,CACV,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACvC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;;;;;;;;;;;IA8B5D,2CAA2C;IACrC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"quests.d.ts","sourceRoot":"","sources":["../../src/kit/quests.ts"],"names":[],"mappings":"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"}
|
package/dist/kit/quests.js
CHANGED
|
@@ -106,6 +106,78 @@ export class QuestsKit {
|
|
|
106
106
|
const mine = containers.filter((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
|
|
107
107
|
return Promise.all(mine.map((c) => this.state(c.containerId)));
|
|
108
108
|
}
|
|
109
|
+
// -- FTUE / tutorial step sequencing (Wave 2) -----------------------------
|
|
110
|
+
/**
|
|
111
|
+
* STUDIO (admin) — define an ordered tutorial chain as quest defs. Steps
|
|
112
|
+
* are plain quests whose `questId` encodes the chain + index
|
|
113
|
+
* (`"<chain>:<i>"`), so no new server surface is involved: the sequencing
|
|
114
|
+
* is a read-side convention enforced by {@link tutorial} /
|
|
115
|
+
* {@link acceptNextTutorialStep} (a step is `locked` until every earlier
|
|
116
|
+
* step completes).
|
|
117
|
+
*/
|
|
118
|
+
async defineTutorial(input) {
|
|
119
|
+
const chain = input.chain ?? 'ftue';
|
|
120
|
+
const created = [];
|
|
121
|
+
for (const [index, step] of input.steps.entries()) {
|
|
122
|
+
created.push(await this.defineQuest({
|
|
123
|
+
questId: `${chain}:${index}`,
|
|
124
|
+
displayName: step.displayName,
|
|
125
|
+
targetCount: step.targetCount ?? 1,
|
|
126
|
+
rewardItemId: step.rewardItemId,
|
|
127
|
+
rewardQty: step.rewardQty,
|
|
128
|
+
rewardGold: step.rewardGold,
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
return created;
|
|
132
|
+
}
|
|
133
|
+
/** One tutorial step joined with the player's progress. */
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- documented shape
|
|
135
|
+
/**
|
|
136
|
+
* A player's view of a tutorial chain: steps in order, each `locked`
|
|
137
|
+
* (an earlier step is incomplete), `active` (the first incomplete step),
|
|
138
|
+
* or `complete`. The client shows/drives only the `active` step; the
|
|
139
|
+
* trusted advance authority is unchanged (players still cannot complete
|
|
140
|
+
* their own quests).
|
|
141
|
+
*/
|
|
142
|
+
async tutorial(ownerUserId, chain = 'ftue') {
|
|
143
|
+
const prefix = `${chain}:`;
|
|
144
|
+
const defs = (await this.catalog())
|
|
145
|
+
.filter((def) => def.questId.startsWith(prefix))
|
|
146
|
+
.map((def) => ({ def, stepIndex: Number(def.questId.slice(prefix.length)) }))
|
|
147
|
+
.filter(({ stepIndex }) => Number.isFinite(stepIndex))
|
|
148
|
+
.sort((a, b) => a.stepIndex - b.stepIndex);
|
|
149
|
+
const progressRows = await this.mine(ownerUserId);
|
|
150
|
+
let blocked = false;
|
|
151
|
+
return defs.map(({ def, stepIndex }) => {
|
|
152
|
+
const progress = progressRows.find((p) => p.questId === def.questId) ?? null;
|
|
153
|
+
const complete = progress?.completed === true;
|
|
154
|
+
const status = complete
|
|
155
|
+
? 'complete'
|
|
156
|
+
: blocked
|
|
157
|
+
? 'locked'
|
|
158
|
+
: 'active';
|
|
159
|
+
if (!complete)
|
|
160
|
+
blocked = true;
|
|
161
|
+
return { stepIndex, def, progress, status };
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Ensure the player's ACTIVE tutorial step has a progress row (accepting
|
|
166
|
+
* it when missing) and return the step. Returns null when the chain is
|
|
167
|
+
* complete. Calling this for a locked step is impossible by construction —
|
|
168
|
+
* it always targets the first incomplete step.
|
|
169
|
+
*/
|
|
170
|
+
async acceptNextTutorialStep(ownerUserId, chain = 'ftue', options = {}) {
|
|
171
|
+
const steps = await this.tutorial(ownerUserId, chain);
|
|
172
|
+
const active = steps.find((step) => step.status === 'active');
|
|
173
|
+
if (!active)
|
|
174
|
+
return null;
|
|
175
|
+
if (active.progress)
|
|
176
|
+
return active;
|
|
177
|
+
await this.accept(ownerUserId, active.def.containerId, options);
|
|
178
|
+
const refreshed = await this.tutorial(ownerUserId, chain);
|
|
179
|
+
return refreshed.find((step) => step.stepIndex === active.stepIndex) ?? null;
|
|
180
|
+
}
|
|
109
181
|
/** Read one progress row. */
|
|
110
182
|
async state(progressId) {
|
|
111
183
|
const container = await this.gameModel.container({
|
package/dist/kit/wire.d.ts
CHANGED
|
@@ -60,6 +60,12 @@ export declare function engineLanes(): Record<string, (state: EnginePose) => boo
|
|
|
60
60
|
export declare const EVENT_CONTACT_DAMAGE = 77;
|
|
61
61
|
/** Weather/season transition from a world engine (kit-sim weather). */
|
|
62
62
|
export declare const EVENT_WEATHER = 90;
|
|
63
|
+
/** Turn changed (kit-play turns; match engines). */
|
|
64
|
+
export declare const EVENT_TURN = 91;
|
|
65
|
+
/** Score / match summary (kit-play score). */
|
|
66
|
+
export declare const EVENT_SCORE = 92;
|
|
67
|
+
/** Match proposal (matchmaking → matches handoff). */
|
|
68
|
+
export declare const EVENT_PROPOSAL = 93;
|
|
63
69
|
/** Split an engine server-event payload into its type + JSON body. */
|
|
64
70
|
export declare function parseEngineEvent(bytes: Uint8Array): {
|
|
65
71
|
eventType: number;
|
|
@@ -84,4 +90,35 @@ export interface WeatherEvent {
|
|
|
84
90
|
}
|
|
85
91
|
/** Parse a weather event; null when the payload is another type. */
|
|
86
92
|
export declare function parseWeatherEvent(bytes: Uint8Array): WeatherEvent | null;
|
|
93
|
+
/** A parsed type-91 turn-changed event (match engines). */
|
|
94
|
+
export interface TurnEvent {
|
|
95
|
+
actorId: string;
|
|
96
|
+
round: number;
|
|
97
|
+
turnInRound: number;
|
|
98
|
+
body: Record<string, unknown>;
|
|
99
|
+
}
|
|
100
|
+
/** Parse a turn event; null when the payload is another type. */
|
|
101
|
+
export declare function parseTurnEvent(bytes: Uint8Array): TurnEvent | null;
|
|
102
|
+
/** A parsed type-92 score/summary event (match engines). */
|
|
103
|
+
export interface ScoreEvent {
|
|
104
|
+
/** Per-actor standings when present. */
|
|
105
|
+
standings: Array<{
|
|
106
|
+
actorId: string;
|
|
107
|
+
score: number;
|
|
108
|
+
rank: number;
|
|
109
|
+
}>;
|
|
110
|
+
winnerId: string | null;
|
|
111
|
+
body: Record<string, unknown>;
|
|
112
|
+
}
|
|
113
|
+
/** Parse a score event; null when the payload is another type. */
|
|
114
|
+
export declare function parseScoreEvent(bytes: Uint8Array): ScoreEvent | null;
|
|
115
|
+
/** A parsed type-93 match-proposal event (matchmaking handoff). */
|
|
116
|
+
export interface ProposalEvent {
|
|
117
|
+
proposalId: string;
|
|
118
|
+
mode: string;
|
|
119
|
+
players: string[];
|
|
120
|
+
body: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
/** Parse a proposal event; null when the payload is another type. */
|
|
123
|
+
export declare function parseProposalEvent(bytes: Uint8Array): ProposalEvent | null;
|
|
87
124
|
//# sourceMappingURL=wire.d.ts.map
|
package/dist/kit/wire.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/kit/wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,eAAO,MAAM,UAAU,KAAK,CAAC;AAE7B,4EAA4E;AAC5E,eAAO,MAAM,aAAa,IAAS,CAAC;AACpC,eAAO,MAAM,QAAQ,IAAS,CAAC;AAC/B,eAAO,MAAM,QAAQ,IAAS,CAAC;AAC/B,eAAO,MAAM,cAAc,IAAS,CAAC;AAErC,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAiBtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAqBrE;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,CAAC,UAAU,CAiBlD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,CAM5E;AAMD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,uEAAuE;AACvE,eAAO,MAAM,aAAa,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/kit/wire.ts"],"names":[],"mappings":"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"}
|
package/dist/kit/wire.js
CHANGED
|
@@ -114,6 +114,12 @@ export function engineLanes() {
|
|
|
114
114
|
export const EVENT_CONTACT_DAMAGE = 77;
|
|
115
115
|
/** Weather/season transition from a world engine (kit-sim weather). */
|
|
116
116
|
export const EVENT_WEATHER = 90;
|
|
117
|
+
/** Turn changed (kit-play turns; match engines). */
|
|
118
|
+
export const EVENT_TURN = 91;
|
|
119
|
+
/** Score / match summary (kit-play score). */
|
|
120
|
+
export const EVENT_SCORE = 92;
|
|
121
|
+
/** Match proposal (matchmaking → matches handoff). */
|
|
122
|
+
export const EVENT_PROPOSAL = 93;
|
|
117
123
|
/** Split an engine server-event payload into its type + JSON body. */
|
|
118
124
|
export function parseEngineEvent(bytes) {
|
|
119
125
|
if (bytes.length < 2)
|
|
@@ -154,3 +160,47 @@ export function parseWeatherEvent(bytes) {
|
|
|
154
160
|
body: parsed.body,
|
|
155
161
|
};
|
|
156
162
|
}
|
|
163
|
+
/** Parse a turn event; null when the payload is another type. */
|
|
164
|
+
export function parseTurnEvent(bytes) {
|
|
165
|
+
const parsed = parseEngineEvent(bytes);
|
|
166
|
+
if (!parsed || parsed.eventType !== EVENT_TURN)
|
|
167
|
+
return null;
|
|
168
|
+
return {
|
|
169
|
+
actorId: String(parsed.body.actorId ?? ''),
|
|
170
|
+
round: Number(parsed.body.round ?? 0),
|
|
171
|
+
turnInRound: Number(parsed.body.turnInRound ?? 0),
|
|
172
|
+
body: parsed.body,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/** Parse a score event; null when the payload is another type. */
|
|
176
|
+
export function parseScoreEvent(bytes) {
|
|
177
|
+
const parsed = parseEngineEvent(bytes);
|
|
178
|
+
if (!parsed || parsed.eventType !== EVENT_SCORE)
|
|
179
|
+
return null;
|
|
180
|
+
const standings = Array.isArray(parsed.body.standings)
|
|
181
|
+
? parsed.body.standings.map((s) => ({
|
|
182
|
+
actorId: String(s.actorId ?? ''),
|
|
183
|
+
score: Number(s.score ?? 0),
|
|
184
|
+
rank: Number(s.rank ?? 0),
|
|
185
|
+
}))
|
|
186
|
+
: [];
|
|
187
|
+
return {
|
|
188
|
+
standings,
|
|
189
|
+
winnerId: parsed.body.winnerId != null ? String(parsed.body.winnerId) : null,
|
|
190
|
+
body: parsed.body,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/** Parse a proposal event; null when the payload is another type. */
|
|
194
|
+
export function parseProposalEvent(bytes) {
|
|
195
|
+
const parsed = parseEngineEvent(bytes);
|
|
196
|
+
if (!parsed || parsed.eventType !== EVENT_PROPOSAL)
|
|
197
|
+
return null;
|
|
198
|
+
return {
|
|
199
|
+
proposalId: String(parsed.body.proposalId ?? ''),
|
|
200
|
+
mode: String(parsed.body.mode ?? ''),
|
|
201
|
+
players: Array.isArray(parsed.body.players)
|
|
202
|
+
? parsed.body.players.map(String)
|
|
203
|
+
: [],
|
|
204
|
+
body: parsed.body,
|
|
205
|
+
};
|
|
206
|
+
}
|