Persistence
Guide on how to script persistence in Sinespace
The Sinespace API has a range of API functions that enable us to create different types of persistence. As scripters, we have to choose the type which is more suitable for the task at hand, or even mix and match. In this guide we will go through all the the different classes and functions and explain how to use them.
Reference
These two tables briefly explains the difference between the different types of classes and members that have persistence functionality, and we will expand even more after that.
Semi-permanent Region Semi-permanent Region Semi-permanent Shard Semi-permanent Shard Semi-permanent Shard/Region
Permanent Player Permanent Player Permanent Player Permanent Region Permanent Region Permanent Region
Semi-permanent Viewer Semi-permanent Viewer
Permanent Player Permanent Player Permanent Region Permanent Region
Semi-permanent Region
Persistence will last until Region is closed (after all players leave the Region).
Persistence applied region-wide (including all shards, if any are active).
Semi-permanent Shard
Persistence will last until Shard is closed (after all players leave the Shard).
Persistence applied only to a specific Shard.
Semi-permanent Viewer
Persistence will last until Viewer is closed. Persistence applied to the Viewer.
Permanent Player
Persistence will last permanently. Persistence applied to specific Player.
Permanent Region
Persistence will last permanently. Persistence applied to Region.
What is persistence?
Sending Network Messages is cool for one off events, for example: a player waving Hello, which is relevant for only a few seconds. However, sometimes we want to make changes that are relevant for more than just a few seconds, for example: a window being opened. If we send a Network Message to broadcast to all players that Window A is now open, when a new player enters our region, they would have missed that Network Message, and Window A would still be closed for them in their viewer. This is why we need the ability to make certain changes to the scene Persist, either permanently or at least until everyone's left the region.
SNetwork class
The SNetwork class has a variety of networking functions but has 4 functions and 1 property which are related to persistence.
SetRegionProperty/GetRegionProperty
SetShardProperty/GetShardProperty
HasShardProperties
Shard Vs Region
You'll notice some functions apply to Shards and some to Regions. What are "shards" anyways?
A Shard is a feature in Sinespace where one Region can have multiple Shards (instances), very much like parallel universes, where players on one Shard cannot see players on another Shard.
For the purpose of this beginner guide, we won't go into scripting multi-Shard experiences, but it's enough to understand the differences.
What are Shard/Region properties?
For every Shard/Region that is open (there's players inside), there's a semi-permanent storage created on the server that holds properties. All scripts using these functions will access this same storage to read and write properties. This storage is a collection of keys and values. This storage will close after the Shard/Region is closed (after all players leave).
What "key" should you use?
You mostly want your key to be a private one, so other scripts cannot access it. You are also most likely to want your key to be specific to a GameObject.
We can achieve both of the above in this way:
Now we've created a key which both private and specific to a GameObject. We will use it later to access the properties storage and read/write a specific value.
HasShardProperties
When a player joins the region, scripts that want to immediately access the properties database might fire off during a very tiny period where we haven't yet connected to the properties storage. This is why use HasShardProperties to check if the storage database is connected and ready for read/write. (HasShardProperties is used for both Shard properties and Region properties)
Let's expand our previous code by adding a coroutine (run our code in a parallel thread) to take care of this:
Setting and Getting properties
Shard properties and Region properties are executed in the exact same way. So for the purpose of this guide we will continue using Region properties only.
Note: The below to functions are usage limited to 10 calls per second. (20 calls per second on Breakroom)
To get a Region property: value = Space.Network.GetRegionProperty(KEY)
Note: Sometimes a Region property may have not been set before, so it might return Nil. We'll have to add a check for that.
To set a Region property: Space.Network.SetRegionProperty(KEY, 'A Value')
Note: Region property values are a string datatype, so you'll have to convert your numbers or tables to a string to store them.
The window example
Let's write a script for a window which when clicked opens/closes and updates it's Region property, and also keeps reading the Region property incase another player opens/closes the window.
We are going to add to our script two main parts. First part is constantly reading the Region property to monitor and react to changes. Second part reacts to clicks and updates the Region property which holds the state of the window (open/close).
The First Part
The Second Part (and final code)
SShared class
The SShared class (client scripting) has a variety of inter-script communication functions and local viewer storage functions but has 2 functions which are related to persistence.
SetSuperGlobal
GetSuperGlobal
What is a Super Global?
A "Global" in the SShared class is a storage within the local player's viewer accessible to all scripts.
A "Super Global" is the same storage but semi-permanent; it will keep existing even when changing regions, until the viewer is closed.
For this example, we will creator a clickable object that teleports us to a region, and on that region we will have a script that reacts depending where we came from.
What "namespace" and "key" should you use?
Unlike our previous case, these functions are storing on a specific player's viewer, and they could be meant to be accessed by multiple scripts (could be our other scripts or other scripters' scripts too). It's inherently specific to a player, and likely to a specific project or operation/objective.
That's why it's accessed using a namespace, key and value, vs just key and value. The namespace could be a type of accessor which doesn't have to be private, while still having a key accessor that we can make private.
Setting and Getting Super Globals
When Setting a Super Global, the value need not be a string. It accepts a value of type DynValue, which means it can be a string, number or table etc...
We set a Super Global like this:
Space.Shared.SetSuperGlobal('namespace', 'key', AVariable)
We get a Super Global like this:
value = Space.Shared.GetSuperGlobal('namespace','key')
The teleporter example
We will create 2 scripts for this example. The first script will be the one teleporting us an Setting a Super Global, and the second one will be at the destination and will access our Super Global and react to where we teleported from.
We will start creating our first script by expanding on our code above by adding a clickable and make it Set a Super Global with the information we need to carry on to the second region. For the purpose of this guide we will pass our information in a Table rather than a single variable.
Now we have an object, that when clicked, Sets a Super Global and then teleports us. On the destination region we will now create the script that processes our carried over information (regiond name and ID).
SPersistence Class
The SPersistence class has 6 functions that are all used for creating permanent persistence.
UpdateInfo/UpdateRegionInfo
RetrieveValue/RetrieveRegionValue
SetValue/SetRegionValue
What are Region Values and Values?
Half the functions in this class create Permanent Region persistence, and the other half create Permanent Player persistence.
If the function has the word region in it, that means it creates Region persistence. If it does not, that means it creates Player persistence.
Region/Player values are values in a permanent storage. Region values are in a permanent storage which is linked to the region, and (Player) Values are in a permanent storage linked to the player running the script.
In terms of usage, Region Values are the equivalent to the permanent version of the SNetwork class. Whereas Player values are the equivalent to the SShared class.
What "key" should you use?
In the case of Region values we will be creating keys in the same way as we did for the SNetwork class.
In the case of (Player) values we will be creating keys in the same way as we did for the SShared class.
Why do we need to "Update Region Info"?
The unique feature of this class is that it is a client scripting class, but gives us the ability to create persistence without the use of a server script.
The storage used to achieve this is an external one, which means we have to start with using the UpdateRegionInfo() function to request the storage to send us a copy of it's most recent values (before trying to access these values).
We do it this way:
Unlike semi-permanent region properties, this function call is not as instant. Because it accesses an external permanent storage, we need to hook a function which will be called once the info has arrived.
The slower or variable response speed of this functionality means that it's not recommended to be called rapidly like we did with SNetwork region properties. Therefore we might have to mix and match our code with other types of persistence.
Smart Lights Example
Visit our Smart Lights sample project page.
SDatabase Class
The SDatabase class is the equivalent of the SPersistence class but the only difference being that it is accessed only through Server Scripts. Server scripts do not have access to the SPersistence class.
A server script is also inherently semi-persistent. That means if you do this aVariable = 5
in a server script. This variable will be persistent until all players leave the region. This makes the usage of the SDatabase class much easier than the SPersistent class due to not having to mix and match persistent methods.
A downside to server scripts is that they can only be placed in furniture items and need to be loaded on a region to be used (unlike client scripts).
Since this class is almost an exact copy of the SPersistence class. We will only be outlining the differences below (to avoid being repetitive).
Differences between SDatabase and SPersistence
The only two small differences between these to classes are:
Functions SetValue/GetValue in SPersistence, are SetPlayerValue/GetPlayerValue in SDatabase
GetRegionValue and GetPlayerValue have an extra onSave parameter which is a hook that lets us know when the value as been successfully set.
Thank You
Thanks for completing this guide. If you run into any issues or would like to recommend improvements, please do so on this page.
Last updated