You can write your topic however you want, but you need to answer these questions:
What do you want to achieve? I’m working a moderation system for my game and I want to log all the moderation actions so my moderation team can check previous actions taken on a User like warns, kicks and bans.
What is the issue? If I save a warning to the datastore and there’s already a existing one then it just replaces the old one.
What solutions have you tried so far? I havent tried a lot because I have no idea how DataStore works.
This is the code I made:
local HS = game:GetService("HttpService")
local DS = game:GetService("DataStoreService"):GetDataStore("DS_modLog2")
local Event = game:GetService("ReplicatedStorage"):FindFirstChild("ExecuteMod")
Event.OnServerEvent:Connect(function(plr, Type, Reason, Username, UserId, Time)
if plr:GetRankInGroup(123456) >= 50 then
local key = "Log_"..UserId
if Type == "Type: Warn" then
local Data = {
"Warn",
plr.Name,
plr.UserId,
Reason,
DateTime.now()
} local String = HS:JSONEncode(Data)
local Success, Failure = pcall(function()
DS:SetAsync(key, String)
end)
if Success then
warn("Success")
else
warn("Fail")
end
end
end
end)
You don’t need to JSONEncode the table. As long as it only contains numbers, strings, and/or booleans (which is all the DataStore accepts anyway), it will save just fine.
You can add to a table of the player’s warnings, bans, kicks, etc.
Get the already existing one
add another one
so you could end up with something like:
local playerMod = {
[1] = {
--player's first warning data
},
[2] = {
--player's second warning data
}
}
If I don’t JSONEncode the table it gives me this error: DataStoreService: CantStoreValue: Cannot store Array in data store. Data stores can only accept valid UTF-8 characters. API: SetAsync, Data Store: DS_modLog2
Also can you tell me how I would check the datastore if there’s a already existing one so I could place a [1] or [2] after it so it doesnt replace it?
I believe the issue is that you’re trying to store DateTime.now() which is a DateTime (userdata) type. Instead you should try saving “DateTime.now().UnixTimestampMillis” which is a number type.
Like @MuPower said, you need to save it as a number. You could also try os.date(), but I don’t know if that’s a number or not. You could also try paring it with tostring(), or have a go experimenting with os.time().
In terms of checking for a warning already, whenever you make the warning, try this:
local playerMod
local success, err = pcall(function()
playerMod = yourStore:GetAsync(key)
end)
if playerMod == nil then --first time
playerMod = {
[1] = { --set it as the first one
--your warning here
}
}
else --not first time
local alreadyExisting = #playerMod --get already existing warnings
local newIndex = alreadyExisting + 1 --create a new warning with the index after the existing ones
playerMod[newIndex] = { --write the warning in
--your warning here
}
end
--then, save it back to the store:
local success, err = pcall(function()
yourStore:SetAsync(key, playerMod)
end)
Firstly to store multiple data in a DataStore you can use scopes.
local DataStore1 = DataStoreService:GetDataStore("DataStore", "Scope1")
local DataStore2 = DataStoreService:GetDataStore("DataStore", "Scope2")
Also you cannot store tables as values, you have to convert them to string using tostring() then assign as value.
To use them as table after you have to split the curly brackets then trim the whitespace. And convert it to a table splitting with commas (,).
To set a value to the latest index you can use table.insert() method. This will bind the data to latest index, if the table is empty then it will assign it to index of 1.
Oops! Kinda forgot about table.insert(). As for scopes, I don’t often use the other parts of the DataStore so I don’t really use them.
As for storing tables as values, I don’t really get what you’re trying to say, but I know that tables/dictionaries consisting of numbers, strings, and booleans can be saved.
I mean you can’t set a table instance as a value of DataStore. If you don’t understand what I mean by value then the output you get when you use DataStore:GetAsync() is the value, or you can call it data.
But if you still want to store a table inside a DataStore then you should use custom functions to serialize and deserialize.
Serialize is basically converting it to string and you can use built-in method
tostring({Value1, Value2, Value3})
will return below but as a string, so it won’t be a table anymore
{Value1, Value2, Value3}
Deserialize is basically converting string to table.
local function StringToTable(StringToConvert)
local OutputTable = {}
--Remote first curly bracket
StringToConvert = StringToConvert:sub(2, #StringToConvert)
--Remove last curly bracket
StringToConvert = StringToConvert:sub(1, #StringToConvert - 1)
--Trim whitespaces
StringToConvert = StringToConvert:gsub("%s+", "")
--Convert to table
for Value in string.gmatch(StringToConvert, "[^,]+") do
table.insert(OutputTable, Value)
end
return OutputTable
end
The function above works perfectly but it only can convert basic tables, so if your table will contain table values then it won’t work properly.
I know you can’t save a table of instances. You can save a table of booleans, strings, and numbers perfectly fine, so I don’t see the point in converting it to a string?