Would it be safe to require multiple times?

I have tons of modules for the sake of the organization of the studio. After some research on Modules, you can not unload the module after require ing them.

So this brought me to a question, would it be safe to require a module multiple times? In this particular case I have this:

requestCombat.OnServerInvoke = function(Player, MouseHit)
	if tick() - COOLDOWN_HANDLER.getCooldown(Player, "Combat") >= 0.5 and STATES_DATA.requestCombat(Player) then
		COOLDOWN_HANDLER.setCooldown(Player, "Combat", tick())

		local PlayerData = DATASTORE.getData(Player)
		
		--> If there are no logs of last combo
		if not module[Player] then
			module[Player] = {1, tick()}		
		elseif tick() - module[Player][2] <= 1 then
			module[Player] = {module[Player][1] + 1, nil}
		else
			module[Player] = {1, nil}
		end
			
		if module[Player][1] > #PlayerData.Equipped.Combo then
			module[Player] = {1, nil}
		end
		
		Player.States["Casting"].Value = true
		
		module[PlayerData.Equipped.Combo[module[Player][1]]].Execute(Player, MouseHit)
		module[Player] = {module[Player][1], tick()}
		
		Player.States["Casting"].Value = false
		
		return true, PlayerData.Equipped.Combo[module[Player][1]]
	else
		return false
	end
end

I have all the modules loaded into a table and then I find the corresponding ability and run the function. I’ve noticed that because of it being the same module, the wait() or anything regarding yielding will stack for the next player or user. So should I require and get a new copy every time? Would this cause some form of memory leak?

My other solution is to wrap it in a coroutine but because it is the same module I’m not sure if that would work.

coroutine.wrap(function()
	module[PlayerData.Equipped.Combo[module[Player][1]]].Execute(Player, MouseHit)
end)()

What are your takes on this?

Please finish reading the post. I’ve stated that currently that all the modules are stored inside a table.

Again, please finish reading the post.

So should I require and get a new copy every time?

Calling require multiple times will return the exact same value for subsequent calls to require, in other words, you are not getting a new copy of the code in the modulescript but the same.

Would it be safe to require multiple times?

To answer the question in the title, yes it is safe.

I’ve noticed that because of it being the same module, the wait() or anything regarding yielding will stack for the next player or user

My other solution is to wrap it in a coroutine

From what I am seeing in the code sample you provided in the post, you are using the modules as a response to a RemoteFunction, this means you are already using a different thread for each call and the “wait stacking” you are experiencing is the result of something else.

Do you perhaps have a variable inside the module scripts that gets locked everytime the function is called? do you have maybe a Queue structure inside?

Well for a quick look inside one of my modules:


module.Execute = function(Player, MouseHit)
	local Character = Player.Character
	local cParts = Character:GetChildren()
	
	coroutine.wrap(function()
		for i = 1, #cParts do
			wait(0.04)
			if cParts[i]:IsA("BasePart") then
				local startPos = (cParts[i].CFrame * CFrame.new(0,0,1)).Position
				local endPos = (Character.HumanoidRootPart.CFrame * CFrame.new(0,0,-5)).Position --(cParts[i].CFrame * CFrame.new(0,0,-5)).Position
				local ray = Ray.new(startPos, (endPos - startPos).Unit * 5)
				local hit, pos = game.Workspace:FindPartOnRayWithIgnoreList(ray, {Character, game.Workspace.World.Visuals})
				if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then	
					local Enemy = hit.Parent
					local Inflicted = DAMAGE_HANDLER.inflictDamage(Player, Enemy, 5)
					local plrs = Players:GetPlayers()
					
					if Inflicted then
						stun(Enemy)
						for i = 1, #plrs do
							if GlobalFunctions.isAlive(plrs[i].Character) then
								if (Character.PrimaryPart.Position - plrs[i].Character.PrimaryPart.Position).Magnitude <= WORLD_DATA.effectsRenderDistance then
									replicateEffects:FireClient(plrs[i], {
										Module = "Left Punch",
										Function = "Execute",
										Data = {
											["Character"] = Character,
											["Target"] = Enemy	
										}	
									})
								end
							end
						end
						
						coroutine.wrap(function()
							wait(0.5)
							unstun(Enemy)
						end)()
						break
					end
				end
			end
		end
	end)()
end

The coroutine was me attempting to put it into a new thread because multiple people would be using this piece of code. I’ve also read that Remote Events and Remote Functions upon being called or triggered automatically creates a new thread which wouldn’t that mean technically I wouldn’t need these coroutines?

EDIT: As far as I know there are no queue system implemented.

wouldn’t that mean technically I wouldn’t need these coroutines?

I’d say it depends, here because you are using a remoteFunction and you want it to return as soon as possible you probably want to keep the coroutines for the Execute() function.

Well for a quick look inside one of my modules

I skimmed through the code at it appears it should work, but what about the “COOLDOWN_HANDLER” in your original script? it seems like the issue could lie there

I can 99% guarantee it has nothing to do with it. I simply log using tick() to check for cooldowns.

Anyway thanks! I’ll be testing it and I will notify you when I get some results. Should I avoid requiring a module multiple times?

Should I avoid requiring a module multiple times?

You can definitely require a module multiple times, but this wont solve any of the issues presented in the thread and there is no real need to do it more than once per script.

If you find the solution make sure to post it so other users with similar issues can find it!

1 Like