it doesnt work
This text will be blurred
it doesnt work
This text will be blurred
Sorry my bad, I forgot to include the two Module functions to Load and Save the store. I have edited the ModuleScript in the original post above and added these mega important bits! Silly me.
This is a bad take when it comes to DataStores. DataStores are extremely difficult to get right and there are so many edge cases that you may not consider. ProfileService is a proven module and has been throughly tested and optimised, you should use it over an unproven solution.
Avoiding using resources that are already available is bad practice, every programmer (professional or not) is likely to use a large amount of libraries that they did not make. You should really only be making your own resources if you cannot find a resource that does not meet your specific requirements.
Like I said in an earlier post, this method is in Robloxâs own examples (Move It Simulator). I adapted it to suit the data I wanted to store. Most of the time it makes sense to use other peoples code because there is no need to re-invent the wheel all the time. Most learning is done by making mistakes and figuring out why it doesnât work. I have encountered lots of issues myself using DataStores but through good code breaking and testing I know why these things were happening. My DataStore works exactly as it should and I have had no issues with it.
Just because a method is used by Roblox it does mean it is the better solution. You cannot vouch for your own method over something like ProfileService that has been used by thousands more people. Using something like ProfileService is better for all developers as it is suited for storing whatever sort of data you need, designing a Datastore to only suit a single games need is pointless as you now need to design another Datastore for any other projects you may end up doing. ProfileService is easily the most user friendly Datastore module available at the moment.
I am not vouching for any method over another. You gave a solution and an opinion, I also gave a solution and an opinion. Itâs up to the OP or anyone else to decide which opinion and solution they will adopt for themselves. Whether it be yours, mine, or anyone elseâs.
it doesnt wrok : ( . here is my code
--playerdata
--=================================================================================
local ReplicatedStorage = game:GetService("ReplicatedStorage");
local ServerEvents = ReplicatedStorage:WaitForChild("Remotes",3);
local NotifyChange = ServerEvents:WaitForChild("NotifyChange",3); -- a data changed notify message to return info to the client, to update GUI's or Stats visible to players
local RemoteSetStat = ServerEvents:WaitForChild("SetStat",3);
local RemoteGetStat = ServerEvents:WaitForChild("GetStat",3);
local RemoteGetTable = ServerEvents:WaitForChild("GetTable",3);
local RemoteSetTableValue = ServerEvents:WaitForChild("SetTableValue",3);
local RemoteGetTableValue = ServerEvents:WaitForChild("GetTableValue",3);
local DataStore = require(script.Parent:WaitForChild("saveandloaddata")); -- a single point to access the DataStore Module
--=================================================================================
local function SetStat(player,stat,value)
-- this is called using a RemoteEvent like this:
-- RemoteSetStat:FireServer("Strength",2);
DataStore:SetStat(player,stat,value);
NotifyChange:FireClient(player,"Some info you may want to send back to a GUI or Leaderstats");
end
--=================================================================================
local function GetStat(player,stat)
-- this is called with a RemoteFunction like this:
-- local strength = RemoteGetStat:InvokeServer("Strength");
return DataStore:GetStat(player,stat);
end
--=================================================================================
local function GetTable(player,table_name)
return DataStore:GetTable(player,table_name);
end
--=================================================================================
local function SetTableValue(player,table_name,value)
return DataStore:SetTableValue(player,table_name,value);
end
--=================================================================================
local function GetTableValue(player,table_name,table_index)
return DataStore:GetTableValue(player,table_name,table_index);
end
--=================================================================================
-- remote events (setters)
--=================================================================================
RemoteSetStat.OnServerEvent:Connect(SetStat);
RemoteSetTableValue.OnServerEvent:Connect(SetTableValue);
--=================================================================================
-- remote functions (getters)
--=================================================================================
RemoteGetStat.OnServerInvoke = GetStat;
RemoteGetTable.OnServerInvoke = GetTable;
RemoteGetTableValue.OnServerInvoke = GetTableValue;
--=================================================================================
-- EOF...
--=================================================================================
--module
--=================================================================================
-- Data store
--=================================================================================
local DataStore = {};
DataStore.__index = DataStore;
--=================================================================================
-- Services
--=================================================================================
local DataStoreService = game:GetService("DataStoreService");
local RunService = game:GetService("RunService");
local Players = game:GetService("Players");
--=================================================================================
-- Bool indicating whether data should save in studio (will not change during runtime)
--=================================================================================
local saveInStudio = false;
--=================================================================================
-- Creates the player data store
--=================================================================================
local playerDataStore = nil;
local DataStoreVersion = 1;
if (not saveInStudio) and game.GameId ~= 0 then
playerDataStore = DataStoreService:GetDataStore("PlayerData"..DataStoreVersion);
end
--=================================================================================
-- Table containing a copy of the player's data
--=================================================================================
local sessionData = {};
--=================================================================================
-- When a players fail to load data, their key is put in a list so that
-- their data does not save and override existing data
--=================================================================================
local tempData = {}
--=================================================================================
-- Constants
--=================================================================================
local AUTOSAVE_DATAINTERVAL = 300; -- 5 minutes auto save interval
local COINS_INDEX = 1; -- these are some indexes for accessing values stored in the Currencies table
local GEMS_INDEX = 2;
local STRENGTH_INDEX = 3;
local Storage_INDEX = 4;
local Equipped = 5;
local Equippedst = 6;
local equippedcl = 7;
--=================================================================================
-- The master Data store table
--=================================================================================
local NEW_PLAYER_DATA =
{
Strength = 0,
Storage = 0,
EquippedDst = 0,
Equipped = 0,
Class = 0,
EquippedClass = 0,
Currencies = {},
OwnedStorage = {},
OwnedTools = {},
OwnedClass = {},
};
--=================================================================================
-- Local Functions
--=================================================================================
local function load(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Return data from cache if it's already loaded
if sessionData[key] then
return sessionData[key];
end
-- Try to load data
if playerDataStore then
-- Data not loaded, let's go get it
local success, data = pcall(function()
return playerDataStore:GetAsync(key);
end)
-- Acces to store was successful
if success then
if data then
-- Data exists for this player so assign the session data
sessionData[key] = data;
else
-- Data store is working, but no current data for this player
warn( "New player ", key );
sessionData[key] = NEW_PLAYER_DATA;
end
return true; -- datastore working
end
warn( "Cannot access data store for ", key );
end
-- Could not load data, treat as new player
sessionData[key] = NEW_PLAYER_DATA;
-- When players fails to load data, their key is put in a list so that their
-- data does not save and override existing data
tempData[key] = true;
return false; -- data store failed!
end
--=================================================================================
--
--=================================================================================
local function save(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Save data if it exists and is not temporary
if sessionData[key] and not tempData[key] then
-- now save the data.
local tries = 0;
local success = nil;
repeat
tries = tries + 1;
success = pcall(function()
playerDataStore:SetAsync(key,sessionData[key]);
end)
if not success then wait(2) end;
until tries == 3 or success
if not success then
warn( "Cannot save data for ", key );
else
warn( "Saved data for ", key );
end
return success;
end
end
--=================================================================================
--
--=================================================================================
local function saveOnExit(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Save data
save(player);
-- Clear cached data
sessionData[key] = nil;
tempData[key] = nil;
end
--=================================================================================
-- Function to periodically save player data
--=================================================================================
local function autoSave()
while wait(AUTOSAVE_DATAINTERVAL) do
warn( "Auto saving player data..." );
for key, data in pairs(sessionData) do
save(key);
end
end
end
--=================================================================================
-- On Startup, Start running "autoSave()" function in the background
--=================================================================================
spawn(autoSave);
--=================================================================================
-- Connections
--=================================================================================
Players.PlayerAdded:Connect(function(player)
DataStore:Load(player);
end)
--=================================================================================
Players.PlayerRemoving:Connect(function(player)
saveOnExit(player);
end)
--=================================================================================
game:BindToClose(function()
if RunService:IsStudio() then return end;
for _, player in ipairs(Players:GetPlayers()) do
saveOnExit(player);
end
warn( "Binding to server close, forced player save.....!" );
end)
--=================================================================================
-- Load/Save data store
--=================================================================================
function DataStore:Load(player)
return load(player);
end
--=================================================================================
function DataStore:Save(player)
save(player);
end
--=================================================================================
function DataStore:GetStat(player,stat)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
if not sessionData[key] then return nil end;
if not sessionData[key][stat] then
return nil;
end
return sessionData[key][stat];
end
--=================================================================================
function DataStore:SetStat(player,stat,value)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
if not sessionData[key] then return nil end;
if not sessionData[key][stat] then
return nil;
end
sessionData[key][stat] = value;
print(stat, " changed to ", value);
return sessionData[key][stat];
end
--=================================================================================
--=================================================================================
return DataStore;
--=================================================================================
-- EOF...
--=================================================================================
Okay there are no functions called âGetTableValueâ, âSetTableValueâ in the DataStore script so it may be why it not functioning. I gave you an incomplete example because I thought you would probably not use it because it nils everything you had done, and required a lot of work (in creating the folder and values, the leaderstats, etc.). We can get this to work now if we simply remove the un-defined functions for now. I can help with these more advanced methods, but letâs just fix it for values and not tables. So change the playerdata Script to this:
--playerdata
--=================================================================================
local ReplicatedStorage = game:GetService("ReplicatedStorage");
local ServerEvents = ReplicatedStorage:WaitForChild("Remotes",3);
local NotifyChange = ServerEvents:WaitForChild("NotifyChange",3); -- a data changed notify message to return info to the client, to update GUI's or Stats visible to players
local RemoteSetStat = ServerEvents:WaitForChild("SetStat",3);
local RemoteGetStat = ServerEvents:WaitForChild("GetStat",3);
local DataStore = require(script.Parent:WaitForChild("saveandloaddata")); -- a single point to access the DataStore Module
--=================================================================================
local function SetStat(player,stat,value)
-- this is called using a RemoteEvent like this:
-- RemoteSetStat:FireServer("Strength",2);
DataStore:SetStat(player,stat,value);
NotifyChange:FireClient(player,"Some info you may want to send back to a GUI or Leaderstats");
end
--=================================================================================
local function GetStat(player,stat)
-- this is called with a RemoteFunction like this:
-- local strength = RemoteGetStat:InvokeServer("Strength");
return DataStore:GetStat(player,stat);
end
--=================================================================================
-- remote events (setters)
--=================================================================================
RemoteSetStat.OnServerEvent:Connect(SetStat);
--=================================================================================
-- remote functions (getters)
--=================================================================================
RemoteGetStat.OnServerInvoke = GetStat;
--=================================================================================
-- EOF...
--=================================================================================
And for the âsaveandloaddataâ module, those fixed indices are there for when we want to store multiple and different values with a predictable key in a dictionary fashion, but by the very nature of dictionaries we cannot store them as dictionaries because we cannot use a named index so we have to use a fixed and constant index that we define and use to simulate dictionaries using tables.
i.e. if you have an inventory system and you want to store different types of stuff, maybe a sword that has four properties -Name, Speed, Damage, Cost- and throwing dagger that has the same properties -Name, Speed, Damage, Cost-. What we can do is use a fixed index and make a table entry that looks like this:
local SWORD_INDEX = 1;
local DAGGER_INDEX = 2;
local AXE_INDEX = 3;
So for the sword we do this to add it to a table, for as many swords that we have:
{[1]=SWORD_INDEX,[2]="Broadsword",[3]=5,[4]=100,[5]=1000} -- identifier, name, speed, damage, cost
{[1]=SWORD_INDEX,[2]="Scimitar",[3]=50,[4]=200,[5]=2000}
And if we want to add a dagger, or an axe, or whatever, then we do this:
{[1]=DAGGER_INDEX,[2]="Dagger",[3]=10,[4]=20,[5]=100} -- identifier, name, speed, damage, cost (the same system)
{[1]=AXE_INDEX,[2]="Woodsman's Axe",[3]=80,[4]=200,[5]=500}
Now we can check the first entry to the table and it will tell us whether it is a sword, dagger, or axe. We can do the same with anything we want to as long as the information we are storing has the same number of properties (this is a rule for all database storage mechanisms, every entry must have the same number of keys, columns if you think of Excel). You canât then add a sword to the same table that has five properties (Name,Speed,Damage,Cost,Mana) you will need a new table called âmagic inventoryâ or something.
From your example you have currencies (if we require several of them), i.e.
local COINS_INDEX = 1;
local GEMS_INDEX = 2;
{[1]=COINS_INDEX ,[2]=100000} -- first index = identifier, second index = value
{[1]=GEMS_INDEX ,[2]=20} -- first index = identifier, second index = value
There is no limit to this method, and they are all saveable with primitive methods and no bloated modules to require. So in the âloadsavedataâ Module under constants you have added some indices for things, they are not required unless they are defining a âfakeâ dictionary item to store as exampled above.
So change the Module code to this and you should not error (hopefully, toes and fingers crossed).
--module
--=================================================================================
-- Data store
--=================================================================================
local DataStore = {};
DataStore.__index = DataStore;
--=================================================================================
-- Services
--=================================================================================
local DataStoreService = game:GetService("DataStoreService");
local RunService = game:GetService("RunService");
local Players = game:GetService("Players");
--=================================================================================
-- Bool indicating whether data should save in studio (will not change during runtime)
--=================================================================================
local saveInStudio = false;
--=================================================================================
-- Creates the player data store
--=================================================================================
local playerDataStore = nil;
local DataStoreVersion = 1;
if (not saveInStudio) and game.GameId ~= 0 then
playerDataStore = DataStoreService:GetDataStore("PlayerData"..DataStoreVersion);
end
--=================================================================================
-- Table containing a copy of the player's data
--=================================================================================
local sessionData = {};
--=================================================================================
-- When a players fail to load data, their key is put in a list so that
-- their data does not save and override existing data
--=================================================================================
local tempData = {}
--=================================================================================
-- Constants
--=================================================================================
local AUTOSAVE_DATAINTERVAL = 300; -- 5 minutes auto save interval
--=================================================================================
-- The master Data store table
--=================================================================================
local NEW_PLAYER_DATA =
{
Strength = 0,
Storage = 0,
EquippedDst = 0,
Equipped = 0,
Class = 0,
EquippedClass = 0,
Currencies = {},
OwnedStorage = {},
OwnedTools = {},
OwnedClass = {},
};
--=================================================================================
-- Local Functions
--=================================================================================
local function load(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Return data from cache if it's already loaded
if sessionData[key] then
return sessionData[key];
end
-- Try to load data
if playerDataStore then
-- Data not loaded, let's go get it
local success, data = pcall(function()
return playerDataStore:GetAsync(key);
end)
-- Acces to store was successful
if success then
if data then
-- Data exists for this player so assign the session data
sessionData[key] = data;
else
-- Data store is working, but no current data for this player
warn( "New player ", key );
sessionData[key] = NEW_PLAYER_DATA;
end
return true; -- datastore working
end
warn( "Cannot access data store for ", key );
end
-- Could not load data, treat as new player
sessionData[key] = NEW_PLAYER_DATA;
-- When players fails to load data, their key is put in a list so that their
-- data does not save and override existing data
tempData[key] = true;
return false; -- data store failed!
end
--=================================================================================
--
--=================================================================================
local function save(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Save data if it exists and is not temporary
if sessionData[key] and not tempData[key] then
-- now save the data.
local tries = 0;
local success = nil;
repeat
tries = tries + 1;
success = pcall(function()
playerDataStore:SetAsync(key,sessionData[key]);
end)
if not success then wait(2) end;
until tries == 3 or success
if not success then
warn( "Cannot save data for ", key );
else
warn( "Saved data for ", key );
end
return success;
end
end
--=================================================================================
--
--=================================================================================
local function saveOnExit(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Save data
save(player);
-- Clear cached data
sessionData[key] = nil;
tempData[key] = nil;
end
--=================================================================================
-- Function to periodically save player data
--=================================================================================
local function autoSave()
while wait(AUTOSAVE_DATAINTERVAL) do
warn( "Auto saving player data..." );
for key, data in pairs(sessionData) do
save(key);
end
end
end
--=================================================================================
-- On Startup, Start running "autoSave()" function in the background
--=================================================================================
spawn(autoSave);
--=================================================================================
-- Connections
--=================================================================================
Players.PlayerAdded:Connect(function(player)
DataStore:Load(player);
end)
--=================================================================================
Players.PlayerRemoving:Connect(function(player)
saveOnExit(player);
end)
--=================================================================================
game:BindToClose(function()
if RunService:IsStudio() then return end;
for _, player in ipairs(Players:GetPlayers()) do
saveOnExit(player);
end
warn( "Binding to server close, forced player save.....!" );
end)
--=================================================================================
-- Load/Save data store
--=================================================================================
function DataStore:Load(player)
return load(player);
end
--=================================================================================
function DataStore:Save(player)
save(player);
end
--=================================================================================
function DataStore:GetStat(player,stat)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
if not sessionData[key] then return nil end;
if not sessionData[key][stat] then
return nil;
end
return sessionData[key][stat];
end
--=================================================================================
function DataStore:SetStat(player,stat,value)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
if not sessionData[key] then return nil end;
if not sessionData[key][stat] then
return nil;
end
sessionData[key][stat] = value;
print(stat, " changed to ", value);
return sessionData[key][stat];
end
--=================================================================================
--=================================================================================
return DataStore;
--=================================================================================
-- EOF...
--=================================================================================
it now actually saves but for some reason it doesnt load
Is playerDataStore
nil when it comes to load it? It may be assigning the tempData instead.
Can I see the code for your version of the ModuleScript please?
--=================================================================================
-- Constants
--=================================================================================
local AUTOSAVE_DATAINTERVAL = 300; -- 5 minutes auto save interval
--=================================================================================
-- The master Data store table
--=================================================================================
local NEW_PLAYER_DATA =
{
Strength = 0,
Storage = 0,
EquippedDst = 0,
Equipped = 0,
Class = 0,
EquippedClass = 0,
Currencies = {},
OwnedStorage = {},
OwnedTools = {},
OwnedClass = {},
};
--=================================================================================
-- Local Functions
--=================================================================================
local function save(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Save data if it exists and is not temporary
if sessionData[key] and not tempData[key] then
-- now save the data.
local tries = 0;
local success = nil;
repeat
tries = tries + 1;
success = pcall(function()
playerDataStore:SetAsync(key,sessionData[key]);
end)
if not success then wait(2) end;
until tries == 3 or success
if not success then
warn( "Cannot save data for ", key );
else
warn( "Saved data for ", key );
end
return success;
end
end
--=================================================================================
--
--=================================================================================
local function saveOnExit(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
-- Save data
save(player);
-- Clear cached data
sessionData[key] = nil;
tempData[key] = nil;
end
--=================================================================================
-- Function to periodically save player data
--=================================================================================
local function autoSave()
while wait(AUTOSAVE_DATAINTERVAL) do
warn( "Auto saving player data..." );
for key, data in pairs(sessionData) do
save(key);
end
end
end
--=================================================================================
-- On Startup, Start running "autoSave()" function in the background
--=================================================================================
spawn(autoSave);
local function load(player)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
print(playerDataStore)
-- Return data from cache if it's already loaded
if sessionData[key] then
return sessionData[key];
end
-- Try to load data
if playerDataStore then
-- Data not loaded, let's go get it
local success, data = pcall(function()
return playerDataStore:GetAsync(key);
end)
-- Acces to store was successful
if success then
if data then
-- Data exists for this player so assign the session data
sessionData[key] = data;
else
-- Data store is working, but no current data for this player
warn( "New player ", key );
sessionData[key] = NEW_PLAYER_DATA;
end
return true; -- datastore working
end
warn( "Cannot access data store for ", key );
end
-- Could not load data, treat as new player
sessionData[key] = NEW_PLAYER_DATA;
-- When players fails to load data, their key is put in a list so that their
-- data does not save and override existing data
tempData[key] = true;
return false; -- data store failed!
end
--=================================================================================
--
--=================================================================================
--=================================================================================
-- Connections
--=================================================================================
Players.PlayerAdded:Connect(function(player)
DataStore:Load(player);
end)
--=================================================================================
Players.PlayerRemoving:Connect(function(player)
saveOnExit(player);
end)
--=================================================================================
game:BindToClose(function()
if RunService:IsStudio() then return end;
for _, player in ipairs(Players:GetPlayers()) do
saveOnExit(player);
end
warn( "Binding to server close, forced player save.....!" );
end)
--=================================================================================
-- Load/Save data store
--=================================================================================
function DataStore:Load(player)
return load(player);
end
--=================================================================================
function DataStore:Save(player)
save(player);
end
--=================================================================================
function DataStore:GetStat(player,stat)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
if not sessionData[key] then return nil end;
if not sessionData[key][stat] then
return nil;
end
return sessionData[key][stat];
end
--=================================================================================
function DataStore:SetStat(player,stat,value)
local userId = player.UserId;
local key = "player_" .. tostring(userId);
if not sessionData[key] then return nil end;
if not sessionData[key][stat] then
return nil;
end
sessionData[key][stat] = value;
print(stat, " changed to ", value);
return sessionData[key][stat];
end
--=================================================================================
--=================================================================================
return DataStore;
--=================================================================================
-- EOF...
--=================================================================================
Just do:
local saveData = {
Coins = plr.leaderstats.Coins.Value,
Strength = plr.leaderstats.Strength.Value,
Gems = plr.leaderstats.Gems.Value,
--etc...
}
local httpService = game:GetService('HttpService')
ds:SetAsync(plr.UserId,httpService:JSONEncode(saveData))
Then to load, just do:
httpService:JSONDecode(ds:GetAsync(plr.UserId))
In your original script. Though donât just copy/paste, youâll need to implement it yourself properly. Thatâs just an example of how it would be constructed.
it says
Argument 1 missing or nil
do u know why?
Could you show your code? 㠤㠤㠤㠤
local save = {}
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("datamaSnef")
local players = game:GetService("Players")
function save.playeraddede(player)
local data = ds:GetAsync(player.UserId)
player.leaderstats.Coins.Vslue = data[1]
player.leaderstats.Strength.Vslue = data[2]
player.leaderstats.Gems.Vslue = data[3]
end
game:BindToClose(function(plr)
wait(2)
pcall(function()
local saveData = {
Coins = plr.leaderstats.Coins.Value,
Strength = plr.leaderstats.Strength.Value,
Gems = plr.leaderstats.Gems.Value
}
local httpService = game:GetService('HttpService')
ds:SetAsync(plr.UserId,httpService:JSONEncode(saveData))
end)
end)
return save
hello, i sent my code, pls help