Hey!
I’m currently working on redo-ing my game’s way of storing and checking player data.
The way I’d like to do this is storing it inside of a ModuleScript inside of replicatedstorage.
The client only ever needs data for visuals and is told by the server what to do and when to do it, so I don’t see any issue with this.
A serverscript placed under SSS would handle player joining, leaving, data changing, and data saving.
I am not very experienced with handling data; Is this okay to do? Could anyone second this before I actually start making this? To my understanding this should be fine, but I’d like to know any pointers or flaws this could have
Store the UserIDs not the player objects themselves.
local PlayerData = {}
PlayerData.Players = {} -- Will contain our User IDs
-- Add a new player when they join
game:GetService('Players').PlayerAdded:Connect(function(player)
table.insert(PlayerData.Players, {
id = player.UserId,
coins = 0 -- Just an example of data
})
end)
-- Remove the player when they leave
-- You could also implement DataStore data saving here
game:GetService('Players').PlayerRemoving:Connect(function(player)
for index, data in pairs(PlayerData.Players) do
if data.id == player.UserId then
table.remove(PlayerData.Players, index)
break
end
end
end)
-- An example utility functions for manipulating data
-- Here we can safely accept a player
function PlayerData:SetCoins(player: Player, coins: number)
-- Same concept as when the player is remvoing just find their data and update their coins
end
return PlayerData
When you require this script by the server its shared across the entire server. All data is persistent across the server. If you were to require this by the client the data would not match since that’s a breach of the server client boundary. In order to query the data from the client you need to setup a RemoteFunction and return the data the client wants from the server.
Yes, it is fine to do it and you can use a normal module or with metatables, here is an example of both
Normal module
local Storage = {}
return {
Set = function(Player, Table)
if not Storage[Player] then Storage[Player] = {} end
for Key, Value in pairs(Table or {}) do
Storage[Player][Key] = Value
end
return Storage[Player]
end,
Get = function(Player, Key)
local Info = Storage[Player]
return Info and Info[Key]
end,
}
-- In another script
local Module = require() -- Module location
Module.Set(Player, {Sword = 1})
print(Module.Get(Player, "Sword")) -- 1
Module.Set(Player, {Sword = 0})
print(Module.Get(Player, "Sword")) -- 0
metatable
local M, Storage = {}, {}
M.__index = M
--// Module base
function M.SetUp(Player, Table)
local NewEntry = setmetatable({}, M)
NewEntry.Storage = Table or {}
Storage[Player] = NewEntry
return NewEntry
end
function M.GetData(Player)
return Storage[Player]
end
--// Methodos
function M:Get(Key)
local Table = self.Storage
return Table[Key] or Table
end
function M:Set(Table)
for Key, Value in pairs(Table or {}) do
self.Storage[Key] = Value
end
end
return M
-- In another script.
local Module = require() -- Module location
local Storage = Module.SetUp(Player, {Sword = 1})
print(M:Get("Sword")) -- 1
M:Set({Sword = 0})
print(M:Get("Sword")) -- 0
Both must have functions that allow you to edit and retrieve the data. PS: for security, it should be only for the server, since I think that the players can see the information of another.
So I’ve been learning how to use metatables lately and I think I’m going to go with that
Question, if a hacker requires the module and sets data (on the client ofcourse), will the server be able to see this? The module would be inside of replicatedstorage.