I have a system which saves animals with the player and tools etc. It works perfectly in studio however in the game sometimes it refuses to save and doesn’t work and doesnt load. It was temporarily fixed by adding task.wait(0.5) but now its just not saving again. I am very confused.
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local ProfileStore = require(ServerScriptService.Libraries.ProfileStore)
local Template = require(ServerScriptService.Data.Template)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local playerStore = ProfileStore.New("HuntTest5", Template)
local DataManager = require(ServerScriptService.Data.DataManager)
local playerEquippedCache = {}
local AnimalStats = require(game.ReplicatedStorage.AnimalStatsModule)
local Mutations = require(game.ReplicatedStorage.MutationStatsModule)
local Bestiary = {}
local function applyMutation(mutation, animal)
for i, fx in pairs(ReplicatedStorage.MutationFX[mutation]:GetChildren()) do
if fx:IsA("ParticleEmitter") then
fx:Clone().Parent = animal.PrimaryPart
end
end
for i, parts in pairs(animal:GetDescendants()) do
if parts:IsA("UnionOperation") or parts:IsA("MeshPart") or parts:IsA("BasePart") then
if ReplicatedStorage.MutationFX[mutation]:FindFirstChild("ColourMultiply") then
local color_1 = parts.Color
local color_2 = ReplicatedStorage.MutationFX[mutation].ColourMultiply.Value
local alpha = ReplicatedStorage.MutationFX[mutation].Alpha.Value
local mixed_color = color_1:Lerp(color_2, alpha)
parts.Color = mixed_color
end
if mutation == "Glow" or mutation == "Celestial" or mutation == "Void" then
parts.Material = Enum.Material.Neon
end
if mutation == "Spirit" then
if parts.Transparency == 0 then
parts.Transparency = 0.5
end
end
end
end
end
local function applyStats(animal, name, weight)
local weight = weight
local minWeight = AnimalStats[name].Weight.min
local maxWeight = AnimalStats[name].Weight.max
local scaleFactor = 1 + (weight - minWeight) / (maxWeight - minWeight) * (1.8 - 0.85)
animal:ScaleTo(scaleFactor)
animal:WaitForChild("Humanoid").WalkSpeed = animal:WaitForChild("Values"):WaitForChild("Speed").Value
end
local function createAnimal(plr, animaldata)
if plr and animaldata then
local regionFolder = game.ReplicatedStorage.Animals:WaitForChild(animaldata.Region)
local Dummy = regionFolder:WaitForChild(animaldata.Animal):Clone()
if Dummy:FindFirstChild("Pathfinding") then
Dummy:FindFirstChild("Pathfinding"):Destroy()
end
local tool = Instance.new("Tool")
applyStats(Dummy, animaldata.Animal, animaldata.Weight)
applyMutation(animaldata.Mutation, Dummy)
local size = Dummy:GetExtentsSize()
local largestDimension = math.max(size.X, size.Y, size.Z)
local distanceOffset = largestDimension * 0.2
local heightOffset = -size.Y * 0.25
local sideOffset = 0
tool.Grip = CFrame.new(distanceOffset, heightOffset, sideOffset) * CFrame.Angles(0, math.rad(90), 0)
if animaldata.Mutation ~= "None" then
tool.Name = animaldata.Mutation .. " " .. Dummy.Name
else
tool.Name = animaldata.Animal
end
tool.CanBeDropped = false
for i, children in pairs(Dummy:GetChildren()) do
children.Parent = tool
if children.Name == "HumanoidRootPart" then
children.Name = "Handle"
children.CanTouch = false
end
if children:IsA("MeshPart") or children:IsA("BasePart") or children:IsA("UnionOperation") then
children.Massless = true
children.CanCollide = false
end
if children:IsA("Humanoid") then
children:Destroy()
end
end
tool:WaitForChild("Values"):WaitForChild("Animal").Value = animaldata.Animal
tool:WaitForChild("Values"):WaitForChild("Despawn").Value = animaldata.Despawn
tool:WaitForChild("Values"):WaitForChild("Health").Value = animaldata.Health
tool:WaitForChild("Values"):WaitForChild("Mutation").Value = animaldata.Mutation
tool:WaitForChild("Values"):WaitForChild("Price").Value = animaldata.Price
tool:WaitForChild("Values"):WaitForChild("Range").Value = animaldata.Range
tool:WaitForChild("Values"):WaitForChild("Rarity").Value = animaldata.Rarity
tool:WaitForChild("Values"):WaitForChild("RarityTier").Value = animaldata.RarityTier
tool:WaitForChild("Values"):WaitForChild("Speed").Value = animaldata.Speed
tool:WaitForChild("Values"):WaitForChild("Weight").Value = animaldata.Weight
tool:WaitForChild("Values"):WaitForChild("Region").Value = animaldata.Region
tool:WaitForChild("Values"):WaitForChild("Damage").Value = animaldata.Damage
tool:WaitForChild("Values"):WaitForChild("Quality").Value = animaldata.Quality
tool.ToolTip = animaldata.Weight .. "kg"
tool.Parent = plr.Backpack
tool:FindFirstChild("HealthGUI"):Destroy()
elseif not animaldata then
local data = {}
plr.AnimalData = data
end
end
local function initialize(player : Player, profile : typeof(playerStore:StartSessionAsync()))
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local PlayerValues = Instance.new("Folder", player)
PlayerValues.Name = "PlayerValues"
local AvailableHealth = Instance.new("NumberValue", PlayerValues)
AvailableHealth.Name = "AvailableHealth"
AvailableHealth.Value = profile.Data.AvailableHealth
local HealAmount = Instance.new("NumberValue", PlayerValues)
HealAmount.Name = "HealAmount"
HealAmount.Value = profile.Data.HealAmount
local HealInterval = Instance.new("NumberValue", PlayerValues)
HealInterval.Name = "HealInterval"
HealInterval.Value = profile.Data.HealInterval
local Islands = Instance.new("StringValue", PlayerValues)
Islands.Name = "Island"
Islands.Value = profile.Data.Island
local Coins = Instance.new("NumberValue", leaderstats)
Coins.Name = "Coins"
Coins.Value = profile.Data.Coins
if game.ReplicatedStorage.Guns:FindFirstChild(profile.Data.EquippedGun) then
game.ReplicatedStorage.Guns:FindFirstChild(profile.Data.EquippedGun):Clone().Parent = player.Backpack
else
game.ReplicatedStorage.Guns:FindFirstChild("Basic Gun"):Clone().Parent = player.Backpack
end
if game.ReplicatedStorage.Nets:FindFirstChild(profile.Data.EquippedNet) then
game.ReplicatedStorage.Nets:FindFirstChild(profile.Data.EquippedNet):Clone().Parent = player.Backpack
else
game.ReplicatedStorage.Nets:FindFirstChild("Basic Net"):Clone().Parent = player.Backpack
end
game.ReplicatedStorage.Events.UpdateEquippedGuns:FireClient(player, profile.Data.EquippedGun)
game.ReplicatedStorage.Events.UpdateEquippedNets:FireClient(player, profile.Data.EquippedNet)
game.ReplicatedStorage.Events.UpdateGuns:FireClient(player, profile.Data.GunsOwned)
game.ReplicatedStorage.Events.UpdateNets:FireClient(player, profile.Data.NetsOwned)
for _, animalData in ipairs(profile.Data.Animals) do
createAnimal(player, animalData)
print(animalData)
end
local actualHealth = Instance.new("NumberValue")
actualHealth.Name = "ActualHealth"
actualHealth.Parent = player
actualHealth.Value = profile.Data.AvailableHealth
local IsImmune = Instance.new("BoolValue")
IsImmune.Name = "IsImmune"
IsImmune.Parent = player
IsImmune.Value = false
local IsInMiniGame = Instance.new("BoolValue")
IsInMiniGame.Name = "IsInMiniGame"
IsInMiniGame.Parent = player
IsInMiniGame.Value = false
game.ReplicatedStorage.Events.UpdateCoins:FireClient(player, profile.Data.Coins)
for _, regionFolder in pairs(ReplicatedStorage.Animals:GetChildren()) do
for _, animal in pairs(regionFolder:GetChildren()) do
local entry = profile.Data.Bestiary[animal.Name]
if not entry then
profile.Data.Bestiary[animal.Name] = {
Region = regionFolder.Name,
Name = animal.Name,
Captured = false,
HighestWeight = 0,
}
else
print("Animal Already in Bestiary")
end
end
end
print(profile.Data.Bestiary)
game.ReplicatedStorage.Events.UpdateBestiary:FireClient(player, profile.Data.Bestiary)
end
local function serializeAnimal(tool)
return {
Animal = tool:WaitForChild("Values"):WaitForChild("Animal").Value,
Despawn = tool:WaitForChild("Values"):WaitForChild("Despawn").Value,
Health = tool:WaitForChild("Values"):WaitForChild("Health").Value,
Mutation = tool:WaitForChild("Values"):WaitForChild("Mutation").Value,
Price = tool:WaitForChild("Values"):WaitForChild("Price").Value,
Range = tool:WaitForChild("Values"):WaitForChild("Range").Value,
Rarity = tool:WaitForChild("Values"):WaitForChild("Rarity").Value,
RarityTier = tool:WaitForChild("Values"):WaitForChild("RarityTier").Value,
Speed = tool:WaitForChild("Values"):WaitForChild("Speed").Value,
Weight = tool:WaitForChild("Values"):WaitForChild("Weight").Value,
Region = tool:WaitForChild("Values"):WaitForChild("Region").Value,
Damage = tool:WaitForChild("Values"):WaitForChild("Damage").Value,
Quality = tool:WaitForChild("Values"):WaitForChild("Quality").Value
}
end
local function playerAdded(player : Player)
local Profile = playerStore:StartSessionAsync("Player_" .. player.UserId, {
Cancel = function()
return player.Parent ~= Players
end,
})
if Profile ~= nil then
Profile:AddUserId(player.UserId)
Profile:Reconcile()
Profile.OnSessionEnd:Connect(function()
DataManager.Profiles[player] = nil
player:Kick("Datastore error. Please rejoin.")
end)
if player.Parent == Players then
DataManager.Profiles[player] = Profile
initialize(player, Profile)
else
Profile:EndSession()
end
else
player:Kick("Datastore error. Please rejoin.")
end
end
local function AddAnimals(player)
local animalsTable = {}
if player then
for _, tool in pairs(player.Backpack:GetChildren()) do
if tool:IsA("Tool") then
local values = tool:FindFirstChild("Values")
local isAnimal = values and values:FindFirstChild("IsAnAnimal")
if isAnimal then
table.insert(animalsTable, serializeAnimal(tool))
end
end
end
if playerEquippedCache[player.UserId] then
for i, v in pairs(playerEquippedCache[player.UserId]) do
table.insert(animalsTable, serializeAnimal(v))
end
playerEquippedCache[player.UserId] = nil
end
print(animalsTable)
if animalsTable then
DataManager.AddAnimals(player, animalsTable)
end
end
end
Players.PlayerAdded:Connect(playerAdded)
for i,plr in Players:GetPlayers() do
task.spawn(playerAdded, plr)
end
Players.PlayerRemoving:Connect(function(plr)
AddAnimals(plr)
local Profile = DataManager.Profiles[plr]
if not Profile then return end
task.wait(0.5)
Profile:EndSession()
DataManager.Profiles[plr] = nil
end)
game:BindToClose(function()
for i,plr in Players:GetPlayers() do
AddAnimals(plr)
local Profile = DataManager.Profiles[plr]
if not Profile then return end
task.wait(0.5)
Profile:EndSession()
DataManager.Profiles[plr] = nil
end
end)
ReplicatedStorage.Events.CacheToolInHand.OnServerEvent:Connect(function(plr, tool, equipped)
if not playerEquippedCache[plr.UserId] then
playerEquippedCache[plr.UserId] = {}
end
if equipped == true then
if not table.find(playerEquippedCache[plr.UserId], tool) then
table.insert(playerEquippedCache[plr.UserId], tool)
end
elseif equipped == false then
for i, t in ipairs(playerEquippedCache[plr.UserId]) do
if t == tool then
table.remove(playerEquippedCache[plr.UserId], i)
break
end
end
end
end)
Im super confused, thanks. I believe its not loading either. Its also worth noting the bestiary loads? When I was testing in game I got kicked for Datastore error. Please rejoin which is fired when profile is nil in my script or session end…
what is going on.