Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Why does the table in my module script not sync?

Asked by 4 years ago

Hi everyone!

I wanted to make a keep tools script, but the script(s) don't keep them in the backpack. I used 3 scripts, A module script, which has a table "list of items" in it, a server script which detects player deaths and attempts to put player tools back into their backpack, and a local script, which inserts a tool into the player's backpack and into the "list of items" table.

Here's the module script

local Main = {}

Main.Survivors = {} -- ignore this

Main.ListOfItems = {}

return Main

Here's the server script

local Main = require(game.Workspace.Main)
game:GetService('Players').PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        character:WaitForChild("Humanoid").Died:Connect(function()
            print("Keep Tools Script: " .. player.Name .. " has died")
            local listOfItems = Main.ListOfItems
            print(listOfItems[1]) -- prints "nil"
            print(listOfItems[1] == nil) -- prints "true"
            player.CharacterAdded:Connect(function(Char)
                for i = 1, #listOfItems do
                    local item = listOfItems[i]
                    local itemClone = item:Clone()
                    local player = game.Players:GetPlayerFromCharacter(Char)
                    itemClone.Parent = player.Backpack
                    print("Keep Tools Script: Successfully kept the " .. item .. " item!")
                end
            end)
        end)
    end)
end)

And here's the local script

local Main = require(game.Workspace.Main)
local Cost = 30
local Item = game.Lighting.GOTTIE
script.Parent.MouseButton1Down:Connect(function()
    local player = game.Players.LocalPlayer
    local Coins = player.leaderstats.Coins.Value
    if Coins >= Cost and not player.Backpack:FindFirstChild("GOTTIE") then
        Coins = Coins - Cost
        player.leaderstats.Coins.Value = Coins
        local ItemClone = Item:Clone()
        ItemClone.Parent = player.Backpack
        table.insert(Main.ListOfItems, #Main.ListOfItems + 1, Item)
        print(Main.ListOfItems[1] ==  nil) -- prints "false"
        print(Main.ListOfItems[1]) -- prints "GOTTIE"
    end
end)

For some reason, the local script says that the item is in the "list of items" table, but the server script says otherwise. Aren't they supposed to be one or the other (nil or not nil)?

Any help is appreciated :)

2 answers

Log in to vote
0
Answered by 4 years ago

This is a common misunderstanding on how modules work

A module runs only when you use require and after the first run the result is cached. The cached version is then returned after that.

A module is not shared between devices e.g the server and player. They each have their own copy of the code which they run in their own enviroment. This is why we use remote functions and events.

Please review your logic and use remote events to do action on the server that replicate to all players.

0
Oh ok! Thanks a lot for telling me this, I'll try it out! JustAnotherGaming 48 — 4y
0
Hey, why dont you put the tools into Player.StarterGear, that way Players wont lose the tools unless they leave, and you can use DataStores to prevent that from happening as well Lord_WitherAlt 206 — 4y
Ad
Log in to vote
0
Answered by 4 years ago
Edited 4 years ago

Tables just don't sync across module scripts. If I run:

local tab = {4}
return tab

as a module script then run a script

local tab = require(workspace.modulescript)
tab = {7}

then run this as a script:

print(require(workspace.modulescript)[1])

it would print out 4.

Using a module script like that, it's physically impossible to change the list of items table. For a solution i would recommend using bindable events or bindable functions. They're like remote events and remote functions, except they allow a script to communicate to a script or a local script to communicate with a local script.

In my example I have a bindable function called "GetValue" in workspace and a bindable event called "SetValue". Then a script with the code:

local tab = {}
workspace.GetValue.OnInvoke = function()
    return tab
end
workspace.SetValue.Event:Connect(function(i,v)
    tab[i] = v
end)

and another script with the code:

workspace.SetValue:Fire("robux", 7)
workspace.SetValue:Fire("yes", false)

print(workspace.GetValue:Invoke().robux, workspace.GetValue:Invoke().yes)

this allows for a table that can be synced across scripts (keep in mind that you need to run GetValue to get the updated table). I've also noticed some issues with some of your other code. You're setting the coins and items via a local script. This doesn't replicate to the server. If your code works like this, then an exploiter could easily set their coin amount to whatever they want. When writing code, keep in mind that an exploiter can run whatever code they want as a local script. You can also use remote events and functions almost the same as bindable ones. Remote functions and events allow communication between local and server scripts.

Answer this question