This module is supposed to handle the data and ban data of players using ProfileStore (updated version of ProfileService), I am not satisfied with the difficulty of reading the code. I have already moved repeating code to helper functions but the code is still rather hard to read, would anyone be willing to provide help of making it more readable and/or optimized?
local dataHandler = {}
-- services
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local SSS = game:GetService("ServerScriptService")
-- modules
local Modules = SSS.Modules
local ProfileStore = require(Modules.ProfileStore)
-- constants
local DATA_TEMPLATE = {
money = 0,
isBanned = false,
}
local BAN_TEMPLATE = {
timesBanned = 0,
history = {},
currentBan = {},
}
-- initialize data
local PlayerData = ProfileStore.New("PlayerData", DATA_TEMPLATE)
local PlayerBanData = ProfileStore.New("BanData", BAN_TEMPLATE)
-- use mock in studio, not live data
if RunService:IsStudio() then
PlayerData = PlayerData.Mock
end
-- active profiles
local Profiles = {}
local BanProfiles = {} -- cache for ban data profiles
-- helper functions
local function cleanupSessions(plr)
local profile = Profiles[plr]
local banCache = BanProfiles[plr]
if banCache then
banCache:EndSession()
banCache[plr] = nil
end
if profile then
profile:EndSession()
Profiles[plr] = nil
end
end
local function safelySaveProfile(profile)
if profile then
local success, err = pcall(function()
profile:Save()
end)
if not success then
warn("failed to save:", err)
end
end
end
local function isValidPlayer(plr)
return plr and plr.Parent == Players
end
-- module functions
-- loads player data and ban data
function dataHandler:loadData(plr)
if not isValidPlayer(plr) then return end
-- loads main profile
local profile = PlayerData:StartSessionAsync(tostring(plr.UserId), {
Cancel = function()
return not isValidPlayer(plr)
end,
})
if profile then
profile:AddUserId(plr.UserId)
profile:Reconcile()
profile.OnSessionEnd:Connect(function()
Profiles[plr] = nil
plr:Kick("profile session ended, please rejoin.")
end)
if isValidPlayer(plr) then
Profiles[plr] = profile
print("loaded player profile: "..plr.Name)
else
profile:EndSession()
end
else
plr:Kick("data couldnt be loaded, rejoin")
end
end
-- saves data
function dataHandler:saveData(plr)
local profile = Profiles[plr]
if profile then
safelySaveProfile(profile)
print("Data saved for " .. plr.Name)
end
end
-- saves data and cleans up sessions
function dataHandler:saveDataOnLeave(plr)
self:saveData(plr)
cleanupSessions(plr)
print(plr.Name .. " left, data saved")
end
-- saves all profiles
function dataHandler:saveAllProfiles()
for plr in pairs(Profiles) do
self:saveData(plr)
end
end
-- gets profile of player
function dataHandler:getProfile(plr)
return Profiles[plr]
end
-- gets bandata
function dataHandler:getBanData(plr)
-- loads ban profile
if BanProfiles[plr] then
return BanProfiles[plr].Data
end
local banProfile = PlayerBanData:StartSessionAsync(tostring(plr.UserId), {
Cancel = function()
return not isValidPlayer(plr)
end,
})
if banProfile then
banProfile:Reconcile()
banProfile:AddUserId(plr.UserId)
BanProfiles[plr] = banProfile
print("Ban data loaded for "..plr.Name)
return banProfile
else
warn("couldnt get ban data for "..plr.Name)
end
end
return dataHandler