Module script for server and client?

is there a way to use a module script for the clients and server to access the same data. because ive been searching for an answer and simply cant find one.

im setting data in the module script on the server side and then attempting to access that data from the client side.

You would still need to send and retrieve data from the server through a remote event. But you can still use a module script for this and have events set up to listen for client requests to read and set data.

1 Like

this was my back up plan i just wanted to be able to do it mostly through client for sake of efficiency but if this is the only way then thank you for taking time to reply

Yes you can.

Module script gets cached once per environment. Meaning once you have called require, the module script will get cache, any other place that tries to use it will be using the same copy.

You can store something inside of it like a variable and that variable can be access using multiple Local Script or Server Script.

You can also edit them provided that you have the right function to change them.

I use module script to maintain and keep track of player data.
This way I avoid doing anything on the client side or keeping any data on them.

sooooooo i have to do require module script after i make changes to it so it gets cached?

No you call module scripts first to be cached first.

Then you can use the variables and functions inside of it.

https://www.roblox.com/library/6346222785/Shared-Server-Client-Data

Here is what the script looks like:

if (game:GetService("RunService"):IsServer()) then
	local serverModule = {}
	local data = {} -- data is kept on the server
	
	-- serverside getter/setter is simple
	serverModule.Get = function(index)
		return data[index]
	end
	serverModule.Set = function(index, value)
		data[index] = value
		script.ChangedServer:Fire(index, value)
		script.ChangedClient:FireAllClients(index, value)
	end
	
	serverModule.Changed = script.ChangedServer.Event
	
	-- client requests call the server getter/setters
	script.Get.OnServerInvoke = function(user, index)
		return serverModule.Get(index)
	end
	script.Set.OnServerEvent:Connect(function(user, index, value)
		serverModule.Set(index, value)
	end)
	
	return serverModule
else
	local clientModule = {}
	
	-- instead of changing the table the client methods send requests for the server to change
	clientModule.Get = function(index)
		return script.Get:InvokeServer(index)
	end
	clientModule.Set = function(index, value)
		script.Set:FireServer(index, value)
	end
	
	clientModule.Changed = script.ChangedClient.OnClientEvent
	
	return clientModule
end

It wraps a remote event and function on the client side so clients can “ask” the server to change values on the server-sided table. I also threw in the ability to listen for events that fire when a value is changed from either side.

Clients that require a shared module don’t get the same table that is returned when the server calls it. So instead each client gets a table of helper functions that looks identical to the server table, except their functions just invoke the server table’s functions.

And to state the obvious, while this is an interesting implementation of module scripts, it is not a safe place to store important information like leaderboard stats since any client can change values in this global table. (Unless you add sanity checks to the server’s listener for the Set event, or disable the client’s Set ability altogether.)

1 Like

well why doesnt this work then when thats what im doing (this is just a simplified version of my code but the main bits)

server script:

local PlayerDataModule = require(game.ReplicatedStorage.Events.Time.PlayerModule)

game.Players.PlayerAdded:Connect(function(Player)
	--make sure names matches what we have stored
	local UserID = tostring("Player"..Player.UserId)
	local Name = Player.Name
	local StoredName = IDsToNameDataStore:GetAsync(UserID)
	if Name ~= StoredName then
		IDsToNameDataStore:SetAsync(UserID, Name)
	end
	--retrieve data
	local HighestTimeData = HighestTimeDataStore:GetAsync(UserID)
	local OverallTimeData = OverallTimeDataStore:GetAsync(UserID)
	PlayerDataModule:SetData(Player.Name, HighestTimeData, OverallTimeData)
end)

module script:

local Data = {}
local PlayersNData = {testperson = {11, 5959 , 111}}

function Data:SetData(Player, HighestTime, TotalTime)
	if HighestTime == nil or HighestTime == 0 then
		PlayersNData[Player] = {0, 0, 0}
	else
		PlayersNData[Player] = {0, HighestTime, TotalTime}
	end
end

function Data:RemoveData(Player)
	PlayersNData[Player] = nil
end

function Data:IncrementData()
	for I,V in pairs(PlayersNData)do
		print("i =", I,"v =", V)
		if V[1] >= V[2]then
			V[2]=V[2]+1
		end
		V[1]=V[1]+1
		V[3]=V[3]+1
	end
end

function Data:GetData(Player)
	print(PlayersNData[Player])
	print(PlayersNData.testperson[1])
	return PlayersNData[Player]
end

return Data

local script:

local PlayerDataModule = require(game.ReplicatedStorage.Events.Time.PlayerModule)
TimePulse.OnClientEvent:Connect(function()
	print(LocalPlayer.Name)
	local Data = PlayerDataModule:GetData(LocalPlayer.Name)
	print(Data) -- prints nill 
end)

when i try printing the whole table from the client side it prints just the test person even though the server has put my data into it

Put a module in ReplicatedStorage and a script in ServerScriptService to change them, if the client changes them, the others and the server will not see it (also it will not be saved)

the module is already in replicated storage and the script in ServerScriptService

thank you very much for this but i think your original solution is best. itll be RemoteEvents or RemoteFunctions in the end anyway but thanks for all the help.

That was my original solution. The actual data is kept on the server and clients use remote events and functions to access it.

Why don’t you take the data by the table?

local PlayerDataModule = require(game.ReplicatedStorage.Events.Time.PlayerModule)
TimePulse.OnClientEvent:Connect(function()
    print(LocalPlayer.Name)
    local Data = PlayerDataModule[LocalPlayer.Name]
    print(Data) 
end)

it is however im not going to be using your second post because the clients dont need to fire events to access it because they just need the data at regular intervals so im just going to fire it to them with an event at regular intervals.

originally my server script was just firing all clients like “its time to get data” at regular intervals but now ill just fire each client individually with their individual data.

1 Like