Help with getting data from module script using a local script

For my game I made an avatar editor… However, I have a local script when the player clicks a “Play” button that checks if the player has saved a character before. It uses a remote function to a script that returns the value from a module. It works with 1 player, but when i have multiple players it always returns “Yes” instead of “No”. How would I fix this? Or is there a better way to check this?

Here is local script:

script.Parent.PlayButton.MouseButton1Click:Connect(function()

 script.Parent.PlayButton.Visible = false
  local send = GetTableEvent:InvokeServer("Character")
  if send == "No" then

   game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 0
   game.Workspace.CurrentCamera.CameraType = "Scriptable"
   game.Workspace.CurrentCamera.CFrame = 
   game.Workspace.CurrentStuff.AvatarEditor.Camera.CFrame
   script.Parent.Parent.AvatarEditorFrame.Visible = true

  elseif send == "Yes" then

  print("HasCharacter")

 end

end)

Here is the normal script:

local GetTableEvent = game.ReplicatedStorage.Stuff.GetFromTable

local DataModule = require(game.ReplicatedStorage.Modules.MainData)

  function ReturnValue(plr,value)

    local NewVal = DataModule:GetFromTable(plr, value)

    return NewVal

    end

GetTableEvent.OnServerInvoke = ReturnValue

And Finally Here is the Module:

function PlayerStatManager:GetFromTable(player, statName)

  local playerUserId = 'Player_" .. player.UserId

  local SendBack = sessionData[playerUserId][statName]

 return SendBack

end

return PlayerStatManager
1 Like

You aren’t going to get help effectively with that unindented code. We can’t read that thing. and only post the codes that are relevant. I also do not see anywhere where you return “Yes” or “No”.

Okay I tried re-organizing it…

The problem seems to be with sessionData containing undesired data. Would you be able to provide the code that updates sessionData?

The wildest guess I’m going to make here is that there is a massive discrepancy between the data that the module is able to reasonably get and your own code. What are you using to add data to the table? There is no way that the only code you have in your PlayerStatManager Module is a singular function.

Here is the rest of the module:

 local PlayerStatManager = {}

 local sessionData = {}

 local Main = {

   ["Name"] = nil,

   ["Tokens"] = 0,

   ["TutorialMayor"] = "No",

   ["Character"] = "No",

   ["AlienTrigger"] = "No",

}

local DataStoreService = game:GetService("DataStoreService")

local playerData = DataStoreService:GetDataStore("PlayerDataTest26)

local AUTOSAVE_INTERVAL = 70

   function PlayerStatManager:ChangeValue(player, statName, value)

    local playerUserId = "Player_" .. player.UserId

    sessionData[playerUserId][statName] = value

    print(sessionData[playerUserId][statName])

end

-- Function to add player to table

   local function setupPlayerData(player)

   local playerUserId = "Player_" .. player.UserId

   local success, data = pcall(function()

  return playerData:GetAsync(playerUserId)

end)

if success then

if data then

-- Data exists for this player

 sessionData[playerUserId] = data

else

-- Data store is working, but no current data for this player

sessionData[playerUserId] = Main

end

else

warn("Cannot access data")

end

end

-- Function to save player's data

local function savePlayerData(playerUserId)

  if sessionData[playerUserId] then

    local success, err = pcall(function()

    playerData:SetAsync(playerUserId, sessionData[playerUserId])

end)

if not success then

warn("Cannot save data")

end

end

end

-- Function to save player data on exit

 local function saveOnExit(player)

 local playerUserId = "Player_" .. player.UserId

 savePlayerData(playerUserId)

end

 local function autoSave()

 while wait(AUTOSAVE_INTERVAL) do

  for playerUserId, data in pairs(sessionData) do

   savePlayerData(playerUserId)

end

end

end

spawn(autoSave) -- runs auto save

game.Players.PlayerAdded:Connect(setupPlayerData)

game.Players.PlayerRemoving:Connect(saveOnExit)

You are referencing the same table here, not setting a new one for each player.

What should i change it to?

Instead of setting it at the top of script, put it in the function.

I would do something like this.

-- Data store is working, but no current data for this player
sessionData[playerUserId]  = {} -- I habitually define the table first
sessionData[playerUserId] = {["Name"] = nil,["Tokens"] = 0,["TutorialMayor"] = "No",["Character"] = "No",["AlienTrigger"] = "No"}

Or you could probably do

local Main = {["Name"] = nil,["Tokens"] = 0,["TutorialMayor"] = "No",["Character"] = "No",["AlienTrigger"] = "No"}
sessionData[playerUserId] = Main

The issue OP is facing is that tables are passed by reference, not by value. Assigning an existing table to a new index is just going to reference that old table and the changes already made to it. (As elaboration why the above works)

You should note though, that your first snippet of code has a ‘habit’ that is entirely redundant; functionally nothing changes, but in practice you are reserving memory for a new table ( {} is the constructor for tables, you are constructing a new one two times ) and then drop all references to it to reserve more memory for another new table. Removing the line entirely changes nothing in the result but uses less memory. Normally habits are fine, but if they are wasting resources it’s worth to take note and stop doing it.

2 Likes

So the ideal solution then would be something simple, like this?

-- Data store is working, but no current data for this player
sessionData[playerUserId] = {["Name"] = nil,["Tokens"] = 0,["TutorialMayor"] = "No",["Character"] = "No",["AlienTrigger"] = "No"}
1 Like

That would indeed be sufficient. To customize it further it’s a thought to instead assign the result of a function that generates the starter table with a few possible presets (from args given), but anything works as long as the table returned is a new one and not a reference to the default itself.

1 Like