Last active
May 12, 2017 18:21
-
-
Save devSparkle/634ea5831c04ffe10904cc4fedf3c041 to your computer and use it in GitHub Desktop.
My own flavor of the Nevermore framework by @Quenty
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--// Initialization | |
local RunService = game:GetService("RunService") | |
local ReplicatedStorage = game:GetService("ReplicatedStorage") | |
local ServerScriptService = game:GetService("ServerScriptService") | |
local Engine = {} | |
--// Variables | |
local RepositoryName = "Modules" | |
local DEBUG_MODE = false | |
--// Functions | |
local function Modify(Instance, Values) | |
assert(type(Values) == "table", "Error: Values is not a table.") | |
for Index, Value in next, Values do | |
if type(Index) == "number" then | |
Value.Parent = Instance | |
else | |
Instance[Index] = Value | |
end | |
end | |
return Instance | |
end | |
local function Make(ClassType, Properties) | |
return Modify(Instance.new(ClassType), Properties) | |
end | |
local function CallOnChildren(Instance, FunctionToCall) | |
FunctionToCall(Instance) | |
for ChildIndex, Child in next, Instance:GetChildren() do | |
CallOnChildren(Child, FunctionToCall) | |
end | |
end | |
local function HandleRetrieving(Retrieving, Function, Argument) | |
assert(type(Retrieving) == "table", "Error: Retrieving must be a table.") | |
assert(type(Function) == "function", "Error: Function must be a function.") | |
local Signal = Instance.new("BindableEvent") | |
local Result | |
Retrieving[Argument] = function() | |
return Result ~= nil and Result or Signal.Event:wait() | |
end; | |
Result = Function(Argument) | |
Retrieving[Argument] = nil | |
Signal:Fire(Result) | |
return Result | |
end | |
local function Cache(Function) | |
assert(type(Function) == "function", "Error: Function must be a userdata.") | |
local Cache = {} | |
local Retrieving = {} | |
return function(Argument) | |
assert(Argument ~= nil, "Error: Argument is nil.") | |
if Cache[Argument] then | |
return Cache[Argument] | |
elseif Retrieving[Argument] then | |
return Retrieving[Argument]() | |
else | |
Cache[Argument] = HandleRetrieving(Retrieving, Function, Argument) | |
return Cache[Argument] | |
end | |
end | |
end | |
local function Retrieve(Parent, ClassName) | |
assert(type(ClassName) == "string", "Error: ClassName must be a string") | |
assert(type(Parent) == "userdata", "Error: Parent must be a userdata") | |
return RunService:IsServer() and function(Name) | |
if DEBUG_MODE then | |
print(ClassName,Name) | |
end | |
return Parent:FindFirstChild(Name) or Make(ClassName, { | |
Parent = Parent; | |
Archivable = false; | |
Name = Name; | |
}) | |
end or function(Name) | |
return Parent:WaitForChild(Name) | |
end | |
end | |
--// Engine | |
local ResourceFolder = Retrieve(ReplicatedStorage, "Folder")("EngineResources") | |
local _LibraryCache = {} do | |
local Repository | |
if RunService:IsServer() then | |
Repository = ServerScriptService:FindFirstChild(RepositoryName) | |
if not Repository then | |
warn("Warning: No repository of modules found (Expected in ServerScriptService with name \"Engine\"). Library retrieval will fail.") | |
Repository = Instance.new("Folder") | |
Repository.Name = RepositoryName | |
end | |
else | |
Repository = ResourceFolder:WaitForChild("Modules") | |
end | |
CallOnChildren(Repository, function(Child) | |
if Child:IsA("ModuleScript") then | |
assert(not _LibraryCache[Child.Name], "Error: Duplicate name of \"" .. Child.Name .. "\" already exists!") | |
_LibraryCache[Child.Name] = Child | |
end | |
end) | |
if not RunService:IsClient() then --/ Written in this way to prevent issues with SoloTestMode. | |
local ReplicationFolder = ResourceFolder:FindFirstChild("Modules") or Make("Folder", { | |
Name = "Modules"; | |
Archivable = false; | |
Parent = ResourceFolder; | |
}) | |
local Secondary | |
for Name, Library in pairs(_LibraryCache) do | |
if not Name:lower():find("server") then | |
Library.Parent = ReplicationFolder | |
end | |
end | |
end | |
end | |
do | |
local SecondCache = {} | |
local DebugID = 0 | |
local RequestDepth = 0 | |
function Engine.LoadLibrary(LibraryName) | |
assert(type(LibraryName) == "string", "Error: LibraryName must be a string!") | |
if SecondCache[LibraryName] then | |
return SecondCache[LibraryName] | |
end | |
DebugID = DebugID + 1 | |
local LocalDebugID = DebugID | |
if DEBUG_MODE then | |
print(("\t"):rep(RequestDepth), LocalDebugID, "Loading: ", LibraryName) | |
RequestDepth = RequestDepth + 1 | |
end | |
local Library = require(_LibraryCache[LibraryName] or error("Error: Library \"" .. LibraryName .. "\" does not exist.")) | |
SecondCache[LibraryName] = Library | |
if DEBUG_MODE then | |
RequestDepth = RequestDepth - 1 | |
print(("\t"):rep(RequestDepth), LocalDebugID, "Done Loading: ", LibraryName) | |
end | |
return Library | |
end | |
end | |
Engine.GetRemoteEvent = Cache(Retrieve(Retrieve(ResourceFolder, "Folder")("RemoteEvents"), "RemoteEvent")) | |
Engine.GetBindableEvent = Cache(Retrieve(Retrieve(ResourceFolder, "Folder")("BindableEvents"), "BindableEvent")) | |
Engine.GetRemoteFunction = Cache(Retrieve(Retrieve(ResourceFolder, "Folder")("RemoteFunctions"), "RemoteFunction")) | |
Engine.GetBindableFunction = Cache(Retrieve(Retrieve(ResourceFolder, "Folder")("BindableFunctions"), "BindableFunction")) | |
return Engine |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment