How to call module script from the server instead of client?

I’ve been diving into module scripts and I know that its depended on the script that requires it whether its going to be on the server or client but I would like it to be on the server. However, you cannot use UserInputService on a server script so everything that happens will be on the client and I can’t figure a way around this. Could anyone help?

LocalScript:

local GameFolder = game.ReplicatedStorage.GameFolder
local Modules = GameFolder.Modules
local PearlModule = require(Modules.PearlAbilities)
local Debounce = true

local UserInputService = game:GetService("UserInputService")
UserInputService.InputBegan:Connect(function(hit, chat)
	if chat then return end
	local ActivateAbility = PearlModule[hit.KeyCode] 
	if ActivateAbility and Debounce == true then
		local Cooldown = ActivateAbility.Cooldown
		Debounce = false
		ActivateAbility.Activate()
		wait(Cooldown)
		Debounce = true
	end
end)

ModuleScript:

local TweenService = game:GetService("TweenService")
local Players = game.Players
local Cooldown = nil
local Abilitys = {
	[Enum.KeyCode.Q] = {
		
		Activate = function(Player)
			local Character = Players.LocalPlayer.Character
			local Gem = Character:WaitForChild("Gem")

			if Gem.Light.Brightness == 0 then
				Gem.Material = Enum.Material.Neon
				TweenService:Create(Gem.Light,TweenInfo.new(1), {Brightness = 10} ):Play()

			else
				Gem.Material = Enum.Material.SmoothPlastic
				TweenService:Create(Gem.Light,TweenInfo.new(0.5), {Brightness = 0} ):Play()
			end
		end,
		Cooldown =  1.1
	},
	[Enum.KeyCode.F] = {
		Activate = function(Player)
			local Character = Players.LocalPlayer.Character
			local Humanoid = Character:WaitForChild("Humanoid")
			local Health = Humanoid.Health
			local MaxHealth = Humanoid.MaxHealth
			local timer = 15
			
			print(Character.Name)
		end,
		Cooldown =  5

	}
}


return Abilitys
1 Like

you could fire a remote event and send the information to the server
then the server would handle the debounce, cooldown, and the function

replace event with the remote event location

Server

local event = game:GetService("ReplicatedStorage").RemoteEvent

local Modules = game:GetService("ReplicatedStorage").GameFolder.Modules
local PearlModule = require(Modules.PearlAbilities)
local playerDebounces = {}

event.OnServerEvent:Connect(function(player, input)
	-- Creates a table for that player if it doesn't exist
	if playerDebounces[player] == nil then
		playerDebounces[player] = {}
	end
	
	-- Checks if input is not an Enum and if there is debounce
	if typeof(input) ~= "EnumItem" and playerDebounces[player][input] then return end
	
	-- make a debounce for that specific keycode
	playerDebounces[player][input] = true
	
	-- If it finds that ability then fire it and wait until setting debounce to nil
	local ability = PearlModule[input]
	if ability then
		-- Fire the function on a pcall just incase it errors
		pcall(function()
			ability.Activate(player) -- This will be server-sided
		end)
		task.wait(ability.Cooldown)
	end
	
	-- Gets rid of the debounce set on that key
	playerDebounces[player][input] = nil
end)

In the client we will just fire the “Abilities” event with hit as the argument

Client

local event = game:GetService("ReplicatedStorage").RemoteEvent

UIS.InputBegan:Connect(function(hit, chat)
	if chat then return end
	
	event:FireServer(hit)
end)

You might want to relocated the module script inside ServerScriptService or inside the server script and make sure it uses server side arguments instead. This is because you are no longer requiring the module on the client and the function is now called on the server. LocalPlayer will no longer work under this circumstance.

I would also get rid of any :WaitForChild()'s because everything is already loaded on the server assuming you created the gem, or other instances on the server side.

eg:

local Abilities = {
	[Enum.KeyCode.F] = {
		
		-- This argument will be the player instance itself.
		-- To call this in the server you would simply do
		-- `ability.Activate(player)` with the script above ^^^
		
		Activate = function(player)
			local character = player.Character
			local humanoid = character:FindFirstChild("Humanoid")
		end
	}
}
1 Like

I’m getting this error

17:15:35.758 ServerScriptService.Script:16: table index is nil - Server - Script:16

Is this error from the script they gave you? I counted 16 lines but the 16th line is all comments…

Yes , It’s line 16 (Character Limit)

For me, line 16 is this:

Have you made sure you haven’t missed anything important?

That part I don’t understand because there is already a cooldown. Or am I thinking about this wrong because I am fairly new to module scripts.

Is there a cool down in the module script? You said there’s already one

Yes, this is where the cooldown is from

In your module script you are setting the Cooldown variable. The script is simply retrieving it and waiting the duration

If you used it in your previous script, then you should understand. We wait for that certain amount of time before turning debounce to nil or false.

I’m not sure where line 16 is as it is a comment, could you give me the whole line of code from line 16?

1 Like

Yeah that’s what I’m wondering too

This was after I changed it because I moved the module script

local event = game:GetService("ReplicatedStorage").GameFolder.Events.Server
local PearlModule = require(script.PearlAbilities)
local playerDebounces = {}

event.OnServerEvent:Connect(function(player, input)
	-- Creates a table for that player if it doesn't exist
	if playerDebounces[player] == nil then
		playerDebounces[player] = {}
	end

	-- Checks if input is not an Enum and if there is debounce
	if typeof(input) ~= "EnumItem" and playerDebounces[player][input] then return end

	-- make a debounce for that specific keycode
	playerDebounces[player][input] = true

	-- If it finds that ability then fire it and wait until setting debounce to nil
	local ability = PearlModule[input]
	if ability then
		-- Fire the function on a pcall just incase it errors
		pcall(function()
			ability.Activate(player) -- This will be server-sided
		end)
		task.wait(ability.Cooldown)
	end

	-- Gets rid of the debounce set on that key
	playerDebounces[player][input] = nil
end)

Is it just me or is Line 16 blank….?

It’s blank now because of me removing a line but I still get this error

  17:46:27.119  ServerScriptService.AbilityCall:15: table index is nil  -  Server - AbilityCall:15

Which is:

OMG I JUST REALISED!

CHANGE EVERYTHING THAT SAYS input To something else because input is a builtin variable and you are referencing that instead of the variable passed through the event

edit: nvm im wrong

Correction: input is not a builtin Luau global

The Devforum doesn’t have proper highlighting for Luau

1 Like

hm ok maybe I’m dumb but just a theory lol