GlobalFramework2
Into the SingleScriptArhitecture world! For games and plugins.
Since the post got way to long, I had to split this into 2 posts. This is part 2 of the GlobalFramework2 documentation, and part 1 is right here!
About GlobalFramework2
Let’s learn how to use this plugin!
First of all, let’s create a new temporary Baseplate project where we’ll learn about the plugin.
Second of all, if you have installed this plugin in the Creator Store way, then whenever you’re prompted with a permission request, like the plugin to have access to script editing, accept the request, then rejoin the project, since there’s a small bug that makes it so that even if you accepted the request, the Studio will still not give the permission to the plugin.
In the Plugins tab, look for the GlobalFramework2 button.
Clicking this button will toggle on/off the plugin’s Window visibility. For now, just open the Window, then dock it anywhere you want! Keep in mind that the Window’s visibility and dock position and size are saved, and you won’t have to always hide/show or dock somewhere the Window’s
Let’s have a first look at what we can see inside the Window. (Note that the Gui colors update based of your currently selected theme, light or dark)
So many things, I know, but there’s even more! Try to scroll in the Window using your mouse wheel, or the scroll bar on the right side.
Good! Now let’s return at the top and start with how you can easily set up/remove/select/check the project components. All these actions are found in the „Project components” Header at the very top.
To set up the project components just click the first action button! Now if you take a look in the Explorer, you’ll see some selected Instances that have been created by the plugin. These are the project components! There are 8 in total.
You should also notice that now some of the plugin’s disabled features have been enabled, like those in the “GlobalFramework2” Header.
This is because most of the plugin’s functionality will be enabled once all the project components are set up. Another way to check if all the project components are set up is to use the fourth action of the header. This will print in the Output either “true” or “false” based of if all project components are set up.
To use this architecture, all project components must be available. If at least one of them is missing then the plugin will detect that and will turn off the functionality. Let’s delete the “StartPlugin” script from the ServerStorage and see what happens.
As you can see, now the plugin has detected that all project components are not set up, and has disabled most of its functionality.
If you ever want to quickly select all the available project components, then use the third action of the header.
Now, to set up all the project components, simply just click the first action from the header again! Now all the project components are set up. When the plugin can’t detect that the project components are set up it might be because of some other Instances that interfere with the actual project components. Let’s duplicate the “StartServer” script from the ServerScriptService and also create a Part Instance named “ServerModuleScripts” still inside the ServerScriptService. Now let’s see what project components can the plugin detect using the third action of the header.
As you can see here, the good “StartServer” script and “ServerModuleScripts” folder are no longer recognized by the plugin, since other Instances interfere with them. Again, using the first action of the header will set up all the project components, no matter what, so let’s use that.
As you can see here, every project component is now successfully set up! But what happened to the Instances that were interfering with the good project components? Were they destroyed? No, they are in the Workspace!
To make the project components set up successful, the plugin sometimes might need to move some Instances that are interfering with the good project components that are about to be set up in the Workspace. In the output we will also receive a warning about what Instances have been moved to the Workspace!
The plugin will never destroy any of your project work!
Now, if you ever want to remove the plugin from your project, or simply just want to temporarily remove the project components, well you can do that with the second action of the header!
As you can see, all project components have been removed! If you had some Instances parented under some of the project components, then those will be parented under the project component’s Service parent. Again, the plugin will never delete any of your project work!
Ok, this should be everything about how to set up the project components! Now let’s set them up again and talk about some rules.
First of all, all this project components have some properties locked. For example, if you go to the “StartPlugin” script and try to disable the script by setting the Enabled property to false, it will be set right back to true. A warning will appear in the Output, telling you to stop.
Second of all, we will only work with the “ServerModuleScripts”, “ClientModuleScripts”, “SharedModuleScripts” and “PluginModuleScripts” project components, basically all the available folders, and not the “StartServer”, “StartClient”, “StartPlugin” and “GlobalFramework2” project components, the LuaSourceContainers. We can parent anything we want under the Folders, but we can’t parent a single Instance under the other project components. Usually, you just want to parent the ModuleScripts under the Folders, and maybe other folders for even better organization, but you can add any Instance you need under the Folders. Descendants are not a problem, meaning that the ModuleScripts can be descendants of the Folders and still be detected by the plugin. The other project components that we don’t work with are managed by the plugin, based on what ModuleScripts you created under the Folders and settings you chose for the plugin/architecture in the plugin’s Window.
Ok, now let’s create 2 ModuleScripts named “ModA” and “ModB” and add them under the “ServerModuleScripts” project component Folder.
Just like this! Now open the editor Windows (ScriptDocuments) for those ModuleScripts.
Just like this!
Now here’s where we’ll start to learn about the “GlobalFramework2” Header! Let’s scroll a little bit down to the Header.
Now, since we’re editing the created ModuleScripts, we’ll have to turn on the “Edit mode” feature. This will activate the framework’s functionality, turning on some features, like highlights, creating the ModuleScript’s autocomplete, exporting the ModuleScripts’ types, etc.
Ok, now, you can see that some weird highlights have appeared, with blue and gray color, something that most of you might not have seen up until now. There are actually the “Hint” and “Information” highlights, that for some reason Roblox has never used these highlight colors, but this plugin found a use for them! Their job is to provide you quick visual information about some of the architecture’s statuses. This plugin will only create highlights that have the color blue (representing something good), information (representing some information, usually you can hover on this type of highlight for some informational text to read) and red (representing something bad, not really an error). You can hover on these highlights with your mouse click to get some helpful information. If you want, you can enable the Roblox’s Script Analysis Window that will show you all the available highlights (I also recommend to turn on the “Display only current script” feature of the Window so you will see only the available highlights for the script you’re editing).
Tip: You can click on a highlight item to quickly select the highlight’s text!
Now let’s check the “ModuleScript checks” from lines 1-3. Here, both highlights are really important and should always be blue! But what do these highlights actually mean? When some specific signals are triggered, the plugin will always do some checks for all the ModuleScripts, making sure they respect the check rules. If one of those 2 highlights (or even both) are red after the checks, then the ModuleScript is marked as bad by the plugin, and some features, like the autocomplete for the ModuleScript, exported types, etc., will be disabled.
But what rules does a ModuleScript have?
The first highlight is for the ModuleScript’s path, from the “game” (DataModel) global to the ModuleScript. Make sure that the ModuleScript has a good path from the “game” global and that it does not interfere with other Instances. (ex. When you apply :FindFirstChild("”) on an Instance to look for a child with a specific name, but there are 2 children with that same name). For a demonstration, let’s create a Part Instance named “ModA” and parent it under the “ServerModuleScript” project component. In order to update the ModuleScript’s highlights, we must either do a change in the ScriptDocument or use the fifth action of the Header.
As you can now see, now the path check of ModA is highlighted with red. This happened because the plugin meet an problem while trying to create the path from the DataModel, that being that at the “ServerModuleScript” when it tried to do :FindFirstChild("ModA”) there were 2 possible results. Now ModA is marked as a bad module. If we delete/rename the added Part Instance then we will fix the problem everything will be back to normal.
The second highlight is for the ModuleScript’s name, if it is unique or not, if other ModuleScripts from the same ModuleScripts container are using the exact given name. Make sure that your created ModuleScripts have unique names. For a demonstration, let’s create a Folder Instance and parent it under the “ServerModuleScript” project component, then let’s create a ModuleScript called “ModA” and parent it under the Folder Instance.
As you can now see, now the unique name check of ModA is highlighted with red. The highlight information text will also tell you the paths to the other ModuleScripts that have the same name, so you can find them easier, like in this photo where we can see that it tells us the path to the temporary ModA. We will see the same red highlight in the temporary ModA as well, with an information text that will tell us the paths to the other ModuleScripts with the same name. If there are more than 2 ModuleScripts with the same name, the paths in the message will stack, each one in its line. Let’s remove the temporary Folder Instance, so everything goes back to normal.
Also, there are no problems if some ModuleScripts from different containers use the same name!
Tip: You can quickly select in the Explorer all the ModuleScripts that have one of their checks red by using the second action of the Header.
Now let’s check the “Comment directives” from lines 5-9. To make sure that you can still use comment directives in your ModuleScripts, the plugin has created some attributes for the ModuleScript that you can use to add comment directives into your ModuleScripts! Let’s have a look at those attributes in the Properties Window!
There they are! It’s a rule that all ModuleScripts need to have these attributes, and you can’t remove them. With these attributes you’ll be able to use comment directives in your ModuleScripts! If we would want to add the “–!strict” comment directive, then we’ll set the “strict_GlobalFramework2CommentDirective” attribute to true by simply just checking the box.
Now our ModuleScript uses the “–!strict” comment directive! This goes on for all the available comment directives that you want to add! Also keep in mind that the “strict”, “nonstrict” and “nocheck” comment directives interfere. Same goes for “optimize 0”, “optimize 1” and “optimize 2”. “native” and “nolint” do not interfere. So, for example if we want to use the “nonstrict” comment directive, then we’ll have to set the “nonstrict_GlobalFramework2CommentDirective” attribute to true. In this case, the “strict_GlobalFramework2CommentDirective” attribute will be automatically set to false by the plugin.
That’s it! That’s how you can add comment directives in your ModuleScripts.
The last part that’s left is just the “GlobalFramework2” project component requirement.
For the ModuleScripts placed under the “PluginModuleScripts”, the last part will be a little bit different. First, the “plugin” global is updated to reference the actual Plugin Instance, while also casting the “Plugin” type to make sure it has autocomplete available, and not to be casted as “any”, then the “GlobalFramework2” project component is required based of if Edit mode is turned on or off.
This is how it will look when Edit mode is on:
And this is how it will look when Edit mode is off:
When using this plugin to create other plugins there are some things that you need to know, not many, but we won’t talk about it now. Let’s turn back to ModA and ModB!
Now, I’m really sorry, but my snipping tool that I used up until now to make these pictures won’t show any autocomplete suggestions in the pictures I create, so it’s a bit hard to show the autofill parts…
Try to index the “GlobalFramework2” variable with the “.”! You will see that it has a lot of indexes available! All of those indexes (except for the “Start” index which is a function) are called Userdatas. Think of them as UtilityModules, that’s what most of them are!
Let’s learn how all the created ModuleScripts can use each other! For this, since ModA and ModB have been placed under the “ServerModuleScripts” project component folder, we’ll need to use the “ServerModuleScripts” Userdata that’s available from the "GlobalFramework2” variable. Since all the Userdatas represent strong memory addresses, we can even create a custom variable for each Userdatas, including the “ServerModuleScripts” Userdata.
Let’s try to index the “ServerModuleScripts” Userdata with “.”. We should see both ModA and ModB results there! We should also go and add proper return results to these modules, so let’s do that!
Now let’s go to ModB and make the return table have some indexes with values available!
Now back at ModA, if we try to index the ModB’s return result then we’ll have 0 autocomplete, which doesn’t seem right, since you’ve heard that this plugin finally fixes the almighty cyclic module dependency problems that break the autocomplete. We’ll, there’s no autocomplete because we must update it! Use the third action of the Header and then try again! Now, you’ll have autocomplete! This thing is insane, I know!
You see, whenever a change to a ModuleScript return result is made, or when a new type is being exported/updated, an autocomplete update is necessary! If you feel like the autocomplete suggestions are old, you can always do an autocomplete update to get the latest autocomplete. You can also try to use the automatic autocomplete update feature by setting the fourth item from the Header to ”On”, so you’ll never ever have to do manual autocomplete updates, however keep in mind that this feature right now is kind of laggy for the new type solver, as there’s currently a “bug” that makes it so the autofill suggestions for the new type solver are really slow. You can try to use the old type solver for the autofill, as it creates the autofill suggestions much faster, however keep in mind that the speed also depends on how good your device is. For example, my computer is really good and fast and it makes the autofill suggestions really fast, so fast that you can’t even see the delay, but moving to my old laptop, things are different, even with the old type solver my laptop still struggles to do the automatic autofill updates. I recommend you to use the new type solver and do manual autofill updates, and when that “bug” with the autofill taking ages for the new type solver is finally fixed, maybe try to turn on the automatic autofill updates! (unless you have a NASA pc)
Let’s talk about how to make “global” types. These types aren’t actually global, they will only be available in the GlobalFramework2 variable.
It’s really easy! So first start by typing the “type” keyword, it should be highlighted in the red color, then give your type a name, in this example I’ll call my type “MyCustomType”, then configure the type using the “=”. I’ll make an OOP class type.
Now the type work and can be used…
only in this ModuleScript… But how do we make it so that the type can be used by the other ModuleScripts? Simple! We just need to add the “export” keyword at the start of the type creation! It should also be highlighted with the red color. If everything is alright, then the whole type creation should be highlighted with a blue color. We’ll also need to do a manual update, since we added a new global type.
Now the Variable will have autocomplete!
There’s no problem if the types are cyclic. For example, let’s update the type by adding an index called “Message” that’s the typeof ModB’s Message index. Again, after a change in an exported type we must update the autofill.
Now if we look at the Variable’s autofill again, we’ll see the newly added “Message” index, and it’ll also tell us that the value is specifically the “Hello world!” string (only works for the new type solver, else will tell us it’s a string).
When creating an exported type, there are some rules to keep in mind:
- Do not name the type after an GlobalFramework2 type. GlobalFramework2 has some already predefined types for its created Userdatas, and trying to use one of the taken names won’t work, resulting in a red highlight with a specific message.
- The type name must be unique. If the plugin detects that in 2 ModuleScripts there are 2 types with the same name that are being created, it will ignore both and won’t add them into the GlobalFramework2, and will also highlight the both creations with the red color and a specific message, telling you in what ModuleScripts the type is being created.
- Both ModuleScript checks must be blue. If at least one of the checks is highlighted with red, then the type wont be added into the GlobalFramework2, even if the other rules are respected, and will instead be highlighted with an orange color with a specific informational message.
- Type must be exported in the main scope of the ModuleScript. Do not export the type when it’s created in other scopes, like if-elseif-else, functions, etc. since it won’t work. Even if the type will be available in the GlobalFramework2, the type will actually result in an error-type. This is actually normal behavior, not a plugin problem.
There is also support for the weirdly created types, as you can see here:
Ok, this should be everything about how autofill works! One thing that I haven’t mentioned is that you can also do automatic updates for the plugin’s custom analysis as well by setting the sixth item of the Header to “On”. This way, whenever the plugin detects that a ModuleScript has old analysis it will update them with new ones! Also, keep in mind that if you turn on this feature then your device might get a bit laggy since this feature relies on some good performance from your device.
Now, let’s talk about the Userdatas/UtilityModules that can be found in the GlobalFramework2. These Userdatas are really important, especially the Stage Userdata, which helps you with the code execution order of your ModuleScripts, and BuildInEvent Userdata, which fixes some problems with some signals that might now work when using the SSA, like for example the PlayerAdded signal that might not fire for some players that joined the game before the GlobalFramework2 had a chance to load. All these Userdatas can be enabled/disabled in the third Header available, the “Utility userdatas” Header. Let’s scroll a bit down to that Header.
The first 2 items of the Header handle the preset for your enabled Utility userdatas, with the first one saving the current preset and the second one loading the previously saved preset. The rest is just the Utility userdatas that you can toggle on/off.
Let’s try to create the code execution order for our ModuleScripts by using the Stages Userdata. The Stages userdata will always be enabled, so we don’t need to enable anything the Header. Back in ModA, let’s create a variable for the “Stages” Userdata.
If we will try to index the Stages variable, we will see some available indexes. These are also some Userdatas that we will use to handle the code execution of our ModuleScripts. Think of them like those indexes functions that we used to put in the return table of our ModuleScripts in the raw SSA to handle the code execution, that’s what these are, but they also help you to not create extra indexes in your return tables, keeping them clean. The order they will execute in is this:
-
Configure;
-
Initialize;
-
Start.
To add a function that will be called on the Stage execution we will apply :AddFunction() on the Stage Userdata with our function to be called as the first and the only parameter. Let’s add a function to all the Stage Userdatas, for both ModA and ModB, where we will print the Name of the Stage.
Now let’s run the game and see if the code execution is respected. But first, we need to turn off Edit mode, or else the architecture won’t work and we’ll get an error!
As we can see in the Output, the code execution was respected! Both ModA and ModB executed their Configure functions first, then the Initialize functions, then lastly the Start functions. Let’s now create in ModA a Part Instance in the Initialize function and also a function that can be used to move the Part at a given CFfame, then in ModB in the Start function use the function provided by the ModA.
Success! This is how you can handle code execution with this architecture!
Now, as you might know, there’s a problem with SSA where due to the fact that it takes a bit of time to load some signals might not fire, like the PlayerAdded signal of Players service. GlobalFramework2 has a solution for this! Introducing BuildInEvents! There are some custom GlobalFramework2 signals that do work and will replace the broken signals. Let’s learn how to use them!
To do this, we must enable the following Userdatas: BuildInEvents, ThreadService, CustomBindableEventConnectionService, CustomBindableEventService. Keep in mind that some Userdatas might depend on other Utility Userdatas! You can see if an Userdata depends on another utility Userdata by checking its description!
Honestly, I would recommend you to enable all available Userdatas, even if you won’t use all of them, since they really do not affect your game with like performance issues or memory consumption, and you also won’t have to worry and always check if an Userdata has been enabled + its dependencies. After this you could even save this preset that has all Userdatas enabled, so when you set up the Framework in another project you can quickly enable all the Userdatas by loading the preset.
Let’s use the custom PlayerAdded signal! First, in ModB, let’s create a variable for the BuildInEvents Userdata, then use the PlayerAdded Userdata available in the BuildInEvents Userdata. To connect a function to the signal, we will apply :Connect() on the signal, with our function as the first and only parameter. The function will receive the Player that joined the game as the first and only parameter. Let’s print to the Output a message that the “Player.Name” has joined the game!
It works! Let’s also use the original PlayerAdded signal and see if it works.
Nope. It did not work. Now do keep in mind that sometimes the signal might work, for example when you load a bit late in the game and the GlobalFramework2 finished loading, but I still recommend you to use the custom signals, so there are no problems in your game.
So, let’s rewind what’s happening in this Framework:
-
The GlobalFramework2 project component is fully required by the StartServer, StartClient and StartPlugin (if the context is right);
-
The Start function of the GlobalFramework2 is used;
-
All ModuleScripts are fully required and saved in GlobalFramework2: Server-Side → ServerModuleScripts and SharedModuleScripts; Client-Side → ClientModuleScripts and SharedModuleScripts; Plugin-Side → PluginModuleScripts; This is where functions for the Stages and BuildInEvents are created and connected.
-
The Stages start executing in their order to manage the code execution.
-
BuildInEvents start working.
This should be about everything about the Framework!
One more thing, if you will use this Framework to create plugins then when you edit module scripts make sure to turn EditMode on, and when you have finished turn it off (this is a must). To save/publish the plugin use the third action of the project components header to select all available project components, right click any selected project component and then save/publish the plugin. Also, note that you can also manually select just the GlobalFramework2, StartPlugin and PluginModuleScripts project components and save/publish only those as the plugin, since the rest of the project components is not needed and would consume a small amount of memory if also saved/published (they won’t break the plugin, though). Also, do not work on the plugin from the PluginDebugService! (I also do not recommend using PluginDebugService to create your plugins, even if you don’t use this Framework)
We could also talk about the other utility Userdatas, but this post is getting way bigger than I expected, so I’ll have to try and stop here.
In the end, let’s see the pros and cons of the GlobalFramework2 based of those from the raw SSA!
Pros:
-
Better organization. This architecture enforces a strict ModuleScripts organization that prevents scripters from scattering them everywhere, as they need to be placed as descendants of their specific containers to be required, which also ensures a clean and structured project layout.
-
Anti duplicated code. This arhitecture prevents duplicated „scripts” that do the same given task, as each ModuleScript name has to be unique and, again, they can’t be placed anywhere like in MSA, which helps with organization and also performance. Scripters will have to find other ways to handle Instances logic, like using the CollectionService and tags feature, ObjectValues, etc…
-
Very modular. Since all ModuleScripts know about each other, this fact makes for a really modular system, since ModuleScripts can share data that can be reused across different systems, like functions, making development more efficient, and encourages a better separation system of the ModuleScripts that keeps different functionalities independent, but interconnected at the same time.
-
Reduces memory used. The „anti duplicated code” and „very modular” pros also help with the memory management as well, since most code parts won’t be declared many times, like functions that do the same thing that might be needed to be declared just once, which helps with the memory used, reducing it down.
-
Controlled code execution. With this arhitecture you have the ability to control the code execution of your ModuleScripts, fixing the race conditions problem in the other arhitecture.
-
Cyclic module dependencies are not a problem. In this arhitecture, cyclic module dependencies are not a problem since they are resolved by the way of how the arhitecture works, so this means that you can use cyclic code among all your ModuleScripts, however keep in mind that this is still your choice if you want to have cyclic code, you’re not forced to use cyclic code.
-
Utility Userdatas/Modules. With GlobalFramework2 you will have access to some really cool utility modules (that are called Userdatas) that contain helpful functions and information, always ready to be added and used in your project with just one click.
Cons:
-
Maybe Harder to learn? This architecture requires a good understanding of how ModuleScripts work and how they will interact with their central script. The beginners who are used to the individual scripts for everything they make may struggle at first with the strict structured architecture. Also, understanding how code should be structured in the ModuleScripts can be a little bit confusing at first, because if it isn’t done right it will lead to errors.
-
Harder portability. It’s hard to copy ModuleScripts and move them to other project since you will need to manage this system there as well, and if its managed then check for other things like the ModuleScripts’ names to be unique.
GlobalFramework2 bugs
In here you can find all GlobalFramework2 bugs! (or most of them that have been found)
-
Bad exported types detection. Even if an exported type is commented, the GlobalFramework2 will still detect that type as being created. This also happens in strings as well. For now, just make sure to not have a type exportation pattern in comments or strings.
-
Source code duplicated. When 2 or more people are editing a ModuleScript, if one of them tries to edit the comment directives for some reason the whole source code will be duplicated and pasted at the top of the script. This doesn’t happen when only one person is editing the ModuleScript.
GlobalFramework2 questions and answers
-
Why is this Framework called GlobalFramework “2”? by nork24elec1. Hey, that’s me asking myself this question! You see, this Framework has been in the works for the past 7-8 months, and meanwhile I was working on it, 5uphi, a really talented Roblox developer btw, about 3 months ago he created his own Framework which is really similar to this one, thought they still do have big differences in how they work. This is the best coincidence that has ever happened in my life up until now, and keep in mind that I haven’t talked to this guy, so we literally had the same idea which is crazy. Now, since he has published his Framework first, and also named it the same as I wanted to name mine, it would’ve been a bit wrong from me to publish mine with the same name, so, what did I do? I added 2 at the end of the name, of course! Also, I gotta thank Suphi Kaner for the idea of visible highlights in the ModuleScripts’ code! 200 IQ moment.
-
Will this Framework ever be updated? by nork24elec1. Hello again, nork24elec1! Yes! Make sure to always have the latest update downloaded!
GlobalFramework2 positive community reviews
In here you can find some (maybe all) GlobalFramework2 positive reviews given by the people who have tried it! Every single review should have a response from nork24elec1, the creator of the plugin.
Currently there aren’t any reviews available.
GlobalFramework2 negative community reviews
In here you can find some (maybe all) GlobalFramework2 negative reviews given by the people who have tried it! Every single review should have a response from nork24elec1, the creator of the plugin.
Currently there aren’t any reviews available.
Outro
Thank you so much for learning about GlobalFramework2 and I hope you’ll find this Framework useful! I would also like to create a video about this plugin on my YouTube channel, but first I want to see what y’all think about this plugin here, and if the overall reviews are good then I’ll surely create the video. I would also like to create another video on how this plugin was made (explaining the source code, mainly talking about how it fixes the autofill problem) and maybe another video where I compare it to other similar Frameworks!
Have I missed anything, like for example some pros and cons for both architectures? Let me know, and I’ll make sure to add them!
Also, fun fact, the plugin’s icon has been made in Paint! What rate would you give it?
Anyways, bye!