My Module Loader is scripting garbage

Here is my custom-made module loader! I have a tagging system which I now realize (from my testing) doesn’t have much of a use, but I mainly made this module loader with customization in mind, and i need advice for improvement.

local loader = {}

local require = require
-------CONST VARIABLES------  (These are just some basic directories if you didn't want to reference them)
loader.generic_client_directories = {
	game:GetService("StarterPlayer").StarterPlayerScripts,
	game:GetService("StarterPlayer").StarterCharacterScripts,
	game:GetService("ReplicatedStorage")
}
loader.generic_server_directories = {
	game:GetService("ReplicatedStorage"),
	game:GetService("ServerStorage"), --FYI Depending on the circumstance ServerStorage may not be where you want to execute scripts
	game:GetService("ServerScriptService")
}
loader.generic_methods = {
	"Init",
	"Start"
}

-------VARIABLES--------
local modulePrintTag = "("..string.upper(script.Name).."): "
local methodFinishedTag = "_"..math.random(1111,9999) --The reason why this exists is so that the key is different than the methodname.

--Attempts to execute the method in a module, and prints any warnings/errors
function loader.attemptMethod(methodName : string, module : {},...)

	if loader.hasFinishedMethod(methodName, module) then
		warn(modulePrintTag.."Attempted to execute "..methodName.."() in module ["..module._name.."] but it has already been executed!")
		return
	end

	if module[methodName] then --If the module has the method
		
		local success, errorMessage = pcall(module[methodName],...) --PCALL the method in the module
		if not success then
			--Failed
			warn(modulePrintTag..methodName.."() in module ["..module._name.."] failed to be executed! Error Message : ")
			error(errorMessage)
		else
			--Finished
			loader.setFinishedMethod(methodName, module)
			print(modulePrintTag.."Method "..methodName.."() in module ["..module._name.."] has executed successfully! :D")
		end
	else
		--No method in module
		warn(modulePrintTag.."Couldn't find "..methodName.."() in module ["..module._name.."]")
	end
end

--Attempts to execute the method for each module in a table
function loader.attemptMassMethodCall(methodName : string, mods : {},...)
	print(modulePrintTag.."Attempting a mass method call of "..methodName.."() in #"..#mods)
	for i,module in pairs(mods) do
		loader.attemptMethod(methodName,module,...)
	end
end

--Gets a table of modules found in the descendences of the inputted folders
function loader.requireModulesInFolders(folders : {Instance} | Instance) : {}
	local mods = {}
	
	if type(folders) ~= "table" then
		folders = {folders}
	end
	
	for _,directory in pairs(folders) do

		for _,child in pairs(directory:GetDescendants()) do
			if child:IsA("ModuleScript") then --Goes through every module script
				local req = require(child)
				
				if type(req) ~= "table" then
					continue
				end
				
				req._name = child.Name

				--Add other variables here! (Make sure to put a _ before any vars as you don't want multiple methods/variables with the same name)



				----------------------
				table.insert(mods,req)
			end
		end

	end
	return mods
end
--Returns true if the module has already executed the method with the name
function loader.hasFinishedMethod(methodName : string, module)
	local tag = methodFinishedTag..methodName --Unique completion tag for the method Ex: module._1234Init = true so it wont call Init again. Just a useful procotion.
	if module[tag] == true then
		return true
	end
	return false
end
--Checks that the module has completed the method with name
function loader.setFinishedMethod(methodName : string, module)
	local tag = methodFinishedTag..methodName
	module[tag] = true
end

function loader.simpleLoad()
	local isClient = game:GetService("RunService"):IsClient()
	local directories : {Instance}
	if isClient then
		directories = loader.generic_client_directories
	else
		directories = loader.generic_server_directories
	end
	local modules = loader.requireModulesInFolders(directories)
	
	for _,method in loader.generic_methods do
		loader.attemptMassMethodCall(method,modules)
	end
end

return loader

ISSUES
I have a simpleLoad() method that is suppose to go through all the common folders you would have modules in, but for the StarterPlayerScripts there are lots of modules which kinda messes everything up, and I was hoping for any advice on like a exclude list or something like that.

I want more convenience, just two or three lines of code and your game is loaded.

Example of a client-side script as you can see it has a lot of bloat (Mainly the directories)

local LoaderModule = require(game:GetService("ReplicatedStorage"):WaitForChild("Module Service"))

local directories = {
	game:GetService("StarterPlayer").StarterPlayerScripts:WaitForChild("Modules", 1),
	game:GetService("StarterPlayer").StarterPlayerScripts:WaitForChild("Events", 1),
	game:GetService("StarterPlayer").StarterCharacterScripts
}

local modules = LoaderModule.requireModulesInFolders(directories)
LoaderModule.attemptMassMethodCall("Init",modules)
LoaderModule.attemptMassMethodCall("Start",modules)


--Example of adding Custom Method Calls for events

local player = game:GetService("Players").LocalPlayer
local char: Model = player.Character or player.CharacterAdded:Wait()
local humanoid: Humanoid? = char:FindFirstChildOfClass("Humanoid")

LoaderModule.attemptMassMethodCall("CharacterLoaded",modules, char, humanoid) --attemptMassMethodCall(methodName,modules,...)
  23:10:56.370  (MODULE SERVICE): Attempting a mass method call of Init() in #2  -  Client - Module Service:52
  23:10:56.370  (MODULE SERVICE): Method Init() in module [CameraScript] has executed successfully! :D  -  Client - Module Service:42
  23:10:56.371  (MODULE SERVICE): Method Init() in module [Animate] has executed successfully! :D  -  Client - Module Service:42
  23:10:56.371  (MODULE SERVICE): Attempting a mass method call of Start() in #2  -  Client - Module Service:52
  23:10:56.371  (MODULE SERVICE): Couldn't find Start() in module [CameraScript]  -  Client - Module Service:46
  23:10:56.371  (MODULE SERVICE): Method Start() in module [Animate] has executed successfully! :D  -  Client - Module Service:42
  23:10:56.371  (MODULE SERVICE): Attempting a mass method call of CharacterLoaded() in #2  -  Client - Module Service:52
  23:10:56.371  (MODULE SERVICE): Method CharacterLoaded() in module [CameraScript] has executed successfully! :D  -  Client - Module Service:42
  23:10:56.372  (MODULE SERVICE): Couldn't find CharacterLoaded() in module [Animate]  -  Client - Module Service:46

Any suggestions are appreciated :v:

7 Likes

Why would you even use anything like that?
That just bloatwaring memory in your game.
In this case you could just make everything run under 1 singular script.
Also why would you use FindFirstChildOfClass?
It has to do so much checks instead of just checking a name.

You see there is a problem if you don’t trust own code.
Also use --!strict mode in your code for better perfomance and organization.
If you need more dirrect help with issue consider using #help-and-feedback:scripting-support