@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,140 @@
|
|
|
1
|
+
import type { ChannelsAPI } from '../domains/channels.js';
|
|
2
|
+
import type { GameModelAPI } from '../domains/gameModel.js';
|
|
3
|
+
import type { UdpAPI } from '../domains/udp.js';
|
|
4
|
+
import type { Scalars } from '../generated/graphql.js';
|
|
5
|
+
import { type KitInvokeResult } from './shared.js';
|
|
6
|
+
/** Options for {@link MatchesKit}. Must match the deployed matches blueprint. */
|
|
7
|
+
export interface MatchesKitOptions {
|
|
8
|
+
/** The `typePrefix` the matches blueprint was deployed with. */
|
|
9
|
+
typePrefix?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The 32-ASCII-char actor uuid used as the sender id on channel pings.
|
|
12
|
+
* Defaults to a random uuid per kit instance.
|
|
13
|
+
*/
|
|
14
|
+
actorUuid?: string;
|
|
15
|
+
}
|
|
16
|
+
/** A parsed view of one match. */
|
|
17
|
+
export interface KitMatch {
|
|
18
|
+
/** The session backing the match (participants + turn order). */
|
|
19
|
+
sessionId: string;
|
|
20
|
+
/** The MatchMeta container id (the `self` of the lifecycle functions). */
|
|
21
|
+
metaId: string;
|
|
22
|
+
displayName: string;
|
|
23
|
+
creatorUserId: number;
|
|
24
|
+
mode: string;
|
|
25
|
+
state: string;
|
|
26
|
+
round: number;
|
|
27
|
+
maxPlayers: number;
|
|
28
|
+
winnerUserId: number;
|
|
29
|
+
/** The per-match notification channel (0 when none was wired). */
|
|
30
|
+
channelId: string;
|
|
31
|
+
/** Present when the blueprint was deployed with `turnTick`. */
|
|
32
|
+
tickCount?: number;
|
|
33
|
+
}
|
|
34
|
+
/** One row of the match standings. */
|
|
35
|
+
export interface KitMatchScore {
|
|
36
|
+
containerId: string;
|
|
37
|
+
ownerUserId: string | null;
|
|
38
|
+
points: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Runtime helpers for the {@link matchesBlueprint} conventions: sessions ARE
|
|
42
|
+
* the match primitive — `create` makes a session + a `MatchMeta` + a
|
|
43
|
+
* per-match channel; turn order goes through the platform's session-turn
|
|
44
|
+
* authority; lifecycle functions ping the channel post-commit and
|
|
45
|
+
* {@link onMatchChanged} wraps the notify-to-pull loop (subscribe →
|
|
46
|
+
* `"match_changed"` ping → re-pull state).
|
|
47
|
+
*
|
|
48
|
+
* Obtained via `client.kit(appId).matches`.
|
|
49
|
+
*/
|
|
50
|
+
export declare class MatchesKit {
|
|
51
|
+
private readonly appId;
|
|
52
|
+
private readonly gameModel;
|
|
53
|
+
private readonly channels;
|
|
54
|
+
private readonly udp;
|
|
55
|
+
private readonly names;
|
|
56
|
+
private readonly actorUuid;
|
|
57
|
+
constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI, channels: ChannelsAPI | undefined, udp: UdpAPI | undefined, options?: MatchesKitOptions);
|
|
58
|
+
private requireChannels;
|
|
59
|
+
private requireUdp;
|
|
60
|
+
/**
|
|
61
|
+
* Create a match: a session (the platform match primitive), a per-match
|
|
62
|
+
* notification channel, and the session-scoped `MatchMeta`.
|
|
63
|
+
*
|
|
64
|
+
* @param input.creatorUserId - The calling player's user id (stored so the
|
|
65
|
+
* creator may start/advance/end the match).
|
|
66
|
+
*/
|
|
67
|
+
create(input: {
|
|
68
|
+
creatorUserId: Scalars['BigInt']['input'];
|
|
69
|
+
mode?: string;
|
|
70
|
+
maxPlayers?: number;
|
|
71
|
+
displayName?: string;
|
|
72
|
+
}): Promise<KitMatch>;
|
|
73
|
+
/** List joinable matches (metas still in the lobby state). */
|
|
74
|
+
open(): Promise<KitMatch[]>;
|
|
75
|
+
/** Read one match by its MatchMeta container. */
|
|
76
|
+
get(metaId: string): Promise<KitMatch>;
|
|
77
|
+
/** Join a match: session participation + the notification channel. */
|
|
78
|
+
join(match: KitMatch): Promise<{
|
|
79
|
+
__typename?: "GmSessionParticipant";
|
|
80
|
+
sessionId: string;
|
|
81
|
+
userId: string;
|
|
82
|
+
role: string;
|
|
83
|
+
}>;
|
|
84
|
+
/** Start the match (creator or host). Pings the match channel post-commit. */
|
|
85
|
+
start(match: KitMatch): Promise<KitInvokeResult<string>>;
|
|
86
|
+
/** Advance to the next round (creator or host). */
|
|
87
|
+
advanceRound(match: KitMatch): Promise<KitInvokeResult<number>>;
|
|
88
|
+
/** Whether it is `userId`'s session turn right now. */
|
|
89
|
+
myTurn(match: KitMatch, userId: Scalars['BigInt']['input']): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Pass the turn to the next player via the platform's session-turn
|
|
92
|
+
* authority (current holder, host, or admin — enforced by the service),
|
|
93
|
+
* then ping the match channel so everyone re-pulls.
|
|
94
|
+
*/
|
|
95
|
+
endTurn(match: KitMatch, nextUserId: Scalars['BigInt']['input']): Promise<{
|
|
96
|
+
__typename?: "GmSession";
|
|
97
|
+
sessionId: string;
|
|
98
|
+
appId: string;
|
|
99
|
+
name: string | null;
|
|
100
|
+
status: string;
|
|
101
|
+
createdByUserId: string | null;
|
|
102
|
+
currentTurnUserId: string | null;
|
|
103
|
+
metadataJson: string;
|
|
104
|
+
}>;
|
|
105
|
+
/** Find-or-create a player's session-scoped Score row. */
|
|
106
|
+
ensureScore(match: KitMatch, ownerUserId: Scalars['BigInt']['input']): Promise<{
|
|
107
|
+
__typename?: "GmContainer";
|
|
108
|
+
containerId: string;
|
|
109
|
+
appId: string;
|
|
110
|
+
sessionId: string | null;
|
|
111
|
+
typeName: string;
|
|
112
|
+
displayName: string;
|
|
113
|
+
description: string | null;
|
|
114
|
+
ownerUserId: string | null;
|
|
115
|
+
metadataJson: string;
|
|
116
|
+
}>;
|
|
117
|
+
/**
|
|
118
|
+
* Add points to a Score row — trusted (host-refereed by default).
|
|
119
|
+
* Resolves with the new points.
|
|
120
|
+
*/
|
|
121
|
+
score(match: KitMatch, scoreId: string, points: number): Promise<KitInvokeResult<number>>;
|
|
122
|
+
/** The match standings, highest points first (client-side sort). */
|
|
123
|
+
standings(match: KitMatch): Promise<KitMatchScore[]>;
|
|
124
|
+
/** Finish the match and record the winner (creator or host). */
|
|
125
|
+
finish(match: KitMatch, winnerUserId: Scalars['BigInt']['input']): Promise<KitInvokeResult<string>>;
|
|
126
|
+
/**
|
|
127
|
+
* Manually ping the match channel with `"match_changed"` (the lifecycle
|
|
128
|
+
* functions do this automatically via their declared notifications; use
|
|
129
|
+
* this after out-of-band changes such as `endTurn`).
|
|
130
|
+
*/
|
|
131
|
+
notifyChanged(match: KitMatch): Promise<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* The notify-to-pull loop, wrapped: subscribe to the app's notifications,
|
|
134
|
+
* and on every ping of THIS match's channel re-pull the match state and
|
|
135
|
+
* hand it to `callback`. Returns the unsubscribe function.
|
|
136
|
+
*/
|
|
137
|
+
onMatchChanged(match: KitMatch, callback: (match: KitMatch) => void): () => void;
|
|
138
|
+
private toMatch;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=matches.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matches.d.ts","sourceRoot":"","sources":["../../src/kit/matches.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { encodeBase64, generateCrowdyUuid } from '../utils.js';
|
|
2
|
+
import { matchesNames } from './blueprints/index.js';
|
|
3
|
+
import { kitContainerProperties, kitInvoke, } from './shared.js';
|
|
4
|
+
/**
|
|
5
|
+
* Runtime helpers for the {@link matchesBlueprint} conventions: sessions ARE
|
|
6
|
+
* the match primitive — `create` makes a session + a `MatchMeta` + a
|
|
7
|
+
* per-match channel; turn order goes through the platform's session-turn
|
|
8
|
+
* authority; lifecycle functions ping the channel post-commit and
|
|
9
|
+
* {@link onMatchChanged} wraps the notify-to-pull loop (subscribe →
|
|
10
|
+
* `"match_changed"` ping → re-pull state).
|
|
11
|
+
*
|
|
12
|
+
* Obtained via `client.kit(appId).matches`.
|
|
13
|
+
*/
|
|
14
|
+
export class MatchesKit {
|
|
15
|
+
constructor(appId, gameModel, channels, udp, options = {}) {
|
|
16
|
+
this.appId = appId;
|
|
17
|
+
this.gameModel = gameModel;
|
|
18
|
+
this.channels = channels;
|
|
19
|
+
this.udp = udp;
|
|
20
|
+
this.names = matchesNames(options.typePrefix ?? '');
|
|
21
|
+
this.actorUuid = options.actorUuid ?? generateCrowdyUuid();
|
|
22
|
+
}
|
|
23
|
+
requireChannels() {
|
|
24
|
+
if (!this.channels) {
|
|
25
|
+
throw new Error('kit.matches needs the channels domain — construct the kit via client.kit(appId)');
|
|
26
|
+
}
|
|
27
|
+
return this.channels;
|
|
28
|
+
}
|
|
29
|
+
requireUdp() {
|
|
30
|
+
if (!this.udp) {
|
|
31
|
+
throw new Error('kit.matches needs the udp domain — construct the kit via client.kit(appId)');
|
|
32
|
+
}
|
|
33
|
+
return this.udp;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Create a match: a session (the platform match primitive), a per-match
|
|
37
|
+
* notification channel, and the session-scoped `MatchMeta`.
|
|
38
|
+
*
|
|
39
|
+
* @param input.creatorUserId - The calling player's user id (stored so the
|
|
40
|
+
* creator may start/advance/end the match).
|
|
41
|
+
*/
|
|
42
|
+
async create(input) {
|
|
43
|
+
const session = await this.gameModel.createSession({
|
|
44
|
+
appId: this.appId,
|
|
45
|
+
name: input.displayName ?? `match-${input.mode ?? 'default'}`,
|
|
46
|
+
});
|
|
47
|
+
const channel = await this.requireChannels().create({
|
|
48
|
+
appId: this.appId,
|
|
49
|
+
name: `match-${session.sessionId}`,
|
|
50
|
+
description: 'Per-match notification channel (kit.matches notify-to-pull).',
|
|
51
|
+
});
|
|
52
|
+
const meta = await this.gameModel.createContainer({
|
|
53
|
+
appId: this.appId,
|
|
54
|
+
typeName: this.names.metaType,
|
|
55
|
+
displayName: input.displayName ?? `Match ${session.sessionId}`,
|
|
56
|
+
sessionId: session.sessionId,
|
|
57
|
+
properties: [
|
|
58
|
+
{
|
|
59
|
+
key: 'creator_user_id',
|
|
60
|
+
valueType: 'int',
|
|
61
|
+
valueJson: String(input.creatorUserId),
|
|
62
|
+
},
|
|
63
|
+
{ key: 'mode', valueType: 'string', valueJson: JSON.stringify(input.mode ?? '') },
|
|
64
|
+
{
|
|
65
|
+
key: 'max_players',
|
|
66
|
+
valueType: 'int',
|
|
67
|
+
valueJson: String(input.maxPlayers ?? 0),
|
|
68
|
+
},
|
|
69
|
+
{ key: 'channel_id', valueType: 'int', valueJson: String(channel.groupId) },
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
return this.toMatch(meta.containerId, session.sessionId, meta.displayName);
|
|
73
|
+
}
|
|
74
|
+
/** List joinable matches (metas still in the lobby state). */
|
|
75
|
+
async open() {
|
|
76
|
+
const metas = await this.gameModel.containers({
|
|
77
|
+
appId: this.appId,
|
|
78
|
+
typeName: this.names.metaType,
|
|
79
|
+
});
|
|
80
|
+
const matches = await Promise.all(metas
|
|
81
|
+
.filter((m) => m.sessionId != null)
|
|
82
|
+
.map((m) => this.toMatch(m.containerId, String(m.sessionId), m.displayName)));
|
|
83
|
+
return matches.filter((m) => m.state === 'lobby');
|
|
84
|
+
}
|
|
85
|
+
/** Read one match by its MatchMeta container. */
|
|
86
|
+
async get(metaId) {
|
|
87
|
+
const meta = await this.gameModel.container({
|
|
88
|
+
appId: this.appId,
|
|
89
|
+
containerId: metaId,
|
|
90
|
+
});
|
|
91
|
+
return this.toMatch(meta.containerId, meta.sessionId != null ? String(meta.sessionId) : '', meta.displayName);
|
|
92
|
+
}
|
|
93
|
+
/** Join a match: session participation + the notification channel. */
|
|
94
|
+
async join(match) {
|
|
95
|
+
const participant = await this.gameModel.joinSession({
|
|
96
|
+
appId: this.appId,
|
|
97
|
+
sessionId: match.sessionId,
|
|
98
|
+
});
|
|
99
|
+
if (match.channelId !== '0' && match.channelId !== '') {
|
|
100
|
+
await this.requireChannels().join(match.channelId);
|
|
101
|
+
}
|
|
102
|
+
return participant;
|
|
103
|
+
}
|
|
104
|
+
/** Start the match (creator or host). Pings the match channel post-commit. */
|
|
105
|
+
async start(match) {
|
|
106
|
+
return kitInvoke(this.gameModel, {
|
|
107
|
+
appId: String(this.appId),
|
|
108
|
+
functionName: this.names.startFn,
|
|
109
|
+
selfContainerId: match.metaId,
|
|
110
|
+
sessionId: match.sessionId,
|
|
111
|
+
params: {},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/** Advance to the next round (creator or host). */
|
|
115
|
+
async advanceRound(match) {
|
|
116
|
+
return kitInvoke(this.gameModel, {
|
|
117
|
+
appId: String(this.appId),
|
|
118
|
+
functionName: this.names.advanceRoundFn,
|
|
119
|
+
selfContainerId: match.metaId,
|
|
120
|
+
sessionId: match.sessionId,
|
|
121
|
+
params: {},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/** Whether it is `userId`'s session turn right now. */
|
|
125
|
+
async myTurn(match, userId) {
|
|
126
|
+
const session = await this.gameModel.session({
|
|
127
|
+
appId: this.appId,
|
|
128
|
+
sessionId: match.sessionId,
|
|
129
|
+
});
|
|
130
|
+
return (session.currentTurnUserId != null &&
|
|
131
|
+
String(session.currentTurnUserId) === String(userId));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Pass the turn to the next player via the platform's session-turn
|
|
135
|
+
* authority (current holder, host, or admin — enforced by the service),
|
|
136
|
+
* then ping the match channel so everyone re-pulls.
|
|
137
|
+
*/
|
|
138
|
+
async endTurn(match, nextUserId) {
|
|
139
|
+
const session = await this.gameModel.setSessionTurn({
|
|
140
|
+
appId: this.appId,
|
|
141
|
+
sessionId: match.sessionId,
|
|
142
|
+
userId: nextUserId,
|
|
143
|
+
});
|
|
144
|
+
await this.notifyChanged(match);
|
|
145
|
+
return session;
|
|
146
|
+
}
|
|
147
|
+
/** Find-or-create a player's session-scoped Score row. */
|
|
148
|
+
async ensureScore(match, ownerUserId) {
|
|
149
|
+
const scores = await this.gameModel.containers({
|
|
150
|
+
appId: this.appId,
|
|
151
|
+
typeName: this.names.scoreType,
|
|
152
|
+
sessionId: match.sessionId,
|
|
153
|
+
});
|
|
154
|
+
const mine = scores.find((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
|
|
155
|
+
if (mine)
|
|
156
|
+
return mine;
|
|
157
|
+
return this.gameModel.createContainer({
|
|
158
|
+
appId: this.appId,
|
|
159
|
+
typeName: this.names.scoreType,
|
|
160
|
+
displayName: `Score ${ownerUserId}`,
|
|
161
|
+
sessionId: match.sessionId,
|
|
162
|
+
properties: [
|
|
163
|
+
{ key: 'owner_user_id', valueType: 'int', valueJson: String(ownerUserId) },
|
|
164
|
+
],
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Add points to a Score row — trusted (host-refereed by default).
|
|
169
|
+
* Resolves with the new points.
|
|
170
|
+
*/
|
|
171
|
+
async score(match, scoreId, points) {
|
|
172
|
+
return kitInvoke(this.gameModel, {
|
|
173
|
+
appId: String(this.appId),
|
|
174
|
+
functionName: this.names.scoreFn,
|
|
175
|
+
selfContainerId: scoreId,
|
|
176
|
+
sessionId: match.sessionId,
|
|
177
|
+
params: { points },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/** The match standings, highest points first (client-side sort). */
|
|
181
|
+
async standings(match) {
|
|
182
|
+
const scores = await this.gameModel.containers({
|
|
183
|
+
appId: this.appId,
|
|
184
|
+
typeName: this.names.scoreType,
|
|
185
|
+
sessionId: match.sessionId,
|
|
186
|
+
});
|
|
187
|
+
const rows = await Promise.all(scores.map(async (c) => {
|
|
188
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
189
|
+
return {
|
|
190
|
+
containerId: c.containerId,
|
|
191
|
+
ownerUserId: c.ownerUserId != null ? String(c.ownerUserId) : null,
|
|
192
|
+
points: Number(props.points ?? 0),
|
|
193
|
+
};
|
|
194
|
+
}));
|
|
195
|
+
return rows.sort((a, b) => b.points - a.points);
|
|
196
|
+
}
|
|
197
|
+
/** Finish the match and record the winner (creator or host). */
|
|
198
|
+
async finish(match, winnerUserId) {
|
|
199
|
+
return kitInvoke(this.gameModel, {
|
|
200
|
+
appId: String(this.appId),
|
|
201
|
+
functionName: this.names.endFn,
|
|
202
|
+
selfContainerId: match.metaId,
|
|
203
|
+
sessionId: match.sessionId,
|
|
204
|
+
params: { winner_user_id: Number(winnerUserId) },
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Manually ping the match channel with `"match_changed"` (the lifecycle
|
|
209
|
+
* functions do this automatically via their declared notifications; use
|
|
210
|
+
* this after out-of-band changes such as `endTurn`).
|
|
211
|
+
*/
|
|
212
|
+
async notifyChanged(match) {
|
|
213
|
+
if (match.channelId === '0' || match.channelId === '')
|
|
214
|
+
return false;
|
|
215
|
+
return this.requireUdp().sendChannelMessage({
|
|
216
|
+
channelId: match.channelId,
|
|
217
|
+
uuid: this.actorUuid,
|
|
218
|
+
payload: encodeBase64(new TextEncoder().encode('match_changed')),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The notify-to-pull loop, wrapped: subscribe to the app's notifications,
|
|
223
|
+
* and on every ping of THIS match's channel re-pull the match state and
|
|
224
|
+
* hand it to `callback`. Returns the unsubscribe function.
|
|
225
|
+
*/
|
|
226
|
+
onMatchChanged(match, callback) {
|
|
227
|
+
return this.requireUdp().subscribe({
|
|
228
|
+
channelMessage: (notification) => {
|
|
229
|
+
if (String(notification.channelId) !== String(match.channelId))
|
|
230
|
+
return;
|
|
231
|
+
void this.get(match.metaId).then(callback);
|
|
232
|
+
},
|
|
233
|
+
}, String(this.appId));
|
|
234
|
+
}
|
|
235
|
+
async toMatch(metaId, sessionId, displayName) {
|
|
236
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), metaId);
|
|
237
|
+
return {
|
|
238
|
+
sessionId,
|
|
239
|
+
metaId,
|
|
240
|
+
displayName,
|
|
241
|
+
creatorUserId: Number(props.creator_user_id ?? 0),
|
|
242
|
+
mode: String(props.mode ?? ''),
|
|
243
|
+
state: String(props.state ?? ''),
|
|
244
|
+
round: Number(props.round ?? 0),
|
|
245
|
+
maxPlayers: Number(props.max_players ?? 0),
|
|
246
|
+
winnerUserId: Number(props.winner_user_id ?? 0),
|
|
247
|
+
channelId: String(props.channel_id ?? '0'),
|
|
248
|
+
...(props.tick_count !== undefined
|
|
249
|
+
? { tickCount: Number(props.tick_count) }
|
|
250
|
+
: {}),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
package/dist/kit/npcs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npcs.d.ts","sourceRoot":"","sources":["../../src/kit/npcs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG1E,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qCAAqC;AACrC,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,OAAO;IAIhB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGf,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,cAAmB;IAK9B,0EAA0E;IACpE,KAAK,CAAC,KAAK,EAAE;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;QACjC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;;;;;;;;;;;IAuBD;;;;OAIG;IACG,IAAI,CAAC,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAclF,gDAAgD;IAC1C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ3C,8EAA8E;IACxE,MAAM,CAAC,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;IAInC;;;OAGG;IACG,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQzD,6EAA6E;IACvE,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM;;;;;;;;;;;;sBA+
|
|
1
|
+
{"version":3,"file":"npcs.d.ts","sourceRoot":"","sources":["../../src/kit/npcs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG1E,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qCAAqC;AACrC,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,OAAO;IAIhB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGf,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,cAAmB;IAK9B,0EAA0E;IACpE,KAAK,CAAC,KAAK,EAAE;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;QACjC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;;;;;;;;;;;IAuBD;;;;OAIG;IACG,IAAI,CAAC,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAclF,gDAAgD;IAC1C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ3C,8EAA8E;IACxE,MAAM,CAAC,cAAc,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;IAInC;;;OAGG;IACG,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQzD,6EAA6E;IACvE,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM;;;;;;;;;;;;sBA+B+2gc,CAAC;;;;;;;;;;IAxBl5gc,2DAA2D;IACrD,IAAI,CAAC,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO;;;;;;;;;;;;;;;;;;;;;;YAIzE,KAAK;CAkBpB"}
|
package/dist/kit/objects.d.ts
CHANGED
|
@@ -25,12 +25,20 @@ export declare class ObjectsKit {
|
|
|
25
25
|
/**
|
|
26
26
|
* Instantiate a lockable object (admin/studio call — the type is
|
|
27
27
|
* admin-instantiable). For key-gated objects set `requiredKeyId` to the key
|
|
28
|
-
* id that opens it; for owner-gated objects set `ownerUserId
|
|
28
|
+
* id that opens it; for owner-gated objects set `ownerUserId`; for
|
|
29
|
+
* chunk-permission-gated objects set `chunk` to where the object stands
|
|
30
|
+
* (feeds the `has_chunk_permission` policy).
|
|
29
31
|
*/
|
|
30
32
|
create(input: {
|
|
31
33
|
displayName: string;
|
|
32
34
|
requiredKeyId?: string;
|
|
33
35
|
ownerUserId?: Scalars['BigInt']['input'];
|
|
36
|
+
/** The chunk the object occupies (chunkPermission authority). */
|
|
37
|
+
chunk?: {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
z: number;
|
|
41
|
+
};
|
|
34
42
|
properties?: SeedPropertyInput[];
|
|
35
43
|
sessionId?: string;
|
|
36
44
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../src/kit/objects.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,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,2FAA2F;IAC3F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;gBAGf,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,iBAAsB;IAKjC
|
|
1
|
+
{"version":3,"file":"objects.d.ts","sourceRoot":"","sources":["../../src/kit/objects.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,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,2FAA2F;IAC3F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;gBAGf,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,iBAAsB;IAKjC;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;QACzC,iEAAiE;QACjE,KAAK,CAAC,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;QACjC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;;;;;;;;;;;IA+BD;;;;OAIG;IACG,QAAQ,CAAC,KAAK,EAAE;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;QACrC,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;;;;;;;;;;;IAiBD,yCAAyC;IACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;;;;;;;;;;;IAU/C;;;;OAIG;IACG,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IASpC,8DAA8D;IACxD,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IASpC,gDAAgD;IAC1C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAShD,8CAA8C;IACxC,IAAI,CAAC,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;;;;;;;;;;;CAOhD"}
|
package/dist/kit/objects.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { lockNames } from './blueprints.js';
|
|
1
|
+
import { lockNames } from './blueprints/index.js';
|
|
2
2
|
import { kitContainerProperties, kitInvoke, } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Runtime helpers for the {@link lockBlueprint} conventions: instantiate
|
|
@@ -18,7 +18,9 @@ export class ObjectsKit {
|
|
|
18
18
|
/**
|
|
19
19
|
* Instantiate a lockable object (admin/studio call — the type is
|
|
20
20
|
* admin-instantiable). For key-gated objects set `requiredKeyId` to the key
|
|
21
|
-
* id that opens it; for owner-gated objects set `ownerUserId
|
|
21
|
+
* id that opens it; for owner-gated objects set `ownerUserId`; for
|
|
22
|
+
* chunk-permission-gated objects set `chunk` to where the object stands
|
|
23
|
+
* (feeds the `has_chunk_permission` policy).
|
|
22
24
|
*/
|
|
23
25
|
async create(input) {
|
|
24
26
|
const properties = [
|
|
@@ -32,6 +34,13 @@ export class ObjectsKit {
|
|
|
32
34
|
},
|
|
33
35
|
]
|
|
34
36
|
: []),
|
|
37
|
+
...(input.chunk
|
|
38
|
+
? [
|
|
39
|
+
{ key: 'cx', valueType: 'int', valueJson: String(input.chunk.x) },
|
|
40
|
+
{ key: 'cy', valueType: 'int', valueJson: String(input.chunk.y) },
|
|
41
|
+
{ key: 'cz', valueType: 'int', valueJson: String(input.chunk.z) },
|
|
42
|
+
]
|
|
43
|
+
: []),
|
|
35
44
|
...(input.properties ?? []),
|
|
36
45
|
];
|
|
37
46
|
return this.gameModel.createContainer({
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { GameAppsAPI } from '../domains/gameApps.js';
|
|
2
|
+
import type { GameModelAPI } from '../domains/gameModel.js';
|
|
3
|
+
import type { Scalars, SeedPropertyInput } from '../generated/graphql.js';
|
|
4
|
+
import { type KitInvokeResult } from './shared.js';
|
|
5
|
+
/** Options for {@link PlotsKit}. Must match the deployed plot blueprint. */
|
|
6
|
+
export interface PlotsKitOptions {
|
|
7
|
+
/** The `typeName` the plot blueprint was deployed with. Defaults to `'Plot'`. */
|
|
8
|
+
typeName?: string;
|
|
9
|
+
}
|
|
10
|
+
/** A parsed view of one plot. */
|
|
11
|
+
export interface KitPlot {
|
|
12
|
+
containerId: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
gridId: number;
|
|
15
|
+
price: number;
|
|
16
|
+
/** 0 when unowned. */
|
|
17
|
+
ownerUserId: number;
|
|
18
|
+
rentPrice?: number;
|
|
19
|
+
rentTtlSeconds?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Runtime helpers for the {@link plotBlueprint} conventions: list/create
|
|
23
|
+
* plots and drive the buy/rent/evict functions whose permission effects grant
|
|
24
|
+
* or revoke real, replication-enforced grid permissions transactionally with
|
|
25
|
+
* the currency mutation. Authorization (wallet ownership, price, plot
|
|
26
|
+
* ownership) is enforced server-side — a denial resolves with
|
|
27
|
+
* `success: false`, never an exception.
|
|
28
|
+
*
|
|
29
|
+
* Obtained via `client.kit(appId).plots`.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PlotsKit {
|
|
32
|
+
private readonly appId;
|
|
33
|
+
private readonly gameModel;
|
|
34
|
+
private readonly gameApps;
|
|
35
|
+
private readonly names;
|
|
36
|
+
constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI, gameApps: GameAppsAPI, options?: PlotsKitOptions);
|
|
37
|
+
/**
|
|
38
|
+
* Instantiate a plot over an existing grid (admin — the type is
|
|
39
|
+
* admin-instantiable). Create the grid first (`client.gameApps.createGrid`)
|
|
40
|
+
* and pass its id here.
|
|
41
|
+
*/
|
|
42
|
+
create(input: {
|
|
43
|
+
displayName: string;
|
|
44
|
+
gridId: Scalars['BigInt']['input'];
|
|
45
|
+
price: number;
|
|
46
|
+
rentPrice?: number;
|
|
47
|
+
rentTtlSeconds?: number;
|
|
48
|
+
properties?: SeedPropertyInput[];
|
|
49
|
+
}): Promise<{
|
|
50
|
+
__typename?: "GmContainer";
|
|
51
|
+
containerId: string;
|
|
52
|
+
appId: string;
|
|
53
|
+
sessionId: string | null;
|
|
54
|
+
typeName: string;
|
|
55
|
+
displayName: string;
|
|
56
|
+
description: string | null;
|
|
57
|
+
ownerUserId: string | null;
|
|
58
|
+
metadataJson: string;
|
|
59
|
+
}>;
|
|
60
|
+
/** List plots with parsed state (grid, price, current owner). */
|
|
61
|
+
list(): Promise<KitPlot[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Buy a plot: spends the price from the caller's wallet AND grants the
|
|
64
|
+
* blueprint's grid permissions in one transaction. Resolves with the
|
|
65
|
+
* wallet's remaining balance.
|
|
66
|
+
*/
|
|
67
|
+
buy(plotId: string, walletId: string): Promise<KitInvokeResult<number>>;
|
|
68
|
+
/**
|
|
69
|
+
* Rent a plot (blueprint deployed with `rentable: true`): like {@link buy}
|
|
70
|
+
* but the grant expires after the plot's `rent_ttl_seconds`.
|
|
71
|
+
*/
|
|
72
|
+
rent(plotId: string, walletId: string): Promise<KitInvokeResult<number>>;
|
|
73
|
+
/** Revoke a user's permissions on a plot (plot owner or app admin). */
|
|
74
|
+
evict(plotId: string, targetUserId: Scalars['BigInt']['input']): Promise<KitInvokeResult>;
|
|
75
|
+
/**
|
|
76
|
+
* A user's effective permission keys on a plot's grid (for HUD display —
|
|
77
|
+
* enforcement happens server-side regardless).
|
|
78
|
+
*/
|
|
79
|
+
accessOf(userId: Scalars['BigInt']['input'], gridId: Scalars['BigInt']['input']): Promise<string[]>;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=plots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plots.d.ts","sourceRoot":"","sources":["../../src/kit/plots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,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,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,qBAAa,QAAQ;IAIjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;gBAGf,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACvB,QAAQ,EAAE,WAAW,EACtC,OAAO,GAAE,eAAoB;IAK/B;;;;OAIG;IACG,MAAM,CAAC,KAAK,EAAE;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;QACnC,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;KAClC;;;;;;;;;;;IA0BD,iEAAiE;IAC3D,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IA2BhC;;;;OAIG;IACG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAS7E;;;OAGG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAS9E,uEAAuE;IACjE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAS/F;;;OAGG;IACG,QAAQ,CACZ,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GACjC,OAAO,CAAC,MAAM,EAAE,CAAC;CAQrB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { plotNames } from './blueprints/index.js';
|
|
2
|
+
import { kitContainerProperties, kitInvoke, } from './shared.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runtime helpers for the {@link plotBlueprint} conventions: list/create
|
|
5
|
+
* plots and drive the buy/rent/evict functions whose permission effects grant
|
|
6
|
+
* or revoke real, replication-enforced grid permissions transactionally with
|
|
7
|
+
* the currency mutation. Authorization (wallet ownership, price, plot
|
|
8
|
+
* ownership) is enforced server-side — a denial resolves with
|
|
9
|
+
* `success: false`, never an exception.
|
|
10
|
+
*
|
|
11
|
+
* Obtained via `client.kit(appId).plots`.
|
|
12
|
+
*/
|
|
13
|
+
export class PlotsKit {
|
|
14
|
+
constructor(appId, gameModel, gameApps, options = {}) {
|
|
15
|
+
this.appId = appId;
|
|
16
|
+
this.gameModel = gameModel;
|
|
17
|
+
this.gameApps = gameApps;
|
|
18
|
+
this.names = plotNames(options.typeName);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Instantiate a plot over an existing grid (admin — the type is
|
|
22
|
+
* admin-instantiable). Create the grid first (`client.gameApps.createGrid`)
|
|
23
|
+
* and pass its id here.
|
|
24
|
+
*/
|
|
25
|
+
async create(input) {
|
|
26
|
+
const properties = [
|
|
27
|
+
{ key: 'grid_id', valueType: 'int', valueJson: String(input.gridId) },
|
|
28
|
+
{ key: 'price', valueType: 'int', valueJson: String(input.price) },
|
|
29
|
+
...(input.rentPrice !== undefined
|
|
30
|
+
? [{ key: 'rent_price', valueType: 'int', valueJson: String(input.rentPrice) }]
|
|
31
|
+
: []),
|
|
32
|
+
...(input.rentTtlSeconds !== undefined
|
|
33
|
+
? [
|
|
34
|
+
{
|
|
35
|
+
key: 'rent_ttl_seconds',
|
|
36
|
+
valueType: 'int',
|
|
37
|
+
valueJson: String(input.rentTtlSeconds),
|
|
38
|
+
},
|
|
39
|
+
]
|
|
40
|
+
: []),
|
|
41
|
+
...(input.properties ?? []),
|
|
42
|
+
];
|
|
43
|
+
return this.gameModel.createContainer({
|
|
44
|
+
appId: this.appId,
|
|
45
|
+
typeName: this.names.plotType,
|
|
46
|
+
displayName: input.displayName,
|
|
47
|
+
properties,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** List plots with parsed state (grid, price, current owner). */
|
|
51
|
+
async list() {
|
|
52
|
+
const containers = await this.gameModel.containers({
|
|
53
|
+
appId: this.appId,
|
|
54
|
+
typeName: this.names.plotType,
|
|
55
|
+
});
|
|
56
|
+
return Promise.all(containers.map(async (c) => {
|
|
57
|
+
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
58
|
+
return {
|
|
59
|
+
containerId: c.containerId,
|
|
60
|
+
displayName: c.displayName,
|
|
61
|
+
gridId: Number(props.grid_id ?? 0),
|
|
62
|
+
price: Number(props.price ?? 0),
|
|
63
|
+
ownerUserId: Number(props.owner_user_id ?? 0),
|
|
64
|
+
...(props.rent_price !== undefined ? { rentPrice: Number(props.rent_price) } : {}),
|
|
65
|
+
...(props.rent_ttl_seconds !== undefined
|
|
66
|
+
? { rentTtlSeconds: Number(props.rent_ttl_seconds) }
|
|
67
|
+
: {}),
|
|
68
|
+
};
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Buy a plot: spends the price from the caller's wallet AND grants the
|
|
73
|
+
* blueprint's grid permissions in one transaction. Resolves with the
|
|
74
|
+
* wallet's remaining balance.
|
|
75
|
+
*/
|
|
76
|
+
async buy(plotId, walletId) {
|
|
77
|
+
return kitInvoke(this.gameModel, {
|
|
78
|
+
appId: String(this.appId),
|
|
79
|
+
functionName: this.names.buyFn,
|
|
80
|
+
selfContainerId: plotId,
|
|
81
|
+
params: { wallet_id: walletId },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Rent a plot (blueprint deployed with `rentable: true`): like {@link buy}
|
|
86
|
+
* but the grant expires after the plot's `rent_ttl_seconds`.
|
|
87
|
+
*/
|
|
88
|
+
async rent(plotId, walletId) {
|
|
89
|
+
return kitInvoke(this.gameModel, {
|
|
90
|
+
appId: String(this.appId),
|
|
91
|
+
functionName: this.names.rentFn,
|
|
92
|
+
selfContainerId: plotId,
|
|
93
|
+
params: { wallet_id: walletId },
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** Revoke a user's permissions on a plot (plot owner or app admin). */
|
|
97
|
+
async evict(plotId, targetUserId) {
|
|
98
|
+
return kitInvoke(this.gameModel, {
|
|
99
|
+
appId: String(this.appId),
|
|
100
|
+
functionName: this.names.evictFn,
|
|
101
|
+
selfContainerId: plotId,
|
|
102
|
+
params: { target_user_id: Number(targetUserId) },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A user's effective permission keys on a plot's grid (for HUD display —
|
|
107
|
+
* enforcement happens server-side regardless).
|
|
108
|
+
*/
|
|
109
|
+
async accessOf(userId, gridId) {
|
|
110
|
+
const res = await this.gameApps.userPermissions(String(this.appId), String(gridId), String(userId));
|
|
111
|
+
return [...res.permissionKeys];
|
|
112
|
+
}
|
|
113
|
+
}
|