This is the datastore module. This is what retrieves and saves the data. As you can see is uses _G[player] to store the players data. Pet module is after this code.
function dataStoreService:getLocalData(player)
local data = _G[player]
if data then
return data
else
local data = dataStoreService:loadData()
end
end
function dataStoreService:saveData(player, data, isPlayerExiting)
local key = "player-"..player.UserId
--//Clone data
local dataToSave = {}
for statName, statValue in pairs(data) do
dataToSave[statName] = statValue
end
--//Remove temporary stats
for statName, statValue in pairs(_G.unsavedStats) do
if dataToSave[statName] then
dataToSave[statName] = nil
end
end
--//Save data
local success, err = pcall(function()
mainDataStore:SetAsync(key, dataToSave)
end)
if success then
if isPlayerExiting then
_G[player] = nil
end
print(player.Name.."'s data was saved.")
else
warn(err)
warn(player.Name.."'s data could NOT be saved")
end
return
end
function dataStoreService:createData(player)
--//Create new data entry
local data = {}
--//Add data values into data so we create a seperate table
for newStatName, newStatValue in pairs(_G.defaultData) do
data[newStatName] = newStatValue
end
--//Insert temporary stats
for statName, statValue in pairs(_G.unsavedStats) do
data[statName] = statValue
end
_G[player] = data
return data
end
function dataStoreService:loadData(player)
local key = "player-"..player.UserId
local data
local success, err = pcall(function()
data = mainDataStore:GetAsync(key)
end)
if success then
--//Datastores working fine
if data then
--//Data exists
print(player.Name.."'s data was found.")
--//Add temporary stats
for statName, statValue in pairs(_G.unsavedStats) do
data[statName] = statValue
end
--//Add new data nodes
for statName, statValue in pairs(_G.defaultData) do
if data[statName] == nil then
data[statName] = statValue
end
end
--//set global table
_G[player] = data
return data
else
--//Data does not exist
--//Create new data
data = dataStoreService:createData(player)
--//Wait to save data
coroutine.wrap(function()
dataStoreService:saveData(player, data)
end)()
return data
end
else
--//Datastores are broken
warn("Could not retrieve any data for "..player.Name)
player:Kick("Datastores are down. You were kicked to prevent data overwriting!")
end
end
When the player joins the game, the data is retrieved like this
local localData = dataModule:loadData(player)
repeat wait() until localData ~= nil
Once the data is loaded, pets are equipped like this
if #localData.currentPets > 0 then
petModule:equipPets(player, localData)
end
The equip function looks like this
function petModule:equipPets(player, localData)
local petsToReturn = {}
for _, petEquipped in pairs(localData.currentPets) do
local petName = petEquipped.name
local uuid = petEquipped.uuid
if petModule:checkOwnership(localData, petEquipped) then
local newPet = script.Parent.Parent.Objects.Pets:FindFirstChild(petName):Clone()
newPet.Parent = workspace.Pets
newPet.Name = player.Name..uuid
table.insert(petsToReturn, #petsToReturn+1, {name = petName, uuid = uuid, object = newPet})
else
updatePlayerUi:FireClient(player, {"Notification"}, {{"Pet not owned!","You must own the pet to equip it!"}})
end
end
return updatePlayerUi:FireClient(player, {"PetsOwned", "MovePet"}, {{localData.petsOwned, localData.currentPets}, {petsToReturn}})
end
The client then handles the movement of the pets like so
local petsToMove = {}
runService.RenderStepped:Connect(function()
for i, petTable in pairs(petsToMove) do
local pet = petTable.object
local CharPos = CFrame.new(player.Character.PrimaryPart.CFrame.p)
local Rot = CFrame.Angles(0,math.rad(45*i),0)
local MakeRotation = CharPos * Rot
local SetPosition = MakeRotation * CFrame.new(-5,0,0).p
if player.Character.Humanoid.MoveDirection == Vector3.new(0,0,0) then
pet:SetPrimaryPartCFrame(CFrame.new(SetPosition, player.Character.Head.CFrame.p))
else
pet:SetPrimaryPartCFrame(CFrame.new(SetPosition, player.Character.PrimaryPart.CFrame.p + player.Character.PrimaryPart.CFrame.LookVector * 20))
end
end
end)
local function movePet(pets)
for a,b in pairs(pets) do
table.insert(petsToMove, #petsToMove+1, b)
end
end
I hope this provides all the info needed. I’ve never made a pet system before, so this could probably be optimized more. I’ve also been at this bug for a few days, so I decided to ask around. Thanks!