@crowdedkingdoms/crowdyjs 8.2.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.
Files changed (102) hide show
  1. package/README.md +21 -3
  2. package/dist/crowdy-client.d.ts.map +1 -1
  3. package/dist/crowdy-client.js +5 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -2
  7. package/dist/kit/blueprints/combat.d.ts +75 -0
  8. package/dist/kit/blueprints/combat.d.ts.map +1 -0
  9. package/dist/kit/blueprints/combat.js +351 -0
  10. package/dist/kit/blueprints/core.d.ts +222 -0
  11. package/dist/kit/blueprints/core.d.ts.map +1 -0
  12. package/dist/kit/blueprints/core.js +185 -0
  13. package/dist/kit/blueprints/decks.d.ts +50 -0
  14. package/dist/kit/blueprints/decks.d.ts.map +1 -0
  15. package/dist/kit/blueprints/decks.js +163 -0
  16. package/dist/kit/blueprints/economy.d.ts +88 -0
  17. package/dist/kit/blueprints/economy.d.ts.map +1 -0
  18. package/dist/kit/blueprints/economy.js +533 -0
  19. package/dist/kit/blueprints/guild.d.ts +51 -0
  20. package/dist/kit/blueprints/guild.d.ts.map +1 -0
  21. package/dist/kit/blueprints/guild.js +50 -0
  22. package/dist/kit/blueprints/index.d.ts +21 -0
  23. package/dist/kit/blueprints/index.d.ts.map +1 -0
  24. package/dist/kit/blueprints/index.js +20 -0
  25. package/dist/kit/blueprints/inventory.d.ts +38 -0
  26. package/dist/kit/blueprints/inventory.d.ts.map +1 -0
  27. package/dist/kit/blueprints/inventory.js +157 -0
  28. package/dist/kit/blueprints/leaderboards.d.ts +49 -0
  29. package/dist/kit/blueprints/leaderboards.d.ts.map +1 -0
  30. package/dist/kit/blueprints/leaderboards.js +126 -0
  31. package/dist/kit/blueprints/locks.d.ts +82 -0
  32. package/dist/kit/blueprints/locks.d.ts.map +1 -0
  33. package/dist/kit/blueprints/locks.js +155 -0
  34. package/dist/kit/blueprints/loot.d.ts +84 -0
  35. package/dist/kit/blueprints/loot.d.ts.map +1 -0
  36. package/dist/kit/blueprints/loot.js +228 -0
  37. package/dist/kit/blueprints/matches.d.ts +59 -0
  38. package/dist/kit/blueprints/matches.d.ts.map +1 -0
  39. package/dist/kit/blueprints/matches.js +246 -0
  40. package/dist/kit/blueprints/npcs.d.ts +71 -0
  41. package/dist/kit/blueprints/npcs.d.ts.map +1 -0
  42. package/dist/kit/blueprints/npcs.js +122 -0
  43. package/dist/kit/blueprints/plots.d.ts +54 -0
  44. package/dist/kit/blueprints/plots.d.ts.map +1 -0
  45. package/dist/kit/blueprints/plots.js +146 -0
  46. package/dist/kit/blueprints/progression.d.ts +68 -0
  47. package/dist/kit/blueprints/progression.d.ts.map +1 -0
  48. package/dist/kit/blueprints/progression.js +324 -0
  49. package/dist/kit/blueprints/quests.d.ts +65 -0
  50. package/dist/kit/blueprints/quests.d.ts.map +1 -0
  51. package/dist/kit/blueprints/quests.js +284 -0
  52. package/dist/kit/blueprints/worldsim.d.ts +84 -0
  53. package/dist/kit/blueprints/worldsim.d.ts.map +1 -0
  54. package/dist/kit/blueprints/worldsim.js +461 -0
  55. package/dist/kit/combat.d.ts +103 -0
  56. package/dist/kit/combat.d.ts.map +1 -0
  57. package/dist/kit/combat.js +151 -0
  58. package/dist/kit/decks.d.ts +123 -0
  59. package/dist/kit/decks.d.ts.map +1 -0
  60. package/dist/kit/decks.js +138 -0
  61. package/dist/kit/economy.d.ts +244 -0
  62. package/dist/kit/economy.d.ts.map +1 -0
  63. package/dist/kit/economy.js +365 -0
  64. package/dist/kit/features.d.ts +60 -0
  65. package/dist/kit/features.d.ts.map +1 -0
  66. package/dist/kit/features.js +65 -0
  67. package/dist/kit/index.d.ts +13 -2
  68. package/dist/kit/index.d.ts.map +1 -1
  69. package/dist/kit/index.js +12 -1
  70. package/dist/kit/inventory.d.ts +5 -0
  71. package/dist/kit/inventory.d.ts.map +1 -1
  72. package/dist/kit/inventory.js +14 -1
  73. package/dist/kit/kit.d.ts +58 -2
  74. package/dist/kit/kit.d.ts.map +1 -1
  75. package/dist/kit/kit.js +24 -2
  76. package/dist/kit/leaderboards.d.ts +66 -0
  77. package/dist/kit/leaderboards.d.ts.map +1 -0
  78. package/dist/kit/leaderboards.js +94 -0
  79. package/dist/kit/loot.d.ts +106 -0
  80. package/dist/kit/loot.d.ts.map +1 -0
  81. package/dist/kit/loot.js +120 -0
  82. package/dist/kit/matches.d.ts +140 -0
  83. package/dist/kit/matches.d.ts.map +1 -0
  84. package/dist/kit/matches.js +253 -0
  85. package/dist/kit/objects.js +1 -1
  86. package/dist/kit/plots.js +1 -1
  87. package/dist/kit/progression.d.ts +181 -0
  88. package/dist/kit/progression.d.ts.map +1 -0
  89. package/dist/kit/progression.js +265 -0
  90. package/dist/kit/quests.d.ts +110 -0
  91. package/dist/kit/quests.d.ts.map +1 -0
  92. package/dist/kit/quests.js +158 -0
  93. package/dist/kit/social.d.ts +267 -0
  94. package/dist/kit/social.d.ts.map +1 -0
  95. package/dist/kit/social.js +230 -0
  96. package/dist/kit/worldsim.d.ts +225 -0
  97. package/dist/kit/worldsim.d.ts.map +1 -0
  98. package/dist/kit/worldsim.js +231 -0
  99. package/package.json +1 -1
  100. package/dist/kit/blueprints.d.ts +0 -370
  101. package/dist/kit/blueprints.d.ts.map +0 -1
  102. package/dist/kit/blueprints.js +0 -643
@@ -0,0 +1,365 @@
1
+ import { economyCurrencyFn, economyNames, } from './blueprints/index.js';
2
+ import { kitContainerProperties, kitInvoke, } from './shared.js';
3
+ /**
4
+ * Runtime helpers for the {@link economyBlueprint} conventions: wallets with
5
+ * per-currency balances, shop purchases, escrow trades, and player market
6
+ * listings. Every movement of currency or items is a single gated invoke —
7
+ * balances, stock, item identity, and ownership are all verified
8
+ * server-side, and a denial resolves with `success: false` (never an
9
+ * exception).
10
+ *
11
+ * `earn` is a trusted grant: with the default blueprint authority
12
+ * (`'server'`) it succeeds only for app admins — call it from studio/backend
13
+ * code, or drive grants through automations instead.
14
+ *
15
+ * Obtained via `client.kit(appId).economy`.
16
+ */
17
+ export class EconomyKit {
18
+ constructor(appId, gameModel, options = {}) {
19
+ this.appId = appId;
20
+ this.gameModel = gameModel;
21
+ /** Shop (admin-priced listings; atomic buys). */
22
+ this.shop = {
23
+ /**
24
+ * Create a shop listing (admin — the type is admin-instantiable).
25
+ * `maxStock` feeds the optional restock automation.
26
+ */
27
+ create: async (input) => {
28
+ return this.gameModel.createContainer({
29
+ appId: this.appId,
30
+ typeName: this.names.listingType,
31
+ displayName: input.displayName,
32
+ properties: [
33
+ { key: 'item_id', valueType: 'string', valueJson: JSON.stringify(input.itemId) },
34
+ { key: 'price', valueType: 'int', valueJson: String(input.price) },
35
+ { key: 'stock', valueType: 'int', valueJson: String(input.stock ?? 0) },
36
+ {
37
+ key: 'max_stock',
38
+ valueType: 'int',
39
+ valueJson: String(input.maxStock ?? input.stock ?? 0),
40
+ },
41
+ ...(input.properties ?? []),
42
+ ],
43
+ });
44
+ },
45
+ /** List shop listings with parsed state. */
46
+ list: async () => {
47
+ const containers = await this.gameModel.containers({
48
+ appId: this.appId,
49
+ typeName: this.names.listingType,
50
+ });
51
+ return Promise.all(containers.map(async (c) => {
52
+ const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
53
+ return {
54
+ containerId: c.containerId,
55
+ displayName: c.displayName,
56
+ itemId: String(props.item_id ?? ''),
57
+ price: Number(props.price ?? 0),
58
+ stock: Number(props.stock ?? 0),
59
+ maxStock: Number(props.max_stock ?? 0),
60
+ };
61
+ }));
62
+ },
63
+ /**
64
+ * Buy one unit: wallet debit + stock decrement + item grant into
65
+ * `toStackId` (a stack of the listed item), all in one transaction.
66
+ * Resolves with the wallet's remaining balance.
67
+ */
68
+ buy: async (input) => {
69
+ return kitInvoke(this.gameModel, {
70
+ appId: String(this.appId),
71
+ functionName: this.names.buyListingFn,
72
+ selfContainerId: input.listingId,
73
+ params: { wallet_id: input.walletId, to_stack_id: input.toStackId },
74
+ });
75
+ },
76
+ };
77
+ /** Escrow trades (player↔player item swaps, atomic on accept). */
78
+ this.trades = {
79
+ /**
80
+ * Create a trade offer to another player. The stacks named here are the
81
+ * OFFERER's: `giveStackId` is the escrowed source, `receiveStackId`
82
+ * receives the wanted items when the trade is accepted. The offer's
83
+ * container ownership (server-assigned to the caller) is what the accept
84
+ * guards trust — a forged offer over someone else's stacks can never be
85
+ * accepted.
86
+ */
87
+ offer: async (input) => {
88
+ return this.gameModel.createContainer({
89
+ appId: this.appId,
90
+ typeName: this.names.tradeType,
91
+ displayName: input.displayName ??
92
+ `Trade ${input.giveQty}x ${input.giveItemId} for ${input.wantQty}x ${input.wantItemId}`,
93
+ ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),
94
+ properties: [
95
+ { key: 'to_user_id', valueType: 'int', valueJson: String(input.toUserId) },
96
+ {
97
+ key: 'give_stack_id',
98
+ valueType: 'string',
99
+ valueJson: JSON.stringify(input.giveStackId),
100
+ },
101
+ {
102
+ key: 'receive_stack_id',
103
+ valueType: 'string',
104
+ valueJson: JSON.stringify(input.receiveStackId),
105
+ },
106
+ {
107
+ key: 'give_item_id',
108
+ valueType: 'string',
109
+ valueJson: JSON.stringify(input.giveItemId),
110
+ },
111
+ { key: 'give_qty', valueType: 'int', valueJson: String(input.giveQty) },
112
+ {
113
+ key: 'want_item_id',
114
+ valueType: 'string',
115
+ valueJson: JSON.stringify(input.wantItemId),
116
+ },
117
+ { key: 'want_qty', valueType: 'int', valueJson: String(input.wantQty) },
118
+ ],
119
+ });
120
+ },
121
+ /**
122
+ * Accept a trade as the invited player, supplying YOUR two stacks: the
123
+ * one paying the wanted items and the one receiving the given items. The
124
+ * offerer's stacks come from the offer record. All four quantity writes
125
+ * commit atomically or not at all.
126
+ */
127
+ accept: async (input) => {
128
+ const offer = await this.trades.get(input.offerId);
129
+ return kitInvoke(this.gameModel, {
130
+ appId: String(this.appId),
131
+ functionName: this.names.acceptTradeFn,
132
+ selfContainerId: input.offerId,
133
+ params: {
134
+ give_stack_id: offer.giveStackId,
135
+ to_give_stack_id: input.toGiveStackId,
136
+ want_stack_id: input.wantStackId,
137
+ to_want_stack_id: offer.receiveStackId,
138
+ },
139
+ });
140
+ },
141
+ /** Cancel an open trade (either party may). */
142
+ cancel: async (offerId) => {
143
+ return kitInvoke(this.gameModel, {
144
+ appId: String(this.appId),
145
+ functionName: this.names.cancelTradeFn,
146
+ selfContainerId: offerId,
147
+ params: {},
148
+ });
149
+ },
150
+ /** Read one trade offer with parsed state. */
151
+ get: async (offerId) => {
152
+ const container = await this.gameModel.container({
153
+ appId: this.appId,
154
+ containerId: offerId,
155
+ });
156
+ return this.toTrade(container.containerId, container.displayName, container.ownerUserId != null ? String(container.ownerUserId) : null);
157
+ },
158
+ /** List trades the user created or was invited to (open ones first). */
159
+ listMine: async (userId) => {
160
+ const containers = await this.gameModel.containers({
161
+ appId: this.appId,
162
+ typeName: this.names.tradeType,
163
+ });
164
+ const all = await Promise.all(containers.map((c) => this.toTrade(c.containerId, c.displayName, c.ownerUserId != null ? String(c.ownerUserId) : null)));
165
+ const uid = String(userId);
166
+ return all
167
+ .filter((t) => t.fromUserId === uid || String(t.toUserId) === uid)
168
+ .sort((a, b) => Number(b.status === 'open') - Number(a.status === 'open'));
169
+ },
170
+ };
171
+ /** Player market (list a stack for currency; atomic purchases). */
172
+ this.market = {
173
+ /**
174
+ * List items for sale: names YOUR escrowed source stack and the ask
175
+ * price. Payment lands straight in your wallet when someone buys.
176
+ */
177
+ list: async (input) => {
178
+ return this.gameModel.createContainer({
179
+ appId: this.appId,
180
+ typeName: this.names.marketType,
181
+ displayName: input.displayName ?? `${input.quantity}x ${input.itemId} for ${input.price}`,
182
+ ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),
183
+ properties: [
184
+ {
185
+ key: 'stack_id',
186
+ valueType: 'string',
187
+ valueJson: JSON.stringify(input.stackId),
188
+ },
189
+ {
190
+ key: 'item_id',
191
+ valueType: 'string',
192
+ valueJson: JSON.stringify(input.itemId),
193
+ },
194
+ { key: 'quantity', valueType: 'int', valueJson: String(input.quantity) },
195
+ { key: 'price', valueType: 'int', valueJson: String(input.price) },
196
+ ],
197
+ });
198
+ },
199
+ /** Browse market listings (active ones only by default). */
200
+ browse: async (options = {}) => {
201
+ const containers = await this.gameModel.containers({
202
+ appId: this.appId,
203
+ typeName: this.names.marketType,
204
+ });
205
+ const all = await Promise.all(containers.map(async (c) => {
206
+ const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
207
+ return {
208
+ containerId: c.containerId,
209
+ displayName: c.displayName,
210
+ sellerUserId: c.ownerUserId != null ? String(c.ownerUserId) : null,
211
+ stackId: String(props.stack_id ?? ''),
212
+ itemId: String(props.item_id ?? ''),
213
+ quantity: Number(props.quantity ?? 0),
214
+ price: Number(props.price ?? 0),
215
+ active: props.active === true,
216
+ };
217
+ }));
218
+ return options.includeInactive ? all : all.filter((l) => l.active);
219
+ },
220
+ /**
221
+ * Buy a market listing: pays the seller's wallet and transfers the items
222
+ * into `toStackId` in one transaction. The seller's wallet and source
223
+ * stack are resolved from the listing. Resolves with the buyer wallet's
224
+ * remaining balance.
225
+ */
226
+ buy: async (input) => {
227
+ const container = await this.gameModel.container({
228
+ appId: this.appId,
229
+ containerId: input.listingId,
230
+ });
231
+ const props = await kitContainerProperties(this.gameModel, String(this.appId), input.listingId);
232
+ if (container.ownerUserId == null) {
233
+ throw new Error('Market listing has no seller (unowned container)');
234
+ }
235
+ const sellerWallet = await this.ensureSellerWallet(String(container.ownerUserId));
236
+ return kitInvoke(this.gameModel, {
237
+ appId: String(this.appId),
238
+ functionName: this.names.buyMarketFn,
239
+ selfContainerId: input.listingId,
240
+ params: {
241
+ wallet_id: input.walletId,
242
+ seller_wallet_id: sellerWallet,
243
+ from_stack_id: String(props.stack_id ?? ''),
244
+ to_stack_id: input.toStackId,
245
+ },
246
+ });
247
+ },
248
+ /** Take a listing down (seller only). */
249
+ cancel: async (listingId) => {
250
+ return kitInvoke(this.gameModel, {
251
+ appId: String(this.appId),
252
+ functionName: this.names.cancelMarketFn,
253
+ selfContainerId: listingId,
254
+ params: {},
255
+ });
256
+ },
257
+ };
258
+ this.typePrefix = options.typePrefix ?? '';
259
+ this.names = economyNames(this.typePrefix);
260
+ this.currencies = options.currencies ?? ['gold'];
261
+ }
262
+ get defaultCurrency() {
263
+ return this.currencies[0];
264
+ }
265
+ /**
266
+ * Find the player's wallet, creating it when absent (member-instantiable;
267
+ * the server assigns ownership to the caller). Sets the `owner_user_id`
268
+ * mirror property the blueprint's guards read.
269
+ *
270
+ * @param ownerUserId - The calling player's user id (decimal string).
271
+ */
272
+ async ensureWallet(ownerUserId, options = {}) {
273
+ const existing = await this.gameModel.containers({
274
+ appId: this.appId,
275
+ typeName: this.names.walletType,
276
+ ...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
277
+ });
278
+ const mine = existing.find((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
279
+ if (mine)
280
+ return mine;
281
+ return this.gameModel.createContainer({
282
+ appId: this.appId,
283
+ typeName: this.names.walletType,
284
+ displayName: options.displayName ?? `Wallet ${ownerUserId}`,
285
+ ...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
286
+ properties: [
287
+ { key: 'owner_user_id', valueType: 'int', valueJson: String(ownerUserId) },
288
+ ],
289
+ });
290
+ }
291
+ /** Read one currency balance (default: the blueprint's first currency). */
292
+ async balance(walletId, currency) {
293
+ const props = await kitContainerProperties(this.gameModel, String(this.appId), walletId);
294
+ return Number(props[currency ?? this.defaultCurrency] ?? 0);
295
+ }
296
+ /** Read a wallet with every configured currency balance parsed. */
297
+ async wallet(walletId) {
298
+ const container = await this.gameModel.container({
299
+ appId: this.appId,
300
+ containerId: walletId,
301
+ });
302
+ const props = await kitContainerProperties(this.gameModel, String(this.appId), walletId);
303
+ const balances = {};
304
+ for (const c of this.currencies)
305
+ balances[c] = Number(props[c] ?? 0);
306
+ return {
307
+ containerId: container.containerId,
308
+ displayName: container.displayName,
309
+ ownerUserId: container.ownerUserId != null ? String(container.ownerUserId) : null,
310
+ balances,
311
+ };
312
+ }
313
+ /**
314
+ * Mint currency into a wallet — a **trusted** grant (default blueprint
315
+ * authority: app admins only). Resolves with the new balance.
316
+ */
317
+ async earn(walletId, amount, currency) {
318
+ return kitInvoke(this.gameModel, {
319
+ appId: String(this.appId),
320
+ functionName: economyCurrencyFn('earn', currency ?? this.defaultCurrency, this.typePrefix),
321
+ selfContainerId: walletId,
322
+ params: { amount },
323
+ });
324
+ }
325
+ /**
326
+ * Spend currency from the caller's own wallet. The server refuses to
327
+ * overdraw. Resolves with the new balance.
328
+ */
329
+ async spend(walletId, amount, currency) {
330
+ return kitInvoke(this.gameModel, {
331
+ appId: String(this.appId),
332
+ functionName: economyCurrencyFn('spend', currency ?? this.defaultCurrency, this.typePrefix),
333
+ selfContainerId: walletId,
334
+ params: { amount },
335
+ });
336
+ }
337
+ /** Find an existing wallet container id for a user (no creation). */
338
+ async ensureSellerWallet(sellerUserId) {
339
+ const wallets = await this.gameModel.containers({
340
+ appId: this.appId,
341
+ typeName: this.names.walletType,
342
+ });
343
+ const wallet = wallets.find((c) => c.ownerUserId != null && String(c.ownerUserId) === sellerUserId);
344
+ if (!wallet) {
345
+ throw new Error(`Seller ${sellerUserId} has no ${this.names.walletType}; they must ensureWallet() before selling`);
346
+ }
347
+ return wallet.containerId;
348
+ }
349
+ async toTrade(containerId, displayName, ownerUserId) {
350
+ const props = await kitContainerProperties(this.gameModel, String(this.appId), containerId);
351
+ return {
352
+ containerId,
353
+ displayName,
354
+ fromUserId: ownerUserId,
355
+ toUserId: Number(props.to_user_id ?? 0),
356
+ giveStackId: String(props.give_stack_id ?? ''),
357
+ receiveStackId: String(props.receive_stack_id ?? ''),
358
+ giveItemId: String(props.give_item_id ?? ''),
359
+ giveQty: Number(props.give_qty ?? 0),
360
+ wantItemId: String(props.want_item_id ?? ''),
361
+ wantQty: Number(props.want_qty ?? 0),
362
+ status: String(props.status ?? ''),
363
+ };
364
+ }
365
+ }
@@ -0,0 +1,60 @@
1
+ import type { GameModelAPI } from '../domains/gameModel.js';
2
+ import type { Scalars } from '../generated/graphql.js';
3
+ import type { KitInvokePolicy } from './blueprints/index.js';
4
+ /**
5
+ * Runtime **monetization** helpers — the app feature/tier surface in shop
6
+ * terms. Features are string keys (`'vip'`, `'land_owner'`, `'battle_pass'`)
7
+ * defined per app and granted to **access tiers** (the management-side
8
+ * `appAccess` tiers players buy/hold); any model function whose policy
9
+ * carries a `tier_feature` leaf then admits only players on a granted tier.
10
+ *
11
+ * Gate blueprint functions by composing {@link gate} (=`featureGate`) into a
12
+ * builder's `*policyExtra` option, e.g.
13
+ * `plotBlueprint({ buyPolicyExtra: kit.features.gate('land_owner') })`.
14
+ *
15
+ * All methods require the app-admin `manage_apps` permission.
16
+ *
17
+ * Obtained via `client.kit(appId).features`.
18
+ */
19
+ export declare class FeaturesKit {
20
+ private readonly appId;
21
+ private readonly gameModel;
22
+ constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI);
23
+ /** Define (or re-describe) a feature key for the app. */
24
+ define(featureKey: string, description?: string): Promise<{
25
+ __typename?: "GmAppFeature";
26
+ appId: string;
27
+ featureKey: string;
28
+ description: string | null;
29
+ }>;
30
+ /** List the app's defined feature keys. */
31
+ list(): Promise<{
32
+ __typename?: "GmAppFeature";
33
+ appId: string;
34
+ featureKey: string;
35
+ description: string | null;
36
+ }[]>;
37
+ /** Grant a feature to an access tier (its holders pass `tier_feature` checks). */
38
+ grantToTier(tierId: Scalars['BigInt']['input'], featureKey: string): Promise<{
39
+ __typename?: "GmTierFeature";
40
+ appId: string;
41
+ tierId: string;
42
+ featureKey: string;
43
+ }>;
44
+ /** Revoke a feature from an access tier. */
45
+ revokeFromTier(tierId: Scalars['BigInt']['input'], featureKey: string): Promise<boolean>;
46
+ /** List tier→feature grants (optionally for one tier). */
47
+ tierFeatures(tierId?: Scalars['BigInt']['input']): Promise<{
48
+ __typename?: "GmTierFeature";
49
+ appId: string;
50
+ tierId: string;
51
+ featureKey: string;
52
+ }[]>;
53
+ /**
54
+ * A `tier_feature` policy leaf for `feature` — pass it to any blueprint
55
+ * builder's `*policyExtra` option to monetization-gate that function.
56
+ * (Also exported standalone as `featureGate`.)
57
+ */
58
+ gate(feature: string): KitInvokePolicy;
59
+ }
60
+ //# sourceMappingURL=features.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/kit/features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY;IAG1C,yDAAyD;IACnD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;;;;;;IAQrD,2CAA2C;IACrC,IAAI;;;;;;IAIV,kFAAkF;IAC5E,WAAW,CACf,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,UAAU,EAAE,MAAM;;;;;;IASpB,4CAA4C;IACtC,cAAc,CAClB,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IAQnB,0DAA0D;IACpD,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;;;;;;IAOtD;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe;CAGvC"}
@@ -0,0 +1,65 @@
1
+ import { featureGate } from './blueprints/index.js';
2
+ /**
3
+ * Runtime **monetization** helpers — the app feature/tier surface in shop
4
+ * terms. Features are string keys (`'vip'`, `'land_owner'`, `'battle_pass'`)
5
+ * defined per app and granted to **access tiers** (the management-side
6
+ * `appAccess` tiers players buy/hold); any model function whose policy
7
+ * carries a `tier_feature` leaf then admits only players on a granted tier.
8
+ *
9
+ * Gate blueprint functions by composing {@link gate} (=`featureGate`) into a
10
+ * builder's `*policyExtra` option, e.g.
11
+ * `plotBlueprint({ buyPolicyExtra: kit.features.gate('land_owner') })`.
12
+ *
13
+ * All methods require the app-admin `manage_apps` permission.
14
+ *
15
+ * Obtained via `client.kit(appId).features`.
16
+ */
17
+ export class FeaturesKit {
18
+ constructor(appId, gameModel) {
19
+ this.appId = appId;
20
+ this.gameModel = gameModel;
21
+ }
22
+ /** Define (or re-describe) a feature key for the app. */
23
+ async define(featureKey, description) {
24
+ return this.gameModel.defineFeature({
25
+ appId: this.appId,
26
+ featureKey,
27
+ ...(description !== undefined ? { description } : {}),
28
+ });
29
+ }
30
+ /** List the app's defined feature keys. */
31
+ async list() {
32
+ return this.gameModel.features({ appId: this.appId });
33
+ }
34
+ /** Grant a feature to an access tier (its holders pass `tier_feature` checks). */
35
+ async grantToTier(tierId, featureKey) {
36
+ return this.gameModel.grantTierFeature({
37
+ appId: this.appId,
38
+ tierId,
39
+ featureKey,
40
+ });
41
+ }
42
+ /** Revoke a feature from an access tier. */
43
+ async revokeFromTier(tierId, featureKey) {
44
+ return this.gameModel.revokeTierFeature({
45
+ appId: this.appId,
46
+ tierId,
47
+ featureKey,
48
+ });
49
+ }
50
+ /** List tier→feature grants (optionally for one tier). */
51
+ async tierFeatures(tierId) {
52
+ return this.gameModel.tierFeatures({
53
+ appId: this.appId,
54
+ ...(tierId !== undefined ? { tierId } : {}),
55
+ });
56
+ }
57
+ /**
58
+ * A `tier_feature` policy leaf for `feature` — pass it to any blueprint
59
+ * builder's `*policyExtra` option to monetization-gate that function.
60
+ * (Also exported standalone as `featureGate`.)
61
+ */
62
+ gate(feature) {
63
+ return featureGate(feature);
64
+ }
65
+ }
@@ -1,8 +1,19 @@
1
- export { inventoryBlueprint, inventoryNames, kitPolicyJson, lockBlueprint, lockNames, mergeBlueprints, npcBehaviorFunctionName, npcBlueprint, plotBlueprint, plotNames, toSnakeCase, type InventoryBlueprintOptions, type InventoryNames, type KitAutomationSpec, type KitAutomationTriggerSpec, type KitBlueprint, type KitInvokePolicy, type KitSelectorSpec, type LockAuthority, type LockBlueprintOptions, type LockNames, type MergedBlueprints, type NpcBehaviorSpec, type NpcBehaviorTrigger, type NpcBlueprintOptions, type PlotBlueprintOptions, type PlotNames, type SelectorPermissionPredicate, } from './blueprints.js';
2
- export { GameKitClient, type GameKitOptions, type KitDeployResult, } from './kit.js';
1
+ export { andPolicies, combatBlueprint, combatNames, composeBlueprints, decksBlueprint, decksNames, economyBlueprint, economyCurrencyFn, economyNames, featureGate, guildBlueprint, guildNames, inventoryBlueprint, inventoryNames, kitPolicyJson, leaderboardsBlueprint, leaderboardsNames, lockBlueprint, lockNames, lootBlueprint, lootNames, lootRollFn, matchesBlueprint, matchesNames, mergeBlueprints, npcBehaviorFunctionName, npcBlueprint, ownerEquals, ownerEqualsCaller, ownerMirrorProperty, plotBlueprint, plotNames, progressionBlueprint, progressionNames, questsBlueprint, questsNames, toSnakeCase, trustedAuthorityFields, worldsimBlueprint, worldsimNames, type CombatBlueprintOptions, type CombatNames, type DecksBlueprintOptions, type DecksNames, type EconomyBlueprintOptions, type EconomyNames, type GuildBlueprintOptions, type GuildNames, type InventoryBlueprintOptions, type InventoryNames, type KitAutomationSpec, type KitAutomationTriggerSpec, type KitBlueprint, type KitInvokePolicy, type KitOwnerIdKind, type KitSelectorSpec, type KitTrustedAuthority, type LeaderboardsBlueprintOptions, type LeaderboardsNames, type LockAuthority, type LockBlueprintOptions, type LockNames, type LootBlueprintOptions, type LootDropSpec, type LootEntrySpec, type LootNames, type LootTableSpec, type MatchesBlueprintOptions, type MatchesNames, type MergedBlueprints, type NpcBehaviorSpec, type NpcBehaviorTrigger, type NpcBlueprintOptions, type PlotBlueprintOptions, type PlotNames, type ProgressionBlueprintOptions, type ProgressionNames, type QuestAdvanceSpec, type QuestsBlueprintOptions, type QuestsNames, type SelectorPermissionPredicate, type WorldsimBlueprintOptions, type WorldsimNames, } from './blueprints/index.js';
2
+ export { GameKitClient, type GameKitDomains, type GameKitOptions, type KitDeployResult, } from './kit.js';
3
+ export { MatchesKit, type KitMatch, type KitMatchScore, type MatchesKitOptions, } from './matches.js';
3
4
  export { InventoryKit, type InventoryKitOptions, type KitItemStack } from './inventory.js';
5
+ export { CombatKit, type CombatKitOptions, type KitCombatant, type KitStatusEffect, } from './combat.js';
6
+ export { DecksKit, type DecksKitOptions, type KitCard } from './decks.js';
7
+ export { FeaturesKit } from './features.js';
8
+ export { EconomyKit, type EconomyKitOptions, type KitMarketListing, type KitShopListing, type KitTradeOffer, type KitWallet, } from './economy.js';
9
+ export { LeaderboardsKit, type KitLeaderboardEntry, type LeaderboardsKitOptions, } from './leaderboards.js';
10
+ export { LootKit, type KitLootRoll, type LootKitOptions } from './loot.js';
4
11
  export { ObjectsKit, type ObjectsKitOptions } from './objects.js';
5
12
  export { NpcsKit, type NpcsKitOptions, type KitNpc } from './npcs.js';
6
13
  export { PlotsKit, type PlotsKitOptions, type KitPlot } from './plots.js';
14
+ export { QuestsKit, type KitQuestDef, type KitQuestProgress, type QuestsKitOptions, } from './quests.js';
15
+ export { ProgressionKit, type KitAchievementDef, type KitAchievementUnlock, type KitProgress, type KitSkillDef, type KitSkillRank, type ProgressionKitOptions, } from './progression.js';
16
+ export { SocialKit, type KitChatMessage, type KitGroupWithChannel, type SocialKitOptions, } from './social.js';
17
+ export { WorldsimKit, type KitCrop, type KitResourceNode, type KitWaveSpawner, type KitWorldState, type WorldsimKitOptions, } from './worldsim.js';
7
18
  export { kitInvoke, toKitInvokeResult, type KitInvokeResult, type RawInvokeResult, } from './shared.js';
8
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,uBAAuB,EACvB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,2BAA2B,GACjC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kit/index.ts"],"names":[],"mappings":"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"}
package/dist/kit/index.js CHANGED
@@ -1,7 +1,18 @@
1
- export { inventoryBlueprint, inventoryNames, kitPolicyJson, lockBlueprint, lockNames, mergeBlueprints, npcBehaviorFunctionName, npcBlueprint, plotBlueprint, plotNames, toSnakeCase, } from './blueprints.js';
1
+ export { andPolicies, combatBlueprint, combatNames, composeBlueprints, decksBlueprint, decksNames, economyBlueprint, economyCurrencyFn, economyNames, featureGate, guildBlueprint, guildNames, inventoryBlueprint, inventoryNames, kitPolicyJson, leaderboardsBlueprint, leaderboardsNames, lockBlueprint, lockNames, lootBlueprint, lootNames, lootRollFn, matchesBlueprint, matchesNames, mergeBlueprints, npcBehaviorFunctionName, npcBlueprint, ownerEquals, ownerEqualsCaller, ownerMirrorProperty, plotBlueprint, plotNames, progressionBlueprint, progressionNames, questsBlueprint, questsNames, toSnakeCase, trustedAuthorityFields, worldsimBlueprint, worldsimNames, } from './blueprints/index.js';
2
2
  export { GameKitClient, } from './kit.js';
3
+ export { MatchesKit, } from './matches.js';
3
4
  export { InventoryKit } from './inventory.js';
5
+ export { CombatKit, } from './combat.js';
6
+ export { DecksKit } from './decks.js';
7
+ export { FeaturesKit } from './features.js';
8
+ export { EconomyKit, } from './economy.js';
9
+ export { LeaderboardsKit, } from './leaderboards.js';
10
+ export { LootKit } from './loot.js';
4
11
  export { ObjectsKit } from './objects.js';
5
12
  export { NpcsKit } from './npcs.js';
6
13
  export { PlotsKit } from './plots.js';
14
+ export { QuestsKit, } from './quests.js';
15
+ export { ProgressionKit, } from './progression.js';
16
+ export { SocialKit, } from './social.js';
17
+ export { WorldsimKit, } from './worldsim.js';
7
18
  export { kitInvoke, toKitInvokeResult, } from './shared.js';
@@ -59,6 +59,10 @@ export declare class InventoryKit {
59
59
  * Create a new stack owned by the caller (server-assigned ownership).
60
60
  * Use {@link grant} afterwards for authority-checked increments; the initial
61
61
  * quantity here is a seed value on a container the caller owns anyway.
62
+ *
63
+ * Pass `ownerUserId` (the caller's own user id) to also set the
64
+ * `owner_user_id` mirror property that cross-container guards (economy
65
+ * trades / market listings) verify.
62
66
  */
63
67
  createStack(input: {
64
68
  itemId: string;
@@ -66,6 +70,7 @@ export declare class InventoryKit {
66
70
  slot?: number;
67
71
  displayName?: string;
68
72
  sessionId?: string;
73
+ ownerUserId?: Scalars['BigInt']['input'];
69
74
  }): Promise<{
70
75
  __typename?: "GmContainer";
71
76
  containerId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/kit/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,qFAAqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;gBAGpB,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,mBAAwB;IAKnC;;;;;;;OAOG;IACG,MAAM,CACV,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACvC,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;;;;;;;;;;;IAmB5D;;;OAGG;IACG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA2B9E;;;;OAIG;IACG,WAAW,CAAC,KAAK,EAAE;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;;;;;;;;;;;IAcD,4EAA4E;IACtE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAS9E;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAShF,0EAA0E;IACpE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAS7E;;;;OAIG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IASnC;;;;OAIG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;IASpD,gFAAgF;IAC1E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CA4B7D"}
1
+ {"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/kit/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,qFAAqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;gBAGpB,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,mBAAwB;IAKnC;;;;;;;OAOG;IACG,MAAM,CACV,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACvC,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;;;;;;;;;;;IAmB5D;;;OAGG;IACG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA2B9E;;;;;;;;OAQG;IACG,WAAW,CAAC,KAAK,EAAE;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;KAC1C;;;;;;;;;;;IAuBD,4EAA4E;IACtE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAS9E;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAShF,0EAA0E;IACpE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAS7E;;;;OAIG;IACG,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IASnC;;;;OAIG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;;;IASpD,gFAAgF;IAC1E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CA4B7D"}
@@ -1,4 +1,4 @@
1
- import { inventoryNames } from './blueprints.js';
1
+ import { inventoryNames } from './blueprints/index.js';
2
2
  import { kitContainerProperties, kitInvoke, } from './shared.js';
3
3
  /**
4
4
  * Runtime helpers for the {@link inventoryBlueprint} conventions: find or
@@ -64,6 +64,10 @@ export class InventoryKit {
64
64
  * Create a new stack owned by the caller (server-assigned ownership).
65
65
  * Use {@link grant} afterwards for authority-checked increments; the initial
66
66
  * quantity here is a seed value on a container the caller owns anyway.
67
+ *
68
+ * Pass `ownerUserId` (the caller's own user id) to also set the
69
+ * `owner_user_id` mirror property that cross-container guards (economy
70
+ * trades / market listings) verify.
67
71
  */
68
72
  async createStack(input) {
69
73
  return this.gameModel.createContainer({
@@ -75,6 +79,15 @@ export class InventoryKit {
75
79
  { key: 'item_id', valueType: 'string', valueJson: JSON.stringify(input.itemId) },
76
80
  { key: 'quantity', valueType: 'int', valueJson: String(input.quantity ?? 0) },
77
81
  { key: 'slot', valueType: 'int', valueJson: String(input.slot ?? 0) },
82
+ ...(input.ownerUserId !== undefined
83
+ ? [
84
+ {
85
+ key: 'owner_user_id',
86
+ valueType: 'int',
87
+ valueJson: String(input.ownerUserId),
88
+ },
89
+ ]
90
+ : []),
78
91
  ],
79
92
  });
80
93
  }