This is a question abt the datastore wrapper, profilestore, this is my first time doing anything datastore related
I want to load a profile from a key, which contains the players userid and a special number made into a string, loading, getting and deleting this works fine in the start place, which is where theyre created, but returns nil, kicking me in any other place, i believe this is due to me creating a new profilestore in the other place (using ProfileStore.new) with the same name as the one that holds the profiles in the start place, although it may not be, because when i check the sessioncount after loading into the second place on a new profile, it’s 2, how do i use the same store as normal?
Start Place
local Players: Players = game:GetService("Players")
local RunService:RunService = game:GetService("RunService")
local ServerScriptService: ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage: ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ServerScriptService.Modules
local Remotes = ReplicatedStorage.Remotes
local ProfileStore = require(Modules.ProfileStore)
local UpdateSlots: RemoteEvent = Remotes.UpdateSlots
local GetData: RemoteEvent = Remotes.GetData
local ErrorMessages = {
["ServerShutdownDuringLoad"] = "Server cooked your data, rejoin",
["SessionLocking"] = "Data error, rejoin"
}
local function GetStoreName()
return RunService:IsStudio() and "Test" or "Live"
end
--Access Player Data
local ProfileTemplate = require(Modules.ProfileTemplate)
local SlotTemplate = require(Modules.SlotTemplate)
local DataManager = require(Modules.DataManager)
local PlayerStore = ProfileStore.New(GetStoreName(), ProfileTemplate)
local SlotStore = ProfileStore.New(GetStoreName().. "_Slots", SlotTemplate)
--Player has fully loaded
local function Initialize(Player: Player, Profile: typeof(PlayerStore:StartSessionAsync()))
--Admin checks
if table.find(DataManager.AdminList, Player.UserId) then
Profile.Data.Admin = true
else
Profile.Data.Admin = false
end
local Profiles = {}
for _, ID: number in Profile.Data.Slots do
local SlotProfile = DataManager:GetSlotData(SlotStore, Player, ID)
table.insert(Profiles, SlotProfile.Data.ID,{
["Data"] = SlotProfile.Data,
["Key"] = SlotProfile.Key
})
end
GetData:FireClient(Player, Profiles)
end
--Creates & stores player profiles
local function PlayerAdded(Player: Player)
--Start new session on Profile
local Profile = PlayerStore:StartSessionAsync("Player_".. Player.UserId, {
Cancel = function ()
return Player.Parent ~= Players
end,
})
--Sanity check
if Profile == nil then
--Server shutdown while loading
Player:Kick(ErrorMessages.ServerShutdownDuringLoad)
else
Profile:AddUserId(Player.UserId) --GDPR compliance
Profile:Reconcile() -- Fill in missing data from ProfileTemplate (optional)
--Session locking
Profile.OnSessionEnd:Connect(function()
DataManager.Profiles[Player.Name] = nil
Player:Kick(ErrorMessages.SessionLocking)
end)
if Player.Parent == Players then
DataManager.Profiles[Player.Name] = Profile
Initialize(Player, Profile)
else
Profile:EndSession()
end
end
end
--Early joiners
for _, Player: Player in Players:GetPlayers() do
task.spawn(PlayerAdded, Player)
end
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(function(Player: Player)
local Profile: typeof(PlayerStore:StartSessionAsync()) = DataManager.Profiles[Player.Name]
if not Profile then
return
end
Profile:EndSession()
DataManager.Profiles[Player.Name] = nil
end)
--Remotes
UpdateSlots.OnServerEvent:Connect(function(Player: Player, Function: string, ID: number)
local Profile: typeof(PlayerStore:StartSessionAsync()) = DataManager.Profiles[Player.Name]
if not Profile then
return
end
if Function == "Start" then
DataManager:StartSlots(SlotStore, Player)
local Profiles = {}
for _, ID: number in Profile.Data.Slots do
local SlotProfile = DataManager:GetSlotData(SlotStore, Player, ID)
table.insert(Profiles, SlotProfile.Data.ID,{
["Data"] = SlotProfile.Data,
["Key"] = SlotProfile.Key
})
end
GetData:FireClient(Player, Profiles)
elseif Function == "Wipe" then
DataManager:WipeSlots(SlotStore, Player, ID)
local Profiles = {}
for _, ID: number in Profile.Data.Slots do
local SlotProfile = DataManager:GetSlotData(SlotStore, Player, ID)
table.insert(Profiles, SlotProfile.Data.ID, {
["Data"] = SlotProfile.Data,
["Key"] = SlotProfile.Key
})
end
GetData:FireClient(Player, Profiles)
end
end)
GetData.OnServerEvent:Connect(function(player: Player)
GetData:FireClient(player, DataManager:GetProfileData(player))
end)
First Place DataManager
local DataManager = {}
local Players: Players = game:GetService("Players")
local RunService:RunService = game:GetService("RunService")
local ServerScriptService: ServerScriptService = game:GetService("ServerScriptService")
local Modules = ServerScriptService.Modules
local ProfileStore = require(Modules.ProfileStore)
local SlotTemplate = require(Modules.SlotTemplate)
local function GetStoreName()
return RunService:IsStudio() and "Test" or "Live"
end
DataManager.AdminList = {
}
table.freeze(DataManager.AdminList)
--Store ProfileStore profiles
DataManager.Profiles = {}
function DataManager:GetSlotData(SlotStore: typeof(ProfileStore), Player: Player, ID: number)
local SlotProfile = SlotStore:GetAsync("Player_".. Player.UserId.. "_Slot_".. ID)
if SlotProfile then
return SlotProfile
else
return
end
end
--Starts a profile with an ID or if a profile doesn't exist for that ID, it creates one.
function DataManager:StartSlots(SlotStore: typeof(ProfileStore), Player: Player)
local Profile = DataManager.Profiles[Player.Name]
if not Profile then
return
end
local RandNum: number = nil
repeat
RandNum = math.random(1, 999999999)
until
not table.find(Profile.Data.Slots, RandNum) and RandNum > 0
local newKey = "Player_".. Player.UserId.. "_Slot_".. RandNum
local SlotProfile = SlotStore:StartSessionAsync(newKey, {
Cancel = function ()
return Player.Parent ~= Players
end,
})
--Sanity check
if SlotProfile == nil then
--Server shutdown while loading
Player:Kick("Server cooked your slots data, rejoin")
else
SlotProfile:AddUserId(Player.UserId) --GDPR compliance
SlotProfile:Reconcile() -- Fill in missing data from SlotTemplate (optional)
--Session locking
SlotProfile.OnSessionEnd:Connect(function()
if Player.Parent == Players then
else
DataManager.Profiles[newKey] = nil
Player:Kick("Slot data error, rejoin")
end
end)
if Player.Parent == Players then
DataManager.Profiles[newKey] = SlotProfile
SlotProfile.Data.ID = RandNum
table.insert(Profile.Data.Slots, RandNum)
SlotProfile:EndSession()
DataManager.Profiles[newKey] = nil
else
SlotProfile:EndSession()
end
end
end
--Deletes a profile of the provided ID
function DataManager:WipeSlots(SlotStore: typeof(ProfileStore), Player: Player, ID: number)
if ID == nil then
warn("ID cannot be nil")
end
local Profile = DataManager.Profiles[Player.Name]
if not Profile then
return
end
local SlotProfile = DataManager:GetSlotData(SlotStore, Player, ID)
if SlotProfile then
SlotStore:RemoveAsync(SlotProfile.Key)
table.remove(Profile.Data.Slots, table.find(Profile.Data.Slots, ID))
else
return
end
end
return DataManager
Second Place
local Players = game:GetService("Players")
local ReplicatedStorage: ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService: ServerScriptService = game:GetService("ServerScriptService")
local RunService: RunService = game:GetService("RunService")
local ServerModules: Folder = ServerScriptService.Modules
local ProfileStore = require(ServerModules.ProfileStore)
local GetData: RemoteEvent = ReplicatedStorage.Remotes.GetData
local function GetStoreName()
return RunService:IsStudio() and "Test" or "Live"
end
--Access Player Data
local ProfileTemplate = require(ServerModules.ProfileTemplate)
local SlotTemplate = require(ServerModules.SlotTemplate)
local DataManager = require(ServerModules.DataManager)
local PlayerStore = ProfileStore.New(GetStoreName(), ProfileTemplate)
local SlotStore = ProfileStore.New(GetStoreName().. "_Slots", SlotTemplate)
local ErrorMessages = {
["SessionLocking"] = "Data error, rejoin"
}
local function Initialize(Player: Player, Profile: typeof(PlayerStore:StartSessionAsync()), SlotProfile: typeof(PlayerStore:StartSessionAsync()))
print(Profile, SlotProfile)
end
local function onPlayerAdded(Player: Player)
local joinData = Player:GetJoinData()
local teleportData: Instance? = joinData.TeleportData
GetData:FireClient(Player)
--Start new session on Profile
local Profile = PlayerStore:GetAsync("Player_".. Player.UserId)
--Start new session on SlotProfile
local SlotProfile = SlotStore:StartSessionAsync("Player_".. Player.UserId.. "_Slot_".. teleportData.ID, {
Cancel = function ()
return Player.Parent ~= Players
end,
})
--Sanity check
if SlotProfile == nil then
--Server shutdown while loading
Player:Kick("Server cooked your profile data, rejoin")
else
SlotProfile:AddUserId(Player.UserId) --GDPR compliance
SlotProfile:Reconcile() -- Fill in missing data from SlotTemplate (optional)
--Session locking
SlotProfile.OnSessionEnd:Connect(function()
DataManager.Profiles[SlotProfile.Key] = nil
Player:Kick("Slot data error, rejoin")
end)
if Player.Parent == Players then
DataManager.Profiles[SlotProfile.Key] = SlotProfile
Initialize(Player, Profile, SlotProfile)
else
SlotProfile:EndSession()
end
end
end
--Early joiners
for _, Player: Player in Players:GetPlayers() do
task.spawn(onPlayerAdded(), Player)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(function(Player: Player)
--WIP
local Profile: typeof(PlayerStore:StartSessionAsync()) = DataManager.Profiles["Player_".. Player.UserId.. "_Slot_"]
if not Profile then
return
end
Profile:EndSession()
DataManager.Profiles[Player.Name] = nil
end)
Players.PlayerAdded:Connect(onPlayerAdded)
(80% of this is from a tutorial, seconds places datamanager only has 1 table)