Hello!
I’d wanted to introduce small “framework” to modularize your code.
Fabric is inspired by knit framework. Better to use it for a client or server only stuff right now, because it doesn’t have server-client communication, which will be added soon.
Here’s how to use it:
Let’s create a MathCloth dependency to later utilize it.
local MathCloth = {}
function MathCloth:initialize()
print("MathCloth: Initializing...")
end
function MathCloth:start()
print("MathCloth: Starting...")
end
function MathCloth:sum(a: number, b: number): number
return a + b
end
return MathCloth
Let’s create the “Example Cloth” where we are going to utilize the MathCloth dependency.
local ExampleCloth = {
dependencies = {"MathCloth"}
}
function ExampleCloth:initialize()
print("ExampleCloth: Initializing...")
end
function ExampleCloth:start()
print("ExampleCloth: Starting...")
local MathCloth = self.dependencies.MathCloth
print(MathCloth:sum(1, 2))
end
return ExampleCloth
So now that we have both cloths to start the whole framework up, we need to create a bootsrap.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Fabric = require(ReplicatedStorage.Fabric)
local serverFabric = Fabric.new()
print("Server Bootstrap: Starting initialization...")
local registeredCloths = serverFabric:registerFromFolder(ServerStorage.Cloths)
print("Server Bootstrap: Registered server cloths:", table.concat(registeredCloths, ", "))
serverFabric:startAll()
print("Server Bootstrap: All server systems started!")
Testing time!
“What are the use cases?”
The main point of the module to make your code decently readable by introducing dependencies and global modularization. Recommended to use on large game systems where it’s already hard to navigate through many modules.
So yeah a pretty solid “framework” i’d say. The fabric also has a various checks for types and errors of the users. Thats about it.
HI! So I’ve seen a few simple errors with your framework.
1st:
I would add assert(clothRegistry[clothName], `could not find module {clothName}`
Just incase someone misspells the cloth name or there was an error with your module.
function Fabric:getCloth(clothName: string)
return clothRegistry[clothName]
end
2nd: You use Ipairs, and pairs alot when It might eventually end up getting deprecated. You can remove them without having much effect on your script and to save you from future issues with deprecation.
3rd: I don’t think pcall is really needed cause it might end up slowing down the performance of this specific function, what you could do is verify that the module exist and all, then continue end, or just do if module exist and if the type is a table then write the code.
for _, item in ipairs(folder:GetDescendants()) do
if item:IsA("ModuleScript") then
local success, result = pcall(function()
local moduleData = require(item)
if type(moduleData) == "table" then
local clothName = item.Name
self:registerCloth(clothName, moduleData)
table.insert(registeredModules, clothName)
end
end)
if not success then
warn(string.format("Failed to register cloth '%s': %s", item.Name, result))
end
end
end
Thanks for the tips i will try to optimize the usage of anything that may slow down or deprecate in the future. Though the pcall is for errors and user friendly experience.
Edit: just got an idea to make two separate versions of the module for starters and pros.
Edit 2: I will also add a tips in errors to actually help people use the module, i will try to make them as simple as they can get so even some n00bs can code something with it.
Networking
Allows to easily send packets from server to client and broadcast data to all clients.
Code example:
Server:
local ExampleCloth = {
dependencies = {"Networking"}
}
function ExampleCloth:initialize()
print("ExampleCloth: Initializing...")
end
function ExampleCloth:start()
print("ExampleCloth: Starting...")
task.wait(5)
local Networking = self.dependencies.Networking
Networking:broadcast("test", {"anything here lol", Instance.new("Part", workspace)})
end
return ExampleCloth
Client:
local ExampleCloth = {
dependencies = {"Networking"}
}
function ExampleCloth:initialize()
print("ExampleCloth: Initializing...")
end
function ExampleCloth:start()
print("ExampleCloth: Starting...")
local Networking = self.dependencies.Networking
Networking:onPacket("test", function()
print("Test packet received!")
end)
end
return ExampleCloth
There was conversation post, and it talked about how to use pairs and Ipairs properly, and a few comments stated that pairs and ipairs might be getting deprecated in the future to make luau syntax cleaner, also not specifying pairs or ipairs is faster so