Global Framework

Yes it works the same on the client side simply make a modulescript and require it the same way you do on the server side

In the video in the game section it shows you how to do it

if your using the global library simply select the script you want and change the run context to client

1 Like

One more thing, I’m kindof confused how Global.Initialize() and Global.Start() works? I’ve always thought these are used to yield scripts so that every script is loaded first before they continue working. I’m asking this because some times there will be an error stating that Global.something is nil while sometimes it works as it is intended to. Can you provide some clarification?

1 Like

its a 3 stage system script stage, init stage and finally the start stage

-- script stage

Global.Initialize()

-- init stage

Global.Start()

-- start stage

In the script stage its never safe to access other globals

In the init stage it safe to access globals that where inserted during the script stage

And finally during the start stage its safe to access globals inserted during the script stage or init stage

as a side note scripts in replicated first should not share a global with scripts outside of replicated first

1 Like

This is how I currently do it, is there something wrong with what I script or what? Because from time to time it still errors

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local Global = require(ReplicatedStorage:WaitForChild("Global"))
		local InventoryManager = Global.InventoryManager

Global.Initialize()
Global.Start()

In the script where InventoryManager is created

-- Variables
local Global = require(game.ReplicatedStorage.Global)

local class = Global("InventoryManager",Global.Metatable()) :: Global.InventoryManager

...

Global.Initialize()
Global.Start()

Edit:
Oh, why didn’t I get it for the first time lol. I just reread what you said and just understanding right now. Thanks!!! (Don’t judge by stupidity lol)

Another Edit:
So base from what you said, from I understand this should fix it?

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local Global = require(ReplicatedStorage:WaitForChild("Global"))

Global.Initialize()
Global.Start()

local InventoryManager = Global.InventoryManager
1 Like

Yes your edit will fix the problem before you was trying to access the global in the script stage that’s not safe

but now your accessing it in the start stage and that’s safe because the start stage will only take place once all the script and init stages have finished

local Global = require(game.ReplicatedStorage.Global)

Global.Start() -- this will wait for the script & init stages to end

print(Global.InventoryManager) -- will never be nil
local Global = require(game.ReplicatedStorage.Global)

-- InventoryManager gets inserted into global during the script stage
local class = Global("InventoryManager", Global.Metatable()) :: Global.InventoryManager
2 Likes

Global Library Updated 1.2

image

Added UnreliableServerEvent & UnreliableClientEvent
Changed ParameterEvent, ParameterTimer and added ParameterCollection


Before you would need to define the parameter type when creating the event

But now you no longer define the parameter type when creating the event

This allows us to use any type we like for the parameter and the type engine can automatically workout what it is

If you prefer how the old version works you can still find it in the Legacy folder

2 Likes

Hello! In your video tutorial at around (1:21:30) you show that Timer needs a generic type of ‘PlayerObject’
image

Does this new update mean that you no longer put anything there?

That is correct it should just be Timer: ParameterTimer<>, with nothing inside it

1 Like

Hello again! I ran into an issue where if I try to use the Global __call function within a module and require it, the Global.Initialization and Global.Start functions doesn’t work anymore. Did I do something wrong here?

Script

local ServerStorage = game:GetService("ServerStorage")
local Global = require(ServerStorage.Global)

local Module = require(script.ModuleScript)

Global.Initialize(function()
	print("Init") -- doesn't run
end)

Global.Start(function()
	print("Start") -- doesn't run
end)

Module

local ServerStorage = game:GetService("ServerStorage")
local Global = require(ServerStorage.Global)

local new = Global("Something") :: any

local module = {}

return module

Place file:
Issue.rbxl (68.1 KB)

This happens because ModuleScript threads never die they stay suspended forever
this causes the Global module to wait forever there are a few ways we can solve this problem

Option 1

When calling Global in a ModuleScript place it in a new thread that will die


Option 2

Call the Global.Start() function at the bottom of your ModuleScript this will unregister the thread and allow the Global module to stop waiting

but if you add Global.Start() at the bottom of your ModuleScript this will cause the script that required the module to also wait until the ModuleScript returns if you don’t want the script to wait you can do this

local Module = task.spawn(require, ServerStorage.ModuleScript)

Option 3

Don’t use ModuleScripts like this

You could just change your ModuleScript into a script and it should all work fine


Option 4

Make a new function that unregisters the thread without yielding

1 Like

Global Library Updated 1.3

image

Added SignalManager & Table
bug fix Thread


Fixed typo in Thread and functions now return the correct type

Table provides two commonly used functions Clone & Reconcile

SignalManager is used to help manage signal connections

function Character.new(instance)
	local self = Global.Metatable(Character) :: Global.Character
	-- Create a SignalManager and connect two signals
	self.Signals = Global.SignalManager()
	self.Signals:Connect(instance.AttributeChanged, Character.AttributeChanged, self)
	self.Signals:Connect(instance.AnimationController.Animator.AnimationPlayed, Character.AnimationPlayed, self)
	return self
end

function Character:AttributeChanged(attribute)
	print(attribute)
end

function Character:AnimationPlayed(animationTrack)
	print(animationTrack)
end

function Character:Destroy()
	-- Disconnect all signals from the SignalManager
	self.Signals:DisconnectAll()
end
2 Likes

Global Library Updated 1.4

image

Removed <P> generic from ParameterEvent, ParameterTimer and SignalManager because there where some small edge cases where the type checking engine would fail

Added Table2D and Table3D

-- Make a 2d table that has string values and number keys
local table2D = Global.Table2D()-- :: Global.Table2D<string, number>

-- Add ABC to index 5x2
table2D:Set(5, 2, "ABC")

print(table2D:Get(5, 2))

-- Remove ABC from index 5x2
table2D:Set(5, 2, nil)
1 Like


typeError signalManager needs capital M

Thank you for reporting this I have fixed it :slight_smile:

1 Like

I noticed that this also happens even with a regular script, when you put a return at it’s last line. Not something that I would do normally, Just something that I found randomly, wanted to let you know :slight_smile:

I just tested this for myself and everything worked perfectly fine with a return at the bottom of a script so I’m guessing the problem you experienced was with something else

1 Like

Oh strange, I tried reproducing it as well again and it seems to be working fine. Must have been something else like you said. Unfortunately I no longer have the project file with the bug I mentioned earlier. I’ll let you know if I find it again :sweat_smile:

Hi! In your next update can you add support for writing custom code before Global framework adds its own types?

^
I want to use FastSignal module with this framework. However, to use this module’s types properly, I must require it before the global’s types are set.

The reason I’m requiring modules and setting it’s types manually, as shown above, is because it is currently difficult to add types using the bracket comments method with modules that don’t have the global framework in mind. For example, I’m using Trove which is a cleanup module by Sleitnick. In order to add the Trove type through the bracket comments method provided by the plugin, I would need to heavily modify the original code, as Trove has a multitude of types it uses within it.

To get around this and simplify the process, inside the global framework module under the ‘local globals = {}’ line, I require the trove module and simply get its type though there. And then afterwards I can use the Trove type though the Global framework normally. Currently this is the only place where edits to the module are not overwritten by the plugin.

image

This works fine with trove, However with FastSignal its a different story since it uses generics.

image

^ If I attempt to do this with the method I talked about, then every time I try to use the FastSignal type through Global, I can’t input my own arguments inside the <> brackets.

To be able to use the generics and global framework properly, I need to require FastSignal before the Global’s types are set. That way in my other scripts I can do the following:

image

here is one option of how you can bring a external module into global

--[[type TroveConstructor = typeof(require(game.ServerStorage.Trove))]]
--[[type Trove = typeof(require(game.ServerStorage.Trove).new())]]

local Global = require(script.Parent)

Global("Trove", require(game.ServerStorage.Trove) :: Global.TroveConstructor)

and here is a example of a class using the trove type

in other modules you might not even need the TroveConstructor type but because trove is setup a bit differently where it returns a separate table

image

this is why we had to make the separate TroveConstructor

1 Like

That’s intresting :thinking:
How would I do this with FastSignal that needs generics arguments?

I tried doing this but it isn’t working:

But I really think that allowing to let people write code above the global types is the best way to do this.