v1.9.0 — Replicated state that always arrives
Replicated state of any size reaches the client, and player data survives migrations and departures.
Before upgrading
Section titled “Before upgrading”Four changes can reach existing code.
- Migrations no longer run for a player with no saved data. If a step also set
up a value that new players need, put that value in the
Template. Remote:Connect,Remote:OnceandRemote:Waitthrow on the server, where they never received anything. Serve the remote withNet.Handle.- A whole number token given a fraction throws. Round the value first, or
declare a fractional token such as
NumberF32. - A
Navigationagent can fail with a new reason,faulted.
Replicated state of any size arrives
Section titled “Replicated state of any size arrives”A player’s first view of Replication used to travel
as one call holding every key. That call used
Types.Any, which stops at 4096 parts. An inventory
of a thousand items with three fields each is past that, so the call was
dropped. The client never received its first view, and every later change for
that player was ignored for the rest of the session.
Each key now travels as its own call. A key that cannot be sent holds back only
itself, is reported, and goes again the next time it is written. Types.Any
also accepts wider bounds for what the server sends:
| Ceiling | Client to server | Server to client |
|---|---|---|
| Depth | 16 | 64 |
| Parts in one call | 4096 | 1048576 |
| Entries in one table | 4096 | 65535 |
The playtest that proved the fix sent 1500 items to a client, then a change to one of them. Both arrived.
Player data survives migrations and departures
Section titled “Player data survives migrations and departures”Three faults in Data could damage what a player owns.
- New players ran every migration. The template was treated as data saved at version 1, so a step that read a field only old data has failed, and the new player was kicked. Migrations now run only for data saved at an older version.
- A failed migration was saved. A step that raised left behind what it had already converted, and the session saved it on the way out. Steps now run on a copy, which replaces the live data only when every step succeeds.
- Data could disappear before services finished. Data was released on its
own
PlayerRemovingconnection, which could run before a service’sOnPlayerRemoving. Release now happens when the player’s bag closes, after every service has had its turn.
Purchases are granted only once saved
Section titled “Purchases are granted only once saved”Monetization answered a redelivered receipt as
granted whenever the grant was recorded in memory, even when the first save had
not been confirmed. A receipt seen before is now answered the same way as a new
one: PurchaseGranted only once the save recording it is confirmed.
Other changes
Section titled “Other changes”- A weighted
Chancedraw from a committed round now lands on the same entry on every server, because entries are weighed in the order they were added. Storeretries a last save that failed, and shutdown no longer counts a save still in flight as finished.Loop.Afterreleases its entry once it runs, so the framework bag no longer grows with every call that names no owner.Schemano longer raises on a bound that is not a number.- A
Watchcallback that raises no longer stops the members after it from being announced.
Full changelog
Section titled “Full changelog”Every change in this release is listed in the changelog.