Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Do tables carry their metatables to DataStores?

Asked by
funyun 958 Moderation Voter
8 years ago

I'm trying to create a messenger GUI that uses DataStores to get data across servers. I'm currently working on actually creating the DataStore, as well as giving it a bit more functionality, like giving it a key index and a way to monitor what happens to it.

datastore = game:GetService("DataStoreService"):GetDataStore("MessengerData")

Info log:

infolog = datastore:GetAsync("INFO_LOG")

if infolog == nil then
    infolog = {}
    setmetatable(infolog, {
        __newindex = function(self, key, value)
            rawset(self, key, value)
            datastore:SetAsync("INFO_LOG", self)
        end
    })
    datastore:SetAsync("INFO_LOG", infolog)
end

Key index:

index = datastore:GetAsync("KEY_INDEX")

if index == nil then
    print("Initializing MessengerData KEY_INDEX for the first time...")
    index = {}
    setmetatable(index, {
        __newindex = function(self, key, value)
            rawset(self, key, value)
            datastore:SetAsync("KEY_INDEX", self)
        end
    })
    datastore:SetAsync("KEY_INDEX", index)
    print("Initialized.")
    table.insert(infolog, "Initialized KEY_INDEX at "..os.time())
end

And then I could just iterate over INFO_LOG to see what's been going on, and KEY_INDEX to see who's in the DataStore. I put a metatable on the index and the info log because I figured that every time I appended to those tables, I'd save them to their DataStore keys. Since I've saved a table with a metatable to the DataStore, would this shortcut apply to other scripts like this?

datastore = game:GetService("DataStoreService"):GetDataStore("MessengerData")
index = datastore:GetAsync("KEY_INDEX")
index.Bob = true
--Assuming the metatable is still there, I wouldn't have to put the SetAsync line here, right?

1 answer

Log in to vote
4
Answered by 8 years ago

Actually, no, they don't. However, we always have the alternative of making some kind of custom "GetAsync" method, that returns an invoked table with a new setmetatable. Here's an example:

-- Get the data store service
local MyDataStore = game:GetService("DataStoreService"):GetDataStore("Metatables")

-- Set "MyTable" to an empty table
MyDataStore:SetAsync("MyTable",{})

-- Make a blank table we can use to get modified information from
local DataUtility = {}

-- The metatable we return to a table with our new GetAsync fucntion
local Metatable = {
    __index = function(tab, key)
        print('Could not find: '..key..' in table: '..tostring(tab))
        return 'Not found'
    end
}

-- Make a custom GetAsync especially for tables and metatables
function DataUtility:GetMetaAsync(Datastore, Key)

    -- Use regular GetAsync to see if our request exists...
    local Past = Datastore:GetAsync(Key)

    -- If it does, and it's a table, then...
    if Past and type(Past) == 'table' then

        -- Return the table, while also giving it the assigned metatable.
        return setmetatable(Past,Metatable)

    else

        -- If the old key isn't found, do this..
        print(tostring(Key)..' was not found, or is not a table.')
    end
end

-- Print the result using our new function, and index it for "Testing" (which will obviously be nil)

print(DataUtility:GetMetaAsync(MyDataStore, "MyTable").Testing)

-- This should print "Not found", because that's what our index metamethod returns.

Didn't mean to reply to this question with just a script, i tried explaining as much as possible as i went. But you seem like you know enough to know what's going on anyway, so i hope this helped.

Ad

Answer this question