Untitled

mail@pastecode.io avatar
unknown
lua
a year ago
4.8 kB
4
Indexable
Never
--[[ Requires modules to be loaded and adds them to a table 
	Required at runtime by server/client bootstrappers
]]

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

_G.MemTrack = {
	Groups = {},

	Add = function(self, groupName, object)
		local group = self.Groups[groupName]

		if not group then
			group = {
				Size = 0,
				Objects = setmetatable({}, { __mode = "v" })
			}

			self.Groups[groupName] = group
		end

		group.Size += 1
		group.Objects[group.Size] = object

		return object
	end,

	CountObjectsAsync = function(self)
		if not self.Counting then
			task.spawn(function()
				self.Counting = true
				local result = {}

				local nextYield = os.clock() + 0.2e-3
				local function throttle()
					if os.clock() >= nextYield then
						task.wait()
						nextYield = os.clock() + 0.2e-3
					end
				end

				for groupName,group in pairs(self.Groups) do
					for index = group.Size, 1, -1 do
						if not group.Objects[index] then
							group.Objects[index] = group.Objects[group.Size]
							group.Objects[group.Size] = nil
							group.Size -= 1
						end

						throttle()
					end

					result[groupName] = group.Size
					throttle()
				end

				self.LastCount = result
				self.Counting = false
			end)
		end

		while self.Counting do
			task.wait()
		end

		return self.LastCount
	end,
}


local Global = {
	IsClient = RunService:IsClient(),
	IsServer = RunService:IsServer(),
	RNG = Random.new()
}

local InitList = {}

--[[ Iterate through modules and initialize them and add to Global ]]
local IsServer = game:GetService("RunService"):IsServer()
local function loadModules(root)
	for i,module in root:GetChildren() do 
		if module:IsA("Folder") then
			loadModules(module)
		end
		if not module:IsA("ModuleScript") then
			continue
		end
		local requiredModule = require(module)
		if type(requiredModule) ~= "table" and type(requiredModule) ~= "function" then
			continue
		end
		local skipLoad =  module:GetAttribute("SkipLoad") 
		if not skipLoad then
			InitList[module.Name] = requiredModule
		end
		if typeof(requiredModule) == "table" then
			requiredModule._skipLoad = skipLoad
		end
		Global[module.Name] = requiredModule
	end
end

function Global:TriggerInit()	
	for moduleName,module in InitList do 
		if type(module) ~= "table" then
			continue
		end
		if module.Init and typeof(module.Init) == "function" then
			module:Init()
		end
	end
	--[[ Start ensures safety(other modules are initialized at this point)]]
	for moduleName,module in InitList do
		if type(module) ~= "table" then
			continue
		end
		if moduleName == "ClientPlayerData" then
			continue -- We start this manually in the loading gate
		end
		if module.Start and typeof(module.Start) == "function" then
			module:Start()
		end
	end
	self:AfterStart()
end
function Global:AfterStart()
	for i,module in Global do
		if typeof(module) ~= "table" then
			continue
		end
		if module._skipLoad then
			continue
		end
		--[[ Module updates ]]
		for i,tab in module do 
			if typeof(tab) ~= "table" then
				continue
			end	
			local label = tab.UpdateLabel
			if label and tab.fn then
				local fn = tab.fn 
				Global:BindToHeartbeat(label,tab.Priority or Global.EventPriority.Default,function(dt)
					fn(module,dt)
				end)
			end
		end
		--
	end
end

task.defer(function()
	print("Loading modules...")
	loadModules(ReplicatedStorage.SharedModules)

	--[[ Some commonly used things ]]
	Global.FrameDelta = Global.Mathf.FrameDelta
	Global.FrameDeltaAlpha = function(n,dt)
		return math.clamp(Global.FrameDelta((1/60) / n,dt),0,1)
	end
	--


	if IsServer then
		loadModules(game.ServerStorage.ServerModules)
	else
		Global.Mouse = Players.LocalPlayer:GetMouse()
		Global.Player = Players.LocalPlayer
		loadModules(ReplicatedStorage.ClientModules)
	end

	loadModules(game.ReplicatedFirst.Modules)
	--
	print("Modules loaded")

	--[[ Init sharedvalues ]]
	if Global.IsServer then
		Global.SharedValues = {}
	else
		Global.SharedValues = Global.Network:InvokeServer("GetSharedValues")
	end
	if Global.IsServer then
		local sharedValues = Global.SharedValues
		Global.Network:BindFunctions({
			GetSharedValues = function(player)
				if player:GetAttribute("GotSharedValues") then
					return
				end
				player:SetAttribute("GotSharedValues", true)
				return sharedValues
			end,
		})
	end
	--

	for i,v in pairs(Global.GameEvents) do
		Global[i] = v
	end

	if RunService:IsServer() then
		Global:TriggerInit()
	end
	Global.IsLoaded = true
end)

return Global