When I try and save a table (encoded into a json format) through SetAsync, it provides me with this error:
"ServerScriptService.InventoryService.main:59: attempt to index number with 'SetAsync' - Server"
I have encoded the table with HTTP:JSONEncode() and I decode it when its read again.
heres an example of the table:
{
["A"] = {
["x"] = 98,
["y"] = "xyz",
["z"] = 15
},
["B"] = {
["c"] = "XYZ",
["d"] = 0, 0, 0,
["e"] = "22",
["f"] = "xyz"
}
}
Here is the Sample code
local Datastore = game:GetService("DataStoreService")
local RunService = game:GetService('RunService')
local HTTP = game:GetService('HttpService')
local item_data = Datastore:GetDataStore("Items")
local function save(Player:Player)
local item_data = {} --contains data created by the user
local savedata = {}
--PLAYER_DATA--
if savedata[Player] == "ERR" then return end
local suc, err = pcall(function()
player_data:SetAsync(Player.UserId, savedata)
end)
if err then
warn("Unable to save data for"..Player.Name,err)
end
--ITEM_DATA--
if item_data[Player] == "ERR" then return end
local suc, err = pcall(function()
local item_json = HTTP:JSONEncode(item_data)
itemdata:SetAsync(Player.UserId,item_json)
end)
if err then
warn("Unable to save data for "..Player.Name,err)
end
end
game.Players.PlayerAdded:Connect(function(Player)
local suc, err = pcall(function()
data = player_data:GetAsync(Player.UserId) or "0"
itemdata = HTTP:JSONDecode(item_data:GetAsync(Player.UserId) or "0")
itemdata = HTTP:JSONDecode(itemdata)
end)
if suc then
savedata[Player] = data
else
savedata[Player] = "ERR"
warn("Error fetching "..Player.Name.."'s data.",err)
end
end)
game.Players.PlayerRemoving:Connect(function(Player)
save(Player)
end)
game:BindToClose(function() -- (only needed inside Studio)
print('BindToClose')
if RunService:IsStudio() then -- (only needed inside Studio)
wait(3) -- this will force the "SetAsync" above to complete
end
end)
Thanks in advance, any help is really appreciated!
itemdata = HTTP:JSONDecode(item_data:GetAsync(Player.UserId) or "0")
itemdata = HTTP:JSONDecode(itemdata)
Not sure why you decode it twice here but take a look at or "0". That means itemdata might end up as 0
itemdata:SetAsync(Player.UserId,item_json)
And here you try to call it. That's why it complains about calling a number.
I assume you meant to use item_data, which is a DataStore. Please use more descriptive names here to avoid such confusion :)
Related
I have tried to fix this script, but i cannot.
It is the primary script which maintains most server side stuff.
I tried to make an DataStore handler, but it returns nil.
Code:
local rep = game:GetService("ReplicatedStorage")
local DrawingData = game:GetService("DataStoreService"):GetDataStore("DrawingData")
rep.SendToRandom.OnServerEvent:Connect(function(plr,data)
end)
rep.LoadFromDatastore.OnServerInvoke = function(plr,...)
local success,gotten =pcall(DrawingData.SetAsync,DrawingData,...)
if not success then
gotten = {}
warn("Failure with DataStore get, replacing with placeholder.")
end
return gotten
end
rep.SaveToDatastore.OnServerInvoke =function(plr,data:string)
local a = {DrawingData:GetAsync("GM")}
local gotten = tonumber(a[1])
DrawingData:SetAsync(tostring(gotten + 1),data)
DrawingData:SetAsync("GM",tostring(gotten + 1))
return gotten + 1
end
Output:
Failure with DataStore get, replacing with placeholder.
Saving works, and loading should work.
But, loading doesn't.
Looks like you're using SetAsync and GetAsync without actual UserId to store it to, you should save and load the data to a UserId unless the data is meant to be accessed by everyone (which I do NOT recommend).
From what I can tell you are trying to save data for individual players, but you are storing their data or their data I suppose to a singular DataStore, which will only make it more difficult for the game to load once it is prompted to load again.
Here is what I wrote based on what I believe you are trying to accomplish
local rep = game:GetService("ReplicatedStorage")
local DrawingData = game:GetService("DataStoreService"):GetDataStore("DrawingData")
rep.LoadFromDatastore.OnServerInvoke = function(plr,...)
local success, response = pcall(function(...)
return DrawingData:SetAsync(plr.UserId, ...)
end, ...)
if success ~= true or type(response) ~= "table" or table.getn(response) == 0 then
return {}, type(response) == "string" and warn(response)
end
return response
end
rep.SaveToDatastore.OnServerInvoke =function(plr, data)
local success, response = pcall(function()
return DrawingData:GetAsync(plr.UserId)
end)
if success ~= true or type(response) ~= "table" or table.getn(response) == 0 then
response = {}
end
table.insert(response, data)
local success, response
while success ~= true do
success, response = pcall(function()
return DrawingData:SetAsync(plr.UserId, response)
end)
if success ~= true then
warn(response)
end
end
end
I've been trying to figure out how to fix this error but I've had no luck, is there any way to get rid of the error?
Me and a friend are working on a game and this is the script I've put in serverscriptservice. I'm trying to help with scripting but the script refuses to work. Any help please?
local DataStoreService = game:GetService("DataStoreService")
local WinsDataStore = DataStoreService:GetOrderedDataStore("WinsRathersCamel")
local function Update()
local success, errormessage = pcall(function()
local Data = WinsDataStore:GetSortedAsync(false, 5)
local WinsPage = Data:GetCurrentPage()
for rank, data in pairs(WinsPage) do
local Username = game.Players:GetNameFromUserIdAsync(tonumber(data.key))
local Name = Username
local Wins = data.value
local isonleaderboard = false
for i, v in pairs(game.Workspace["Total Wins"].Leaderboard.Holder:GetChildren()) do
if v.Player.Text == Name then
isonleaderboard = true
break
end
end
if Wins and isonleaderboard == false then
local newlibframe = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone()
newlibframe.Player.Text = Name
newlibframe.Wins = Wins
newlibframe.Rank = "#"..rank
newlibframe.Position = UDim2.new(0, 0, newlibframe.Position.Y.Scale + (.08 * #game.Workspace["Total Wins"].Leaderboard.Holder:GetChildren()), 0)
newlibframe.Parent = game.Workspace["Total Wins"].Leaderboard.Holder
end
end
end)
if not success then
print(errormessage)
end
end
while true do
for _, player in pairs(game.Players:GetPlayers()) do
WinsDataStore:SetAsync(player.UserId.."-Wins",player.leaderstats.Wins.Value)
end
for _, frame in pairs(game.Workspace["Total Wins"].Leaderboard.Holder:GetChildren()) do
frame:Destroy()
end
Update()
print("Updated")
end
i get this error at line 94 and i dont really know how to fix this error. if someone could help fix this error it would really help me.
-- a basic market implementation
local lang = vRP.lang
local cfg = module("cfg/markets")
local market_types = cfg.market_types
local markets = cfg.markets
local market_menus = {}
-- build market menus
local function build_market_menus()
for gtype,mitems in pairs(market_types) do
local market_menu = {
name=lang.market.title({gtype}),
css={top = "75px", header_color="rgba(0,255,125,0.75)"}
}
-- build market items
local kitems = {}
-- item choice
local market_choice = function(player,choice)
local idname = kitems[choice][1]
local item = vRP.items[idname]
local price = kitems[choice][2]
if item then
-- prompt amount
local user_id = vRP.getUserId(player)
if user_id ~= nil then
vRP.prompt(player,lang.market.prompt({item.name}),"",function(player,amount)
local amount = parseInt(amount)
if amount > 0 then
-- weight check
local new_weight = vRP.getInventoryWeight(user_id)+item.weight*amount
if new_weight <= vRP.getInventoryMaxWeight(user_id) then
-- payment
if vRP.tryFullPayment(user_id,amount*price) then
vRP.giveInventoryItem(user_id,idname,amount,true)
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.paid({amount*price})}, type = "success", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.not_enough()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.inventory.full()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.common.invalid_value()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
end)
end
end
end
-- add item options
for k,v in pairs(mitems) do
local item = vRP.items[k]
if item then
kitems[item.name] = {k,math.max(v,0)} -- idname/price
market_menu[item.name] = {market_choice,lang.market.info({v,item.description.. "\n\n" ..item.weight.. " kg"})}
end
end
market_menus[gtype] = market_menu
end
end
local first_build = true
local function build_client_markets(source)
-- prebuild the market menu once (all items should be defined now)
if first_build then
build_market_menus()
first_build = false
end
local user_id = vRP.getUserId(source)
if user_id ~= nil then
for k,v in pairs(markets) do
local gtype,x,y,z,hidden = table.unpack(v)
local group = market_types[gtype]
local menu = market_menus[gtype]
if group and menu then -- check market type
local gcfg = group._config
local function market_enter()
local user_id = vRP.getUserId(source)
if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
vRP.openMenu(source,menu)
end
end
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:close()
local function adminz_open()
TriggerClientEvent("chatMessage", source, "Min bror " .. gudsp)
end
local function market_leave()
vRP.closeMenu(source)
end
if hidden == true then
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
else
vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.market.title({gtype})})
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
end
vRP.setArea(source,"vRP:adminz",153.53675842285,-255.70140075684,51.399478912354,1,1.5,adminz_open,market_leave)
end
end
end
end
AddEventHandler("vRP:playerSpawn",function(user_id, source, first_spawn)
if first_spawn then
build_client_markets(source)
end
end)
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:read() is syntactic sugar for gudz["read"](gudz).
gudz["read"] is an indexing operation. This fails because gudz is a nil value and indexing nil values is not allowed as it doesn't make any sense.
That's like referring to a book page of a book that does not exist. You won't be able to read that page anyway.
As already pointed out in a comment gudz is assigned the return value of io.open( "vfs-core.txt", "r" ) which in this case is nil.
So let's refer to the Lua Reference Manual may its wisdom enlighten us.
io.open (filename [, mode])
This function opens a file, in the mode specified in the string mode.
In case of success, it returns a new file handle.
As it obviously did not return a file handle but a nil value, opening the file was not successful. So check path and file.
I'm getting this Error when my Leaderboard tries to update.
502: API Services rejected request with error. Invalid value format for datastore type Sorted.
Parameter name: value
This is the script:
local CoinsDS = game:GetService("DataStoreService"):GetOrderedDataStore("MoneyLeaderboard")
local suffixes = {'','K','M','B','T','qd','Qn','sx','Sp','O','N','de','Ud','DD','tdD','qdD','QnD','sxD','SpD','OcD','NvD','Vgn','UVg','DVg','TVg','qtV','QnV','SeV','SPG','OVG','NVG','TGN','UTG','DTG','tsTG','qtTG','QnTG','ssTG','SpTG','OcTG','NoAG','UnAG','DuAG','TeAG','QdAG','QnAG','SxAG','SpAG','OcAG','NvAG','CT'}
local function format(val)
for i=1, #suffixes do
if tonumber(val) < 10^(i*3) then
return math.floor(val/((10^((i-1)*3))/100))/(100)..suffixes[i]
end
end
end
while true do
for _,Player in pairs(game.Players:GetPlayers()) do
local Leaderstats = Player:FindFirstChild("leaderstats")
if Leaderstats then
local coins = Leaderstats:FindFirstChild("CloudCoins")
if coins then
CoinsDS:SetAsync(Player.UserId, coins.Value)
end
end
end
local boards = workspace:WaitForChild("LeaderboardStuff")
local sellected = boards:WaitForChild("ViewCoins")
local Count = boards:WaitForChild("CountCoins")
local Info = Count:WaitForChild("Info")
for i,v in pairs(sellected:WaitForChild("GUI"):GetChildren()) do
v:Destroy()
end
for _,v in pairs(boards:WaitForChild("TopCoins"):GetChildren()) do
v:Destroy()
end
local Success, Err = pcall(function()
local Data = CoinsDS:GetSortedAsync(false, 10)
local LPage = Data:GetCurrentPage()
for i, v in pairs(LPage) do
if v.key ~= nil and tonumber(v.key) and tonumber(v.key) > 0 then
local name = game:GetService("Players"):GetNameFromUserIdAsync(v.key)
if name ~= nil then
local Val = v.value
local NewObj = game.ServerStorage:WaitForChild("TemplateCoins"):Clone()
NewObj:WaitForChild("Player").Text = name
NewObj:WaitForChild("Coins").Text = format(Val)
NewObj:WaitForChild("Stats").Text = i.."°"
NewObj:WaitForChild("PlayerIcon").Image = "https://www.roblox.com/headshot-thumbnail/image?userId="..(v.key).."&width=150&height=150&format=png"
local boards = workspace:WaitForChild("LeaderboardStuff")
local sellected = boards:WaitForChild("ViewCoins")
NewObj.Position = UDim2.new(0, 0, NewObj.Position.Y.Scale + (0.09 * #sellected:WaitForChild("GUI"):GetChildren()), 0)
NewObj.Parent = sellected:WaitForChild("GUI")
end
end
end
end)
if not Success then
error(Err)
end
for i=30,1,-1 do
wait(1)
Info:WaitForChild("UpdateTime").Text = "Update In("..i..")"
end
wait()
end
The value is a Number Value. The Value of it is 44909800000000002968496892153981593868198948444510090605799389908923580416 or 44.9TVg.
I'm not great with this and I could be wrong, however, I believe you need to convert the UserId to a string, all DataStore keys need to be a string, UserId returns an int.
Sorry I only just checked this but I have found a Solution. Basically I compress the number down and Save it to the Leader board DataStore with this:
local Coins = coins ~= 0 and math.floor(math.log(coins) / math.log(1.00000000000001)) or 0
then when I Loop through the DataStore I do UnPack it to its Original Number:
Val = Val ~= 0 and (1.00000000000001^Val) or 0
I'm trying to make a datastore and change the value of player data, but I am having an issue getting the script to run the function. I will paste the code I'm having issues with and mark the lines giving errors. I apologize for any rookie mistakes, this'll be my first time programming a game with Lua and on Roblox. I think it may be an issue with how I call the statName and how a statName of "Wheat" isn't there, but I don't know how to call it otherwise, or why it isn't there.
This is the relevant stuff from the modulescript:
function PlayerStatManager:ChangeStat(player, statName, value)
local playerUserId = "Player_" .. player.UserId
assert(typeof(sessionData[playerUserId][statName]) == typeof(value), "ChangeStat error: types do not match") <--this line
if typeof(sessionData[playerUserId][statName]) == "number" then
sessionData[playerUserId][statName] = sessionData[playerUserId][statName] + value
else
sessionData[playerUserId][statName] = value
end
end
-- Function to add player to the 'sessionData' table
local function setupPlayerData(player)
local playerUserId = "Player_" .. player.UserId
local data
local success, err = pcall(function()
playerData:UpdateAsync(playerUserId, function(playerData)
data = playerData
end)
end)
if success then
if data then
-- Data exists for this player
sessionData[playerUserId] = data
else
-- Data store is working, but no current data for this player
sessionData[playerUserId] = {Money=0, Wheat=0, Silo=0, Feeders=0, Chickens=0}
end
else
warn("Cannot set up data for player!")
end
end
This is the relevant stuff from the script using the modulescript:
local SrvrStats = require(game.ServerStorage.moduleScript)
SrvrStats:ChangeStat(player, 'Wheat', playerWheat.Value) <-- this line
Try This:
local PlayerStatManager = {}
PlayerStatManager.ChangeStat = function(player, statName, value)
local playerUserId = "Player_" .. player.UserId
assert(typeof(sessionData[playerUserId][statName]) == typeof(value), "ChangeStat error: types do not match") <--this line
if typeof(sessionData[playerUserId][statName]) == "number" then
sessionData[playerUserId][statName] = sessionData[playerUserId][statName] + value
else
sessionData[playerUserId][statName] = value
end
end
-- Function to add player to the 'sessionData' table
PlayerStatManager.setupPlayerData = PlayerStatManager(player)
local playerUserId = "Player_" .. player.UserId
local data
local success, err = pcall(function()
playerData:UpdateAsync(playerUserId, function(playerData)
data = playerData
end)
end)
if success then
if data then
-- Data exists for this player
sessionData[playerUserId] = data
else
-- Data store is working, but no current data for this player
sessionData[playerUserId] = {Money=0, Wheat=0, Silo=0, Feeders=0, Chickens=0}
end
else
warn("Cannot set up data for player!")
end
end
return PlayerStatManager