Currently I have a datastore which saves various tables of data.
To improve my game, I need to add metatables to these tables, which will be saved.
I just wanted to check: Will the metatables save alongside the tables, and can I retrieve them normally (i.e. getmetatable(table)) when loading the datastore?
Here is some code you can run to test whether metatables will persist:
local dataStore = game:GetService("DataStoreService"):GetDataStore("TestDataStore")
local t = setmetatable({}, {})
local key = "test"
dataStore:SetAsync(key, t)
print(getmetatable(dataStore:GetAsync(key)))
The answer is no, metatables do not save to data stores.
Basically, translate (serialize) your class instances into something that can be stored in the datastore when you’re about to save them. Later on, you can retrieve the serialized instance and translate it back (deserialize) into a carbon-copy of the original instance.
(if you’re wondering what CAN be saved into datastores: DataStores can only save arrays (a sequential table, starting at index 1), dictionaries with string keys*, booleans, numbers, and strings.)
* I’m not sure if boolean keys work. Probably not.
You can create a table which maps a string “type” to a metatable, and then when you write something to the data store, you can look up its metatable in that map and then assign it the right “type” string. Then, when you load from the data store, you can check the “type” string and assign a metatable based on the map.
For example:
local Foo = {}
Foo.__index = Foo
function Foo.new()
return setmetatable({}, Foo)
end
local Bar = {}
Bar.__index = Bar
function Bar.new()
return setmetatable({}, Bar)
end
local typeMap = {
Foo = Foo,
Bar = Bar,
}
function makeReadyToSave(object)
for k,v in pairs(typeMap) do
if v == getmetatable(object) then
object.type = k
return
end
end
error("Unknown metatable")
end
function loadFromSave(object)
setmetatable(object, typeMap[object.type])
return object
end