I want to create a hat changing system through GUI, but I believe there’s a problem with my server script that has to do with DataStore.
When pressing on one of my GUI buttons, the hat applies to the player. But, sometimes when I respawn or rejoin, the hat disappears. The only way for me to fix it is by either going to get that specific hat again from the GUI, or respawning until it re-appears.
Is there a flaw in my DataStore approach?
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local HttpService = game:GetService("HttpService")
local HAT_DATASTORE_NAME = "HatCustomizationDataStore"
local HatChangeEvent = ReplicatedStorage:WaitForChild("HatChangeEvent")
local hatDataStore = DataStoreService:GetDataStore(HAT_DATASTORE_NAME)
local function ApplyHat(player, hatName, cframe)
local character = player.Character
if not character then return end
local head = character:FindFirstChild("Head")
if not head then return end
for _, child in ipairs(head:GetChildren()) do
if ServerStorage.HatStorage:FindFirstChild(child.Name) then
child:Destroy()
end
end
local hat = ServerStorage.HatStorage:FindFirstChild(hatName)
if hat then
local clonedHat = hat:Clone()
clonedHat.Name = hatName
clonedHat.Parent = head
clonedHat.CFrame = head.CFrame * cframe
local weld = Instance.new("WeldConstraint")
weld.Parent = clonedHat
weld.Part0 = head
weld.Part1 = clonedHat
else
warn("Hat not found: " .. hatName)
end
end
local function SaveHatCustomization(player, hatName, cframe)
local data = {
Name = hatName,
Position = {cframe.Position.X, cframe.Position.Y, cframe.Position.Z},
Rotation = {cframe:ToEulerAnglesXYZ()}
}
local success, errorMessage = pcall(function()
hatDataStore:SetAsync(player.UserId .. "_Hat", HttpService:JSONEncode(data))
end)
if not success then
warn("Failed to save hat for " .. player.Name .. ": " .. errorMessage)
end
end
local function LoadHatCustomization(player)
local success, dataString = pcall(function()
return hatDataStore:GetAsync(player.UserId .. "_Hat")
end)
if success and dataString then
local decodedData = HttpService:JSONDecode(dataString)
if decodedData and decodedData.Name and decodedData.Position and decodedData.Rotation then
local position = Vector3.new(unpack(decodedData.Position))
local rotation = Vector3.new(unpack(decodedData.Rotation))
local cframe = CFrame.new(position) * CFrame.Angles(rotation.X, rotation.Y, rotation.Z)
return decodedData.Name, cframe
end
end
return nil, CFrame.new(0, 0.5, 0)
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
while not character or not character:FindFirstChild("HumanoidRootPart") do
task.wait()
end
local hatName, cframe = LoadHatCustomization(player)
if hatName then
ApplyHat(player, hatName, cframe)
end
end)
end)
HatChangeEvent.OnServerEvent:Connect(function(player, hatName, cframe)
if ServerStorage.HatStorage:FindFirstChild(hatName) then
ApplyHat(player, hatName, cframe)
SaveHatCustomization(player, hatName, cframe)
else
warn("Invalid hat name received: " .. hatName)
end
end)