Profile Service Dataloss Issue (PLEASE HELP QUICK)

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

If you have too much data to save and you use a for loop once the player is leaving to save the data, then it probably cant save the data in time

I’d suggest you to make a table which contains the player’s data and save it per 60 seconds

1 Like