summer-engine 3.3.0 → 3.4.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +4 -2
- package/.codex-plugin/plugin.json +5 -3
- package/.cursor-plugin/plugin.json +4 -2
- package/.factory-plugin/plugin.json +4 -2
- package/CHANGELOG.md +36 -0
- package/README.md +2 -1
- package/assets/api-docs.json.gz +0 -0
- package/dist/cli/commands/install.d.ts +10 -0
- package/dist/cli/commands/install.js +55 -10
- package/dist/cli/commands/tool.d.ts +7 -0
- package/dist/cli/commands/tool.js +36 -1
- package/dist/core/capabilities/capture-gameplay.d.ts +69 -0
- package/dist/core/capabilities/capture-gameplay.js +283 -0
- package/dist/core/capabilities/creator.js +1 -1
- package/dist/core/capabilities/doctor.d.ts +9 -1
- package/dist/core/capabilities/doctor.js +47 -4
- package/dist/core/capabilities/engine-run.d.ts +4 -0
- package/dist/core/capabilities/engine-run.js +33 -5
- package/dist/core/capabilities/export-engine-version.d.ts +15 -0
- package/dist/core/capabilities/export-engine-version.js +24 -0
- package/dist/core/capabilities/export-game.d.ts +9 -1
- package/dist/core/capabilities/export-game.js +112 -36
- package/dist/core/capabilities/image-generation.d.ts +9 -0
- package/dist/core/capabilities/image-generation.js +19 -1
- package/dist/core/capabilities/publish-build.d.ts +14 -1
- package/dist/core/capabilities/publish-build.js +74 -22
- package/dist/core/capabilities/tool-dispatch.js +10 -0
- package/dist/core/config.js +2 -2
- package/dist/core/engine-install.d.ts +16 -0
- package/dist/core/engine-install.js +32 -2
- package/dist/core/hosted-mcp.d.ts +115 -0
- package/dist/core/hosted-mcp.js +164 -0
- package/dist/core/launch-posture.d.ts +3 -0
- package/dist/core/launch-posture.js +15 -2
- package/dist/mcp/hosted-mount.d.ts +13 -59
- package/dist/mcp/hosted-mount.js +24 -30
- package/dist/mcp/server.js +3 -2
- package/dist/mcp/tools/creator-tools.js +13 -3
- package/dist/mcp/tools/generate-tools.js +12 -2
- package/gemini-extension.json +3 -1
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +3 -2
- package/library/skills/README.md +6 -4
- package/library/skills/bounded-engine-runs/SKILL.md +96 -0
- package/library/skills/bounded-engine-runs/resource.yaml +29 -0
- package/library/skills/compatibility-renderer-traps/SKILL.md +78 -0
- package/library/skills/compatibility-renderer-traps/resource.yaml +28 -0
- package/library/skills/concept-art/SKILL.md +2 -2
- package/library/skills/export-and-ship/SKILL.md +2 -0
- package/library/skills/headless-scripting/resource.yaml +1 -0
- package/library/skills/in-game-purchases/SKILL.md +123 -118
- package/library/skills/in-game-purchases/resource.yaml +2 -2
- package/library/skills/web-compatibility-look/resource.yaml +1 -0
- package/library/tools/capture-gameplay/resource.yaml +73 -0
- package/library/tools/generate-image/resource.yaml +15 -1
- package/library/tools/publish-build/resource.yaml +1 -1
- package/package.json +1 -1
- package/registry/generated/aliases.json +1 -0
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +3 -1
- package/registry/generated/index.json +125 -12
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +4 -2
- package/registry/generated/plugin.codex.json +5 -3
- package/registry/generated/plugin.cursor.json +4 -2
- package/registry/generated/plugin.factory.json +4 -2
- package/registry/generated/skills-index.md +6 -4
- package/registry/generated/skills-registry.json +28 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: in-game-purchases
|
|
3
|
-
description: "Sell items for Sparks
|
|
3
|
+
description: "Sell items for Sparks in a game shop via the Summer purchase sheet: checkout, results, not enough Sparks, inventory unlocks, authority grants, store policy."
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: gameplay
|
|
@@ -11,14 +11,19 @@ paths: ["**/*.gd"]
|
|
|
11
11
|
# In-game purchases with Sparks
|
|
12
12
|
|
|
13
13
|
Sparks are Summer's currency. A game never takes money, never holds a
|
|
14
|
-
balance and never approves a payment. It asks Summer
|
|
15
|
-
purchase sheet over the game, and the game reacts to the
|
|
16
|
-
result.
|
|
14
|
+
balance and never approves a payment. It asks Summer for a checkout, Summer
|
|
15
|
+
shows its own purchase sheet over the game, and the game reacts to the
|
|
16
|
+
authoritative result.
|
|
17
17
|
|
|
18
18
|
| The player wants to | Call | Validated by |
|
|
19
19
|
| --- | --- | --- |
|
|
20
20
|
| buy an item with Sparks they have | `Summer.client.store.request_checkout(lines)` | the Summer ledger (debit) |
|
|
21
|
-
| buy Sparks because they are short |
|
|
21
|
+
| buy Sparks because they are short | no game call: the player gets Sparks in the Summer app | the Summer app |
|
|
22
|
+
|
|
23
|
+
The engine has no call that sells Sparks from inside the game. When a
|
|
24
|
+
checkout fails with `insufficient_funds`, tell the player they need more
|
|
25
|
+
Sparks and that they can get them in the Summer app, then let them press Buy
|
|
26
|
+
again.
|
|
22
27
|
|
|
23
28
|
## When to sell with Sparks
|
|
24
29
|
|
|
@@ -28,9 +33,9 @@ result. There are two calls and they follow the same shape:
|
|
|
28
33
|
game.
|
|
29
34
|
- Do not invent your own currency that is bought with money. *Why:* Summer
|
|
30
35
|
can only refund, protect and pay you out for Sparks purchases.
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
- Open the shop only from an explicit shop or buy button. *Why:* the Summer
|
|
37
|
+
sheet interrupts play; surprise payment prompts read as pressure and get
|
|
38
|
+
games reported.
|
|
34
39
|
|
|
35
40
|
## Rules and the reason for each
|
|
36
41
|
|
|
@@ -38,66 +43,66 @@ result. There are two calls and they follow the same shape:
|
|
|
38
43
|
`Summer.client.items` shows the player owns it. *Why:* the receipt proves
|
|
39
44
|
the debit; the inventory projection is what the platform guarantees the
|
|
40
45
|
player owns, including after a crash or on another device.
|
|
41
|
-
2. **Never send prices
|
|
42
|
-
|
|
43
|
-
client-supplied price is exactly what a
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
2. **Never send prices or amounts.** The game passes an offer ID and a
|
|
47
|
+
quantity (`SummerCheckoutLine.create(offer_id, quantity)`). *Why:* the
|
|
48
|
+
platform prices everything; a client-supplied price is exactly what a
|
|
49
|
+
cheater edits.
|
|
50
|
+
3. **One call is one purchase.** Every `request_checkout` creates a new
|
|
51
|
+
identity. Never call again to "retry" an unknown outcome
|
|
52
|
+
(`SummerCheckoutOperation.is_outcome_unknown()`). *Why:* the first request
|
|
53
|
+
may already be charged; the SDK recovers it and delivers the result on the
|
|
54
|
+
signal.
|
|
55
|
+
4. **Handle results in `checkout_status_changed`, and deduplicate by
|
|
49
56
|
`request_id` plus `version`.** Connect normally (not deferred) before
|
|
50
|
-
requesting.
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
requesting. To draw a checkout panel, read `get_checkout_statuses()` and
|
|
58
|
+
`has_pending_checkouts()` instead of keeping your own list. *Why:* results
|
|
59
|
+
can arrive after a restart or twice after a crash; a synchronous handler is
|
|
60
|
+
how the SDK knows the result was delivered.
|
|
61
|
+
5. **Treat `manual_review` and `pending` as not done.** *Why:* the platform
|
|
53
62
|
has not decided yet; showing success or failure would be a guess.
|
|
54
63
|
6. **Check readiness and hide what is unavailable.**
|
|
55
|
-
`check_checkout_readiness()` and `
|
|
56
|
-
a `SummerResult`. *Why:* editor play,
|
|
57
|
-
do not offer purchases; a dead button
|
|
64
|
+
`check_checkout_readiness()` (buying) and `check_browse_readiness()`
|
|
65
|
+
(listing with `list_items()`) return a `SummerResult`. *Why:* editor play,
|
|
66
|
+
guest sessions and older Summer apps do not offer purchases; a dead button
|
|
67
|
+
is worse than no button.
|
|
58
68
|
|
|
59
69
|
## Result states
|
|
60
70
|
|
|
61
|
-
|
|
71
|
+
`checkout_status_changed(status: SummerCheckoutStatus)` delivers a status
|
|
72
|
+
whose `state` is one of:
|
|
62
73
|
|
|
63
74
|
| State | Meaning | What the game does |
|
|
64
75
|
| --- | --- | --- |
|
|
65
76
|
| `awaiting_approval` | the Summer sheet is open | nothing; optionally dim the shop |
|
|
66
|
-
| `pending` |
|
|
67
|
-
| `purchased` | done; Sparks debited
|
|
77
|
+
| `pending` | the debit is in progress | show "processing" |
|
|
78
|
+
| `purchased` | done; Sparks debited, `status.receipt` is set | refresh items and unlock from inventory |
|
|
68
79
|
| `declined` | the player closed the sheet | return to the shop quietly |
|
|
69
|
-
| `expired` | the sheet
|
|
70
|
-
| `rejected` | refused; read `error_code` |
|
|
80
|
+
| `expired` | the sheet timed out | same as declined |
|
|
81
|
+
| `rejected` | refused; read `error_code` | `insufficient_funds`: "Not enough Sparks. Get Sparks in the Summer app." Other codes: "The purchase was not completed." |
|
|
71
82
|
| `manual_review` | platform is checking it | "We are confirming this purchase" |
|
|
72
|
-
| `refunded` | Sparks only: a credited purchase was refunded or charged back (`full_refund`, `dispute_lost`) | nothing to undo; Summer already took the Sparks back. Refresh any balance display |
|
|
73
83
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
(only adults with a saved age can buy Sparks). Show a short message and no
|
|
77
|
-
retry button. *Why:* both limits are platform policy; retrying changes nothing.
|
|
84
|
+
`status.is_terminal()` tells you whether the state can still change. Unknown
|
|
85
|
+
future `error_code` values never mean success.
|
|
78
86
|
|
|
79
|
-
The operation returned by
|
|
80
|
-
`purchased
|
|
81
|
-
or `sparks_purchase_declined`. The status signal is the one to build UI on.
|
|
87
|
+
The operation returned by `request_checkout` also completes: ok on
|
|
88
|
+
`purchased`, a failure otherwise. The status signal is the one to build UI on.
|
|
82
89
|
|
|
83
90
|
## Minimal complete example
|
|
84
91
|
|
|
85
92
|
```gdscript
|
|
86
93
|
extends Node
|
|
87
|
-
## A one-item shop. Buys `offer_id
|
|
88
|
-
## Sparks through the Summer sheet, then they press Buy again.
|
|
94
|
+
## A one-item shop. Buys `offer_id` and unlocks from inventory.
|
|
89
95
|
|
|
90
96
|
@export var offer_id := "offer_sword"
|
|
91
97
|
@export var definition_id := "item_sword"
|
|
92
|
-
@export var price_sparks := 250 # display only; the platform charges its own price
|
|
93
98
|
|
|
94
99
|
signal message(text: String)
|
|
95
100
|
var _seen := {}
|
|
96
101
|
|
|
97
102
|
func _ready() -> void:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
store.
|
|
103
|
+
if Summer.client == null:
|
|
104
|
+
return # not running as a player's game
|
|
105
|
+
Summer.client.store.checkout_status_changed.connect(_on_checkout)
|
|
101
106
|
Summer.client.items.refreshed.connect(_sync_owned)
|
|
102
107
|
_sync_owned()
|
|
103
108
|
|
|
@@ -108,13 +113,7 @@ func buy() -> void:
|
|
|
108
113
|
var lines: Array[SummerCheckoutLine] = [SummerCheckoutLine.create(offer_id, 1)]
|
|
109
114
|
Summer.client.store.request_checkout(lines) # result arrives in _on_checkout
|
|
110
115
|
|
|
111
|
-
func
|
|
112
|
-
if not Summer.client.store.check_sparks_purchase_readiness().ok:
|
|
113
|
-
message.emit("Get Sparks from the Summer app.")
|
|
114
|
-
return
|
|
115
|
-
Summer.client.store.request_sparks_purchase(price_sparks) # hint only
|
|
116
|
-
|
|
117
|
-
func _first_time(status) -> bool:
|
|
116
|
+
func _first_time(status: SummerCheckoutStatus) -> bool:
|
|
118
117
|
var key := "%s:%d" % [status.request_id, status.version]
|
|
119
118
|
if _seen.has(key):
|
|
120
119
|
return false
|
|
@@ -129,7 +128,7 @@ func _on_checkout(status: SummerCheckoutStatus) -> void:
|
|
|
129
128
|
Summer.client.items.refresh() # ownership comes from inventory
|
|
130
129
|
&"rejected":
|
|
131
130
|
if status.error_code == &"insufficient_funds":
|
|
132
|
-
message.emit("Not enough Sparks.
|
|
131
|
+
message.emit("Not enough Sparks. Get Sparks in the Summer app, then buy again.")
|
|
133
132
|
else:
|
|
134
133
|
message.emit("The purchase was not completed.")
|
|
135
134
|
&"manual_review":
|
|
@@ -137,84 +136,91 @@ func _on_checkout(status: SummerCheckoutStatus) -> void:
|
|
|
137
136
|
&"declined", &"expired":
|
|
138
137
|
pass
|
|
139
138
|
|
|
140
|
-
func _on_sparks(status: SummerSparksPurchaseStatus) -> void:
|
|
141
|
-
if not _first_time(status):
|
|
142
|
-
return
|
|
143
|
-
match status.state:
|
|
144
|
-
&"purchased":
|
|
145
|
-
message.emit("%d Sparks added." % status.receipt.sparks_credited)
|
|
146
|
-
&"rejected":
|
|
147
|
-
message.emit("The payment did not go through.")
|
|
148
|
-
&"manual_review":
|
|
149
|
-
message.emit("We are confirming your payment.")
|
|
150
|
-
|
|
151
139
|
func _sync_owned() -> void:
|
|
152
140
|
if Summer.client.items.has_owned_definition(definition_id):
|
|
153
141
|
message.emit("Sword unlocked.") # the only place the item is granted
|
|
154
142
|
```
|
|
155
143
|
|
|
156
|
-
After Sparks are added the player presses Buy again. That is a new checkout
|
|
157
|
-
and Summer shows it again. *Why:* the player confirms each spend separately.
|
|
158
|
-
|
|
159
144
|
## Multiplayer: granting an effect on a dedicated authority
|
|
160
145
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
146
|
+
Anything the Sparks buy ("Grow now", "Summon rain") is a checkout for an
|
|
147
|
+
item, and on a server the authority must never grant it because a client says
|
|
148
|
+
it paid. *Why:* a client message is the one thing a cheater controls.
|
|
149
|
+
|
|
150
|
+
Model the effect as a catalog item with instance ownership (each purchase is a
|
|
151
|
+
separate owned item, not a stack). *Why:* a stackable item shares one owned
|
|
152
|
+
item ID across purchases, so the ID could not tell two purchases apart.
|
|
153
|
+
|
|
154
|
+
The client checks out; the receipt's `items[i].owned_item_ids` are the owned
|
|
155
|
+
items. The client sends the authority only an owned item ID. The authority:
|
|
156
|
+
|
|
157
|
+
1. reads that player's inventory with
|
|
158
|
+
`Summer.authority.items.inventory_for_session(session)` and checks the
|
|
159
|
+
item is there, owned, and of the right definition;
|
|
160
|
+
2. checks its own record of redeemed item IDs, kept in the player's secret
|
|
161
|
+
player data (`Summer.authority.player_data`), so the item grants once per
|
|
162
|
+
player in every world;
|
|
163
|
+
3. writes the new record, and applies the effect only after that write
|
|
164
|
+
succeeds.
|
|
176
165
|
|
|
177
166
|
```gdscript
|
|
178
|
-
# On the dedicated authority.
|
|
167
|
+
# On the dedicated authority.
|
|
168
|
+
const EFFECT_DEFINITION := "item_grow_now"
|
|
169
|
+
|
|
179
170
|
func redeem(session: SummerSession, owned_item_id: String) -> void:
|
|
171
|
+
var inv := Summer.authority.items.inventory_for_session(session)
|
|
172
|
+
var read: SummerResult = await inv.get_result_or_completed_signal()
|
|
173
|
+
if not read.ok:
|
|
174
|
+
return # unavailable: the client may ask again later
|
|
175
|
+
var item: SummerInventoryItem = null
|
|
176
|
+
for candidate in inv.items:
|
|
177
|
+
if candidate.get_owned_item_id() == owned_item_id:
|
|
178
|
+
item = candidate
|
|
179
|
+
if item == null or not item.is_owned() or item.get_definition_id() != EFFECT_DEFINITION:
|
|
180
|
+
return # not owned by this player: never grant
|
|
181
|
+
|
|
182
|
+
var load_op := Summer.authority.player_data.load(session)
|
|
183
|
+
var loaded: SummerResult = await load_op.get_result_or_completed_signal()
|
|
184
|
+
if not loaded.ok:
|
|
185
|
+
return
|
|
186
|
+
var data: Dictionary = load_op.secret_record.data
|
|
187
|
+
var redeemed: Dictionary = data.get("redeemed", {})
|
|
180
188
|
if redeemed.has(owned_item_id):
|
|
181
189
|
return # a repeated message grants once
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
var
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return
|
|
189
|
-
redeemed[owned_item_id] = op.command_id # record, apply, then save the world
|
|
190
|
+
redeemed[owned_item_id] = true
|
|
191
|
+
data["redeemed"] = redeemed
|
|
192
|
+
var save_id := "redeem_" + owned_item_id.sha256_text().substr(0, 40)
|
|
193
|
+
var commit := Summer.authority.player_data.commit_secret(session, save_id, data)
|
|
194
|
+
var saved: SummerResult = await commit.get_result_or_completed_signal()
|
|
195
|
+
if not saved.ok:
|
|
196
|
+
return # retryable: commit again with the same save_id
|
|
190
197
|
apply_grow_now(session)
|
|
191
198
|
```
|
|
192
199
|
|
|
193
|
-
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
- Apply the effect when the
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
- The save ID comes from the owned item ID. *Why:* resending the same save ID
|
|
201
|
+
with the same content returns the earlier commit (`commit.replayed`), so a
|
|
202
|
+
retry after a timeout records the redemption once.
|
|
203
|
+
- Apply the effect when the commit succeeds even if `commit.replayed` is true
|
|
204
|
+
and the effect is not in your world yet. *Why:* a replay means the
|
|
205
|
+
redemption was recorded earlier, but your world may have crashed before it
|
|
206
|
+
applied the effect.
|
|
207
|
+
- The engine has no call that uses up an owned item. The item stays in the
|
|
208
|
+
player's inventory after it is redeemed; the redeemed list is what stops a
|
|
209
|
+
second grant. Show redeemed items as used in your UI.
|
|
202
210
|
|
|
203
211
|
## Idempotency
|
|
204
212
|
|
|
205
|
-
The SDK generates the request ID and replays it across transport
|
|
206
|
-
app restarts; the platform
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
message or play an effect twice.
|
|
213
|
+
The SDK generates the checkout request ID and replays it across transport
|
|
214
|
+
failures and app restarts; the platform debits a checkout once per request.
|
|
215
|
+
Your only job is the `request_id:version` dedupe above, so a replayed signal
|
|
216
|
+
does not show a message or play an effect twice.
|
|
210
217
|
|
|
211
218
|
## Per-surface behaviour
|
|
212
219
|
|
|
213
|
-
- **Summer Games app on iOS:** a native Summer sheet over the game.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
- **Web:** the same sheet in the page, paid with Stripe.
|
|
220
|
+
- **Summer Games app on iOS:** a native Summer sheet over the game.
|
|
221
|
+
- **Summer desktop app:** an overlay sheet; the result returns to the game on
|
|
222
|
+
the signal.
|
|
223
|
+
- **Web:** the same sheet in the page.
|
|
218
224
|
- **Editor play and local runs:** readiness is `unavailable`. Build the
|
|
219
225
|
unavailable path first.
|
|
220
226
|
|
|
@@ -222,31 +228,30 @@ The game code is identical on every surface.
|
|
|
222
228
|
|
|
223
229
|
## Testing
|
|
224
230
|
|
|
225
|
-
- Test against Summer staging, which runs
|
|
226
|
-
|
|
227
|
-
builds. *Why:* no real money moves and results are identical to production.
|
|
231
|
+
- Test against Summer staging, which runs in sandbox mode. *Why:* no real
|
|
232
|
+
money moves and results are identical to production.
|
|
228
233
|
- Walk every state: decline the sheet, let it expire, buy with too few
|
|
229
|
-
Sparks,
|
|
230
|
-
pending and relaunch; the result must still arrive once.
|
|
234
|
+
Sparks, get Sparks in the Summer app, then buy the item. Kill the game while
|
|
235
|
+
a checkout is pending and relaunch; the result must still arrive once.
|
|
231
236
|
- Verify the unlock comes from `items.refreshed`, not from the checkout
|
|
232
237
|
signal.
|
|
233
238
|
|
|
234
239
|
## Store policy notes
|
|
235
240
|
|
|
236
241
|
- Apple requires In-App Purchase for digital goods and currency sold inside
|
|
237
|
-
iOS apps. Summer's iOS sheet
|
|
238
|
-
web prices or "cheaper on the web" text inside the game. *Why:* it
|
|
239
|
-
the Summer app removed from the App Store for every game.
|
|
242
|
+
iOS apps. Summer's iOS sheet and app handle this; never add your own payment
|
|
243
|
+
links, web prices or "cheaper on the web" text inside the game. *Why:* it
|
|
244
|
+
can get the Summer app removed from the App Store for every game.
|
|
240
245
|
- Randomized paid rewards must disclose their odds before purchase (Apple and
|
|
241
246
|
most regions require it).
|
|
242
247
|
- Say what a purchase gives in plain words next to the price.
|
|
243
248
|
|
|
244
249
|
## Availability
|
|
245
250
|
|
|
246
|
-
`request_checkout`
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
`request_checkout`, `list_items`, `Summer.client.items`,
|
|
252
|
+
`Summer.authority.items.inventory_for_session` and `Summer.authority.player_data`
|
|
253
|
+
ship in the engine today. Buying Sparks inside the game does not: players get
|
|
254
|
+
Sparks in the Summer app.
|
|
250
255
|
|
|
251
256
|
## See also
|
|
252
257
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
id: skill/in-game-purchases
|
|
2
2
|
kind: skill
|
|
3
3
|
version: 1.0.0
|
|
4
|
-
summary: "Sell items for Sparks
|
|
4
|
+
summary: "Sell items for Sparks in a game shop via the Summer purchase sheet: checkout, results, not enough Sparks, inventory unlocks, authority grants, store policy."
|
|
5
5
|
use_when:
|
|
6
6
|
- "adding a shop, buy button or paid item to a Summer game and wiring request_checkout"
|
|
7
|
-
- "
|
|
7
|
+
- "the player does not have enough Sparks (checkout rejected with insufficient_funds) and the game should tell them how to buy more Sparks"
|
|
8
8
|
- "deciding whether an item should be sold for Sparks, or handling pending, declined, expired, rejected or manual_review purchase results"
|
|
9
9
|
do_not_use_when:
|
|
10
10
|
- "designing multiplayer state ownership unrelated to purchases (use multiplayer-state)"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
id: tool/capture-gameplay
|
|
2
|
+
kind: tool
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
summary: Capture real gameplay frames (PNG, HUD included) in Summer Engine's offscreen verify instance, without a running editor, e.g. store screenshots.
|
|
5
|
+
use_when:
|
|
6
|
+
- '"take gameplay screenshots for my store page"'
|
|
7
|
+
- '"I need screenshots but the editor is not open"'
|
|
8
|
+
- '"capture a 1920x1080 frame of my game"'
|
|
9
|
+
- collecting real gameplay screenshots for summer_store_set_art desktop.screenshots or mobile.screenshots
|
|
10
|
+
do_not_use_when:
|
|
11
|
+
- the editor is open and the game is running — tool/screenshot with target game shows the live game
|
|
12
|
+
- key art, covers or icons — those are generated art, not gameplay frames
|
|
13
|
+
- checking an interaction with inputs and assertions — RunVerification through tool/batch
|
|
14
|
+
facets:
|
|
15
|
+
lifecycle:
|
|
16
|
+
- launch
|
|
17
|
+
- build
|
|
18
|
+
domains:
|
|
19
|
+
- creator
|
|
20
|
+
- headless
|
|
21
|
+
compatibility:
|
|
22
|
+
engine: ">=4.6"
|
|
23
|
+
source: official
|
|
24
|
+
license: MIT
|
|
25
|
+
status: preview
|
|
26
|
+
aliases:
|
|
27
|
+
- summer_capture_gameplay
|
|
28
|
+
implementation:
|
|
29
|
+
module: src/core/capabilities/capture-gameplay.ts
|
|
30
|
+
export: captureGameplay
|
|
31
|
+
surfaces:
|
|
32
|
+
mcp:
|
|
33
|
+
tool_name: summer_capture_gameplay
|
|
34
|
+
remote: true
|
|
35
|
+
input_schema:
|
|
36
|
+
type: object
|
|
37
|
+
properties:
|
|
38
|
+
project:
|
|
39
|
+
type: string
|
|
40
|
+
description: Project folder with project.godot. Defaults to the MCP's bound project, then the working directory.
|
|
41
|
+
scene:
|
|
42
|
+
type: string
|
|
43
|
+
description: Scene to start (res://... or uid://...). Default is the project's main scene, often a title menu; pass the gameplay scene for gameplay frames.
|
|
44
|
+
resolution:
|
|
45
|
+
type: string
|
|
46
|
+
description: Window size WIDTHxHEIGHT (default 1920x1080; 1080x1920 for portrait).
|
|
47
|
+
frames:
|
|
48
|
+
type: integer
|
|
49
|
+
minimum: 1
|
|
50
|
+
maximum: 10
|
|
51
|
+
description: Frames to save (default 1).
|
|
52
|
+
waitSeconds:
|
|
53
|
+
type: number
|
|
54
|
+
minimum: 0
|
|
55
|
+
maximum: 120
|
|
56
|
+
description: Seconds the game runs before the first frame (default 3).
|
|
57
|
+
intervalSeconds:
|
|
58
|
+
type: number
|
|
59
|
+
minimum: 0.1
|
|
60
|
+
maximum: 60
|
|
61
|
+
description: Seconds between frames (default 1).
|
|
62
|
+
out:
|
|
63
|
+
type: string
|
|
64
|
+
description: Output folder. Defaults to <project>/.summer/captures/<time>/ (ignored by git).
|
|
65
|
+
additionalProperties: false
|
|
66
|
+
authority:
|
|
67
|
+
filesystem: true
|
|
68
|
+
editor_mutation: false
|
|
69
|
+
network: false
|
|
70
|
+
credentials: false
|
|
71
|
+
publish: false
|
|
72
|
+
evidence_checks:
|
|
73
|
+
- none
|
|
@@ -45,10 +45,24 @@ input_schema:
|
|
|
45
45
|
removeBackground:
|
|
46
46
|
type: boolean
|
|
47
47
|
description: Remove the background server-side and return an alpha PNG for sprites, icons, or isolated objects.
|
|
48
|
+
aspectRatio:
|
|
49
|
+
type: string
|
|
50
|
+
enum: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "5:4", "4:5", "21:9"]
|
|
51
|
+
description: Aspect ratio of the output (default 1:1). The result reports the real width and height.
|
|
52
|
+
width:
|
|
53
|
+
type: integer
|
|
54
|
+
minimum: 64
|
|
55
|
+
maximum: 4096
|
|
56
|
+
description: Smallest output width in pixels; pass with height. 1920 with height 1080 for store key art, 1080 with 1920 for a tall cover.
|
|
57
|
+
height:
|
|
58
|
+
type: integer
|
|
59
|
+
minimum: 64
|
|
60
|
+
maximum: 4096
|
|
61
|
+
description: Smallest output height in pixels; pass with width.
|
|
48
62
|
options:
|
|
49
63
|
type: object
|
|
50
64
|
additionalProperties: {}
|
|
51
|
-
description:
|
|
65
|
+
description: Extra model params (seed, negative_prompt, ...). The result lists any it did not use in ignoredOptions.
|
|
52
66
|
required:
|
|
53
67
|
- prompt
|
|
54
68
|
additionalProperties: false
|
|
@@ -37,7 +37,7 @@ input_schema:
|
|
|
37
37
|
properties:
|
|
38
38
|
gameId:
|
|
39
39
|
type: string
|
|
40
|
-
description: The store game id (Studio store page URL).
|
|
40
|
+
description: The store game id (from summer_store_list_games, or the Studio store page URL). Without it the call fails with game_required and lists your store games, or says why the store did not list them.
|
|
41
41
|
file:
|
|
42
42
|
type: string
|
|
43
43
|
description: Exported .zip. Defaults to the last summer_export_game result.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "summer-engine",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Local Summer CLI and MCP server for Summer Engine. Install and run the engine, connect Claude Code, Cursor, Codex, Gemini, and other agents, and build real games with bundled skills, hooks, and plugins.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"summer-engine",
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
"summer_attach_to_surface": "tool/attach-to-surface",
|
|
104
104
|
"summer_batch": "tool/batch",
|
|
105
105
|
"summer_camera_bookmark": "tool/camera-bookmark",
|
|
106
|
+
"summer_capture_gameplay": "tool/capture-gameplay",
|
|
106
107
|
"summer_check_job": "tool/check-job",
|
|
107
108
|
"summer_clear_console": "tool/clear-console",
|
|
108
109
|
"summer_connect_ports": "tool/connect-ports",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_generated": "GENERATED from integrations/gemini — do not edit; npm run generate:registry",
|
|
3
3
|
"name": "summer",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.0",
|
|
5
5
|
"description": "Agent tooling for Summer Engine: MCP bridge, context primer, and game-dev skills. Use with the npm CLI for skill files on disk.",
|
|
6
6
|
"contextFileName": "GEMINI.md",
|
|
7
7
|
"mcpServers": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"./library/skills/asset-strategy/",
|
|
36
36
|
"./library/skills/audio-direction/",
|
|
37
37
|
"./library/skills/auto-fire-targeting/",
|
|
38
|
+
"./library/skills/bounded-engine-runs/",
|
|
38
39
|
"./library/skills/brainstorm-game/",
|
|
39
40
|
"./library/skills/brainstorming/",
|
|
40
41
|
"./library/skills/browse-templates/",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"./library/skills/character-portrait/",
|
|
47
48
|
"./library/skills/cinematic-cutscene/",
|
|
48
49
|
"./library/skills/combat-basics/",
|
|
50
|
+
"./library/skills/compatibility-renderer-traps/",
|
|
49
51
|
"./library/skills/concept-art/",
|
|
50
52
|
"./library/skills/create-asset-sheet/",
|
|
51
53
|
"./library/skills/debug/",
|