@crowdedkingdoms/crowdyjs 8.1.0 → 8.3.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/README.md +43 -4
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +5 -1
- package/dist/generated/graphql.d.ts +1 -1
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/kit/blueprints/combat.d.ts +75 -0
- package/dist/kit/blueprints/combat.d.ts.map +1 -0
- package/dist/kit/blueprints/combat.js +351 -0
- package/dist/kit/blueprints/core.d.ts +222 -0
- package/dist/kit/blueprints/core.d.ts.map +1 -0
- package/dist/kit/blueprints/core.js +185 -0
- package/dist/kit/blueprints/decks.d.ts +50 -0
- package/dist/kit/blueprints/decks.d.ts.map +1 -0
- package/dist/kit/blueprints/decks.js +163 -0
- package/dist/kit/blueprints/economy.d.ts +88 -0
- package/dist/kit/blueprints/economy.d.ts.map +1 -0
- package/dist/kit/blueprints/economy.js +533 -0
- package/dist/kit/blueprints/guild.d.ts +51 -0
- package/dist/kit/blueprints/guild.d.ts.map +1 -0
- package/dist/kit/blueprints/guild.js +50 -0
- package/dist/kit/blueprints/index.d.ts +21 -0
- package/dist/kit/blueprints/index.d.ts.map +1 -0
- package/dist/kit/blueprints/index.js +20 -0
- package/dist/kit/blueprints/inventory.d.ts +38 -0
- package/dist/kit/blueprints/inventory.d.ts.map +1 -0
- package/dist/kit/blueprints/inventory.js +157 -0
- package/dist/kit/blueprints/leaderboards.d.ts +49 -0
- package/dist/kit/blueprints/leaderboards.d.ts.map +1 -0
- package/dist/kit/blueprints/leaderboards.js +126 -0
- package/dist/kit/blueprints/locks.d.ts +82 -0
- package/dist/kit/blueprints/locks.d.ts.map +1 -0
- package/dist/kit/blueprints/locks.js +155 -0
- package/dist/kit/blueprints/loot.d.ts +84 -0
- package/dist/kit/blueprints/loot.d.ts.map +1 -0
- package/dist/kit/blueprints/loot.js +228 -0
- package/dist/kit/blueprints/matches.d.ts +59 -0
- package/dist/kit/blueprints/matches.d.ts.map +1 -0
- package/dist/kit/blueprints/matches.js +246 -0
- package/dist/kit/blueprints/npcs.d.ts +71 -0
- package/dist/kit/blueprints/npcs.d.ts.map +1 -0
- package/dist/kit/blueprints/npcs.js +122 -0
- package/dist/kit/blueprints/plots.d.ts +54 -0
- package/dist/kit/blueprints/plots.d.ts.map +1 -0
- package/dist/kit/blueprints/plots.js +146 -0
- package/dist/kit/blueprints/progression.d.ts +68 -0
- package/dist/kit/blueprints/progression.d.ts.map +1 -0
- package/dist/kit/blueprints/progression.js +324 -0
- package/dist/kit/blueprints/quests.d.ts +65 -0
- package/dist/kit/blueprints/quests.d.ts.map +1 -0
- package/dist/kit/blueprints/quests.js +284 -0
- package/dist/kit/blueprints/worldsim.d.ts +84 -0
- package/dist/kit/blueprints/worldsim.d.ts.map +1 -0
- package/dist/kit/blueprints/worldsim.js +461 -0
- package/dist/kit/combat.d.ts +103 -0
- package/dist/kit/combat.d.ts.map +1 -0
- package/dist/kit/combat.js +151 -0
- package/dist/kit/decks.d.ts +123 -0
- package/dist/kit/decks.d.ts.map +1 -0
- package/dist/kit/decks.js +138 -0
- package/dist/kit/economy.d.ts +244 -0
- package/dist/kit/economy.d.ts.map +1 -0
- package/dist/kit/economy.js +365 -0
- package/dist/kit/features.d.ts +60 -0
- package/dist/kit/features.d.ts.map +1 -0
- package/dist/kit/features.js +65 -0
- package/dist/kit/index.d.ts +14 -2
- package/dist/kit/index.d.ts.map +1 -1
- package/dist/kit/index.js +13 -1
- package/dist/kit/inventory.d.ts +5 -0
- package/dist/kit/inventory.d.ts.map +1 -1
- package/dist/kit/inventory.js +14 -1
- package/dist/kit/kit.d.ts +63 -2
- package/dist/kit/kit.d.ts.map +1 -1
- package/dist/kit/kit.js +26 -2
- package/dist/kit/leaderboards.d.ts +66 -0
- package/dist/kit/leaderboards.d.ts.map +1 -0
- package/dist/kit/leaderboards.js +94 -0
- package/dist/kit/loot.d.ts +106 -0
- package/dist/kit/loot.d.ts.map +1 -0
- package/dist/kit/loot.js +120 -0
- package/dist/kit/matches.d.ts +140 -0
- package/dist/kit/matches.d.ts.map +1 -0
- package/dist/kit/matches.js +253 -0
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/objects.d.ts +9 -1
- package/dist/kit/objects.d.ts.map +1 -1
- package/dist/kit/objects.js +11 -2
- package/dist/kit/plots.d.ts +81 -0
- package/dist/kit/plots.d.ts.map +1 -0
- package/dist/kit/plots.js +113 -0
- package/dist/kit/progression.d.ts +181 -0
- package/dist/kit/progression.d.ts.map +1 -0
- package/dist/kit/progression.js +265 -0
- package/dist/kit/quests.d.ts +110 -0
- package/dist/kit/quests.d.ts.map +1 -0
- package/dist/kit/quests.js +158 -0
- package/dist/kit/social.d.ts +267 -0
- package/dist/kit/social.d.ts.map +1 -0
- package/dist/kit/social.js +230 -0
- package/dist/kit/worldsim.d.ts +225 -0
- package/dist/kit/worldsim.d.ts.map +1 -0
- package/dist/kit/worldsim.js +231 -0
- package/package.json +1 -1
- package/dist/kit/blueprints.d.ts +0 -259
- package/dist/kit/blueprints.d.ts.map +0 -1
- package/dist/kit/blueprints.js +0 -480
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { GameModelAPI } from '../domains/gameModel.js';
|
|
2
|
+
import type { Scalars, SeedPropertyInput } from '../generated/graphql.js';
|
|
3
|
+
import { type KitInvokeResult } from './shared.js';
|
|
4
|
+
/** Options for {@link ProgressionKit}. Must match the deployed blueprint. */
|
|
5
|
+
export interface ProgressionKitOptions {
|
|
6
|
+
/** The `typePrefix` the progression blueprint was deployed with. */
|
|
7
|
+
typePrefix?: string;
|
|
8
|
+
}
|
|
9
|
+
/** A parsed view of one player's progression. */
|
|
10
|
+
export interface KitProgress {
|
|
11
|
+
containerId: string;
|
|
12
|
+
displayName: string;
|
|
13
|
+
ownerUserId: string | null;
|
|
14
|
+
xp: number;
|
|
15
|
+
level: number;
|
|
16
|
+
skillPoints: number;
|
|
17
|
+
rating: number;
|
|
18
|
+
}
|
|
19
|
+
/** A parsed view of one skill catalog row. */
|
|
20
|
+
export interface KitSkillDef {
|
|
21
|
+
containerId: string;
|
|
22
|
+
displayName: string;
|
|
23
|
+
skillId: string;
|
|
24
|
+
cost: number;
|
|
25
|
+
requiresSkillId: string;
|
|
26
|
+
maxRank: number;
|
|
27
|
+
}
|
|
28
|
+
/** A parsed view of one player skill rank. */
|
|
29
|
+
export interface KitSkillRank {
|
|
30
|
+
containerId: string;
|
|
31
|
+
displayName: string;
|
|
32
|
+
ownerUserId: string | null;
|
|
33
|
+
skillId: string;
|
|
34
|
+
rank: number;
|
|
35
|
+
}
|
|
36
|
+
/** A parsed view of one achievement definition. */
|
|
37
|
+
export interface KitAchievementDef {
|
|
38
|
+
containerId: string;
|
|
39
|
+
displayName: string;
|
|
40
|
+
achievementId: string;
|
|
41
|
+
threshold: number;
|
|
42
|
+
}
|
|
43
|
+
/** A parsed view of one player achievement unlock. */
|
|
44
|
+
export interface KitAchievementUnlock {
|
|
45
|
+
containerId: string;
|
|
46
|
+
displayName: string;
|
|
47
|
+
ownerUserId: string | null;
|
|
48
|
+
achievementId: string;
|
|
49
|
+
unlocked: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Runtime helpers for the {@link progressionBlueprint} conventions: ensure a
|
|
53
|
+
* player's `Progress`, grant XP (trusted — app admins by default), buy
|
|
54
|
+
* skills against the catalog's costs and prerequisites, unlock threshold
|
|
55
|
+
* achievements, and apply match rating results. Everything is
|
|
56
|
+
* authority-checked server-side; denials resolve with `success: false`.
|
|
57
|
+
*
|
|
58
|
+
* Obtained via `client.kit(appId).progression`.
|
|
59
|
+
*/
|
|
60
|
+
export declare class ProgressionKit {
|
|
61
|
+
private readonly appId;
|
|
62
|
+
private readonly gameModel;
|
|
63
|
+
private readonly names;
|
|
64
|
+
constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI, options?: ProgressionKitOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Find the player's Progress container, creating it when absent (with the
|
|
67
|
+
* `owner_user_id` mirror the guards read).
|
|
68
|
+
*/
|
|
69
|
+
ensure(ownerUserId: Scalars['BigInt']['input'], options?: {
|
|
70
|
+
displayName?: string;
|
|
71
|
+
sessionId?: string;
|
|
72
|
+
}): Promise<{
|
|
73
|
+
__typename?: "GmContainer";
|
|
74
|
+
containerId: string;
|
|
75
|
+
appId: string;
|
|
76
|
+
sessionId: string | null;
|
|
77
|
+
typeName: string;
|
|
78
|
+
displayName: string;
|
|
79
|
+
description: string | null;
|
|
80
|
+
ownerUserId: string | null;
|
|
81
|
+
metadataJson: string;
|
|
82
|
+
}>;
|
|
83
|
+
/** Read one player's progression state. */
|
|
84
|
+
state(progressId: string): Promise<KitProgress>;
|
|
85
|
+
/**
|
|
86
|
+
* Grant XP — a **trusted** call (default blueprint authority: app admins
|
|
87
|
+
* via server scope; or drive it from an event automation). Awards skill
|
|
88
|
+
* points and levels up when the curve is crossed. Resolves with the new
|
|
89
|
+
* level.
|
|
90
|
+
*/
|
|
91
|
+
grantXp(progressId: string, amount: number): Promise<KitInvokeResult<number>>;
|
|
92
|
+
/** List the skill catalog (admin-seeded SkillDef containers). */
|
|
93
|
+
skillCatalog(): Promise<KitSkillDef[]>;
|
|
94
|
+
/** Define a skill (admin — the catalog type is admin-instantiable). */
|
|
95
|
+
defineSkill(input: {
|
|
96
|
+
skillId: string;
|
|
97
|
+
cost?: number;
|
|
98
|
+
requiresSkillId?: string;
|
|
99
|
+
maxRank?: number;
|
|
100
|
+
displayName?: string;
|
|
101
|
+
properties?: SeedPropertyInput[];
|
|
102
|
+
}): Promise<{
|
|
103
|
+
__typename?: "GmContainer";
|
|
104
|
+
containerId: string;
|
|
105
|
+
appId: string;
|
|
106
|
+
sessionId: string | null;
|
|
107
|
+
typeName: string;
|
|
108
|
+
displayName: string;
|
|
109
|
+
description: string | null;
|
|
110
|
+
ownerUserId: string | null;
|
|
111
|
+
metadataJson: string;
|
|
112
|
+
}>;
|
|
113
|
+
/**
|
|
114
|
+
* Find-or-create the caller's SkillRank row for a skill (rank 0 until
|
|
115
|
+
* bought).
|
|
116
|
+
*/
|
|
117
|
+
ensureSkillRank(ownerUserId: Scalars['BigInt']['input'], skillId: string, options?: {
|
|
118
|
+
displayName?: string;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
__typename?: "GmContainer";
|
|
121
|
+
containerId: string;
|
|
122
|
+
appId: string;
|
|
123
|
+
sessionId: string | null;
|
|
124
|
+
typeName: string;
|
|
125
|
+
displayName: string;
|
|
126
|
+
description: string | null;
|
|
127
|
+
ownerUserId: string | null;
|
|
128
|
+
metadataJson: string;
|
|
129
|
+
}>;
|
|
130
|
+
/**
|
|
131
|
+
* Buy one rank of a skill. `prereqRankId` is the caller's SkillRank for
|
|
132
|
+
* the prerequisite skill; omit it for skills without one (the rank row
|
|
133
|
+
* itself is passed to satisfy the required param — the condition ignores
|
|
134
|
+
* it when the def declares no prerequisite).
|
|
135
|
+
*/
|
|
136
|
+
buySkill(input: {
|
|
137
|
+
skillRankId: string;
|
|
138
|
+
progressId: string;
|
|
139
|
+
skillDefId: string;
|
|
140
|
+
prereqRankId?: string;
|
|
141
|
+
}): Promise<KitInvokeResult<number>>;
|
|
142
|
+
/** List a player's skill ranks. */
|
|
143
|
+
skills(ownerUserId: Scalars['BigInt']['input']): Promise<KitSkillRank[]>;
|
|
144
|
+
/** List the achievement catalog (admin-seeded AchievementDef containers). */
|
|
145
|
+
achievementCatalog(): Promise<KitAchievementDef[]>;
|
|
146
|
+
/** Define an achievement (admin). */
|
|
147
|
+
defineAchievement(input: {
|
|
148
|
+
achievementId: string;
|
|
149
|
+
threshold: number;
|
|
150
|
+
displayName?: string;
|
|
151
|
+
}): Promise<{
|
|
152
|
+
__typename?: "GmContainer";
|
|
153
|
+
containerId: string;
|
|
154
|
+
appId: string;
|
|
155
|
+
sessionId: string | null;
|
|
156
|
+
typeName: string;
|
|
157
|
+
displayName: string;
|
|
158
|
+
description: string | null;
|
|
159
|
+
ownerUserId: string | null;
|
|
160
|
+
metadataJson: string;
|
|
161
|
+
}>;
|
|
162
|
+
/** List a player's achievement unlocks. */
|
|
163
|
+
achievements(ownerUserId: Scalars['BigInt']['input']): Promise<KitAchievementUnlock[]>;
|
|
164
|
+
/**
|
|
165
|
+
* Unlock an achievement once its xp threshold is met. Creates the caller's
|
|
166
|
+
* unlock row when absent, then invokes the gated function (idempotent).
|
|
167
|
+
*/
|
|
168
|
+
unlockAchievement(input: {
|
|
169
|
+
ownerUserId: Scalars['BigInt']['input'];
|
|
170
|
+
progressId: string;
|
|
171
|
+
achievementDefId: string;
|
|
172
|
+
achievementId: string;
|
|
173
|
+
}): Promise<KitInvokeResult<boolean>>;
|
|
174
|
+
/**
|
|
175
|
+
* Apply a match result as a rating delta (trusted — host-gated by
|
|
176
|
+
* default; `kit.matches` computes the delta). Resolves with the new
|
|
177
|
+
* rating.
|
|
178
|
+
*/
|
|
179
|
+
applyMatchResult(progressId: string, delta: number): Promise<KitInvokeResult<number>>;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=progression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progression.d.ts","sourceRoot":"","sources":["../../src/kit/progression.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { progressionNames, } from './blueprints/index.js';
|
|
2
|
+
import { kitContainerProperties, kitInvoke, } from './shared.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runtime helpers for the {@link progressionBlueprint} conventions: ensure a
|
|
5
|
+
* player's `Progress`, grant XP (trusted — app admins by default), buy
|
|
6
|
+
* skills against the catalog's costs and prerequisites, unlock threshold
|
|
7
|
+
* achievements, and apply match rating results. Everything is
|
|
8
|
+
* authority-checked server-side; denials resolve with `success: false`.
|
|
9
|
+
*
|
|
10
|
+
* Obtained via `client.kit(appId).progression`.
|
|
11
|
+
*/
|
|
12
|
+
export class ProgressionKit {
|
|
13
|
+
constructor(appId, gameModel, options = {}) {
|
|
14
|
+
this.appId = appId;
|
|
15
|
+
this.gameModel = gameModel;
|
|
16
|
+
this.names = progressionNames(options.typePrefix ?? '');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Find the player's Progress container, creating it when absent (with the
|
|
20
|
+
* `owner_user_id` mirror the guards read).
|
|
21
|
+
*/
|
|
22
|
+
async ensure(ownerUserId, options = {}) {
|
|
23
|
+
const existing = await this.gameModel.containers({
|
|
24
|
+
appId: this.appId,
|
|
25
|
+
typeName: this.names.progressType,
|
|
26
|
+
...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
|
|
27
|
+
});
|
|
28
|
+
const mine = existing.find((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
|
|
29
|
+
if (mine)
|
|
30
|
+
return mine;
|
|
31
|
+
return this.gameModel.createContainer({
|
|
32
|
+
appId: this.appId,
|
|
33
|
+
typeName: this.names.progressType,
|
|
34
|
+
displayName: options.displayName ?? `Progress ${ownerUserId}`,
|
|
35
|
+
...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
|
|
36
|
+
properties: [
|
|
37
|
+
{ key: 'owner_user_id', valueType: 'int', valueJson: String(ownerUserId) },
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** Read one player's progression state. */
|
|
42
|
+
async state(progressId) {
|
|
43
|
+
const container = await this.gameModel.container({
|
|
44
|
+
appId: this.appId,
|
|
45
|
+
containerId: progressId,
|
|
46
|
+
});
|
|
47
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), progressId);
|
|
48
|
+
return {
|
|
49
|
+
containerId: container.containerId,
|
|
50
|
+
displayName: container.displayName,
|
|
51
|
+
ownerUserId: container.ownerUserId != null ? String(container.ownerUserId) : null,
|
|
52
|
+
xp: Number(props.xp ?? 0),
|
|
53
|
+
level: Number(props.level ?? 1),
|
|
54
|
+
skillPoints: Number(props.skill_points ?? 0),
|
|
55
|
+
rating: Number(props.rating ?? 0),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Grant XP — a **trusted** call (default blueprint authority: app admins
|
|
60
|
+
* via server scope; or drive it from an event automation). Awards skill
|
|
61
|
+
* points and levels up when the curve is crossed. Resolves with the new
|
|
62
|
+
* level.
|
|
63
|
+
*/
|
|
64
|
+
async grantXp(progressId, amount) {
|
|
65
|
+
return kitInvoke(this.gameModel, {
|
|
66
|
+
appId: String(this.appId),
|
|
67
|
+
functionName: this.names.grantXpFn,
|
|
68
|
+
selfContainerId: progressId,
|
|
69
|
+
params: { amount },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** List the skill catalog (admin-seeded SkillDef containers). */
|
|
73
|
+
async skillCatalog() {
|
|
74
|
+
const containers = await this.gameModel.containers({
|
|
75
|
+
appId: this.appId,
|
|
76
|
+
typeName: this.names.skillDefType,
|
|
77
|
+
});
|
|
78
|
+
return Promise.all(containers.map(async (c) => {
|
|
79
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
80
|
+
return {
|
|
81
|
+
containerId: c.containerId,
|
|
82
|
+
displayName: c.displayName,
|
|
83
|
+
skillId: String(props.skill_id ?? ''),
|
|
84
|
+
cost: Number(props.cost ?? 1),
|
|
85
|
+
requiresSkillId: String(props.requires_skill_id ?? ''),
|
|
86
|
+
maxRank: Number(props.max_rank ?? 1),
|
|
87
|
+
};
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
/** Define a skill (admin — the catalog type is admin-instantiable). */
|
|
91
|
+
async defineSkill(input) {
|
|
92
|
+
return this.gameModel.createContainer({
|
|
93
|
+
appId: this.appId,
|
|
94
|
+
typeName: this.names.skillDefType,
|
|
95
|
+
displayName: input.displayName ?? `Skill ${input.skillId}`,
|
|
96
|
+
properties: [
|
|
97
|
+
{ key: 'skill_id', valueType: 'string', valueJson: JSON.stringify(input.skillId) },
|
|
98
|
+
{ key: 'cost', valueType: 'int', valueJson: String(input.cost ?? 1) },
|
|
99
|
+
{
|
|
100
|
+
key: 'requires_skill_id',
|
|
101
|
+
valueType: 'string',
|
|
102
|
+
valueJson: JSON.stringify(input.requiresSkillId ?? ''),
|
|
103
|
+
},
|
|
104
|
+
{ key: 'max_rank', valueType: 'int', valueJson: String(input.maxRank ?? 1) },
|
|
105
|
+
...(input.properties ?? []),
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Find-or-create the caller's SkillRank row for a skill (rank 0 until
|
|
111
|
+
* bought).
|
|
112
|
+
*/
|
|
113
|
+
async ensureSkillRank(ownerUserId, skillId, options = {}) {
|
|
114
|
+
const mine = await this.skills(ownerUserId);
|
|
115
|
+
const existing = mine.find((s) => s.skillId === skillId);
|
|
116
|
+
if (existing) {
|
|
117
|
+
return this.gameModel.container({
|
|
118
|
+
appId: this.appId,
|
|
119
|
+
containerId: existing.containerId,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return this.gameModel.createContainer({
|
|
123
|
+
appId: this.appId,
|
|
124
|
+
typeName: this.names.skillRankType,
|
|
125
|
+
displayName: options.displayName ?? `Skill ${skillId} ${ownerUserId}`,
|
|
126
|
+
properties: [
|
|
127
|
+
{ key: 'owner_user_id', valueType: 'int', valueJson: String(ownerUserId) },
|
|
128
|
+
{ key: 'skill_id', valueType: 'string', valueJson: JSON.stringify(skillId) },
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Buy one rank of a skill. `prereqRankId` is the caller's SkillRank for
|
|
134
|
+
* the prerequisite skill; omit it for skills without one (the rank row
|
|
135
|
+
* itself is passed to satisfy the required param — the condition ignores
|
|
136
|
+
* it when the def declares no prerequisite).
|
|
137
|
+
*/
|
|
138
|
+
async buySkill(input) {
|
|
139
|
+
return kitInvoke(this.gameModel, {
|
|
140
|
+
appId: String(this.appId),
|
|
141
|
+
functionName: this.names.buySkillFn,
|
|
142
|
+
selfContainerId: input.skillRankId,
|
|
143
|
+
params: {
|
|
144
|
+
progress_id: input.progressId,
|
|
145
|
+
def_id: input.skillDefId,
|
|
146
|
+
prereq_id: input.prereqRankId ?? input.skillRankId,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/** List a player's skill ranks. */
|
|
151
|
+
async skills(ownerUserId) {
|
|
152
|
+
const containers = await this.gameModel.containers({
|
|
153
|
+
appId: this.appId,
|
|
154
|
+
typeName: this.names.skillRankType,
|
|
155
|
+
});
|
|
156
|
+
const mine = containers.filter((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
|
|
157
|
+
return Promise.all(mine.map(async (c) => {
|
|
158
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
159
|
+
return {
|
|
160
|
+
containerId: c.containerId,
|
|
161
|
+
displayName: c.displayName,
|
|
162
|
+
ownerUserId: c.ownerUserId != null ? String(c.ownerUserId) : null,
|
|
163
|
+
skillId: String(props.skill_id ?? ''),
|
|
164
|
+
rank: Number(props.rank ?? 0),
|
|
165
|
+
};
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
/** List the achievement catalog (admin-seeded AchievementDef containers). */
|
|
169
|
+
async achievementCatalog() {
|
|
170
|
+
const containers = await this.gameModel.containers({
|
|
171
|
+
appId: this.appId,
|
|
172
|
+
typeName: this.names.achievementDefType,
|
|
173
|
+
});
|
|
174
|
+
return Promise.all(containers.map(async (c) => {
|
|
175
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
176
|
+
return {
|
|
177
|
+
containerId: c.containerId,
|
|
178
|
+
displayName: c.displayName,
|
|
179
|
+
achievementId: String(props.achievement_id ?? ''),
|
|
180
|
+
threshold: Number(props.threshold ?? 0),
|
|
181
|
+
};
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
/** Define an achievement (admin). */
|
|
185
|
+
async defineAchievement(input) {
|
|
186
|
+
return this.gameModel.createContainer({
|
|
187
|
+
appId: this.appId,
|
|
188
|
+
typeName: this.names.achievementDefType,
|
|
189
|
+
displayName: input.displayName ?? `Achievement ${input.achievementId}`,
|
|
190
|
+
properties: [
|
|
191
|
+
{
|
|
192
|
+
key: 'achievement_id',
|
|
193
|
+
valueType: 'string',
|
|
194
|
+
valueJson: JSON.stringify(input.achievementId),
|
|
195
|
+
},
|
|
196
|
+
{ key: 'threshold', valueType: 'int', valueJson: String(input.threshold) },
|
|
197
|
+
],
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
/** List a player's achievement unlocks. */
|
|
201
|
+
async achievements(ownerUserId) {
|
|
202
|
+
const containers = await this.gameModel.containers({
|
|
203
|
+
appId: this.appId,
|
|
204
|
+
typeName: this.names.achievementUnlockType,
|
|
205
|
+
});
|
|
206
|
+
const mine = containers.filter((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
|
|
207
|
+
return Promise.all(mine.map(async (c) => {
|
|
208
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
209
|
+
return {
|
|
210
|
+
containerId: c.containerId,
|
|
211
|
+
displayName: c.displayName,
|
|
212
|
+
ownerUserId: c.ownerUserId != null ? String(c.ownerUserId) : null,
|
|
213
|
+
achievementId: String(props.achievement_id ?? ''),
|
|
214
|
+
unlocked: props.unlocked === true,
|
|
215
|
+
};
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Unlock an achievement once its xp threshold is met. Creates the caller's
|
|
220
|
+
* unlock row when absent, then invokes the gated function (idempotent).
|
|
221
|
+
*/
|
|
222
|
+
async unlockAchievement(input) {
|
|
223
|
+
const mine = await this.achievements(input.ownerUserId);
|
|
224
|
+
let unlockId = mine.find((a) => a.achievementId === input.achievementId)?.containerId;
|
|
225
|
+
if (!unlockId) {
|
|
226
|
+
const created = await this.gameModel.createContainer({
|
|
227
|
+
appId: this.appId,
|
|
228
|
+
typeName: this.names.achievementUnlockType,
|
|
229
|
+
displayName: `Achievement ${input.achievementId} ${input.ownerUserId}`,
|
|
230
|
+
properties: [
|
|
231
|
+
{
|
|
232
|
+
key: 'owner_user_id',
|
|
233
|
+
valueType: 'int',
|
|
234
|
+
valueJson: String(input.ownerUserId),
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
key: 'achievement_id',
|
|
238
|
+
valueType: 'string',
|
|
239
|
+
valueJson: JSON.stringify(input.achievementId),
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
});
|
|
243
|
+
unlockId = created.containerId;
|
|
244
|
+
}
|
|
245
|
+
return kitInvoke(this.gameModel, {
|
|
246
|
+
appId: String(this.appId),
|
|
247
|
+
functionName: this.names.unlockAchievementFn,
|
|
248
|
+
selfContainerId: unlockId,
|
|
249
|
+
params: { progress_id: input.progressId, def_id: input.achievementDefId },
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Apply a match result as a rating delta (trusted — host-gated by
|
|
254
|
+
* default; `kit.matches` computes the delta). Resolves with the new
|
|
255
|
+
* rating.
|
|
256
|
+
*/
|
|
257
|
+
async applyMatchResult(progressId, delta) {
|
|
258
|
+
return kitInvoke(this.gameModel, {
|
|
259
|
+
appId: String(this.appId),
|
|
260
|
+
functionName: this.names.adjustRatingFn,
|
|
261
|
+
selfContainerId: progressId,
|
|
262
|
+
params: { delta },
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { GameModelAPI } from '../domains/gameModel.js';
|
|
2
|
+
import type { Scalars, SeedPropertyInput } from '../generated/graphql.js';
|
|
3
|
+
import { type KitInvokeResult } from './shared.js';
|
|
4
|
+
/** Options for {@link QuestsKit}. Must match the deployed quests blueprint. */
|
|
5
|
+
export interface QuestsKitOptions {
|
|
6
|
+
/** The `typePrefix` the quests blueprint was deployed with. */
|
|
7
|
+
typePrefix?: string;
|
|
8
|
+
}
|
|
9
|
+
/** A parsed view of one quest catalog row. */
|
|
10
|
+
export interface KitQuestDef {
|
|
11
|
+
containerId: string;
|
|
12
|
+
displayName: string;
|
|
13
|
+
questId: string;
|
|
14
|
+
targetCount: number;
|
|
15
|
+
rewardItemId: string;
|
|
16
|
+
rewardQty: number;
|
|
17
|
+
rewardGold: number;
|
|
18
|
+
repeatable: boolean;
|
|
19
|
+
daily: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** A parsed view of one player's quest progress. */
|
|
22
|
+
export interface KitQuestProgress {
|
|
23
|
+
containerId: string;
|
|
24
|
+
displayName: string;
|
|
25
|
+
ownerUserId: string | null;
|
|
26
|
+
questId: string;
|
|
27
|
+
count: number;
|
|
28
|
+
target: number;
|
|
29
|
+
completed: boolean;
|
|
30
|
+
claimed: boolean;
|
|
31
|
+
daily: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Runtime helpers for the {@link questsBlueprint} conventions: browse the
|
|
35
|
+
* quest catalog, accept quests into per-player progress rows, advance them
|
|
36
|
+
* (trusted — app admins or event automations), and claim rewards atomically
|
|
37
|
+
* into a stack + wallet. Denials resolve with `success: false`.
|
|
38
|
+
*
|
|
39
|
+
* Obtained via `client.kit(appId).quests`.
|
|
40
|
+
*/
|
|
41
|
+
export declare class QuestsKit {
|
|
42
|
+
private readonly appId;
|
|
43
|
+
private readonly gameModel;
|
|
44
|
+
private readonly names;
|
|
45
|
+
constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI, options?: QuestsKitOptions);
|
|
46
|
+
/** List the quest catalog (admin-seeded QuestDef containers). */
|
|
47
|
+
catalog(): Promise<KitQuestDef[]>;
|
|
48
|
+
/** Define a quest (admin — the catalog type is admin-instantiable). */
|
|
49
|
+
defineQuest(input: {
|
|
50
|
+
questId: string;
|
|
51
|
+
targetCount?: number;
|
|
52
|
+
rewardItemId?: string;
|
|
53
|
+
rewardQty?: number;
|
|
54
|
+
rewardGold?: number;
|
|
55
|
+
repeatable?: boolean;
|
|
56
|
+
daily?: boolean;
|
|
57
|
+
displayName?: string;
|
|
58
|
+
properties?: SeedPropertyInput[];
|
|
59
|
+
}): Promise<{
|
|
60
|
+
__typename?: "GmContainer";
|
|
61
|
+
containerId: string;
|
|
62
|
+
appId: string;
|
|
63
|
+
sessionId: string | null;
|
|
64
|
+
typeName: string;
|
|
65
|
+
displayName: string;
|
|
66
|
+
description: string | null;
|
|
67
|
+
ownerUserId: string | null;
|
|
68
|
+
metadataJson: string;
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* Accept a quest: creates the caller's progress row seeded from the def
|
|
72
|
+
* (target and daily flag copied at accept time).
|
|
73
|
+
*/
|
|
74
|
+
accept(ownerUserId: Scalars['BigInt']['input'], questDefId: string, options?: {
|
|
75
|
+
displayName?: string;
|
|
76
|
+
sessionId?: string;
|
|
77
|
+
}): Promise<{
|
|
78
|
+
__typename?: "GmContainer";
|
|
79
|
+
containerId: string;
|
|
80
|
+
appId: string;
|
|
81
|
+
sessionId: string | null;
|
|
82
|
+
typeName: string;
|
|
83
|
+
displayName: string;
|
|
84
|
+
description: string | null;
|
|
85
|
+
ownerUserId: string | null;
|
|
86
|
+
metadataJson: string;
|
|
87
|
+
}>;
|
|
88
|
+
/** List a player's quest progress rows. */
|
|
89
|
+
mine(ownerUserId: Scalars['BigInt']['input']): Promise<KitQuestProgress[]>;
|
|
90
|
+
/** Read one progress row. */
|
|
91
|
+
state(progressId: string): Promise<KitQuestProgress>;
|
|
92
|
+
/**
|
|
93
|
+
* Advance quest progress — a **trusted** call (default blueprint
|
|
94
|
+
* authority: app admins; or wire `advanceOn` event automations). Resolves
|
|
95
|
+
* with the new count.
|
|
96
|
+
*/
|
|
97
|
+
advance(progressId: string, amount?: number): Promise<KitInvokeResult<number>>;
|
|
98
|
+
/**
|
|
99
|
+
* Turn in a completed quest: marks it claimed AND grants the item +
|
|
100
|
+
* currency rewards in one transaction. Resolves with the wallet's new
|
|
101
|
+
* balance.
|
|
102
|
+
*/
|
|
103
|
+
claim(input: {
|
|
104
|
+
progressId: string;
|
|
105
|
+
questDefId: string;
|
|
106
|
+
toStackId: string;
|
|
107
|
+
walletId: string;
|
|
108
|
+
}): Promise<KitInvokeResult<number>>;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=quests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quests.d.ts","sourceRoot":"","sources":["../../src/kit/quests.ts"],"names":[],"mappings":"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"}
|