Hello! I’m scripting1st, and today I’ll be teaching you about game Frameworks, how they are used, and how to create a framework.
Note: Most of the functions I will mention will be from AeroGameFramework.
#CHAPTER I: How they are used, their functions, and the framework’s format (Highly debatable, so you can choose the format of your own framework.)
You can see a game framework as a way to organize your game, and to make things simpler. Frameworks usually initialize their modules so that they can have access to the Framework’s Children(Functions, Values, etc). Framework just make programming much easier.
Functions For my Framework (will get into how I write them later)
Initialize: Stated above
ConnectEvent: Connecting Function to Event. The parameters are the function and the name of the Event: (func, name). These are made by the server, and run in the client. They DO NOT create Remote Events, instead they look for them in ReplicatedStorage.
ConnectClientEvent: Self Explanatory. These are made by the client, and run in the server. Cannot Create RemoteEvents.
RegisterEvent: Creates a new RemoteEvent. This has to be called on the server. Parameters: (name)
RegisterFunction: Looks at all functions under “Client” table. We’ll go into that a tiny bit later. After it checks all functions, it creates the RemoteFunction, adding the function onto OnServerInvoke. This is run by the server.
RegisterClientEvent: Same as RegisterFunction, all functions under “Server” Table.
Fire Functions: Three different functions, Fire, FireClient, and FireAllClients. Will go over that later in the post as well.
Formats:
Ahh, the most debatable topic in this tutorial. Many people have their own ways of doing things, so for the sake of this post I’ll list a couple people who have posted their own formats.
https://devforum.roblox.com/t/how-did-you-organize-your-games-framework-show-us/230000
Mine:
Chapter II: Initialize
For Initialize, It is not that hard. There are two types of them though. New, and Initialize. “New” runs on the module script, but requires you to to a require on the Framework to run it. I’ll give an example of the New Function.
New Framework:
function Framework:New(Table, __type, Name)
self[Name] = setmetatable(Table, CFramework)
self[Name].Type = __type
return self[Name]
end
Now it’s time for initialize. I’ve improved on this version, so it’s a tiny bit different.
function Framework:Initalize(module)
local org = require(module)
local tab = setmetatable(org, self)
local _type = self[module.Parent.Name]
_type[module.Name] = org
org._type = module.Parent.Name
return org
end
Basically, “new” is supposed to create a new table that you are able to make functions with and access the Framework. On the contrary, “initialize” is supposed to be used at the end of your module script, or in a server script.
Example:
“New”
-- Module
local Framework = require("framework blah blah")
local Table = Framework:New({}, "Class", "Table")
Table.__index = Table
function Table.new()
local self = setmetatable({}, Table)
print("You studied this yay", self.ValueFromFramework)
end
return Table
--- Server
local ModuleScript = require("module blah blah")
ModuleScript.new()
Example 2:
“Initalize”
-- ModuleScript
local Module = {}
Module._type = "Class"
Module.__index = Module
function Module.new()
local self = setmetatable({}, Module)
print(self.ValueFromFramework)
end
return Module
-- Server
local Framework = require("framework blah")
local module = game.serverScripts:FindFirstChild("module")
local Mod = Framework:Initalize(Framework)
Mod.new()
Chapter III: Functions Involving Remotes.
Note: I’ll only be explaining server functions, because Client Functions are pretty indifferent, and you could search up the client parameters on roblox. If you try and struggle enough, ask questions for small errors, you will be able to recreate these functions. I have a book more to learn too.
ConnectEvent Func: ConnectEvent has two parameters, as you already know. func, and Name. For func, you must have to sub parameters (as you may call it), which is (player, …) the … signifies that you could add as much parameters as you want, so you can add anything you please.
This is what the function consists of;
function Framework:ConnectEvent(func, name)
local RemoteEvent = Remotes:FindFirstChild(name)
if RemoteEvent then
RemoteEvent.OnServerEvent:Connect(func)
end
end
And this is how you use it in most cases:
--Server
local Service = {}
function Service:Test()
self:ConnectEvent(function(player, ...)
print(player.Name)
end, "SayHi")
end
function Service:Pre()
self:RegisterEvent("SayHi")
-- we'll get to register event
end
-- Client
local clientthing = {}
clientthing:Fire("SayHi", ...)
RegisterEvent basically creates a new RemoteEvent to the server, allowing the Server to use that specific RemoteEvent. Only 1 parameter, and that is, (name). The name of the RemoteEvent is determined by the parameter.
RegisterFunction is similar to RegisterEvent, except that it turns functions from a certain table, called ‘client’, which is supposed to be the table returned in the function.
Here is an example, of course.
--Server
local module = {Client = {}}
function module.Client.Test(player, ...)
print(player.Name)
end
function module:Init()
self:RegisterFunction("Test")
end
---Client
local module = {}
function module:Start()
self:Fire("Test"), --- Should print player.Name from the Client.
end
The final thing we will be talking about in this post is the “Fire” function. It’s pretty obvious that it fires the event, and that the first parameter is the name of the event/function. However, there is a … next to the name parameter, signifying that the arguments next to player we could’ve added into the second, third, or 50,000th parameter. An example of this is above, of course.
function Framework:Fire(name, ...)
local Remote = Remotes:FindFirstChild(name)
if Remote then
if Remote.ClassName == "RemoteEvent" then
Remote:FireServer(...)
elseif Remote.ClassName == "RemoteFunction" then
Remote:InvokeServer(...)
end
end
end
Chapter 4: Sub Tables
Anyways, this version is running on Initalize, but you could always change it if you want. This is how I made my sub tables.
Only Controllers and Services are actually run into the server, and Class/Module serves as a module for the Controller/Service.
local CEngine = {
Class = {
};
Service = {
};
Controller = {
};
Module = {
};
Other = {
}
}
If you aren’t aware, what’s happening is that I’m initalizing all Modules that are in a certain Parent, such as ReplicatedStorage.Shared, or ServerStorage. After this is done (basically all the modules are done loading and have all of the original Framework’s functions), I do a in pairs loop for the framework itself, looking for tables, and if I have found a table (has to be one of those 5 types of my framework), I do another in pairs loop to then, do a module:Init() first, and then a module:Start(), starting each module extremely fast.
Good things to know:
RunService.HeartBeat:Wait() is actually much faster than wait() suggest you use RunService Wait instead of wait(). By the way, RunService.Stepped:Wait() works too of course. Anyways, this is the most basic tutorial in my opinion, and this tutorial is more or so a guide on what to do. I highly suggest you try to create your own methods.
Anyways, thank you for reading my tutorial, goodbye.
Also, if you catch any mistakes or inconsistencies please point it out.
Edit: forgot to mention that you are able to access any service from the Framework, the modules are actually put inside the sub tables as soon as they are Initialized (in the Initialized version only, though)
Below is a poll. Highly suggest you to fill it out, and also give me feedback. Thanks.
glitch accidentally occured with polls. as of today the average is 4.
- 1
- 2
- 3
- 4
- 5
0 voters