Is it fine to have a modulescript in replicatedstorage that has values the server changes, and the client can access? Or should I use attributes instead?.
If I were to use attributes I’d have 15 total including other attributes per player. But if I use this table it would be 8 attributes + this table.
local Template = {
Cash = 1,
Level = 1,
Xp = 1,
NeededXp = 1,
MaxHealth = 1,
Stamina = 1,
MaxStamina = 1,
}
local PlayerStats = {}
PlayerStats.Stats = {}
function PlayerStats:SetNewStats(PlayerName : string, NewData : {})
if not PlayerStats.Stats[PlayerName] then
PlayerStats.Stats[PlayerName] = Template
end
for Entry, Change in NewData do
if PlayerStats.Stats[PlayerName][Entry] then
PlayerStats.Stats[PlayerName][Entry] = Change
end
end
end
function PlayerStats:GetStats(PlayerName : string)
if PlayerStats.Stats[PlayerName] then
return PlayerStats.Stats[PlayerName]
end
end
function PlayerStats:RemoveStats(PlayerName)
if PlayerStats.Stats[PlayerName] then
PlayerStats.Stats[PlayerName] = nil
end
end
return PlayerStats
I would avoid giving the client access to stats in any way other than to read them.
Personally how I usually handle player data is by setting attributes on the player object, this way the client can read them and the server can change them. It’s also easy for my data handler to create data which can then be easily used by my other server scripts.
When the player joins the attributes are generated and populated with either default data or player data found in the DataStore. When the player leaves these attributes are then organized back into a table and saved to the DataStore.
I’m not too sure why setting attributes would create more variables than not though?
You can use JSONDecode and JSONEncode to store tables in singular string values.
Here’s an example:
local HTTPService = game:GetService("HttpService")
local CollectedRewards = {
one = false,
two = false,
three = true,
};
game.Players.PlayerAdded:connect(function(Player)
Player:SetAttribute("CollectedRewards", HTTPService:JSONEncode(CollectedRewards))
local PlayersCollectedRewards = HTTPService:JSONDecode(Player:GetAttribute("CollectedRewards"))
print(PlayersCollectedRewards.three) -- true
end)
Can I ask why not just put the players data module in server script, the server can make changes and it can be sent to the client through remote event or function? Client can’t change anything on it, just read it.
I tried doing that but the event kept getting dropped even after the character was loaded in.
In studio it worked, but in the actual game the server would send everything before the OnClientEvent was actually there or something.
local DoneLoadingClient = StateMachine.New(player.Name, player)
if DoneLoadingClient then
local Data = profile.Data.Client
Network:FireClient("ValueChange", player, {
Cash = Data.Cash,
Level = Data.Level,
Xp = Data.EXP,
NeededXp = DataManager:RequestNeededEXP(player),
MaxHealth = Data.MaxHealth,
Stamina = Data.MaxStamina,
MaxStamina = Data.MaxStamina,
})
end
end