Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Why does the table in my module script not sync?

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

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.

2 comments

0

Oh ok! Thanks a lot for telling me this, I'll try it out!

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

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.

This discussion is preserved as it was. New answers, comments, and votes are closed.