Skip to content

Commit 5d3c17b

Browse files
update Open Source Docs from Roblox internal teams
1 parent dd4ffec commit 5d3c17b

File tree

8 files changed

+186
-57
lines changed

8 files changed

+186
-57
lines changed

content/common/navigation/engine/guides.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,10 @@ navigation:
448448
- title: Monitoring Performance
449449
path: /performance-optimization/monitoring
450450
- title: Cloud Services
451+
path: /cloud-services/data-stores-vs-memory-stores
451452
section:
453+
- title: Data Stores vs Memory Stores
454+
path: /cloud-services/data-stores-vs-memory-stores
452455
- title: Data Stores
453456
path: /cloud-services/data-stores/
454457
section:
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: Data Stores vs Memory Stores
3+
description: When to use standard data stores, ordered data stores, and memory stores.
4+
---
5+
6+
To store data, you can use [data stores](./data-stores/index.md) with the `Class.DataStoreService` or [memory stores](./memory-stores/index.md) with the `Class.MemoryStoreService`.
7+
8+
Alternatively, you can also use Lua types and variables to [store data in-memory in Lua](#when-to-use-in-memory-storage-in-lua), without using the data or memory store services.
9+
10+
## When to Use Data Stores
11+
12+
The `Class.DataStoreService` stores long-term data that needs to last between sessions, such as user progress or inventory items. Data stores are consistent per experience, so every server for every place within an experience can access and change the same data. There are two types of data stores: standard and ordered.
13+
14+
**Standard data stores** can store data like numbers, strings, and tables that don't need to be ranked or sorted. This data is stored as key-value pairs, where each entry is stored under a key that is unique within its data store and that you can retrieve, update, or delete.
15+
16+
**Ordered data stores** can only store numbers. Each entry is stored under a key that is unique within its data store and that you can retrieve, update, or delete. You can rank and sort this data numerically and retrieve it in ascending or descending order based on stored numerical values. For more information, see [Ordered Data Stores](./data-stores/index.md#ordered-data-stores).
17+
18+
<table>
19+
<thead>
20+
<td width="10%"></td>
21+
<td width="30%">**Standard data stores**</td>
22+
<td width="30%">**Ordered data stores**</td>
23+
</thead>
24+
<tbody>
25+
<tr>
26+
<td>**Data type**</td>
27+
<td>Numbers, strings, booleans, and tables.</td>
28+
<td>Only numbers.</td>
29+
</tr>
30+
<tr>
31+
<td>**Common use cases**</td>
32+
<td>User progress, inventory items, and experience settings.</td>
33+
<td>All-time, persistent ranking systems and leaderboards. Unlike leaderboards in memory stores, this leaderboard data is permanent.</td>
34+
</tr>
35+
<tr>
36+
<td>**Past version backup**</td>
37+
<td>Automatically manages previous versions of your data for 30 days.</td>
38+
<td>Does not manage previous versions of your data.</td>
39+
</tr>
40+
</tbody>
41+
</table>
42+
43+
<Alert severity="info">
44+
Data stores can only be accessed by server-side scripts.
45+
</Alert>
46+
47+
<Alert severity="info">
48+
If you want to add granular permission control to your data stores and access them outside of Studio or Roblox servers, you can use [Open Cloud APIs for data stores](/cloud/reference/DataStore).
49+
</Alert>
50+
51+
## When to Use Memory Stores
52+
53+
The `Class.MemoryStoreService` is a high throughput and low latency service that stores temporary data that needs to be updated or accessed frequently, such as global leaderboards or matchmaking queues. With memory stores, every server for every place within an experience can access and change the same data quickly and frequently. Data in a memory store expires after a certain period of time, lasting up to 45 days.
54+
55+
Although memory stores store temporary data, they also support permanent features like a global marketplace. The marketplace is permanent, but the items for sale inside it have an expiration date.
56+
57+
<table>
58+
<thead>
59+
<td width="15%"></td>
60+
<td width="50%">**Memory stores**</td>
61+
</thead>
62+
<tbody>
63+
<tr>
64+
<td>**Data type**</td>
65+
<td>Numbers, strings, booleans, and tables that don't need to persist for over 45 days.</td>
66+
</tr>
67+
<tr>
68+
<td>**Common use cases**</td>
69+
<td>Skill-based matchmaking, match states for multiplayer games, daily and monthly leaderboards.</td>
70+
</tr>
71+
</tbody>
72+
</table>
73+
74+
## When to Use In-Memory Storage in Lua
75+
76+
You can use in-memory storage in Lua to store temporary data that needs to be accessed with minimal latency and without the cost of making external service calls to data stores or memory stores. There are no extra steps required to set up in-memory storage as it's already built in by default in Lua.
77+
78+
<table>
79+
<thead>
80+
<td width="15%"></td>
81+
<td width="30%">**In-memory storage in Lua**</td>
82+
<td width="30%"></td>
83+
</thead>
84+
<tbody>
85+
<tr>
86+
<td>**Data type**</td>
87+
<td>Numbers, strings, booleans, and tables.</td>
88+
<td></td>
89+
</tr>
90+
<tr>
91+
<td>**Common use cases**</td>
92+
<td>Data that is only relevant to a single server session and that you can update instantly without worrying about persistence.</td>
93+
<td>Example: Active buffs, temporary points, and ongoing quest progress that resets when the user leaves the experience.</td>
94+
</tr>
95+
<tr>
96+
<td></td>
97+
<td>Values that change frequently, like counters, timers, or state flags.</td>
98+
<td>Example: A user's health bar that updates on each hit.</td>
99+
</tr>
100+
<tr>
101+
<td></td>
102+
<td>Avoiding rate limit restrictions for high-frequency operations in large active experiences.</td>
103+
<td>Example: An experience with dozens of users interacting with the same object.</td>
104+
</tr>
105+
<tr>
106+
<td></td>
107+
<td>Data that drives game logic, like temporary variables or power-up states where quick access with no delay is essential.</td>
108+
<td>Example: A user's current attack state or an enemy's current health, which needs to be accessible instantly and without the latency involved in calling external services like data or memory stores.</td>
109+
</tr>
110+
<tr>
111+
<td></td>
112+
<td>Multiplayer interactions that only matter within a single server.</td>
113+
<td>Example: A shared objective in a co-op mission experience.</td>
114+
</tr>
115+
</tbody>
116+
</table>

content/en-us/cloud-services/data-stores/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ The `Class.DataStoreService` lets you store data that needs to persist between s
88

99
If you want to add granular permission control to your data stores and access them outside of Studio or Roblox servers, you can use [Open Cloud APIs for data stores](/cloud/reference/DataStore).
1010

11+
For temporary data that you need to update or access frequently, use [memory stores](./../memory-stores/index.md).
12+
1113
## Enabling Studio Access
1214

1315
By default, experiences tested in Studio can't access data stores, so you must first enable them. Accessing data stores in Studio can be dangerous for live experiences because Studio accesses the same data stores as the client application. To avoid overwriting production data, do not enable this setting for live experiences. Instead, enable it for a separate test version of the experience.
@@ -198,7 +200,7 @@ end
198200
## Metadata
199201

200202
<Alert severity="info">
201-
Ordered data stores don't support [versioning and metadata](../../cloud-services/data-stores/managing-data-stores.md#versioning), so `Class.DataStoreKeyInfo|DataStoreKeyInfo` is always `nil` for keys in an `Class.OrderedDataStore|OrderedDataStore`. If you need to support versioning and metadata, use `Class.DataStore|DataStore`.
203+
Ordered data stores don't support [versioning](../../cloud-services/data-stores/managing-data-stores.md#versioning) and metadata, so `Class.DataStoreKeyInfo|DataStoreKeyInfo` is always `nil` for keys in an `Class.OrderedDataStore|OrderedDataStore`. If you need to support versioning and metadata, use `Class.DataStore|DataStore`.
202204
</Alert>
203205

204206
There are two types of metadata associated with keys:

content/en-us/cloud-services/data-stores/managing-data-stores.md

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Manage your data using versioning, listing, and caching.
77

88
## Versioning
99

10-
The functions `Class.GlobalDataStore:SetAsync()|SetAsync()`, `Class.GlobalDataStore:UpdateAsync()|UpdateAsync()`, and `Class.GlobalDataStore:IncrementAsync()|IncrementAsync()` create versioned backups of your data using the first write to each key in each UTC hour. Successive writes to a key in the same UTC hour permanently overwrite the previous data.
10+
Versioning happens when you [set](./index.md#creating-data), [update](./index.md#updating-data), and [increment](./index.md#incrementing-data) data. The functions `Class.GlobalDataStore:SetAsync()|SetAsync()`, `Class.GlobalDataStore:UpdateAsync()|UpdateAsync()`, and `Class.GlobalDataStore:IncrementAsync()|IncrementAsync()` create versioned backups of your data using the first write to each key in each UTC hour. Successive writes to a key in the same UTC hour permanently overwrite the previous data.
1111

1212
Versioned backups expire 30 days after a new write overwrites them. The latest version never expires.
1313

@@ -88,9 +88,7 @@ end
8888

8989
### Snapshots
9090

91-
The [Snapshot Data Stores Open Cloud API](/cloud/reference/DataStore#Snapshot-Data-Stores) lets you take a snapshot of all data stores in an experience once a day.
92-
93-
Before you publish any experience update that changes your data storage logic, make sure to take a snapshot. Taking a snapshot guarantees that you have the most recent data available from the previous version of the experience.
91+
The [Snapshot Data Stores Open Cloud API](/cloud/reference/DataStore#Snapshot-Data-Stores) lets you take a snapshot of all data stores in an experience once a day. Before you publish any experience update that changes your data storage logic, make sure to take a snapshot. Taking a snapshot guarantees that you have the most recent data available from the previous version of the experience.
9492

9593
For example, without a snapshot, if you publish an update at 3:30 UTC that causes data corruption, the corrupted data overwrites any data written between 3:00-3:30 UTC. If you take a snapshot at 3:29 UTC, though, the corrupted data doesn't overwrite anything written before 3:29 UTC, and the latest data for all keys written between 3:00-3:29 UTC is preserved.
9694

@@ -172,7 +170,7 @@ end)
172170

173171
### AllScopes Property
174172

175-
`Class.DataStoreOptions` contains an `Class.DataStoreOptions.AllScopes|AllScopes` property that lets you return keys from all [scopes](#scopes) in a list. You can then use the `Class.DataStoreKey.KeyName|KeyName` property of a list item for common data store operations like `Class.GlobalDataStore:GetAsync()|GetAsync()` and `Class.GlobalDataStore:RemoveAsync()|RemoveAsync()`.
173+
`Class.DataStoreOptions` contains an `Class.DataStoreOptions.AllScopes|AllScopes` property that lets you return keys from all [scopes](#scopes) in a list. You can then use the `Class.DataStoreKey.KeyName|KeyName` property of a list item for common data store operations like [reading data](./index.md#reading-data) with `Class.GlobalDataStore:GetAsync()|GetAsync()` and [removing data](./index.md#removing-data) with `Class.GlobalDataStore:RemoveAsync()|RemoveAsync()`.
176174

177175
When you use the `AllScopes` property, the second parameter of `Class.DataStoreService:GetDataStore()|GetDataStore()` must be an empty string (`""`).
178176

@@ -214,11 +212,11 @@ Use caching to temporarily store data from data stores to improve performance an
214212

215213
Caching applies to modifications you make to data store keys using:
216214

217-
- `Class.GlobalDataStore:GetAsync()|GetAsync()`
218-
- `Class.GlobalDataStore:SetAsync()|SetAsync()`
219-
- `Class.GlobalDataStore:UpdateAsync()|UpdateAsync()`
220-
- `Class.GlobalDataStore:IncrementAsync()|IncrementAsync()`
221-
- `Class.GlobalDataStore:RemoveAsync()|RemoveAsync()`
215+
- `Class.GlobalDataStore:GetAsync()|GetAsync()` to [read data](./index.md#reading-data).
216+
- `Class.GlobalDataStore:SetAsync()|SetAsync()` to [create data](./index.md#creating-data).
217+
- `Class.GlobalDataStore:UpdateAsync()|UpdateAsync()` to [update data](./index.md#updating-data).
218+
- `Class.GlobalDataStore:IncrementAsync()|IncrementAsync()` to [increment data](./index.md#incrementing-data).
219+
- `Class.GlobalDataStore:RemoveAsync()|RemoveAsync()` to [remove data](./index.md#removing-data).
222220

223221
`Class.DataStore:GetVersionAsync()|GetVersionAsync()`, `Class.DataStore:ListVersionsAsync()|ListVersionsAsync()`, `Class.DataStore:ListKeysAsync()|ListKeysAsync()`, and `Class.DataStoreService:ListDataStoresAsync()|ListDataStoresAsync()` don't implement caching and always fetch the latest data from the service backend.
224222

@@ -235,3 +233,30 @@ All `Class.GlobalDataStore:GetAsync()|GetAsync()` calls that retrieve a value no
235233
To disable caching and opt out of using the cache to retrieve the most up-to-date value from the servers, add the `Class.DataStoreGetOptions` parameter to your `Class.GlobalDataStore:GetAsync()|GetAsync()` call and set the `Class.DataStoreGetOptions.UseCache|UseCache` property to `false` to make your request ignore any keys in the cache.
236234

237235
Disabling caching is useful if you have multiple servers writing to a key with high frequency and need to get the latest value from servers. However, it can cause you to consume more of your [data stores limits and quotas](../../cloud-services/data-stores/error-codes-and-limits.md#limits), since `Class.GlobalDataStore:GetAsync()|GetAsync()` requests bypassing caching always count towards your throughput and server limits.
236+
237+
## Serialization
238+
239+
The `Class.DataStoreService` stores data in JSON format. When you save Lua data in Studio, Roblox uses a process called serialization to convert that data into JSON to save it in data stores. Roblox then converts your data back to Lua and returns it to you in another process called deserialization.
240+
241+
Serialization and deserialization support the following Lua data types:
242+
243+
- [Nil](../../luau/nil.md)
244+
- [Booleans](../../luau/booleans.md)
245+
- [Numbers](../../luau/numbers.md)
246+
- You should not store the special numeric values `inf`, `-inf`, and `nan`, because these values don't conform to JSON standards. You can't access keys that contain these values with Open Cloud.
247+
- [Strings](../../luau/strings.md)
248+
- [Tables](../../luau/tables.md)
249+
- Tables must only contain other supported data types
250+
- Numeric keys are translated into strings if the length of the table is 0
251+
- [Buffers](../../reference/engine/libraries/buffer.yaml)
252+
253+
If you try to store a data type that serialization doesn't support, you either:
254+
255+
- Fail in storing that data type and get an error message.
256+
- Succeed in storing that data type as `nil`.
257+
258+
To debug why your data type is being stored as `nil`, you can use the `Class.HttpService.JSONEncode|JSONEncode` function. When you pass your Lua data type into this function, you receive it back in the format Roblox would have stored it with data stores, which lets you preview and investigate the returned data.
259+
260+
<Alert severity="info">
261+
Serialization doesn't happen when you use the [DataStore Open Cloud API](/cloud/reference/DataStore) because that data is already sent to Roblox in JSON format and doesn't need to be converted.
262+
</Alert>

content/en-us/production/promotion/referral-system.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ As a developer, you can use these shareable referral links to:
1616
- Create and distribute rewards to both inviters and invitees.
1717

1818
<img src="../../assets/promotion/referral-system/Invite-Friends.png" width="90%" />
19+
<sup>The **Invite Friends** pop-up and **Friend Referral Rewards** banner will become available in early 2025.</sup>
20+
<br/><br/>
1921

2022
To implement a friend referral system, [set up a referral event](#set-up-a-referral-event) and [create referral rewards](#grant-referral-rewards). The `ReferredByPlayerId` property of `Class.Player:GetJoinData()|GetJoinData()` automatically populates for all types of invitations and gives you access to the user ID of the referring player. You can then access this data in the `Players.PlayerAdded` event to identify the inviter and grant rewards to the inviter and the invitee.
2123

content/en-us/reference/engine/classes/AudioPlayer.yaml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,17 @@ methods:
392392
writeCapabilities: []
393393
events:
394394
- name: AudioPlayer.Ended
395-
summary: ''
396-
description: ''
395+
summary: |
396+
Fires when the `Class.AudioPlayer` has completed playback and stopped.
397+
description: |
398+
Fires after the `Class.AudioPlayer` has completed playback and stopped. Note this
399+
event will **not** fire for audio with `Class.AudioPlayer.Looped|Looped` set to `true`
400+
since it continues playing upon reaching its end. This event will also **not** fire when
401+
the audio is stopped before playback has completed; for this, use
402+
`Class.AudioPlayer:GetPropertyChangedSignal()` on the
403+
`Class.AudioPlayer.IsPlaying|IsPlaying` property.
404+
405+
This event is often used to destroy an `Class.AudioPlayer` when it has completed playback.
397406
code_samples: []
398407
parameters: []
399408
tags: []
@@ -403,8 +412,16 @@ events:
403412
capabilities: []
404413
writeCapabilities: []
405414
- name: AudioPlayer.Looped
406-
summary: ''
407-
description: ''
415+
summary: |
416+
Fires when the `Class.AudioPlayer` loops.
417+
description: |
418+
Event that fires after the `Class.AudioPlayer` loops. This happens when the
419+
audio reaches the end of its content (or the end of the
420+
`Class.AudioPlayer.LoopRegion|LoopRegion` if it is active)
421+
and `Class.AudioPlayer.Looping|Looping` is `true`.
422+
423+
This event does **not** fire if the audio is looped manually by changing its
424+
`Class.AudioPlayer.TimePosition|TimePosition`.
408425
code_samples: []
409426
parameters: []
410427
tags: []

content/en-us/reference/engine/classes/EditableImage.yaml

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,11 @@ description: |
88
`Class.EditableImage` allows for the runtime creation and manipulation of
99
images.
1010
11-
To create a blank `Class.EditableImage`, use `Datatype.Instance.new()`. To
11+
To create a blank `Class.EditableImage`, use `Class.AssetService:CreateEditableImage()`. To
1212
create an `Class.EditableImage` from an existing image, use
1313
`Class.AssetService:CreateEditableImageAsync()`.
1414
15-
`Class.EditableImage` overrides the image or texture displayed when parented
16-
to certain objects:
17-
18-
<table size="small">
19-
<thead>
20-
<tr>
21-
<th>Object</th>
22-
<th>Overridden</th>
23-
</tr>
24-
</thead>
25-
<tbody>
26-
<tr>
27-
<td><code>Class.MeshPart</code></td>
28-
<td><code>Class.MeshPart.TextureID</code></td>
29-
</tr>
30-
<tr>
31-
<td><code>Class.ImageLabel</code></td>
32-
<td><code>Class.ImageLabel.Image</code></td>
33-
</tr>
34-
<tr>
35-
<td><code>Class.ImageButton</code></td>
36-
<td><code>Class.ImageButton.Image</code></td>
37-
</tr>
38-
<tr>
39-
<td><code>Class.Decal</code></td>
40-
<td><code>Class.Decal.Texture</code></td>
41-
</tr>
42-
<tr>
43-
<td><code>Class.Texture</code></td>
44-
<td><code>Class.Texture.Texture</code></td>
45-
</tr>
46-
<tr>
47-
<td><code>Class.SurfaceAppearance</code></td>
48-
<td><code>Class.SurfaceAppearance.ColorMap</code></td>
49-
</tr>
50-
</tbody>
51-
</table>
15+
`Class.EditableImage` can be used in any `Datatype.Content` property which takes an image, such as `Class.ImageLabel.ImageContent` or `Class.MeshPart.TextureContent`. This is done by setting the content property to `Datatype.Content.fromObject(editableImage)`.
5216
5317
The `Class.EditableImage` coordinate system is relative to the top left of the
5418
image:
@@ -57,8 +21,8 @@ description: |
5721
- Bottom-right: `(Size.X - 1, Size.Y - 1)`
5822
5923
When you use `Class.AssetService:PromptCreateAssetAsync()` to publish an
60-
object that has a property overridden by a child `Class.EditableImage`, the
61-
editable image is published as an image and the overridden property is set to
24+
object that has a `Datatype.Content` property which references an `Class.EditableImage`, the
25+
editable image is published as an image and the property is set to
6226
a new asset ID.
6327
code_samples: []
6428
inherits:

0 commit comments

Comments
 (0)