Converting a ModuleScript to a Server Script

hey all,
i’ve encountered a rather unique challenge.
i need to have an easily editable list of values (numbers, strings, keycodes, brickcolors, and bools) that several scripts can read. i have a modulescript that does this perfectly, but i need to switch to using a serverscript instead (for various reasons)
i’ve tried using things like bindableevents and bindablefunctions but i can’t really figure out how to make them work, and nobody else seems to have a similar issue so i can’t find how someone else did it; this is why i want to ask you guys how you would go about doing this. thanks in advance

1 Like

Could you give your reasons?

[dont mind this]

1 Like

Something like this?

local data = {}
local bf = --bindable function

bf.OnInvoke = function(request, sentdata)
	if request == "changedata" then
		data = sentdata
	end
	
	return data
end

Now, I put the function like this for multiple reasons. For one, it makes it much easier to actually change the data, and also return the data. The only issue with this is the fact that every script that uses the data will need to refresh the data before using it every time. Now, there is a way to solve this, but it can be a bit annoying.

local data = {}
local bf = --bindable function
local scripts = {}

bf.OnInvoke = function(request, sentdata, requesting)
	if not table.find(scripts, requesting) then
		table.insert(scripts, requesting)
	end
	
	if request == "changedata" then
		data = sentdata
		
		for i,v in pairs(bf:GetChildren()) do
			if v:IsA("ObjectValue") and v.Value:IsA("Script") then
				v:Destroy()
			end
		end
		
		for i,v in pairs(scripts)
			if v ~= requesting then
				local ov = Instance.new("ObjectValue")
				ov.Name = v.Name
				ov.Value  = v
				ov.Parent = bf
			end
		end
	end
	
	for i,v in pairs(bf:GetChildren()) do
		if v:IsA("ObjectValue") and v.Value == requesting then
			v:Destroy()
		end
	end
	
	return data
end

Now, this may be a bit complicated, but it should work as you want. So, to change the data, it would look something like this:

local bf = --bindable function
local data = bf:Invoke("changedata", {a = 4}, script)
--data would usually be defined before changing, but whatever you need.

Also, to check before using the current data the script has, you can check if it needs updating like so:

local bf = --bindable function
local data = bf:Invoke(nil, nil, script)

--later on
for i,v in pairs(bf:GetChildren()) do
	if v:IsA("ObjectValue") and v.Value == script then --script hasn't been updated
		data = bf:InvokeServer(nil, nil, script) --nil, nil since no request or data to send
	end
end

print(data)

tl;dr you can view modulescripts with exploits

Just put it inside ss or sss, simple as heck

4 Likes

One thing that I’ve done was copy the module script into a server script, then redefine all the functions.

Convert a module script like this:

someModule = {}

someModule.someFunction = function(someParam)
	-- So something
end

return someModule

…into a server script like this:

local function someFunction(someParam)
	-- Do Something
end

And that’s all there is to it. You will need to change all the function references in the new script though.

@aobunau getdownhacktomen means ServerStorage or ServerScriptService. Unless you want to convert the code to an actual server script, this is the best way to do it.

1 Like

that isn’t viable because i’m making a model and not a game

A model?

I assume you mean something that you’re going to publish to the marketplace?

If I’ve assumed correctly, then I would include a README that instructs the user as to where to put things.

ModuleScripts can be read by the server when in ServerScriptService, but not by the client.

i’d like it to be self-contained because you’re supposed to be able to have more than one in a single game

That’s good if you are publishing something to the marketplace. The problem is if you have a bunch of copies of the same model, then if the script needs to be updated, you have to do one of two things:

  1. Change each and every script.
  2. Change the script in a model and then copy that model everywhere it needs to be.

Neither are exactly feasible if you have hundreds of copies of the same model.

well there’s not really any time the script would need to be updated - the only time the scripts really need to read the data would be when the model is initialized

One thing that I’ve done is have folders in the workspace for active parts. You place all the parts/models in these folders, set attributes for anything specific that needs to be handled, and let one common script handle it.

necropost but, how would you deal with ‘self’?

If you’re dealing with self, then that means that it’s a class and you do not convert it to a script. Those you keep as a module script.