@indiegems/gem-web-sdk 7.4.2 → 7.6.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/CHANGELOG.md +886 -0
- package/README.md +1 -0
- package/dist/function.d.ts +978 -0
- package/dist/game.d.ts +11 -1
- package/dist/gem-web-sdk.bridge.js +1 -1
- package/dist/gem-web-sdk.esm.js +2 -2
- package/dist/gem-web-sdk.function.js +3 -0
- package/dist/gem-web-sdk.game.js +2 -2
- package/dist/gem-web-sdk.min.js +2 -2
- package/dist/gem-web-sdk.sdk.js +2 -2
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +16 -3
- package/dist/sdk.d.ts +11 -1
- package/docs/analytics.md +15 -5
- package/docs/api/api-reference-game.md +60 -33
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +29 -12
- package/docs/changelog.md +886 -0
- package/docs/getting-started.md +8 -6
- package/docs/manifest.json +18 -8
- package/docs/server-bundles.md +2 -2
- package/docs/serverless-functions-js.md +139 -0
- package/docs/what-a-game-must-do.md +46 -26
- package/package.json +7 -2
- package/schema/bridge.v1.json +62 -1
- package/schema/capabilities.public.json +6 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
What changed in each release of the SDK, and what a game has to do about it. Releases are listed newest first, and each one is described against the release before it.
|
|
4
|
+
|
|
5
|
+
Each release states its impact on a game that upgrades to it:
|
|
6
|
+
|
|
7
|
+
- **required**: the release is a new major version, or a type in it changed in a way that can stop code compiling. That includes a widened type, such as a new member of a union your code switches over, which may ask nothing more than a rebuild. Read every entry before you upgrade.
|
|
8
|
+
- **recommended**: nothing should break, but something is worth acting on: a type to rebuild against, a deprecation, or work you may stop doing.
|
|
9
|
+
- **none**: upgrading asks nothing of a game.
|
|
10
|
+
|
|
11
|
+
Its entries are grouped under up to five headings:
|
|
12
|
+
|
|
13
|
+
- **Must change**: code or behaviour a game has to change, or it stops compiling or stops working.
|
|
14
|
+
- **Should change**: something is deprecated. It keeps working for now; move off it before it is removed.
|
|
15
|
+
- **May stop**: work a game can drop, because the SDK or the Arcade now does it.
|
|
16
|
+
- **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
|
|
17
|
+
- **New capability**: something a game can now do. Nothing changes unless you use it.
|
|
18
|
+
|
|
19
|
+
## 7.5.0
|
|
20
|
+
|
|
21
|
+
Upgrading from 7.4.2. Impact: required.
|
|
22
|
+
|
|
23
|
+
### Rebuild
|
|
24
|
+
|
|
25
|
+
- GemCapability gained engagement, and the bridge's frame message list and union gained the new engaged message. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
26
|
+
|
|
27
|
+
### New capability
|
|
28
|
+
|
|
29
|
+
- When the Arcade starts your game on its own, such as an autoplay on its desktop information page, the SDK holds every analytics event, the platform's and your own track calls alike, until the player's first pointer press, key press or gamepad button inside the game. The session then starts at that input and the held events follow it, while the boot time still reports the real load. A launch nobody touches sends nothing, and you write nothing for this. gem.frame.unbiddenLaunch says whether this launch was one, and gem.analytics.held says whether events are still held. Make the first seconds of your game watchable, because one that waits on a press-any-key screen autoplays as a still picture.
|
|
30
|
+
|
|
31
|
+
## 7.4.2
|
|
32
|
+
|
|
33
|
+
Upgrading from 7.4.1. Impact: none.
|
|
34
|
+
|
|
35
|
+
Nothing in this release asks anything of a game.
|
|
36
|
+
|
|
37
|
+
## 7.4.1
|
|
38
|
+
|
|
39
|
+
Upgrading from 7.4.0. Impact: none.
|
|
40
|
+
|
|
41
|
+
Nothing in this release asks anything of a game.
|
|
42
|
+
|
|
43
|
+
## 7.4.0
|
|
44
|
+
|
|
45
|
+
Upgrading from 7.3.1. Impact: required.
|
|
46
|
+
|
|
47
|
+
### Must change
|
|
48
|
+
|
|
49
|
+
- The Arcade shows its wallets, Gems, Tickets and the Achievement Score, over your game by default. Call gem.setWalletVisible(false) when gameplay starts and gem.setWalletVisible(true) on your menus. On a screen that sells in one currency, show just that wallet by passing its slug in the only option.
|
|
50
|
+
- On phones the Arcade's Back tab and wallets sit in the frame's top-left corner, and gem.viewport now reports that corner in reserved instead of folding it into the top inset. Keep the corner clear by reading gem.viewport.reserved or the --gem-reserved-tl-width and --gem-reserved-tl-height CSS variables. Put your settings top-right, and draw no back arrow of your own top-left.
|
|
51
|
+
- GemFunctionError's retryAfterSeconds is now read-only. Code that assigns to it no longer compiles.
|
|
52
|
+
|
|
53
|
+
### Rebuild
|
|
54
|
+
|
|
55
|
+
- GemCapability gained the new capabilities, and the bridge's message lists and unions gained the new messages. The FriendsApi and PlatformApi constructors take optional extra arguments. A switch that assumes it knows every GemCapability value must handle the new ones. Other code that compiles today keeps compiling.
|
|
56
|
+
|
|
57
|
+
### New capability
|
|
58
|
+
|
|
59
|
+
- gem.friends.challenge(request) asks the Arcade to send a friend a challenge from one of the config's friend challenge templates. The player confirms it in the Arcade.
|
|
60
|
+
- gem.share.request({ params }) asks the Arcade to share a link to your game, and gem.share.available says whether it can.
|
|
61
|
+
- gem.platform.earnAllowance.get() reads how many Gems and Tickets the player can still earn in your game, for display, and its changed event says when to read it again.
|
|
62
|
+
- GameConfig carries the config's rewarded ad placements.
|
|
63
|
+
|
|
64
|
+
## 7.3.1
|
|
65
|
+
|
|
66
|
+
Upgrading from 7.3.0. Impact: none.
|
|
67
|
+
|
|
68
|
+
Nothing in this release asks anything of a game.
|
|
69
|
+
|
|
70
|
+
## 7.3.0
|
|
71
|
+
|
|
72
|
+
Upgrading from 7.2.0. Impact: required.
|
|
73
|
+
|
|
74
|
+
### May stop
|
|
75
|
+
|
|
76
|
+
- A result verifier may stop calling the bare listChallenges with player_id. gem.challenges.list({ playerId }) returns the same periods and refuses a call that forgets the player.
|
|
77
|
+
|
|
78
|
+
### Rebuild
|
|
79
|
+
|
|
80
|
+
- The SDK's ProfileShowcaseEntry type keeps its name for code that imports it. Only its declaration inside the bundled type files was renamed, because the server API now has a ProfileShowcaseEntry of its own. No code change is needed.
|
|
81
|
+
|
|
82
|
+
### New capability
|
|
83
|
+
|
|
84
|
+
- A dedicated server has six more calls on gem.api. getChannelAssignment reads which game config its own channel runs. getPlayerGameProfile, getShowcaseValue, putShowcaseValue and deleteShowcaseValue read and write a player's showcase slots that the config opens to servers. maxEntityProgression raises a progression to a new value only when it is higher.
|
|
85
|
+
- A dedicated server reads one player's challenges with gem.challenges.list({ playerId }), and gets the same entries that player's browser gets. A call that names no player is refused.
|
|
86
|
+
|
|
87
|
+
## 7.2.0
|
|
88
|
+
|
|
89
|
+
Upgrading from 7.1.1. Impact: required.
|
|
90
|
+
|
|
91
|
+
### Must change
|
|
92
|
+
|
|
93
|
+
- Daily, weekly and monthly challenge periods are now dates on each player's own calendar, so a period ends at the player's midnight. Key a period on periodLocalDate, or on seed for a cron challenge, and never on periodStartAt.
|
|
94
|
+
- ChallengeWindow has the value cron. A switch over it must handle cron.
|
|
95
|
+
- A result verifier on a dedicated server must read the player's own periods. Pass player_id to listChallenges and match on the period's date: without player_id the answer is in UTC, which is the wrong day for a player outside it.
|
|
96
|
+
|
|
97
|
+
### New capability
|
|
98
|
+
|
|
99
|
+
- Each challenge says its boundary, the player's own time zone or a fixed one, and its resetTime. A server's inventory period rows carry period_id, period_local_date and boundary.
|
|
100
|
+
|
|
101
|
+
## 7.1.1
|
|
102
|
+
|
|
103
|
+
Upgrading from 7.1.0. Impact: required.
|
|
104
|
+
|
|
105
|
+
### Must change
|
|
106
|
+
|
|
107
|
+
- On the direct purchase path, the platform's refusal for insufficient funds now rejects with the code insufficient_funds rather than invalid. If you branch on a purchase error's code, handle insufficient_funds.
|
|
108
|
+
- Name the Tickets currency ARCADE_TICKETS. TICKETS is no longer an accepted spelling, and a purchase in it is refused with unknown_currency.
|
|
109
|
+
|
|
110
|
+
### Rebuild
|
|
111
|
+
|
|
112
|
+
- PurchaseOutcome's declined and unavailable outcomes gain an optional reason, and GemHost.answerPurchase accepts one. Code that compiles today keeps compiling.
|
|
113
|
+
- The Tickets art in the package is redrawn as a solid tangerine ticket. A game that bundles it picks up the new art when it rebuilds.
|
|
114
|
+
|
|
115
|
+
### New capability
|
|
116
|
+
|
|
117
|
+
- A refused purchase says why. A declined or unavailable outcome carries a reason from PurchaseRefusalCode, the same string as the direct path's error code, and the direct path's own checks throw PurchaseRefusal, still a RangeError, with a code.
|
|
118
|
+
|
|
119
|
+
## 7.1.0
|
|
120
|
+
|
|
121
|
+
Upgrading from 7.0.0. Impact: required.
|
|
122
|
+
|
|
123
|
+
### Must change
|
|
124
|
+
|
|
125
|
+
- In the server API types, a room member's player_id is now optional. Room members, leaderboard rows and entity leaderboards are now written as the shared PlayerIdentityFields joined with their own fields, so every other field they had is still there. Code that assumes a room member always has a player_id must handle it missing.
|
|
126
|
+
- Server API unions gained values. PlatformGrantClamp has holdings_cap, a platform grant or achievement unlock in InventoryChange may carry principal, and an unmet prerequisite in UnavailabilityReason may carry required and current. A switch that assumes it knows every PlatformGrantClamp value must handle holdings_cap.
|
|
127
|
+
|
|
128
|
+
### Rebuild
|
|
129
|
+
|
|
130
|
+
- Several server API reads now accept null for their options: getEntityLeaderboard, getLeaderboard, getPurchaseCatalog and listTransfers. Code that compiles today keeps compiling.
|
|
131
|
+
- The SDK's PlayerBadge type keeps its name for code that imports it. Only its declaration inside the bundled type files was renamed, because the server API now has a PlayerBadge of its own. No code change is needed.
|
|
132
|
+
|
|
133
|
+
### New capability
|
|
134
|
+
|
|
135
|
+
- Server API player identities carry badges, a title and name styles.
|
|
136
|
+
- A challenge can carry the content the studio pre-generated for its period, as data and dataHash on each Challenge, and a dedicated server can read challenges with listChallenges.
|
|
137
|
+
- gem.player.boost tells a game the player's Boost multipliers. It is for display only: never gate content, difficulty, matchmaking, prices or power on it.
|
|
138
|
+
- Items have a category, cosmetic or progression, and Tickets buy cosmetics only. recipeAvailability says whether a recipe is locked and why, as locked and lockReasons.
|
|
139
|
+
- A dedicated server can call the game's serverless function with invokeFunction, the request underneath gem.functions.
|
|
140
|
+
- The package's brand art includes Tickets, as hero images and icons.
|
|
141
|
+
|
|
142
|
+
## 7.0.0
|
|
143
|
+
|
|
144
|
+
Upgrading from 6.0.0. Impact: required.
|
|
145
|
+
|
|
146
|
+
### Must change
|
|
147
|
+
|
|
148
|
+
- A dedicated server can no longer end its match with matchEnd: it is gone from gem.api and from @indiegems/gem-web-sdk/server/api. Call gem.match.end() instead. It always asks the platform runtime to end the match, because only the runtime holds the proof that this server was allocated to it.
|
|
149
|
+
- On a platform image too old to end the match for the bundle, gem.match.end() now throws instead of ending the match itself. The SDK also no longer ends the match for you after your shutdown handler returns. The platform ends an idle match itself.
|
|
150
|
+
- When the platform refuses a room's automatic start because the room's region stopped running or no server was free, the host's SDK now starts the match itself, at most once per room until a match begins. The matchAutoStartFailed event gains handled, which is true when that start is on its way. If your game handles the event to decide for itself, for example by showing the host a Start button, pass retryAutoStart: false to createGem. A handler that calls startMatch() straight away needs no change.
|
|
151
|
+
- In the server API types a room no longer has region. Read cluster_target_id instead, the cluster a room's matches start in, which rooms and room summaries now carry.
|
|
152
|
+
- PurchasePrice is gone from the server API types. Catalog items and recipes list their platform prices as CatalogPrice, which adds a required field, unconfirmed_spend.
|
|
153
|
+
- Two server API unions gained values. InventoryChange has a new kind, achievement_unlocked, and a platform grant may carry platform_order_id. PlatformGrantClamp has game_max_per_window and platform_max_per_window. A switch that assumes it knows every value of either must handle the new ones.
|
|
154
|
+
|
|
155
|
+
### Rebuild
|
|
156
|
+
|
|
157
|
+
- Several server API reads now accept null for their pagination cursors and limits: getEntityInventory, getEntityRecipeUsage, listEntityOrders and listEntitySaves. getEntityInventory also takes include_custom_data. Progression rows in a collection read gain updated_at and may carry achievements. Code that compiles today keeps compiling.
|
|
158
|
+
- The SDK's own AnalyticsRejection type keeps its name for code that imports it. Only its declaration inside the bundled type files was renamed, because the server API now has a wire type of the same name. No code change is needed.
|
|
159
|
+
|
|
160
|
+
### New capability
|
|
161
|
+
|
|
162
|
+
- Serverless functions have a named call, gem.functions.invoke(input), in the browser and on a dedicated server. It sends JSON or bytes, and a refusal is a GemFunctionError that says whether trying again could help.
|
|
163
|
+
- GemClient.postBytes sends and receives raw bytes.
|
|
164
|
+
- A dedicated server can send a batch of analytics events with ingestAnalyticsEvents.
|
|
165
|
+
- Server API inventory reads carry period progress and each currency bucket's last and next reset times, and leaderboard rows carry the player's avatar_icon_url.
|
|
166
|
+
|
|
167
|
+
## 6.0.0
|
|
168
|
+
|
|
169
|
+
Upgrading from 5.12.0. Impact: required.
|
|
170
|
+
|
|
171
|
+
### Rebuild
|
|
172
|
+
|
|
173
|
+
- This release changes nothing in the package. Its API and behaviour are those of 5.12.0, and the new major number was a release decision. Moving your pin to it takes a rebuild and no code change.
|
|
174
|
+
|
|
175
|
+
## 5.12.0
|
|
176
|
+
|
|
177
|
+
Upgrading from 5.11.0. Impact: recommended.
|
|
178
|
+
|
|
179
|
+
### May stop
|
|
180
|
+
|
|
181
|
+
- You may stop listing the Gem Arcade's origins in allowedEmbedders. The SDK carries them as ARCADE_EMBEDDERS, and createGem() with no options connects to the Arcade. allowedEmbedders is now added to those origins rather than replacing them, so pass it only for a site of your own. A blank or non-string entry now throws when the game is created.
|
|
182
|
+
|
|
183
|
+
## 5.11.0
|
|
184
|
+
|
|
185
|
+
Upgrading from 5.10.0. Impact: required.
|
|
186
|
+
|
|
187
|
+
### Must change
|
|
188
|
+
|
|
189
|
+
- gem.player.displayTag now holds the whole tag, the player's name followed by its number, as PlayerText, and it is optional. It used to hold only the number. Read gem.player.discriminator for the number, and convert displayTag with toPlain() where you render it.
|
|
190
|
+
- Names and tags on friends, leaderboard entries, player profiles and showcase friend entries are now PlayerText instead of strings. Convert them with toPlain() where you render them.
|
|
191
|
+
- On a dedicated server, a player profile's displayTag is now the whole tag as PlayerText, and it is optional. Read discriminator for the number alone.
|
|
192
|
+
- For code that drives the parent's half of the bridge from the package root: the root's PlayerIdentity is renamed SendPlayerInput, which GemHost.sendPlayer takes. GemHost.sendClusterTarget takes up to three cluster targets, best first, and onPlayer receives a FramePlayer. A game that imports the game entry is not affected.
|
|
193
|
+
|
|
194
|
+
### Should change
|
|
195
|
+
|
|
196
|
+
- GemPlayer.displayHandle and GemPlayer.avatarUrl are deprecated. Read displayTag and avatarIconUrl instead, the same values under the names every other surface uses. Both keep working for the rest of 6.x. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
197
|
+
|
|
198
|
+
### Rebuild
|
|
199
|
+
|
|
200
|
+
- GemCapability gained autoStartFailure, and the bridge's message lists and unions gained its message. The untrusted part of gem.player gains displayTag, a room member is a PlayerIdentity, and several low-level room and cluster-target calls take optional extra arguments. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
201
|
+
|
|
202
|
+
### New capability
|
|
203
|
+
|
|
204
|
+
- Every surface that shows a player carries the same PlayerIdentity fields: playerId, displayName, discriminator, displayTag, avatarIconId, avatarIconUrl and badges. Room members and leaderboard entries now keep the portrait. Pass an icon URL through platformIconUrl before you put it in an image, and key rows on playerId, never on a name.
|
|
205
|
+
- Rooms are made in the player's best region, and quick-join pairs only players near each other, with no change to your game. The room region option is now ignored by the platform. When a room's automatic start is refused, the host's game hears matchAutoStartFailed with the error code, and calling startMatch() from the handler is the usual answer.
|
|
206
|
+
- A dedicated server can read the achievements an order unlocked with achievementReceipts(order), from @indiegems/gem-web-sdk/server.
|
|
207
|
+
- The brand art includes the Arcade's Gems icon for inline amounts, at 20 and 32 pixels, each at four pixel densities. Gems are shown by the Arcade: a game keeps no Gems balance of its own and draws no Gems celebration, and when gem.cueReward returns false it shows nothing in its place.
|
|
208
|
+
|
|
209
|
+
## 5.10.0
|
|
210
|
+
|
|
211
|
+
Upgrading from 5.9.0. Impact: none.
|
|
212
|
+
|
|
213
|
+
### New capability
|
|
214
|
+
|
|
215
|
+
- The package ships the platform's Gems and trophy hero art, from 128 to 768 pixels, through its new brand export. A bundled game imports only the files it uses, and the same files are on the CDN for each version.
|
|
216
|
+
|
|
217
|
+
## 5.9.0
|
|
218
|
+
|
|
219
|
+
Upgrading from 5.8.2. Impact: recommended.
|
|
220
|
+
|
|
221
|
+
### Should change
|
|
222
|
+
|
|
223
|
+
- Stop declaring gameVersion in clientVersion. The Arcade now tells the SDK which build is playing, and when the two disagree the Arcade's number wins. Remove clientVersion as well once nothing else in it is set. It stays accepted for the rest of 5.x. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
224
|
+
|
|
225
|
+
### Rebuild
|
|
226
|
+
|
|
227
|
+
- From this release the package is published to npm as @indiegems/gem-web-sdk, as well as to the CDN. Earlier versions stay on the CDN only. Install it pinned to an exact version.
|
|
228
|
+
|
|
229
|
+
## 5.8.2
|
|
230
|
+
|
|
231
|
+
Upgrading from 5.8.1. Impact: none.
|
|
232
|
+
|
|
233
|
+
Nothing in this release asks anything of a game.
|
|
234
|
+
|
|
235
|
+
## 5.8.1
|
|
236
|
+
|
|
237
|
+
Upgrading from 5.8.0. Impact: none.
|
|
238
|
+
|
|
239
|
+
### New capability
|
|
240
|
+
|
|
241
|
+
- gem.me.mutations.purchase(request) buys directly, with no Arcade prompt. A configured payment runs a recipe and charges its costs from your game config. A platform currency payment spends the player's balance at the published platform price, and your game owns the confirmation. The SDK supplies the price, the config version and the nonce. gem.purchases.request() is unchanged and still shows the Arcade's purchase sheet.
|
|
242
|
+
|
|
243
|
+
## 5.8.0
|
|
244
|
+
|
|
245
|
+
Upgrading from 5.7.0. Impact: required.
|
|
246
|
+
|
|
247
|
+
### Rebuild
|
|
248
|
+
|
|
249
|
+
- GemCapability gained frameStats, and the bridge's message lists and unions gained the frame stats message. GemHost.sendPrefs accepts an optional showFrameStats. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
250
|
+
|
|
251
|
+
### New capability
|
|
252
|
+
|
|
253
|
+
- Players can turn on the Arcade's FPS overlay. While it is on, the SDK measures the frames your game draws and reports them, and GemPrefs says so in showFrameStats. A game draws and sends nothing itself.
|
|
254
|
+
|
|
255
|
+
## 5.7.0
|
|
256
|
+
|
|
257
|
+
Upgrading from 5.6.0. Impact: required.
|
|
258
|
+
|
|
259
|
+
### Rebuild
|
|
260
|
+
|
|
261
|
+
- GemCapability gained rewardCue, and the bridge's message lists and unions gained the reward cue message. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
262
|
+
|
|
263
|
+
### New capability
|
|
264
|
+
|
|
265
|
+
- gem.cueReward(cue) asks the Arcade's wallet to show a platform currency reward landing, from a point on your screen. The amount shown is the platform's, not the game's, and the call returns whether the Arcade will show it.
|
|
266
|
+
- gem.platform.currencies.get() reads the balances of the platform currencies staff approved for your game, with read or spend access. It returns an empty list when none is approved. An approved game may also see gem.purchases.request() complete without a platform prompt.
|
|
267
|
+
|
|
268
|
+
## 5.6.0
|
|
269
|
+
|
|
270
|
+
Upgrading from 5.5.1. Impact: required.
|
|
271
|
+
|
|
272
|
+
### Rebuild
|
|
273
|
+
|
|
274
|
+
- GemCapability gained deviceSettings, and the bridge's message lists and unions gained the device settings messages. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
275
|
+
|
|
276
|
+
### New capability
|
|
277
|
+
|
|
278
|
+
- gem.deviceSettings keeps a small settings object, such as volume or graphics quality, on the Arcade's side, so it survives a new build of your game. Read it with current or wait() and replace it with put(). It holds at most DEVICE_SETTINGS_MAX_BYTES, is kept per device, and can vanish at any time, so never keep progress in it.
|
|
279
|
+
|
|
280
|
+
## 5.5.1
|
|
281
|
+
|
|
282
|
+
Upgrading from 5.5.0. Impact: recommended.
|
|
283
|
+
|
|
284
|
+
### Rebuild
|
|
285
|
+
|
|
286
|
+
- A backend call made before the bridge connects, such as reading a cloud save during boot, no longer leaves the game without a play token after a ten second timeout. The token request is held and sent when the bridge connects. Moving the pin takes a rebuild and no code change.
|
|
287
|
+
|
|
288
|
+
## 5.5.0
|
|
289
|
+
|
|
290
|
+
Upgrading from 5.4.0. Impact: required.
|
|
291
|
+
|
|
292
|
+
### Rebuild
|
|
293
|
+
|
|
294
|
+
- GemCapability gained signIn, and the bridge's message lists and unions gained the sign-in messages. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
295
|
+
|
|
296
|
+
### New capability
|
|
297
|
+
|
|
298
|
+
- gem.account.requestSignIn() asks the Arcade to sign the player in, and answers signed_in, declined or unavailable. Save the game first: the Arcade may sign the player in by reloading the game under the account.
|
|
299
|
+
- gem.challenges.list() reads the game's challenges with the current period and the seed every player is handed for it, so all players get the same daily board. periodsBack reads earlier periods.
|
|
300
|
+
|
|
301
|
+
## 5.4.0
|
|
302
|
+
|
|
303
|
+
Upgrading from 5.3.0. Impact: none.
|
|
304
|
+
|
|
305
|
+
### New capability
|
|
306
|
+
|
|
307
|
+
- GameConfig carries the config's declared analytics events and funnels.
|
|
308
|
+
|
|
309
|
+
## 5.3.0
|
|
310
|
+
|
|
311
|
+
Upgrading from 5.2.1. Impact: required.
|
|
312
|
+
|
|
313
|
+
### Rebuild
|
|
314
|
+
|
|
315
|
+
- GemCapability gained viewport, and the bridge's message lists and unions gained the viewport message. leaveAndExit takes an optional analytics argument. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
316
|
+
|
|
317
|
+
### New capability
|
|
318
|
+
|
|
319
|
+
- gem.viewport tells a game which edges of its own frame are unsafe for essential UI, and the SDK sets the --gem-safe-top, --gem-safe-right, --gem-safe-bottom and --gem-safe-left CSS variables to match. Inside the Arcade, env(safe-area-inset-top) and its siblings can be wrong, so pad with var(--gem-safe-top, env(safe-area-inset-top, 0px)) and the same for each edge. GemOptions.onViewport hears each update.
|
|
320
|
+
- gem.analytics tracks your own events, with track, flush and setContext, and the SDK sends a set of platform events on its own. A dedicated server has analytics too.
|
|
321
|
+
|
|
322
|
+
## 5.2.1
|
|
323
|
+
|
|
324
|
+
Upgrading from 5.2.0. Impact: none.
|
|
325
|
+
|
|
326
|
+
Nothing in this release asks anything of a game.
|
|
327
|
+
|
|
328
|
+
## 5.2.0
|
|
329
|
+
|
|
330
|
+
Upgrading from 5.1.0. Impact: required.
|
|
331
|
+
|
|
332
|
+
### Must change
|
|
333
|
+
|
|
334
|
+
- DedicatedServerFailure has two new values, credential_reused and join_rate_limited, and both are retryable. The SDK refreshes a reused credential once and waits out a rate-limited join on the same transport before it reports either. A switch that assumes it knows every DedicatedServerFailure value must handle them.
|
|
335
|
+
|
|
336
|
+
### Rebuild
|
|
337
|
+
|
|
338
|
+
- A match's auto-reconnect is now bounded by time rather than by six attempts: by default it keeps trying for 90 seconds of visible time, and time while the page is hidden is not counted. Set autoReconnect.budgetMs to change the budget, or autoReconnect.attempts to cap the attempts as well. matchReconnecting reports remainingMs.
|
|
339
|
+
- A server bundle's join can receive superseded in its meta, set when the player's earlier link was still attached. The listen host now sets rejoin and superseded and delivers that leave before the join, as the dedicated runtime does. Code that compiles today keeps compiling.
|
|
340
|
+
|
|
341
|
+
## 5.1.0
|
|
342
|
+
|
|
343
|
+
Upgrading from 5.0.2. Impact: required.
|
|
344
|
+
|
|
345
|
+
### Rebuild
|
|
346
|
+
|
|
347
|
+
- GemCapability gained ads, and the bridge's message lists and unions gained the ad messages. A switch that assumes it knows every GemCapability value must handle the new one. A dedicated offer refused because the page's socket was down for a moment now reports platformCode embedder_relay_unavailable and is retryable. Other code that compiles today keeps compiling.
|
|
348
|
+
|
|
349
|
+
### New capability
|
|
350
|
+
|
|
351
|
+
- gem.ads.requestAd({ placement, format }) asks the Arcade for an ad at a natural break. No ad is an ordinary outcome, never an error, and the answer says nothing about why.
|
|
352
|
+
|
|
353
|
+
## 5.0.2
|
|
354
|
+
|
|
355
|
+
Upgrading from 5.0.1. Impact: recommended.
|
|
356
|
+
|
|
357
|
+
### Rebuild
|
|
358
|
+
|
|
359
|
+
- gem.purchases.request() now resolves ok only after the platform confirms that the purchase granted something. An ok the platform does not confirm, or one with no purchaseId, resolves unavailable, so on unavailable re-read the inventory rather than assume nothing was spent. Moving the pin takes a rebuild and no code change.
|
|
360
|
+
|
|
361
|
+
## 5.0.1
|
|
362
|
+
|
|
363
|
+
Upgrading from 5.0.0. Impact: none.
|
|
364
|
+
|
|
365
|
+
Nothing in this release asks anything of a game.
|
|
366
|
+
|
|
367
|
+
## 5.0.0
|
|
368
|
+
|
|
369
|
+
Upgrading from 4.1.0. Impact: required.
|
|
370
|
+
|
|
371
|
+
### Must change
|
|
372
|
+
|
|
373
|
+
- gem.rooms.leaveAll() now rejects when it cannot list the rooms the player holds, for example while offline, instead of resolving an empty list. Catch the rejection, and do not navigate away or reload until the leave has resolved, or the player can land back in the old match on the next launch.
|
|
374
|
+
- TransportAdvert.match_id is now required. An advert with no match_id is ignored and the connection uses WebRTC, so code that builds a TransportAdvert must set the match it was written for.
|
|
375
|
+
|
|
376
|
+
### May stop
|
|
377
|
+
|
|
378
|
+
- On a dedicated seat, matchReconnected now fires once the new connection can send, so a resync sent from the handler arrives. You may stop polling the connection state before sending. A P2P peer that loses its link now dials the host again instead of waiting for the old link to recover.
|
|
379
|
+
|
|
380
|
+
### Rebuild
|
|
381
|
+
|
|
382
|
+
- GemFrame.requestParty now returns whether the request went out, as the parent's half always has. The bridge's message lists and unions gained the purchase messages. Code that compiles today keeps compiling.
|
|
383
|
+
|
|
384
|
+
### New capability
|
|
385
|
+
|
|
386
|
+
- gem.purchases.request({ kind, targetId, currencySlug }) asks the Arcade to sell the player one of your game's items for a platform currency. targetId is the item's id, not its slug. The Arcade shows the confirmation, and the answer is ok, declined or unavailable, with no reason.
|
|
387
|
+
- A dedicated WebSocket link that goes silent is dropped within two heartbeat intervals, on a runtime that sends heartbeats, and the join welcome reports the interval as heartbeatIntervalMs.
|
|
388
|
+
|
|
389
|
+
## 4.1.0
|
|
390
|
+
|
|
391
|
+
Upgrading from 4.0.0. Impact: required.
|
|
392
|
+
|
|
393
|
+
### Rebuild
|
|
394
|
+
|
|
395
|
+
- GemCapability gained audioState, and the bridge's message lists and unions gained the audio state message. readTransportAdvert takes the match being joined. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
396
|
+
- A transport advert can carry the match_id it was written for, and the SDK ignores an advert bound to another match, falling back to WebRTC instead of dialling a server whose match is over. An advert with no match_id is still honoured.
|
|
397
|
+
|
|
398
|
+
### New capability
|
|
399
|
+
|
|
400
|
+
- The Arcade's mute now silences a game: when the player mutes, the SDK holds the game's Web Audio output and its audio and video elements silent, and restores the game's own setting on unmute. A game with its own mute control calls gem.reportMuted(muted) so the two never disagree. Set GemOptions.manageAudio to false to handle gem.prefs muted in onPrefs yourself. Create your audio after createGem.
|
|
401
|
+
|
|
402
|
+
## 4.0.0
|
|
403
|
+
|
|
404
|
+
Upgrading from 3.9.0. Impact: required.
|
|
405
|
+
|
|
406
|
+
### Must change
|
|
407
|
+
|
|
408
|
+
- A connection from gem.match.connect() now reconnects by itself after a drop: by default six attempts, waiting from half a second up to eight seconds. On a transient drop onClose no longer fires and send drops messages until the link is back. Show the reconnect with matchSuspended, matchReconnecting and matchReconnected, and resync from matchReconnected, because nothing is replayed. onClose still fires once with a reason when the match is really over. Set GemOptions.autoReconnect to false to keep the old behaviour. MatchConnection.state reads connected, suspended or closed.
|
|
409
|
+
|
|
410
|
+
### Should change
|
|
411
|
+
|
|
412
|
+
- MatchHosting.stop() is deprecated. A host player calls end() when the match is over, or leave() to hand it to another host. stop() posts nothing to the platform, so a host that meant to end the match starts a migration instead. It keeps working for the rest of 4.x. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
413
|
+
|
|
414
|
+
### Rebuild
|
|
415
|
+
|
|
416
|
+
- MatchSessionPhase gained connected, which follows ready once the link is up. A switch that assumes it knows every phase must handle it. GemCapability gained cohorts, and the bridge's message lists and unions gained the cohorts message. Other code that compiles today keeps compiling.
|
|
417
|
+
- A server bundle's shutdown now receives why it is shutting down, and its join meta can say rejoin, set when a player comes back after a drop. In shutdown, end the match unless info.reason is signal, which means a drain with players still in it. gem.match.end() goes through the runtime when it can. Code that compiles today keeps compiling.
|
|
418
|
+
|
|
419
|
+
### New capability
|
|
420
|
+
|
|
421
|
+
- gem.cohorts says which store page experiment cohorts the player is in, and GemOptions.onCohorts hears each update. An empty list means the player is in no experiment, and null means the Arcade has not said. gem.awaitCohorts() waits for the answer and resolves null on timeout. Never block the game on it.
|
|
422
|
+
|
|
423
|
+
## 3.9.0
|
|
424
|
+
|
|
425
|
+
Upgrading from 3.8.3. Impact: required.
|
|
426
|
+
|
|
427
|
+
### Must change
|
|
428
|
+
|
|
429
|
+
- A MatchOutcome can now have status ended, with the platform's reason, as well as ready and failed, and a match that answered before and then answers not found is ended rather than failed. Code that switches on a MatchOutcome status must handle ended.
|
|
430
|
+
- GemHost.relaySocketEvent now returns every destination a socket frame was relayed to, as a list, instead of one destination or null. This concerns only code that drives the parent half; a game changes nothing.
|
|
431
|
+
|
|
432
|
+
### Rebuild
|
|
433
|
+
|
|
434
|
+
- GemCapability gained socketState, and the bridge's message lists and unions gained the socket state message, which the SDK uses to re-read the room when the player's connection returns. A switch that assumes it knows every GemCapability value must handle the new one. P2pFailure gained not_expected_player, which a joining peer now reports when the host refuses it for another player's credential. A host that refuses a joiner says why in the console and keeps hosting. Other code that compiles today keeps compiling.
|
|
435
|
+
|
|
436
|
+
### New capability
|
|
437
|
+
|
|
438
|
+
- gem.rooms raises matchEnded with the match, its reason and whether the room reopened, whether or not the platform's push arrived, and a second match in the same room now works for host and members. matchSuspended fires when the link drops or a P2P host vanishes. gem.rooms.matchSession holds the current phase, and reconcile() re-reads it.
|
|
439
|
+
|
|
440
|
+
## 3.8.3
|
|
441
|
+
|
|
442
|
+
Upgrading from 3.8.2. Impact: recommended.
|
|
443
|
+
|
|
444
|
+
### Rebuild
|
|
445
|
+
|
|
446
|
+
- A screenshot is now sent as encoded image bytes, which Firefox delivers, and an image too large to send is refused as too_large rather than lost. A game that answers onScreenshot by hand should send bytes too. Moving the pin takes a rebuild and no code change.
|
|
447
|
+
|
|
448
|
+
## 3.8.2
|
|
449
|
+
|
|
450
|
+
Upgrading from 3.8.1. Impact: recommended.
|
|
451
|
+
|
|
452
|
+
### Rebuild
|
|
453
|
+
|
|
454
|
+
- A screenshot is no longer lost on Firefox when the SDK hands it over. Before this release every Firefox capture timed out and the report said the game did not answer. Moving the pin takes a rebuild and no code change.
|
|
455
|
+
|
|
456
|
+
## 3.8.1
|
|
457
|
+
|
|
458
|
+
Upgrading from 3.8.0. Impact: required.
|
|
459
|
+
|
|
460
|
+
### Must change
|
|
461
|
+
|
|
462
|
+
- The server API no longer offers initiatePurchase. The platform refuses it for every credential a dedicated server holds, so a call could only fail; remove it. Purchases are made by the player.
|
|
463
|
+
- Leaderboard.updateFrequencySeconds is now optional. A board that states no cadence reads undefined instead of 0, which used to mean poll as fast as you like. Code that does arithmetic with it must handle undefined. LeaderboardEntry now extends RankedRow, with the same fields.
|
|
464
|
+
|
|
465
|
+
### May stop
|
|
466
|
+
|
|
467
|
+
- A game served from the developer's own machine, framed by a loopback origin with an explicit port, is now admitted by rule. You may stop adding loopback origins with ports to allowedEmbedders; they change on every run anyway.
|
|
468
|
+
|
|
469
|
+
### Rebuild
|
|
470
|
+
|
|
471
|
+
- The server API types follow the platform. InventoryChange gained the platform grant and unknown arms, UnavailabilityReason gained not_client_executable, and OperationRequest gained progression_max. A switch that assumes it knows every arm must handle the new ones. GemCapability gained screenshot and feedbackContext, and the bridge's message lists and unions gained their messages. The parent's port types accept transferred ports.
|
|
472
|
+
|
|
473
|
+
### New capability
|
|
474
|
+
|
|
475
|
+
- gem.leaderboards.mine(id) reads the player's own entity board, where rank 1 is their personal best, character(id, characterId) reads a character's, and friends(id) reads the friend board. A row's isViewer says whether it is the player, and is absent on a read that cannot tell. A dedicated server reads the entity board with getEntityLeaderboard.
|
|
476
|
+
- The Arcade can attach a screenshot and your own debug state to a bug report a player files. By default the SDK captures the largest visible canvas; a WebGL game must create its context with preserveDrawingBuffer set to true, or supply the picture with GemOptions.onScreenshot. GemOptions.onFeedbackContext returns the debug state, once per report, within about a second, and must hold nothing about a person.
|
|
477
|
+
- gem.me.mutations.maxProgression(id, value) raises a progression to value only when that is higher, the write for a best score or the most stars on a level. The server API types carry the room template's transports and offline member timeout, an order's changes, and the platform grant outcome.
|
|
478
|
+
|
|
479
|
+
## 3.8.0
|
|
480
|
+
|
|
481
|
+
Upgrading from 3.7.0. Impact: recommended.
|
|
482
|
+
|
|
483
|
+
### May stop
|
|
484
|
+
|
|
485
|
+
- A gem.rooms call made before the first play token now waits for the game id, within the same 15 second wait as gem.awaitIdentity(), instead of refusing as misconfigured. You may stop awaiting gem.awaitIdentity() before the first room call. A wait that runs out reaches the rooms error event with reason timeout.
|
|
486
|
+
|
|
487
|
+
### Rebuild
|
|
488
|
+
|
|
489
|
+
- A failed save upload or download now reports what the far end said on every failing status, and blames an expired link only on a 403. Moving the pin takes a rebuild and no code change.
|
|
490
|
+
|
|
491
|
+
## 3.7.0
|
|
492
|
+
|
|
493
|
+
Upgrading from 3.6.1. Impact: required.
|
|
494
|
+
|
|
495
|
+
### Must change
|
|
496
|
+
|
|
497
|
+
- GemHost.start() now offers the handshake again every two seconds until the frame answers or close() is called, instead of giving up once, so HostState no longer has timed-out. start() also accepts a function that makes a fresh channel for each offer. This concerns only code that drives the parent half; a game changes nothing, and a game whose bridge starts late now connects.
|
|
498
|
+
|
|
499
|
+
## 3.6.1
|
|
500
|
+
|
|
501
|
+
Upgrading from 3.6.0. Impact: recommended.
|
|
502
|
+
|
|
503
|
+
### Rebuild
|
|
504
|
+
|
|
505
|
+
- A game now advertises the localHost capability that 3.6.0 implemented, so a development tool that offers to run the game server is actually asked. An embedder origin may now use any scheme and a bracketed IPv6 address, and its port must be a real port; an allowedEmbedders entry still matches only that exact origin. Moving the pin takes a rebuild and no code change.
|
|
506
|
+
|
|
507
|
+
## 3.6.0
|
|
508
|
+
|
|
509
|
+
Upgrading from 3.5.0. Impact: required.
|
|
510
|
+
|
|
511
|
+
### Rebuild
|
|
512
|
+
|
|
513
|
+
- GemCapability gained localHost, and the bridge's message lists and unions gained the local server messages. A switch that assumes it knows every GemCapability value must handle the new one. The generated bridge validators are now constants rather than function declarations, and are called the same way. Other code that compiles today keeps compiling.
|
|
514
|
+
|
|
515
|
+
### New capability
|
|
516
|
+
|
|
517
|
+
- gem.profiles.of(playerId) reads the inspect this player screen in one request: the player's display identity and every showcase value the viewer may see. It resolves null for an unknown player and for one who has blocked the viewer alike.
|
|
518
|
+
- A dedicated server's request for a save upload URL is now retried like a read, so a dropped connection no longer loses the player's save. RequestOptions.replaySafe declares any other single write safe to repeat. The storage upload itself bypasses the SDK client, so retry it in your own code, as the server saves example now does.
|
|
519
|
+
|
|
520
|
+
## 3.5.0
|
|
521
|
+
|
|
522
|
+
Upgrading from 3.4.0. Impact: required.
|
|
523
|
+
|
|
524
|
+
### Rebuild
|
|
525
|
+
|
|
526
|
+
- GemCapability gained partySeating, and the bridge's message lists and unions gained the seated message. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
|
|
527
|
+
|
|
528
|
+
### New capability
|
|
529
|
+
|
|
530
|
+
- gem.rooms raises seated when the player is put in a room without asking, which is how a party member's game learns that the leader seated the whole party. Show the room instead of the start menu. Nothing runs until a handler subscribes. GemOptions.watchSeats turns the watch off, gem.rooms.reconcileSeats() checks on demand, and GemOptions.seatPollIntervalMs sets the slow poll.
|
|
531
|
+
- The package ships the gem-sdk-stamp command. Run in a game build on the directory it uploads, it writes one small file recording which SDK version the build was made with, so the platform can tell a game is on an unsupported version without scanning its scripts.
|
|
532
|
+
|
|
533
|
+
## 3.4.0
|
|
534
|
+
|
|
535
|
+
Upgrading from 3.3.0. Impact: none.
|
|
536
|
+
|
|
537
|
+
### New capability
|
|
538
|
+
|
|
539
|
+
- gem.friends.list() reads the signed-in player's accepted friends, display identity only, a page at a time.
|
|
540
|
+
- gem.showcase shares small values for friends to see: set and clear write a slot, friends(key) reads every friend's value in one request, and of(playerId, key) reads one player's value. of() resolves null when the value is missing or not visible, and a mistyped key looks the same.
|
|
541
|
+
|
|
542
|
+
## 3.3.0
|
|
543
|
+
|
|
544
|
+
Upgrading from 3.2.2. Impact: recommended.
|
|
545
|
+
|
|
546
|
+
### May stop
|
|
547
|
+
|
|
548
|
+
- The transport ladder for a dedicated match now comes from the room template's transports list, in the template's order. You may stop passing transports to connect(): a list you pass now only narrows the template's list and never reorders or widens it, and a list that filters out every transport is refused as misconfigured. A room with no list uses WebTransport, then WebRTC, then WebSocket, as before.
|
|
549
|
+
|
|
550
|
+
### New capability
|
|
551
|
+
|
|
552
|
+
- GameConfig carries the config's async opponent types.
|
|
553
|
+
|
|
554
|
+
## 3.2.2
|
|
555
|
+
|
|
556
|
+
Upgrading from 3.2.1. Impact: recommended.
|
|
557
|
+
|
|
558
|
+
### New capability
|
|
559
|
+
|
|
560
|
+
- gem.match.connect() takes onMatchEnded, called once with the platform's reason before the connection closes, on every seat and never for the game's own close(). A reconnect loop can stop guessing from close messages. MatchConnection.transport says which transport a dedicated connection used.
|
|
561
|
+
- GemOptions.recoverStaleMembership, on by default, clears the room memberships this page cannot see when a quick-join is refused for holding one, and retries once. Set it to false in a game whose players hold rooms on purpose, and handle the refusal with gem.rooms.leaveAll().
|
|
562
|
+
|
|
563
|
+
## 3.2.1
|
|
564
|
+
|
|
565
|
+
Upgrading from 3.2.0. Impact: none.
|
|
566
|
+
|
|
567
|
+
Nothing in this release asks anything of a game.
|
|
568
|
+
|
|
569
|
+
## 3.2.0
|
|
570
|
+
|
|
571
|
+
Upgrading from 3.1.5. Impact: required.
|
|
572
|
+
|
|
573
|
+
### Should change
|
|
574
|
+
|
|
575
|
+
- The game entry carries the same deprecation of the server host roomArgs and roster snapshots as the server entry: read gem.room?.args() and gem.room?.get() instead. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
576
|
+
|
|
577
|
+
### Rebuild
|
|
578
|
+
|
|
579
|
+
- GemCapability gained asyncOpponents. A switch that assumes it knows every GemCapability value must handle the new one. GameServerLink.send and SendOptions changed only in the name the type declarations use internally. Other code that compiles today keeps compiling.
|
|
580
|
+
|
|
581
|
+
### New capability
|
|
582
|
+
|
|
583
|
+
- One entry, @indiegems/gem-web-sdk/sdk, now serves every seat of a game: the browser, the dedicated server bundle, and a player's browser hosting a P2P match. The game and server entries stay as they were. The game entry also names the server bundle types, so one source file can carry both halves.
|
|
584
|
+
- gem.match is the multiplayer branch written once. gem.match.serve(server) runs the same server a game publishes for dedicated hosting in the host player's browser when the room template says P2P, and gem.match.connect() joins the match on whichever seat the template chose.
|
|
585
|
+
|
|
586
|
+
## 3.1.5
|
|
587
|
+
|
|
588
|
+
Upgrading from 3.1.4. Impact: none.
|
|
589
|
+
|
|
590
|
+
Nothing in this release asks anything of a game.
|
|
591
|
+
|
|
592
|
+
## 3.1.4
|
|
593
|
+
|
|
594
|
+
Upgrading from 3.1.3. Impact: none.
|
|
595
|
+
|
|
596
|
+
Nothing in this release asks anything of a game.
|
|
597
|
+
|
|
598
|
+
## 3.1.3
|
|
599
|
+
|
|
600
|
+
Upgrading from 3.1.2. Impact: recommended.
|
|
601
|
+
|
|
602
|
+
### Should change
|
|
603
|
+
|
|
604
|
+
- A dedicated server's roomArgs and roster snapshots are deprecated. Read gem.room?.args() for the room's settings, which tells no settings apart from empty ones, and gem.room?.get() for live membership with names, roles and ready state. Both snapshots are still delivered. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
605
|
+
|
|
606
|
+
### Rebuild
|
|
607
|
+
|
|
608
|
+
- The SDK package and its browser modules are published on the CDN from this release, so a dedicated server or a page without a bundler can install it by its versioned URL. To move the pin, edit the version in that URL and install again.
|
|
609
|
+
|
|
610
|
+
### New capability
|
|
611
|
+
|
|
612
|
+
- GemOptions.onDevToolsPermissionChange tells a game whether the developer panel would open for this player, and again whenever that changes, so a game can show its own panel button only to the people allowed to use it.
|
|
613
|
+
|
|
614
|
+
## 3.1.2
|
|
615
|
+
|
|
616
|
+
Upgrading from 3.1.1. Impact: none.
|
|
617
|
+
|
|
618
|
+
Nothing in this release asks anything of a game.
|
|
619
|
+
|
|
620
|
+
## 3.1.1
|
|
621
|
+
|
|
622
|
+
Upgrading from 3.1.0. Impact: recommended.
|
|
623
|
+
|
|
624
|
+
### Rebuild
|
|
625
|
+
|
|
626
|
+
- gem.me.currencies.get() now finds a currency by its slug as well as by its id, as documented. Before this release a slug such as coins answered null, which reads as a balance of none. Moving the pin takes a rebuild and no code change.
|
|
627
|
+
|
|
628
|
+
## 3.1.0
|
|
629
|
+
|
|
630
|
+
Upgrading from 3.0.0. Impact: required.
|
|
631
|
+
|
|
632
|
+
### Rebuild
|
|
633
|
+
|
|
634
|
+
- GameConfig.leaderboards and GameConfig.run_types are now typed from the config snapshot's own fields, with the same shape. The server's OperationRequest currency operations take an optional bucket. Code that compiles today keeps compiling.
|
|
635
|
+
|
|
636
|
+
### New capability
|
|
637
|
+
|
|
638
|
+
- gem.leaderboards.get(id) reads one of your game's leaderboards, with its rows and the interval at which the board is regenerated, which is how often it is worth polling. A dedicated server reads the same board with getLeaderboard. Boards are computed from run history on the platform; a browser cannot submit a score.
|
|
639
|
+
|
|
640
|
+
## 3.0.0
|
|
641
|
+
|
|
642
|
+
Upgrading from 2.4.2. Impact: required.
|
|
643
|
+
|
|
644
|
+
### Must change
|
|
645
|
+
|
|
646
|
+
- The server entry no longer re-exports the generated platform operations and their wire types. A dedicated server that imported one of them by name from the server entry must import it from @indiegems/gem-web-sdk/server/api instead. The server entry keeps defineServer, createGemServer and the rest of what a bundle calls, and gem.api in a server bundle is unchanged.
|
|
647
|
+
- HostTokenSource no longer carries source. Nothing the server entry exports accepts one, so code that read it must stop; createGemServer reaches the token source by itself.
|
|
648
|
+
- gem.me.mutations.executeRecipe() now resolves a typed RecipeResult instead of the raw response body. Read orderId, status, granted, consumed, autoClaimedRewards and lootResults in place of the snake case wire fields such as order_id.
|
|
649
|
+
|
|
650
|
+
### Should change
|
|
651
|
+
|
|
652
|
+
- ClientVersion.platform is deprecated, because the SDK reports the client platform itself: remove the field. CreateRoomOptions.maxPlayers is deprecated and never sent, because a room takes its seats from its template. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
653
|
+
|
|
654
|
+
### Rebuild
|
|
655
|
+
|
|
656
|
+
- gem.me.saves.put() now sends the upload headers the platform's grant names, so a browser save stores its bytes again: from 2.2.0 to 2.4.2 the upload was refused even though the call resolved. Save data that is not base64 encoded is now a compile error on the browser path too, where the platform would refuse it at runtime. Moving the pin takes a rebuild.
|
|
657
|
+
|
|
658
|
+
### New capability
|
|
659
|
+
|
|
660
|
+
- The server entry now exports every type its own functions take or return, so a bundle can name them: ClientOptions, HostTokenSourceOptions, TokenGrant, RoomArgValue, VersionedGetOptions, ConditionalRequestHeaders and CONDITIONAL_HEADERS among them. Base64String and toBase64 encode save data for the platform.
|
|
661
|
+
- GameConfig carries the config's leaderboards and run types. The player's economy gains reads for currency buckets, recipe usage, item instances, orders, progressions and loot table drop rates.
|
|
662
|
+
|
|
663
|
+
## 2.4.2
|
|
664
|
+
|
|
665
|
+
Upgrading from 2.4.1. Impact: recommended.
|
|
666
|
+
|
|
667
|
+
### Rebuild
|
|
668
|
+
|
|
669
|
+
- A WebTransport link with no unreliable lane is now refused before it is used, so on Safari a match connects over WebRTC, whose unreliable messages arrive. Before this release those messages were silently lost.
|
|
670
|
+
|
|
671
|
+
## 2.4.1
|
|
672
|
+
|
|
673
|
+
Upgrading from 2.4.0. Impact: required.
|
|
674
|
+
|
|
675
|
+
### Rebuild
|
|
676
|
+
|
|
677
|
+
- The bridge gains a devtools message and capability, sent by the parent page when the Arcade opens the developer panel. A game changes nothing. Code that compiles today keeps compiling.
|
|
678
|
+
- When a dedicated server connect falls back from one transport to the next, it now logs each failure and where it goes next through the game's log option. A WebTransport link with no datagram lane sends its unreliable messages on the stream instead.
|
|
679
|
+
|
|
680
|
+
### New capability
|
|
681
|
+
|
|
682
|
+
- gem.devtools opens the developer panel, which loads on demand, for a player whose session the embedder allows it for. FrameState names the bridge states that onStateChange and awaitBridge report.
|
|
683
|
+
|
|
684
|
+
## 2.4.0
|
|
685
|
+
|
|
686
|
+
Upgrading from 2.3.0. Impact: required.
|
|
687
|
+
|
|
688
|
+
### Must change
|
|
689
|
+
|
|
690
|
+
- Embedders only: the token grant carries apiBaseUrl, the API origin, in place of the short backend name, which is gone from GemToken and accepted as any string on TokenGrant. A game names no backend and changes nothing.
|
|
691
|
+
|
|
692
|
+
### Rebuild
|
|
693
|
+
|
|
694
|
+
- The SDK now reports the platform as web for a browser game, so the Arcade's release controls, such as blocking a bad build, apply to it. ClientVersion.platform is optional for that reason, and the resolved version always carries it.
|
|
695
|
+
- GameConfig's fields are now typed straight from the config snapshot, with the same shapes. A WebTransport offer may carry a named address, which the SDK dials first so that Safari can use WebTransport. Code that compiles today keeps compiling.
|
|
696
|
+
|
|
697
|
+
### New capability
|
|
698
|
+
|
|
699
|
+
- A save can set timeoutMs, so it fails quickly against the deadline the game is actually racing, such as a session that is ending, instead of the fixed 30 seconds.
|
|
700
|
+
|
|
701
|
+
## 2.3.0
|
|
702
|
+
|
|
703
|
+
Upgrading from 2.2.0. Impact: required.
|
|
704
|
+
|
|
705
|
+
### Rebuild
|
|
706
|
+
|
|
707
|
+
- connect keeps its old call shape alongside the new one, and a data channel can send bytes as well as text. On the server, send and broadcast take options, the lifecycle methods receive an extra details argument, and playerNumber names each player. Code that compiles today keeps compiling.
|
|
708
|
+
|
|
709
|
+
### New capability
|
|
710
|
+
|
|
711
|
+
- A dedicated server connect can negotiate its transport. Pass transports to try WebTransport, WebRTC and WebSocket in order, and connect resolves a MultiTransportSession whose GameServerLink sends reliable or unreliable messages over whichever one connected.
|
|
712
|
+
|
|
713
|
+
## 2.2.0
|
|
714
|
+
|
|
715
|
+
Upgrading from 2.1.0. Impact: required.
|
|
716
|
+
|
|
717
|
+
### Must change
|
|
718
|
+
|
|
719
|
+
- Mock mode is gone. Remove the mode and mock options and any use of gem.mode, gem.mock, GemMode or MockBackend. Outside the Arcade a game now runs as a frame whose parent has not spoken yet, and gem.frame is always present. To develop with no Arcade, run the game under a local parent page that answers the handshake.
|
|
720
|
+
- The game bundle on the CDN is renamed gem-web-sdk.min.js from this release. A page that loads it by URL must use the new name when it moves its pin; older versions keep their old name.
|
|
721
|
+
- On a dedicated server, a setting value is now typed as base64 text, so passing plain text fails to compile. Encode the value before a put and decode it after a read. GemErrorReason gains too large, and a server that switches over every reason must handle it.
|
|
722
|
+
|
|
723
|
+
### Rebuild
|
|
724
|
+
|
|
725
|
+
- gem.me.settings now encodes and decodes values itself, so a put no longer fails and a read returns what was written instead of the encoded text. A match start that waits for a server now waits at least as long as the platform asks.
|
|
726
|
+
|
|
727
|
+
### New capability
|
|
728
|
+
|
|
729
|
+
- gem.me.saves keeps a player's progress in a slot your game config declares, with one call to put and one to get. GemSaveError reports a save that failed, and a payload that is too large is its own reason, not worth retrying.
|
|
730
|
+
- A room's settings are back as roomArgs. Pass them when creating or updating a room, and read room.roomArgs and room.roomArgsTemplate, the typed list of settings the room's template allows.
|
|
731
|
+
- A dedicated server bundle can be written with defineServer, a typed lifecycle with named methods. The SDK binds the match runtime for it and hands each method one object with both the match, to send and broadcast to players, and the platform API.
|
|
732
|
+
|
|
733
|
+
## 2.1.0
|
|
734
|
+
|
|
735
|
+
Upgrading from 2.0.0. Impact: none.
|
|
736
|
+
|
|
737
|
+
### New capability
|
|
738
|
+
|
|
739
|
+
- A dedicated server reads its own room from the platform with gem.room, instead of trusting the data the runtime pushed. The server API adds reading, updating, listing and closing rooms, moving the host, kicking a player, and reading and writing room arguments.
|
|
740
|
+
|
|
741
|
+
## 2.0.0
|
|
742
|
+
|
|
743
|
+
Upgrading from 1.5.3. Impact: required.
|
|
744
|
+
|
|
745
|
+
### Must change
|
|
746
|
+
|
|
747
|
+
- GameConfig is now the published config document itself, with every collection and the platform's field names. Read display name, icon url, fungible, stack size, item type, consumable, max balance and min balance by their snake case wire names, and give a definition with no display name your own fallback. item() and currency() still look a definition up by id or slug.
|
|
748
|
+
- RoomsApi.templateMatchType is gone from the low-level rooms API. A game that uses gem.rooms changes nothing.
|
|
749
|
+
|
|
750
|
+
### Rebuild
|
|
751
|
+
|
|
752
|
+
- When the platform refuses a call, the sentence it wrote now reaches GemApiError, where a game used to read no detail, and the mock's rule list says so. Code that compiles today keeps compiling.
|
|
753
|
+
|
|
754
|
+
## 1.5.3
|
|
755
|
+
|
|
756
|
+
Upgrading from 1.5.2. Impact: recommended.
|
|
757
|
+
|
|
758
|
+
### Rebuild
|
|
759
|
+
|
|
760
|
+
- GemApiError.retryAfterSeconds now carries the wait the platform asked for, and the SDK's own retry uses it. A config load that storage refuses reports what storage said instead of guessing that the link expired.
|
|
761
|
+
|
|
762
|
+
## 1.5.2
|
|
763
|
+
|
|
764
|
+
Upgrading from 1.5.1. Impact: required.
|
|
765
|
+
|
|
766
|
+
### Must change
|
|
767
|
+
|
|
768
|
+
- gameArgs is gone from room creation, room updates and the room, and templateArgs is gone from the room, because the platform now refuses a request that carries game arguments. Remove them; room settings return as roomArgs in a later release.
|
|
769
|
+
- DedicatedServerFailure has three new reasons: no server ready, start rate limited, and peer to peer unavailable. A game that switches over every reason must handle them. GemApiError now carries the code the platform sent with a refusal.
|
|
770
|
+
|
|
771
|
+
### Should change
|
|
772
|
+
|
|
773
|
+
- CreateRoomOptions.maxPlayers is deprecated, because the platform refuses a seat count at creation. A room's seats come from its template; the SDK drops the value and logs a warning. See [the deprecation policy](docs/deprecation-policy.md#4-what-is-deprecated-today).
|
|
774
|
+
|
|
775
|
+
### May stop
|
|
776
|
+
|
|
777
|
+
- A game may stop retrying a match start itself. When no server is ready the SDK now waits up to 30 seconds and emits matchStartWaiting so the game can show it, and a peer to peer room never waits. The retry option sets the wait per call, and a budget of 0 restores the old behaviour.
|
|
778
|
+
|
|
779
|
+
### Rebuild
|
|
780
|
+
|
|
781
|
+
- A retry wait the platform asks for is capped at 60 seconds and now observes an abort, and a baseUrl with a query or fragment is refused when createGem runs instead of sending every call to the wrong place.
|
|
782
|
+
|
|
783
|
+
### New capability
|
|
784
|
+
|
|
785
|
+
- A dedicated game server can import @indiegems/gem-web-sdk/server, which calls the platform with the server token the match runtime provides. AuthError.isAuthError and TransportRefusal.isRefusal tell those errors apart across bundles.
|
|
786
|
+
|
|
787
|
+
## 1.5.1
|
|
788
|
+
|
|
789
|
+
Upgrading from 1.5.0. Impact: recommended.
|
|
790
|
+
|
|
791
|
+
### Rebuild
|
|
792
|
+
|
|
793
|
+
- A request the SDK refuses to send, because it would leave the allowed origin, now rejects once with TransportRefusal. Before this release it was retried three times and reported as a server outage.
|
|
794
|
+
|
|
795
|
+
## 1.5.0
|
|
796
|
+
|
|
797
|
+
Upgrading from 1.4.0. Impact: required.
|
|
798
|
+
|
|
799
|
+
### Rebuild
|
|
800
|
+
|
|
801
|
+
- The mock models the config document too, and its list of modelled rules says so. An inventory read that was in flight when a write landed no longer refills the cache with the old bag. Code that compiles today keeps compiling.
|
|
802
|
+
|
|
803
|
+
### New capability
|
|
804
|
+
|
|
805
|
+
- gem.gameConfig.load() reads your game's published config, so an item or currency id from the inventory resolves to its name, icon and stack limit. It resolves null when the game has no config assigned.
|
|
806
|
+
|
|
807
|
+
## 1.4.0
|
|
808
|
+
|
|
809
|
+
Upgrading from 1.3.3. Impact: required.
|
|
810
|
+
|
|
811
|
+
### Must change
|
|
812
|
+
|
|
813
|
+
- DedicatedServerFailure has a new reason, match ended. When the platform ends a dedicated match the SDK closes the connection itself and reports that reason, so a tab left open stops holding the server. A game that switches over every reason must handle it.
|
|
814
|
+
|
|
815
|
+
### Rebuild
|
|
816
|
+
|
|
817
|
+
- A cluster target option now accepts null, which means no relay, where it used to send a cluster named null. put, patch and delete on gem.client take request options for an If-Match precondition, and GemApiError keeps the detail the platform wrote. Code that compiles today keeps compiling.
|
|
818
|
+
- The mock's list of modelled platform rules grew, and peer to peer telemetry samples now name their transport. A 401 now asks the Arcade for a fresh token once instead of ending the game's API access, and a single push no longer slows the room poll for the rest of the room's life.
|
|
819
|
+
|
|
820
|
+
### New capability
|
|
821
|
+
|
|
822
|
+
- gem.me and gem.characters read and write per key settings for the player and for each character, with an ETag per key. gem.transfers moves currencies and items between players; a transfer completes with no action from the recipient, and the recipient's SDK is not told.
|
|
823
|
+
- gem.prefs and the onPrefs option give the preferences the Arcade sends. onPause and onWillTerminate tell a game when it is paused and when its session is ending, so it can save in time. room.templateArgs reads the arguments the room was created with, and rooms.gameId names the game.
|
|
824
|
+
|
|
825
|
+
## 1.3.3
|
|
826
|
+
|
|
827
|
+
Upgrading from 1.3.2. Impact: recommended.
|
|
828
|
+
|
|
829
|
+
### Rebuild
|
|
830
|
+
|
|
831
|
+
- A token request the Arcade can never answer now settles at once as chain exhausted, which is terminal, instead of timing out as if it might recover. A game that retried on that timeout stops retrying forever.
|
|
832
|
+
|
|
833
|
+
## 1.3.2
|
|
834
|
+
|
|
835
|
+
Upgrading from 1.3.1. Impact: required.
|
|
836
|
+
|
|
837
|
+
### Rebuild
|
|
838
|
+
|
|
839
|
+
- A browser MessagePort now assigns to PortLike without a cast, which matters to an embedder that owns the window listener. A port handler still has to check the data it is handed. Code that compiles today keeps compiling.
|
|
840
|
+
- A token the Arcade pushes before the game asks for one is now installed at once, so onAuthStateChange reports ready as soon as the player is known. Before this release it waited for the game's first API call.
|
|
841
|
+
|
|
842
|
+
## 1.3.1
|
|
843
|
+
|
|
844
|
+
Upgrading from 1.3.0. Impact: none.
|
|
845
|
+
|
|
846
|
+
Nothing in this release asks anything of a game.
|
|
847
|
+
|
|
848
|
+
## 1.3.0
|
|
849
|
+
|
|
850
|
+
Upgrading from 1.2.0. Impact: none.
|
|
851
|
+
|
|
852
|
+
### New capability
|
|
853
|
+
|
|
854
|
+
- gem.awaitBridge() resolves once the bridge handshake settles, connected or not, which is the moment to start work that needs the Arcade. ready() now reaches the Arcade exactly once per session, so calling it again in a finally block is safe.
|
|
855
|
+
- gem.boot records a timeline of the SDK's own boot steps and prints it as one line, after success as well as failure, and markOnResolve and reportOnResolve add a game's own steps to it. A peer to peer connect now names its own steps in that line.
|
|
856
|
+
|
|
857
|
+
## 1.2.0
|
|
858
|
+
|
|
859
|
+
Upgrading from 1.1.0. Impact: required.
|
|
860
|
+
|
|
861
|
+
### Must change
|
|
862
|
+
|
|
863
|
+
- A dedicated server connect now presents the join credential and waits for the server to welcome the player, so it resolves with a channel the server has accepted. A game that sent its own join message and waited for the welcome must remove that code, or pass presentCredential false to keep the raw channel.
|
|
864
|
+
- DedicatedServerFailure has two new reasons, offer refused and join refused, and DedicatedServerError carries the platform code behind a failure. A game that switches over every reason must handle the new ones.
|
|
865
|
+
|
|
866
|
+
### May stop
|
|
867
|
+
|
|
868
|
+
- A game may stop priming the play token before its first room call: the SDK asks for the token as soon as the bridge connects, and gem.awaitIdentity() resolves when it arrives. A game may also stop holding ready() until the handshake lands, because an early ready is now delivered on connect.
|
|
869
|
+
- A game may stop clearing leftover rooms before a quick join. Quick join now clears the memberships the player still holds and retries once, and recoverStaleMembership false turns that off for a game with its own lobby. rooms.leaveAll() is there for a game that clears them itself.
|
|
870
|
+
|
|
871
|
+
### Rebuild
|
|
872
|
+
|
|
873
|
+
- gem.identity is now typed as GemIdentity, with the same fields. rooms.leave takes a keepalive option, and leaving on page unload now leaves the room first, so a player who closes the tab is no longer still a member when they come back. Code that compiles today keeps compiling.
|
|
874
|
+
|
|
875
|
+
### New capability
|
|
876
|
+
|
|
877
|
+
- gem.player, the onPlayer option and gem.awaitPlayer() give the display identity the Arcade pushes, or null when it never does. Display names arrive as PlayerText, text written by another player, and the text helpers wrap and compare it safely.
|
|
878
|
+
- gem.exit() leaves the room and then asks the Arcade to close the game, in that order, and leaveAndExit does the same for code that holds the pieces. handshakeWarningMs sets when the SDK logs which of three things kept the bridge from connecting.
|
|
879
|
+
|
|
880
|
+
## 1.1.0
|
|
881
|
+
|
|
882
|
+
The oldest release in this changelog. Impact: none.
|
|
883
|
+
|
|
884
|
+
### New capability
|
|
885
|
+
|
|
886
|
+
- A game imports createGem from @indiegems/gem-web-sdk/game, which connects the bridge to the Arcade, holds the play token and calls the platform API. An embedder imports the parent half of the bridge from @indiegems/gem-web-sdk, and the bridge schema is published as its own entry. Building with the package needs Node 22 or newer.
|