@crowdedkingdoms/crowdyjs 18.12.0-dev.1 → 18.13.0-dev.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/MIGRATION.md +25 -0
- package/README.md +7 -1
- package/dist/generated/graphql-schema.d.ts +4 -4
- package/dist/generated/graphql-schema.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/kit/index.d.ts +2 -0
- package/dist/kit/index.d.ts.map +1 -1
- package/dist/kit/index.js +2 -0
- package/dist/kit/kit.d.ts +40 -1
- package/dist/kit/kit.d.ts.map +1 -1
- package/dist/kit/kit.js +71 -1
- package/dist/kit/modules/market.d.ts +159 -0
- package/dist/kit/modules/market.d.ts.map +1 -0
- package/dist/kit/modules/market.js +141 -0
- package/dist/kit/modules/player.d.ts +264 -0
- package/dist/kit/modules/player.d.ts.map +1 -0
- package/dist/kit/modules/player.js +258 -0
- package/dist/kit/protocol.d.ts +2 -0
- package/dist/kit/protocol.d.ts.map +1 -1
- package/dist/kit/protocol.js +2 -0
- package/dist/kit/runtime.d.ts.map +1 -1
- package/dist/kit/runtime.js +6 -1
- package/dist/live-coding/assets/browser-authoring-index.json +1 -1
- package/dist/live-coding/assets/manifest.json +1 -1
- package/dist/live-coding/browser-authoring-index.generated.d.ts.map +1 -1
- package/dist/live-coding/browser-authoring-index.generated.js +1474 -4
- package/package.json +1 -1
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import type { KitRuntime } from '../runtime.js';
|
|
2
|
+
import { WritableKitStore, type KitStore } from '../store.js';
|
|
3
|
+
/** Items and currency moved together: a price, a reward, a hold. */
|
|
4
|
+
export interface EconBundle {
|
|
5
|
+
items: Record<string, number>;
|
|
6
|
+
currency: Record<string, number>;
|
|
7
|
+
}
|
|
8
|
+
export interface EconStack {
|
|
9
|
+
item: string;
|
|
10
|
+
count: number;
|
|
11
|
+
}
|
|
12
|
+
/** What the `inventory` read answers: only the player reads it. */
|
|
13
|
+
export interface InventoryView {
|
|
14
|
+
slots: number;
|
|
15
|
+
stacks: EconStack[];
|
|
16
|
+
/** Items given that did not fit, waiting for {@link InventoryKit.takeMail}. */
|
|
17
|
+
mail: Record<string, number>;
|
|
18
|
+
/** Items held for a trade or an order. */
|
|
19
|
+
held: Record<string, number>;
|
|
20
|
+
}
|
|
21
|
+
/** What the `wallet` read answers. */
|
|
22
|
+
export interface WalletView {
|
|
23
|
+
balances: Record<string, number>;
|
|
24
|
+
/** Currency held for a trade or an order. */
|
|
25
|
+
held: Record<string, number>;
|
|
26
|
+
}
|
|
27
|
+
export interface AchievementView {
|
|
28
|
+
id: string;
|
|
29
|
+
counter: string;
|
|
30
|
+
target: number;
|
|
31
|
+
count: number;
|
|
32
|
+
unlocked_at: number | null;
|
|
33
|
+
}
|
|
34
|
+
export interface QuestObjectiveView {
|
|
35
|
+
counter: string;
|
|
36
|
+
target: number;
|
|
37
|
+
count: number;
|
|
38
|
+
}
|
|
39
|
+
export interface QuestView {
|
|
40
|
+
id: string;
|
|
41
|
+
state: 'locked' | 'available' | 'active' | 'complete' | 'done';
|
|
42
|
+
objectives: QuestObjectiveView[];
|
|
43
|
+
reward: EconBundle;
|
|
44
|
+
xp: number;
|
|
45
|
+
tutorial: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** What the `progress` read answers. */
|
|
48
|
+
export interface ProgressView {
|
|
49
|
+
level: number;
|
|
50
|
+
xp: number;
|
|
51
|
+
/** What the level takes to finish; null at the top. */
|
|
52
|
+
next: number | null;
|
|
53
|
+
total_xp: number;
|
|
54
|
+
achievements: AchievementView[];
|
|
55
|
+
quests: QuestView[];
|
|
56
|
+
}
|
|
57
|
+
/** What the `player` topic carries and `profile` answers: anyone may read it. */
|
|
58
|
+
export interface PlayerProfile {
|
|
59
|
+
player: number;
|
|
60
|
+
level: number;
|
|
61
|
+
achievements: string[];
|
|
62
|
+
quests_done: number;
|
|
63
|
+
}
|
|
64
|
+
export interface ProductionView {
|
|
65
|
+
producers: Array<[string, number]>;
|
|
66
|
+
stock: Record<string, number>;
|
|
67
|
+
capacity: Record<string, number>;
|
|
68
|
+
}
|
|
69
|
+
/** Everything a player's hub keeps for them (`me`). */
|
|
70
|
+
export interface PlayerView {
|
|
71
|
+
profile: PlayerProfile;
|
|
72
|
+
inventory: InventoryView;
|
|
73
|
+
wallet: WalletView;
|
|
74
|
+
progress: ProgressView;
|
|
75
|
+
production: ProductionView;
|
|
76
|
+
}
|
|
77
|
+
/** What one change earned: levels, achievements, quests complete. */
|
|
78
|
+
export interface PlayerEarned {
|
|
79
|
+
levels: number;
|
|
80
|
+
achievements: string[];
|
|
81
|
+
quests: string[];
|
|
82
|
+
}
|
|
83
|
+
export interface EconRecipe {
|
|
84
|
+
id: string;
|
|
85
|
+
inputs: EconBundle;
|
|
86
|
+
outputs: EconBundle;
|
|
87
|
+
level: number;
|
|
88
|
+
}
|
|
89
|
+
export interface LootTableView {
|
|
90
|
+
id: string;
|
|
91
|
+
cost: EconBundle;
|
|
92
|
+
entries: Array<{
|
|
93
|
+
item: string;
|
|
94
|
+
count: number;
|
|
95
|
+
weight: number;
|
|
96
|
+
pity_group: string | null;
|
|
97
|
+
}>;
|
|
98
|
+
pity_within: Record<string, number>;
|
|
99
|
+
}
|
|
100
|
+
/** What `rules` answers: the game's items, recipes, loot tables, quests and achievements. */
|
|
101
|
+
export interface PlayerRules {
|
|
102
|
+
slots: number;
|
|
103
|
+
items: Array<{
|
|
104
|
+
id: string;
|
|
105
|
+
max_stack: number;
|
|
106
|
+
tradable: boolean;
|
|
107
|
+
name: string;
|
|
108
|
+
}>;
|
|
109
|
+
currencies: string[];
|
|
110
|
+
recipes: EconRecipe[];
|
|
111
|
+
loot: LootTableView[];
|
|
112
|
+
quests: Array<Record<string, unknown>>;
|
|
113
|
+
achievements: Array<Record<string, unknown>>;
|
|
114
|
+
client_counters: string[];
|
|
115
|
+
}
|
|
116
|
+
export interface LootRoll {
|
|
117
|
+
item: string;
|
|
118
|
+
count: number;
|
|
119
|
+
/** Pity picked it. */
|
|
120
|
+
pity: boolean;
|
|
121
|
+
roll: number;
|
|
122
|
+
}
|
|
123
|
+
/** A `player` topic event: a level gained, an achievement unlocked. */
|
|
124
|
+
export type PlayerEvent = {
|
|
125
|
+
type: 'level';
|
|
126
|
+
player: number;
|
|
127
|
+
level: number;
|
|
128
|
+
} | {
|
|
129
|
+
type: 'achievement';
|
|
130
|
+
player: number;
|
|
131
|
+
achievement: string;
|
|
132
|
+
};
|
|
133
|
+
/** A store fed by another once it exists. */
|
|
134
|
+
declare class Relay<T> extends WritableKitStore<T | undefined> {
|
|
135
|
+
constructor();
|
|
136
|
+
attach(source: KitStore<T | undefined>): void;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The caller's own `player` hub (the `player` starter), keyed by their player id: what they own
|
|
140
|
+
* and what they have done. Its stores exist from the start and fill once {@link watch} has read
|
|
141
|
+
* them; only the player reads `inventory`, `wallet` and `progress`, and each is read again when
|
|
142
|
+
* the hub says it changed. The economy is not a ledger: see the Game Kit's economy page.
|
|
143
|
+
*/
|
|
144
|
+
export declare class PlayerKit {
|
|
145
|
+
private readonly runtime;
|
|
146
|
+
readonly nodeType: string;
|
|
147
|
+
private readonly playerKey?;
|
|
148
|
+
readonly profile: Relay<PlayerProfile>;
|
|
149
|
+
readonly inventory: Relay<InventoryView>;
|
|
150
|
+
readonly wallet: Relay<WalletView>;
|
|
151
|
+
readonly progress: Relay<ProgressView>;
|
|
152
|
+
private parts;
|
|
153
|
+
private rulesRead;
|
|
154
|
+
private readonly events;
|
|
155
|
+
constructor(runtime: KitRuntime, nodeType?: string, playerKey?: string | undefined);
|
|
156
|
+
/** The hub's key: the player's id. */
|
|
157
|
+
key(): Promise<string>;
|
|
158
|
+
private ready;
|
|
159
|
+
/** Mirrors the profile and reads what only the player reads (all of it, or the parts named). */
|
|
160
|
+
watch(...which: Array<'profile' | 'inventory' | 'wallet' | 'progress'>): Promise<void>;
|
|
161
|
+
unwatch(): Promise<void>;
|
|
162
|
+
/** Levels gained and achievements unlocked, as the `player` topic announces them. */
|
|
163
|
+
onEvent(listener: (e: PlayerEvent) => void): () => void;
|
|
164
|
+
/** Calls the player's hub; a change carries an action id. */
|
|
165
|
+
call<T>(method: string, args?: unknown, change?: boolean): Promise<T>;
|
|
166
|
+
/** Everything the hub keeps for the player. */
|
|
167
|
+
me(): Promise<PlayerView>;
|
|
168
|
+
/** The game's items, recipes, loot tables, quests and achievements (read once). */
|
|
169
|
+
rules(): Promise<PlayerRules>;
|
|
170
|
+
/** Another player's public profile. */
|
|
171
|
+
profileOf(player: number | string): Promise<PlayerProfile>;
|
|
172
|
+
}
|
|
173
|
+
/** The player's items: stacks in slots, and mail for what did not fit. */
|
|
174
|
+
export declare class InventoryKit {
|
|
175
|
+
private readonly player;
|
|
176
|
+
constructor(player: PlayerKit);
|
|
177
|
+
get items(): KitStore<InventoryView | undefined>;
|
|
178
|
+
watch(): Promise<InventoryView | undefined>;
|
|
179
|
+
/** How many of `item` the player has, as last read. */
|
|
180
|
+
count(item: string): number;
|
|
181
|
+
/** @throws {KitError} `insufficient`. */
|
|
182
|
+
discard(item: string, count: number): Promise<boolean>;
|
|
183
|
+
/** Moves what fits from the mail into the inventory; resolves with what moved. */
|
|
184
|
+
takeMail(): Promise<EconBundle>;
|
|
185
|
+
}
|
|
186
|
+
/** The player's soft currencies. */
|
|
187
|
+
export declare class WalletKit {
|
|
188
|
+
private readonly player;
|
|
189
|
+
constructor(player: PlayerKit);
|
|
190
|
+
get balances(): KitStore<WalletView | undefined>;
|
|
191
|
+
watch(): Promise<WalletView | undefined>;
|
|
192
|
+
/** The balance of `currency`, as last read. */
|
|
193
|
+
balance(currency: string): number;
|
|
194
|
+
}
|
|
195
|
+
/** Experience and levels, and the public profile. */
|
|
196
|
+
export declare class ProgressionKit {
|
|
197
|
+
private readonly player;
|
|
198
|
+
constructor(player: PlayerKit);
|
|
199
|
+
get progress(): KitStore<ProgressView | undefined>;
|
|
200
|
+
get profile(): KitStore<PlayerProfile | undefined>;
|
|
201
|
+
watch(): Promise<ProgressView | undefined>;
|
|
202
|
+
/** Another player's public profile. */
|
|
203
|
+
profileOf(player: number | string): Promise<PlayerProfile>;
|
|
204
|
+
/** Called with each level the player reaches. */
|
|
205
|
+
onLevel(listener: (level: number) => void): () => void;
|
|
206
|
+
}
|
|
207
|
+
/** Achievements: counts of what the player did, unlocked once. */
|
|
208
|
+
export declare class AchievementsKit {
|
|
209
|
+
private readonly player;
|
|
210
|
+
constructor(player: PlayerKit);
|
|
211
|
+
watch(): Promise<AchievementView[]>;
|
|
212
|
+
/** The achievements with their counts, as last read (hidden ones once unlocked). */
|
|
213
|
+
list(): AchievementView[];
|
|
214
|
+
/** Called with each achievement the player unlocks. */
|
|
215
|
+
onUnlock(listener: (achievement: string) => void): () => void;
|
|
216
|
+
}
|
|
217
|
+
/** Quests, first-session tutorials among them. */
|
|
218
|
+
export declare class QuestsKit {
|
|
219
|
+
private readonly player;
|
|
220
|
+
constructor(player: PlayerKit);
|
|
221
|
+
watch(): Promise<QuestView[]>;
|
|
222
|
+
list(): QuestView[];
|
|
223
|
+
/** @throws {KitError} `conflict` (taken, done, or another first), `forbidden` (level), `not_found`. */
|
|
224
|
+
accept(quest: string): Promise<boolean>;
|
|
225
|
+
/** Claims a complete quest's reward. @throws {KitError} `not_ready`, `full`. */
|
|
226
|
+
claim(quest: string): Promise<EconBundle>;
|
|
227
|
+
/**
|
|
228
|
+
* Reports one of the counters the game lets a client report (a tutorial step).
|
|
229
|
+
* @throws {KitError} `forbidden` for a counter the game's hubs count.
|
|
230
|
+
*/
|
|
231
|
+
step(counter: string): Promise<PlayerEarned>;
|
|
232
|
+
}
|
|
233
|
+
/** Crafting from the game's recipes. */
|
|
234
|
+
export declare class CraftingKit {
|
|
235
|
+
private readonly player;
|
|
236
|
+
constructor(player: PlayerKit);
|
|
237
|
+
recipes(): Promise<EconRecipe[]>;
|
|
238
|
+
/** Crafts `times` (once by default). @throws {KitError} `insufficient`, `full`, `forbidden` (level), `not_found`. */
|
|
239
|
+
craft(recipe: string, times?: number): Promise<{
|
|
240
|
+
made: EconBundle;
|
|
241
|
+
earned: PlayerEarned;
|
|
242
|
+
}>;
|
|
243
|
+
}
|
|
244
|
+
/** Loot tables with pity. */
|
|
245
|
+
export declare class LootKit {
|
|
246
|
+
private readonly player;
|
|
247
|
+
constructor(player: PlayerKit);
|
|
248
|
+
tables(): Promise<LootTableView[]>;
|
|
249
|
+
/** Pays the table's cost and rolls once. @throws {KitError} `insufficient`, `full`, `not_found`. */
|
|
250
|
+
open(table: string): Promise<{
|
|
251
|
+
roll: LootRoll;
|
|
252
|
+
earned: PlayerEarned;
|
|
253
|
+
}>;
|
|
254
|
+
}
|
|
255
|
+
/** Idle production that catches up on the time away. */
|
|
256
|
+
export declare class ProductionKit {
|
|
257
|
+
private readonly player;
|
|
258
|
+
constructor(player: PlayerKit);
|
|
259
|
+
view(): Promise<ProductionView>;
|
|
260
|
+
/** Moves what the producers made into the inventory, as far as it fits. */
|
|
261
|
+
collect(): Promise<EconBundle>;
|
|
262
|
+
}
|
|
263
|
+
export {};
|
|
264
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../../src/kit/modules/player.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { CrowdyError } from '../../errors.js';
|
|
2
|
+
import { HubState, PrivateState } from '../mirror.js';
|
|
3
|
+
import { WritableKitStore } from '../store.js';
|
|
4
|
+
const TOPIC = 'player';
|
|
5
|
+
/** A store fed by another once it exists. */
|
|
6
|
+
class Relay extends WritableKitStore {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(undefined);
|
|
9
|
+
}
|
|
10
|
+
attach(source) {
|
|
11
|
+
source.subscribe((v) => this.set(v));
|
|
12
|
+
if (source.get() !== undefined)
|
|
13
|
+
this.set(source.get());
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The caller's own `player` hub (the `player` starter), keyed by their player id: what they own
|
|
18
|
+
* and what they have done. Its stores exist from the start and fill once {@link watch} has read
|
|
19
|
+
* them; only the player reads `inventory`, `wallet` and `progress`, and each is read again when
|
|
20
|
+
* the hub says it changed. The economy is not a ledger: see the Game Kit's economy page.
|
|
21
|
+
*/
|
|
22
|
+
export class PlayerKit {
|
|
23
|
+
constructor(runtime, nodeType = 'player', playerKey) {
|
|
24
|
+
this.runtime = runtime;
|
|
25
|
+
this.nodeType = nodeType;
|
|
26
|
+
this.playerKey = playerKey;
|
|
27
|
+
this.profile = new Relay();
|
|
28
|
+
this.inventory = new Relay();
|
|
29
|
+
this.wallet = new Relay();
|
|
30
|
+
this.progress = new Relay();
|
|
31
|
+
this.parts = null;
|
|
32
|
+
this.rulesRead = null;
|
|
33
|
+
this.events = new Set();
|
|
34
|
+
}
|
|
35
|
+
/** The hub's key: the player's id. */
|
|
36
|
+
async key() {
|
|
37
|
+
const key = this.playerKey ?? (await this.runtime.playerId());
|
|
38
|
+
if (key === null || key === undefined) {
|
|
39
|
+
throw new CrowdyError({ message: 'the kit does not know which player it is: pass playerId to client.kit()' });
|
|
40
|
+
}
|
|
41
|
+
return key;
|
|
42
|
+
}
|
|
43
|
+
ready() {
|
|
44
|
+
this.parts ?? (this.parts = (async () => {
|
|
45
|
+
const key = await this.key();
|
|
46
|
+
const read = (method) => () => this.runtime.call(this.nodeType, key, method);
|
|
47
|
+
const source = { nodeType: this.nodeType, key, topic: TOPIC };
|
|
48
|
+
const parts = {
|
|
49
|
+
key,
|
|
50
|
+
profile: new HubState(this.runtime, this.nodeType, key, TOPIC),
|
|
51
|
+
inventory: new PrivateState(this.runtime, { ...source, what: 'inventory', read: read('inventory') }),
|
|
52
|
+
wallet: new PrivateState(this.runtime, { ...source, what: 'wallet', read: read('wallet') }),
|
|
53
|
+
progress: new PrivateState(this.runtime, { ...source, what: 'progress', read: read('progress') }),
|
|
54
|
+
};
|
|
55
|
+
this.profile.attach(parts.profile);
|
|
56
|
+
this.inventory.attach(parts.inventory);
|
|
57
|
+
this.wallet.attach(parts.wallet);
|
|
58
|
+
this.progress.attach(parts.progress);
|
|
59
|
+
parts.profile.onEvent((body) => {
|
|
60
|
+
for (const l of [...this.events])
|
|
61
|
+
l(body);
|
|
62
|
+
});
|
|
63
|
+
return parts;
|
|
64
|
+
})().catch((e) => {
|
|
65
|
+
this.parts = null;
|
|
66
|
+
throw e;
|
|
67
|
+
}));
|
|
68
|
+
return this.parts;
|
|
69
|
+
}
|
|
70
|
+
/** Mirrors the profile and reads what only the player reads (all of it, or the parts named). */
|
|
71
|
+
async watch(...which) {
|
|
72
|
+
const parts = await this.ready();
|
|
73
|
+
const all = which.length ? which : ['profile', 'inventory', 'wallet', 'progress'];
|
|
74
|
+
await Promise.all(all.map((w) => parts[w].start()));
|
|
75
|
+
}
|
|
76
|
+
async unwatch() {
|
|
77
|
+
if (!this.parts)
|
|
78
|
+
return;
|
|
79
|
+
const parts = await this.parts;
|
|
80
|
+
await Promise.all([parts.profile.stop(), parts.inventory.stop(), parts.wallet.stop(), parts.progress.stop()]);
|
|
81
|
+
}
|
|
82
|
+
/** Levels gained and achievements unlocked, as the `player` topic announces them. */
|
|
83
|
+
onEvent(listener) {
|
|
84
|
+
this.events.add(listener);
|
|
85
|
+
return () => this.events.delete(listener);
|
|
86
|
+
}
|
|
87
|
+
/** Calls the player's hub; a change carries an action id. */
|
|
88
|
+
async call(method, args, change = true) {
|
|
89
|
+
return this.runtime.call(this.nodeType, await this.key(), method, args ?? null, change ? { action: true } : {});
|
|
90
|
+
}
|
|
91
|
+
/** Everything the hub keeps for the player. */
|
|
92
|
+
me() {
|
|
93
|
+
return this.call('me', null, false);
|
|
94
|
+
}
|
|
95
|
+
/** The game's items, recipes, loot tables, quests and achievements (read once). */
|
|
96
|
+
rules() {
|
|
97
|
+
this.rulesRead ?? (this.rulesRead = this.call('rules', null, false).catch((e) => {
|
|
98
|
+
this.rulesRead = null;
|
|
99
|
+
throw e;
|
|
100
|
+
}));
|
|
101
|
+
return this.rulesRead;
|
|
102
|
+
}
|
|
103
|
+
/** Another player's public profile. */
|
|
104
|
+
profileOf(player) {
|
|
105
|
+
return this.runtime.call(this.nodeType, String(player), 'profile');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** The player's items: stacks in slots, and mail for what did not fit. */
|
|
109
|
+
export class InventoryKit {
|
|
110
|
+
constructor(player) {
|
|
111
|
+
this.player = player;
|
|
112
|
+
}
|
|
113
|
+
get items() {
|
|
114
|
+
return this.player.inventory;
|
|
115
|
+
}
|
|
116
|
+
async watch() {
|
|
117
|
+
await this.player.watch('inventory');
|
|
118
|
+
return this.player.inventory.get();
|
|
119
|
+
}
|
|
120
|
+
/** How many of `item` the player has, as last read. */
|
|
121
|
+
count(item) {
|
|
122
|
+
return (this.player.inventory.get()?.stacks ?? []).filter((s) => s.item === item).reduce((n, s) => n + s.count, 0);
|
|
123
|
+
}
|
|
124
|
+
/** @throws {KitError} `insufficient`. */
|
|
125
|
+
discard(item, count) {
|
|
126
|
+
return this.player.call('discard', { item, count });
|
|
127
|
+
}
|
|
128
|
+
/** Moves what fits from the mail into the inventory; resolves with what moved. */
|
|
129
|
+
takeMail() {
|
|
130
|
+
return this.player.call('take_mail');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** The player's soft currencies. */
|
|
134
|
+
export class WalletKit {
|
|
135
|
+
constructor(player) {
|
|
136
|
+
this.player = player;
|
|
137
|
+
}
|
|
138
|
+
get balances() {
|
|
139
|
+
return this.player.wallet;
|
|
140
|
+
}
|
|
141
|
+
async watch() {
|
|
142
|
+
await this.player.watch('wallet');
|
|
143
|
+
return this.player.wallet.get();
|
|
144
|
+
}
|
|
145
|
+
/** The balance of `currency`, as last read. */
|
|
146
|
+
balance(currency) {
|
|
147
|
+
return this.player.wallet.get()?.balances[currency] ?? 0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Experience and levels, and the public profile. */
|
|
151
|
+
export class ProgressionKit {
|
|
152
|
+
constructor(player) {
|
|
153
|
+
this.player = player;
|
|
154
|
+
}
|
|
155
|
+
get progress() {
|
|
156
|
+
return this.player.progress;
|
|
157
|
+
}
|
|
158
|
+
get profile() {
|
|
159
|
+
return this.player.profile;
|
|
160
|
+
}
|
|
161
|
+
async watch() {
|
|
162
|
+
await this.player.watch('profile', 'progress');
|
|
163
|
+
return this.player.progress.get();
|
|
164
|
+
}
|
|
165
|
+
/** Another player's public profile. */
|
|
166
|
+
profileOf(player) {
|
|
167
|
+
return this.player.profileOf(player);
|
|
168
|
+
}
|
|
169
|
+
/** Called with each level the player reaches. */
|
|
170
|
+
onLevel(listener) {
|
|
171
|
+
return this.player.onEvent((e) => e.type === 'level' && listener(e.level));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Achievements: counts of what the player did, unlocked once. */
|
|
175
|
+
export class AchievementsKit {
|
|
176
|
+
constructor(player) {
|
|
177
|
+
this.player = player;
|
|
178
|
+
}
|
|
179
|
+
async watch() {
|
|
180
|
+
await this.player.watch('profile', 'progress');
|
|
181
|
+
return this.list();
|
|
182
|
+
}
|
|
183
|
+
/** The achievements with their counts, as last read (hidden ones once unlocked). */
|
|
184
|
+
list() {
|
|
185
|
+
return this.player.progress.get()?.achievements ?? [];
|
|
186
|
+
}
|
|
187
|
+
/** Called with each achievement the player unlocks. */
|
|
188
|
+
onUnlock(listener) {
|
|
189
|
+
return this.player.onEvent((e) => e.type === 'achievement' && listener(e.achievement));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Quests, first-session tutorials among them. */
|
|
193
|
+
export class QuestsKit {
|
|
194
|
+
constructor(player) {
|
|
195
|
+
this.player = player;
|
|
196
|
+
}
|
|
197
|
+
async watch() {
|
|
198
|
+
await this.player.watch('progress');
|
|
199
|
+
return this.list();
|
|
200
|
+
}
|
|
201
|
+
list() {
|
|
202
|
+
return this.player.progress.get()?.quests ?? [];
|
|
203
|
+
}
|
|
204
|
+
/** @throws {KitError} `conflict` (taken, done, or another first), `forbidden` (level), `not_found`. */
|
|
205
|
+
accept(quest) {
|
|
206
|
+
return this.player.call('accept', { quest });
|
|
207
|
+
}
|
|
208
|
+
/** Claims a complete quest's reward. @throws {KitError} `not_ready`, `full`. */
|
|
209
|
+
claim(quest) {
|
|
210
|
+
return this.player.call('claim', { quest });
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Reports one of the counters the game lets a client report (a tutorial step).
|
|
214
|
+
* @throws {KitError} `forbidden` for a counter the game's hubs count.
|
|
215
|
+
*/
|
|
216
|
+
step(counter) {
|
|
217
|
+
return this.player.call('step', { counter });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/** Crafting from the game's recipes. */
|
|
221
|
+
export class CraftingKit {
|
|
222
|
+
constructor(player) {
|
|
223
|
+
this.player = player;
|
|
224
|
+
}
|
|
225
|
+
async recipes() {
|
|
226
|
+
return (await this.player.rules()).recipes;
|
|
227
|
+
}
|
|
228
|
+
/** Crafts `times` (once by default). @throws {KitError} `insufficient`, `full`, `forbidden` (level), `not_found`. */
|
|
229
|
+
craft(recipe, times) {
|
|
230
|
+
return this.player.call('craft', times === undefined ? { recipe } : { recipe, times });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/** Loot tables with pity. */
|
|
234
|
+
export class LootKit {
|
|
235
|
+
constructor(player) {
|
|
236
|
+
this.player = player;
|
|
237
|
+
}
|
|
238
|
+
async tables() {
|
|
239
|
+
return (await this.player.rules()).loot;
|
|
240
|
+
}
|
|
241
|
+
/** Pays the table's cost and rolls once. @throws {KitError} `insufficient`, `full`, `not_found`. */
|
|
242
|
+
open(table) {
|
|
243
|
+
return this.player.call('open', { table });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Idle production that catches up on the time away. */
|
|
247
|
+
export class ProductionKit {
|
|
248
|
+
constructor(player) {
|
|
249
|
+
this.player = player;
|
|
250
|
+
}
|
|
251
|
+
async view() {
|
|
252
|
+
return (await this.player.me()).production;
|
|
253
|
+
}
|
|
254
|
+
/** Moves what the producers made into the inventory, as far as it fits. */
|
|
255
|
+
collect() {
|
|
256
|
+
return this.player.call('collect');
|
|
257
|
+
}
|
|
258
|
+
}
|
package/dist/kit/protocol.d.ts
CHANGED
|
@@ -90,6 +90,8 @@ export declare const KIT_CODES: {
|
|
|
90
90
|
readonly EXPIRED: "expired";
|
|
91
91
|
readonly INSUFFICIENT: "insufficient";
|
|
92
92
|
readonly ALREADY_DONE: "already_done";
|
|
93
|
+
/** A hub the call needed did not answer: the kit sends it again with its action id. */
|
|
94
|
+
readonly UNAVAILABLE: "unavailable";
|
|
93
95
|
};
|
|
94
96
|
/**
|
|
95
97
|
* A kit hub refused the call (`AppError` with a `kit:<code>:` message): `code` is what to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/kit/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,sDAAsD;AACtD,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAExE,4CAA4C;AAC5C,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,uCAAuC;AACvC,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,iCAAiC;AACjC,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAKD,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,KAAK,EAAE,OAAO,GACb;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAAG,IAAI,CAQvC;AAMD,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGtF;AAED,wFAAwF;AACxF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/kit/protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/kit/protocol.js
CHANGED
|
@@ -81,6 +81,8 @@ export const KIT_CODES = {
|
|
|
81
81
|
EXPIRED: 'expired',
|
|
82
82
|
INSUFFICIENT: 'insufficient',
|
|
83
83
|
ALREADY_DONE: 'already_done',
|
|
84
|
+
/** A hub the call needed did not answer: the kit sends it again with its action id. */
|
|
85
|
+
UNAVAILABLE: 'unavailable',
|
|
84
86
|
};
|
|
85
87
|
/**
|
|
86
88
|
* A kit hub refused the call (`AppError` with a `kit:<code>:` message): `code` is what to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/kit/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAG5B,iFAAiF;AACjF,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,8EAA8E;IAC9E,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,6FAA6F;IAC7F,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8CD;;;;;;GAMG;AACH,qBAAa,UAAU;IAYnB,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAd1B,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqC;IACxE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuC;IACtE,OAAO,CAAC,EAAE,CAAuC;gBAGtC,KAAK,EAAE,MAAM,EACL,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,OAAO,GAAE,iBAAsB,EAC/B,MAAM,CAAC,GAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,aAAA;IAMxD,2CAA2C;IACrC,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;YAY7B,IAAI;IAmBlB,mFAAmF;IAC7E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQxC;;;OAGG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/kit/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAG5B,iFAAiF;AACjF,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,8EAA8E;IAC9E,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,6FAA6F;IAC7F,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8CD;;;;;;GAMG;AACH,qBAAa,UAAU;IAYnB,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAd1B,OAAO,CAAC,IAAI,CAA+B;IAC3C,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqC;IACxE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuC;IACtE,OAAO,CAAC,EAAE,CAAuC;gBAGtC,KAAK,EAAE,MAAM,EACL,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,OAAO,GAAE,iBAAsB,EAC/B,MAAM,CAAC,GAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,aAAA;IAMxD,2CAA2C;IACrC,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;YAY7B,IAAI;IAmBlB,mFAAmF;IAC7E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQxC;;;OAGG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC;IAgCb;;;;OAIG;IACG,SAAS,CAAC,CAAC,GAAG,OAAO,EACzB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IA2B/B,sDAAsD;IACtD,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,yFAAyF;IACzF,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAKzD,wFAAwF;IACxF,aAAa,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAK7D,mEAAmE;IACnE,KAAK,IAAI,IAAI;CAMd"}
|
package/dist/kit/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CrowdyExecError, } from '../domains/exec.js';
|
|
2
|
-
import { KitError, newActionId, withActionId } from './protocol.js';
|
|
2
|
+
import { KIT_CODES, KitError, newActionId, withActionId } from './protocol.js';
|
|
3
3
|
/** Subscriptions one connection holds at most (the gateway refuses the next). */
|
|
4
4
|
export const KIT_SUBSCRIPTIONS_MAX = 256;
|
|
5
5
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -120,6 +120,11 @@ export class KitRuntime {
|
|
|
120
120
|
}
|
|
121
121
|
catch (e) {
|
|
122
122
|
const err = KitError.from(e);
|
|
123
|
+
// A hub that could not hear from another one did not finish, and keeps no receipt.
|
|
124
|
+
if (attempt < this.retries && actionId && err instanceof KitError && err.code === KIT_CODES.UNAVAILABLE) {
|
|
125
|
+
await sleep(Math.min(2000, 200 * 2 ** attempt) * (0.5 + Math.random() / 2));
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
123
128
|
if (attempt < this.retries && err instanceof CrowdyExecError && !(err instanceof KitError)) {
|
|
124
129
|
if (err.status === 'Busy' && err.rateLimited) {
|
|
125
130
|
this.budget.hold(err.retryAfterMs ?? 1000);
|