So i hope someone can help me fast, so let me give some quick context.
Im the owner of a Bee Swarm Simulator inspired game, and my Players are having huge Data loss issues, i’ve tried moving to Profile Service to save my Data instead.
But i’ve had the same Data loss problem.
I will send my main Module Script for saving Data here, and i hope y’all can take a look and see if theres any Problems.
The Data loads in and saves Properly, but Players lose their Bees.
--DATE: 24/11/24
--====================
--// Services
local DataStore_Service = game:GetService("DataStoreService");
local Players_Service = game:GetService("Players");
--
local Replicated_Storage = game:GetService("ReplicatedStorage");
local Server_Script_Service = game:GetService("ServerScriptService");
--
--====================
--// Modules
local Loaded_Player_Data = require(script.Loaded_Player_Data);
local Player_Bee_Data = require(Server_Script_Service.Bees_Server.Bees_Handler.Bee_Data);
--
local Shop_Data = require(Replicated_Storage.Shared_Data.Shop_Data);
local Quest_Data = require(Replicated_Storage.Shared_Data.Quest_Data);
--
local Zones_Handler = require(Server_Script_Service.Other.Zones_Server.Zones_Handler);
local Codes_Data = require(Server_Script_Service.Data.Codes_Data);
--
local Enemies_Handler = require(Server_Script_Service.Field_Related.Enemies.Enemies_Handler);
local Profile_Service = require(script.Parent.ProfileService);
--
--====================
--// Events
local Get_Client_Settings = Replicated_Storage.Get_Client_Settings;
--====================
--// Variables
local Players_To_Save_Data = {};
--====================
--// SETTINGS
local TIMEOUT = 15;
local Profile_Template = {
Fully_Loaded_All_Data = false;
Bee_Data = {};
Buffs_Data = {};
Inventory_Data = {};
Shop_Data = {};
Equipment_Data = {
["Stash"] = true;
};
Quests_Data = {};
Currency_Data = {
Honey = 0;
Pollen = 0;
};
Questline_Data = {};
Collector_Data = "Shovel";
Zones_Data = {};
Codes_Data = {};
Player_Leave_Time = os.time();
Enemy_Data = {
};
Event_Quests_Data = {
};
Settings_Data = {Pollen_Text = true;
Background_Music = true;
Sound_Effects = true;
Sound_Settings = {
Music_Volume = 1;
Sound_Effects = 1;
};
};
};
--
local Profile_Store = Profile_Service.GetProfileStore("Player", Profile_Template);
local KICK_MESSAGE = "Data issue, try again in a few seconds, if issue continues please contact us on Discord!";
--
local DataStore_Handler = {};
DataStore_Handler.Player_Passcodes = {};
DataStore_Handler.Player_Settings = {};
local Things_To_Save = { -- Name of the things you wanna save should be in the Player_Data type with the exact same name.
["Bee_Data"] = function(Player: Player): Loaded_Player_Data.Bee_Data
if Player:GetAttribute("Claimed_Hive") == "" then
return DataStore_Handler.Get_Player_Loaded_Data(Player).Bee_Data;
end
local Saved_Player_Bee_Data = Player_Bee_Data.Player_Bee_Data[Player.UserId];
for ID: number, Data: {} in pairs(Saved_Player_Bee_Data) do
for _, Bee: Model in pairs(workspace.Bees[Player.UserId]:GetChildren()) do
if Bee:GetAttribute("Id") == ID then
Data.Level = Bee:GetAttribute("Level");
break;
end
end
end
return Saved_Player_Bee_Data;
end;
["Buffs_Data"] = function(Player: Player): Loaded_Player_Data.Buffs_Data
local Player_Buffs: Loaded_Player_Data.Buffs_Data = {};
for Buff: string, Stack_Amount in pairs(Player.Buffs:GetAttributes()) do
if Player.Buffs:GetAttribute(Buff) <= 0 or Player.Buffs_Duration:GetAttribute(Buff) <= 0 then
continue;
end
Player_Buffs[Buff] = {};
Player_Buffs[Buff].Stack_Amount = Player.Buffs:GetAttribute(Buff);
Player_Buffs[Buff].Duration = Player.Buffs_Duration:GetAttribute(Buff);
end
return Player_Buffs;
end;
["Inventory_Data"] = function(Player: Player): Loaded_Player_Data.Inventory_Data
local Inventory_Data = {};
for Item: string, Amount: number in pairs(Player.Inventory:GetAttributes()) do
Inventory_Data[Item] = Amount;
end
return Inventory_Data;
end;
["Shop_Data"] = function(Player: Player): Loaded_Player_Data.Shop_Data
return Shop_Data.Player_Data[Player.UserId];
end;
["Equipment_Data"] = function(Player: Player): Loaded_Player_Data.Equipment_Data
local Equipment_Data = {};
for Equipment: string, Equipped: boolean in pairs(Player.Equipment:GetAttributes()) do
Equipment_Data[Equipment] = Equipped;
end
return Equipment_Data;
end;
["Quests_Data"] = function(Player: Player): Loaded_Player_Data.Quests_Data
return Quest_Data.Get_Full_Player_Quest_Data(Player);
end;
["Event_Quests_Data"] = function(Player: Player): Loaded_Player_Data.Event_Quests_Data
return Quest_Data.Event_Player_Data[Player.UserId];
end;
["Questline_Data"] = function(Player: Player): Loaded_Player_Data.Questline_Data
return Quest_Data.Player_Questline_Data[Player.UserId];
end;
["Currency_Data"] = function(Player: Player): Loaded_Player_Data.Currency_Data
local Currency_Data = {};
for Attribute: string, Value: any in pairs(Player:GetAttributes()) do
if Attribute == "Honey" or Attribute == "Pollen" then
Currency_Data[Attribute] = Value;
end
end
return Currency_Data;
end;
["Collector_Data"] = function(Player: Player): Loaded_Player_Data.Collector_Data
return Player:GetAttribute("Collector");
end;
["Zones_Data"] = function(Player: Player): Loaded_Player_Data.Collector_Data
return Zones_Handler.Zones_Data[Player.UserId];
end;
["Codes_Data"] = function(Player: Player): Loaded_Player_Data.Codes_Data
return Codes_Data.Player_Data[Player.UserId];
end;
["Player_Leave_Time"] = function(Player: Player): Loaded_Player_Data.Player_Leave_Time
return os.time();
end;
["Enemy_Data"] = function(Player: Player): Loaded_Player_Data.Enemy_Data
return Enemies_Handler.Player_Data[Player.UserId];
end;
["Settings_Data"] = function(Player: Player): Loaded_Player_Data.Enemy_Data
return DataStore_Handler.Player_Settings[Player.UserId];
end;
}
--// Load Player Data Function
--[[
Loads given Player's Data, and stores it.
]]
function DataStore_Handler.Load_Player_Data(Player: Player): ()
local Profile = Profile_Store:LoadProfileAsync(tostring(Player.UserId));
if not Profile then
Player:Kick(KICK_MESSAGE);
return;
end
Profile:AddUserId(Player.UserId);
Profile:Reconcile();
Profile:ListenToRelease(function()
Loaded_Player_Data.Profiles[Player.UserId] = nil;
Player:Kick(KICK_MESSAGE);
end)
if not Player:IsDescendantOf(Players_Service) then
Profile:Release();
end
Loaded_Player_Data.Profiles[Player.UserId] = Profile;
DataStore_Handler.Player_Passcodes[Player.UserId] = math.random(1, 969595693) * math.random(1, 100) / math.random(1023, 10100) ^ 2;
DataStore_Handler.Player_Settings[Player.UserId] = Loaded_Player_Data.Profiles[Player.UserId].Data.Settings_Data;
Loaded_Player_Data.Profiles[Player.UserId].Data.Fully_Loaded_All_Data = true;
Players_To_Save_Data[Player.UserId] = true;
end
--// Save Player Data Function
--[[
Saves given Player's Data.
]]
function DataStore_Handler.Save_Player_Data(Player: Player): ()
local Profile = Loaded_Player_Data.Profiles[Player.UserId];
if not Profile then
return;
end
for Data_Name, Function in pairs(Things_To_Save) do
Profile.Data[Data_Name] = Function(Player);
end
Profile:Release();
DataStore_Handler.Player_Passcodes[Player.UserId] = nil;
DataStore_Handler.Player_Settings[Player.UserId] = nil;
Loaded_Player_Data.Profiles[Player.UserId] = nil;
Players_To_Save_Data[Player.UserId] = nil;
end
--// Save Every Player Data Function
--[[
Saves every single Player's Data.
]]
function DataStore_Handler.Save_Every_Player_Data(): ()
for _, Player: Player in pairs(Players_Service:GetPlayers()) do
task.spawn(DataStore_Handler.Save_Player_Data, Player);
end
end
--// Wait Until Player Data Saves Function
--[[
Waits until Player's Data saves.
]]
function DataStore_Handler.Wait_Until_Player_Data_Saves(Player: Player): ()
repeat
task.wait();
until not Players_To_Save_Data[Player.UserId];
end
--// Get Player Loaded Data Function
--[[
Gets Player's Loaded Data, if Data hasn't loaded in yet waits until it Loads with a timeout of 15 seconds.
]]
function DataStore_Handler.Get_Player_Loaded_Data(Player: Player): Loaded_Player_Data.Player_Data
if Loaded_Player_Data.Profiles[Player.UserId] == nil then
local Tick = tick();
repeat
task.wait();
until math.abs(Tick - tick()) >= TIMEOUT or Loaded_Player_Data.Profiles[Player.UserId] ~= nil;
if Loaded_Player_Data.Profiles[Player.UserId] == nil then
warn(`{Player.Name} has waited 15 seconds and Data has not loaded or did not save, returning empty Table!`);
return {};
else
Tick = tick();
repeat
task.wait();
until math.abs(Tick - tick()) >= TIMEOUT or Loaded_Player_Data.Profiles[Player.UserId].Data.Fully_Loaded_All_Data == true;
return Loaded_Player_Data.Profiles[Player.UserId].Data;
end
elseif Loaded_Player_Data.Profiles[Player.UserId] ~= nil and Loaded_Player_Data.Profiles[Player.UserId].Data.Fully_Loaded_All_Data == false then
local Tick = tick();
repeat
task.wait();
until math.abs(Tick - tick()) >= TIMEOUT or Loaded_Player_Data.Profiles[Player.UserId].Data.Fully_Loaded_All_Data == true;
if Loaded_Player_Data.Profiles[Player.UserId].Data.Fully_Loaded_All_Data == false then
warn(`{Player.Name} has waited 15 seconds and Data has not loaded or did not save, returning empty Table!`);
return {};
else
return Loaded_Player_Data.Profiles[Player.UserId].Data;
end
elseif Loaded_Player_Data.Profiles[Player.UserId] ~= nil then
local Tick = tick();
repeat
task.wait();
until math.abs(Tick - tick()) >= TIMEOUT or Loaded_Player_Data.Profiles[Player.UserId] == nil or Loaded_Player_Data.Profiles[Player.UserId].Data.Fully_Loaded_All_Data == true;
if not Loaded_Player_Data.Profiles[Player.UserId] then
return nil;
end
return Loaded_Player_Data.Profiles[Player.UserId].Data;
end
end
return DataStore_Handler
PLEASE someone help me fast, because i’ve tried everything and it doesn’t work.
Im saving all Player Data, when the Player leaves as well, by running a for loop in the Things To Save Table, this could be an issue but hey idk.
Thanks for reading