ModuleScript function running without being called

  1. What do you want to achieve?

When the player presses a button, it should send a request to the server to get information from a moduleScript. To prevent exploiters from being able to mess with things like the admin list, operators they shouldn’t have access to, etc, this moduleScript is in ServerScriptService and not replicatedStorage. I use a remoteFunction and serverScript to make the requests and return the data.

This is a localScript inside a button in StarterGui - There’s more code inside this same area but for length it is not included, and none of it messes with this. This is the only line in my game that calls this particular part of the moduleScript so far, but not the only one that calls the remoteFunction.

script.Parent.MouseButton1Down:Connect(function() 
	local operatorPerks = infoManager:InvokeServer("GetOperatorData",script.Parent.Name)
end

When this is sent it goes to this script inside of the ServerScriptService which should call the function from the moduleScript and return what comes back:

game.ReplicatedStorage.Remotes.InfoManager.OnServerInvoke = function(plr,func,content)
	-- Variables --
	local infoManager = require(script.InfoManager)
	
	local switch = {
		["GetOperatorList"] = infoManager:GetOperatorList(plr,content),
		["GetOperatorData"] = infoManager:GetOperatorData(plr,content),
		-- There will be more but these are the only two made so far
		["default"] = function()
			error(script.Name.. ": Unknown Function")
		end
	}
	
	if switch[func] then
		return switch[func]
	else
		return switch["default"]
	end
end

Finally, this is the function in the moduleScript being called. It takes data from the operator’s model and a switch case (which has been removed for length) and then returns it.

function infoManager:GetOperatorData(plr,operatorName)
	warn(script.Name.. ": Operator " ..operatorName.. " Data Requested By " ..plr.Name)

	-- Variables --
	local operators = game:GetService("ReplicatedStorage").Operators
	local operatorPerks = {}
	local operatorLine = ""
	
	-- Switch Case For Operator Lines --
	-- Removed to keep length short
	
	-- Extract Operator Data --
	for _,perk in operators:FindFirstChild(operatorName,true):GetAttributes() do
		table.insert(operatorPerks,perk)
	end
	
	if operatorLineSwitch[operatorName] then
		operatorLineSwitch[operatorName]()
	else 
		operatorLineSwitch["default"]()
	end
	
	return {operatorLine,operatorPerks} 
end
  1. What is the issue?

The function in the moduleScript is running when it shouldn’t. It runs once for each folder I have that contains an operator (which is 4. We have 4 separate groups) and uses those folder names as the “operatorName”. I have no idea what it causing this, since the above code is the only code that calls this function (but it is not the only code that calls the remoteFunction, so maybe that’s a reason?)
image

  1. What solutions have you tried so far?
    I could not find anything helpful on the developer forum or Youtube for this. Nobody else in my team does scripting either, so they aren’t of much help in this regard.

Is this the right way to go about trying to make sure people don’t exploit and gain access to operators they don’t have? I suppose that’s a different question, but this seems a bit overcomplicated and was the best we could come up with, so any suggestions on another system are also welcome.

I didn’t quite understand your question. You said that the function is called 4 times and has 4 warnings in the output. Isn’t it happening as it should?

Sorry if it’s not clear. The function should not be running at all, because it should only run when I press a button. For some reason, it’s running immediately when I start the game.

Can I see the structure of your UI?

I assume you mean this. It’s sort of a nightmare, sorry. ViewScript is the script that calls the remoteFunction when ViewButton is pressed.

RemoteFunction:
image

ModuleScript in question:
image

If that’s not what you meant lmk, I’m still pretty new to this stuff.
It should be noted that I have a script that copies the viewport frames for every operator and then renames the buttons to the operator’s name, which is what is passed as the “content” name if that makes sense.