ProfileHandler is an open-sourced data module developed by @iamtryingtofindname , which makes use of session locking for saving player data and using ordered data stores for backups. It was designed to be intuitive enough for a beginner to understand, while still powerful for experienced scripters. In addition, this module provides the option to save player data using a player instance, but also provides the option to save with a key.
Where can I download it?
You can download and view the module with the following links:
local Players = game:GetService("Players")
local ProfileHandler = require(script.ProfileHandler) -- Reference to module, can be wherever, in this case, parented to the script
local KillsStore = ProfileHandler:GetPlayerStore("Kills") -- Gets a store called 'Kills', which is meant to save player data
Players.PlayerAdded:Connect(function(player) -- When a player joins
local plrKills = KillsStore(player) -- Gets the key for 'player' from the 'Kills' store
local leaderstats = Instance.new("Folder") -- Creating a leaderboard
leaderstats.Name = "leaderstats"
local Kills = Instance.new("IntValue")
Kills.Name = "Kills"
Kills.Parent = leaderstats
Kills.Value = plrKills:Get(0) -- Gets 'Kills' data for player, and updates the leaderboard
plrKills:Bind(Kills) -- Binds the leaderboard 'Kills' to the store
leaderstats.Parent = player -- Finalize the leaderboard
end)
local function incrementKills(player) -- Call this function when you want to increment a player's Kills
local plrKills = KillsStore(player) -- Gets the key for 'player' from the 'Kills' store
-- Now we increment it by 1
plrKills:Increment(1) -- It is that simple!
end
while wait(1) do -- Runs the following code every second
for _,player in pairs(Players:GetPlayers()) do -- Increments for all players
incrementKills(player)
end
end
-- No need to deal with saving data, that is already covered by :GetPlayerStore()!
If you have any questions at all, do not hesitate to post a reply to this thread. Thanks for reading!
This module expands upon datastores. Also, it uses datastores in a way that allows for session locking and backups. It is like a regular datastore, except it is more intuitive and more powerful. So yes, this does use regular datastores, but what this module does is makes it easier to use with more functionality.
Also, backups now, now even a big deal since DataStore 1.1 will support backups internally. (versioning) I literally released DataSave+ 3 days ago, I actually made it 15/20 days ago, and it seems to do the same as what yours does.
As someone who has experience with messing with the berezaa method, I can tell you, it gets quite expensive in the way of how many versions you end up needing to save and such, it gets messy, the way I’m doing is having a main version, and only keeping backups to the developer. I only update the main version when doing session locking, that’s for me personally.
This is a good alternative to use over profile service because this provides easy ways to store player data. Also, this includes backups with ordered data stores, which ProfileService doe snot provide.
This module is really cool and seems useful! Bookmarked.
Adding on to what @iamtryingtofindname said, I agree. I took at look at your module, and it does not seem to make much sense the way it is written. Also, I looked into your code, and I saw some bad practices. For example, in many places, you did this:
if not profiles[self.ProfileStore] then
profiles[self.ProfileStore] = {}
end
when you could simply do this:
profiles[self.ProfileStore] = profiles[self.ProfileStore] or {}
Also, I saw you use newproxy() a lot. I did some research, and it is deprecated, and has pretty much no use. Also, it isn’t entirely clear how to use your module or how it can possibly be better than this one. Also, backups for developers only isn’t really backups.
Since Luau is based on Lua 5.1, which is what Roblox was using, it inherits anything Lua 5.1 had. Therefore it inherited the deprecated state of the newproxy function.
You’re claiming that this module is “powerful” for advanced scripters, how is that? Only a beginner would find the benefits you provided useful. It doesn’t provide any useful functionality which an advanced scripter would find useful.
You would handle it by successively loading data for the key that is session locked and check if the session lock is assumed “dead” or expired, then set it a new session lock and save it.
That is one way to do it, but not the way I resorted to. However, if you wish to do it this way, you can use the Profile:BindToLock function to bind a new function to locking, so you can change the method used.