Skip to content

Instantly share code, notes, and snippets.

@Validark
Last active May 5, 2017 04:36
Show Gist options
  • Save Validark/29eba42d4f9ab0e18b8c07cf78577a8e to your computer and use it in GitHub Desktop.
Save Validark/29eba42d4f9ab0e18b8c07cf78577a8e to your computer and use it in GitHub Desktop.
Now supports infinite yielding for Folder creation as well!
-- @author Validark
-- @original Quenty
-- @readme https://github.com/NevermoreFramework/Nevermore
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
-- Configuration
local FolderName = "Modules" -- Name of Module Folder in ServerScriptService
local ResourcesLocation = script -- Where the "Resources" folder is, it will be generated if needed
local Classes = { -- Allows for abbreviations
Event = "RemoteEvent"; -- You can use Nevermore:GetEvent() instead of GetRemoteEvent()
Function = "RemoteFunction";
}
local Plurals = { -- If you want to name the folder something besides [Name .. "s"]
Accessory = "Accessories";
Folder = script.Name
}
if script.Name == "ModuleScript" then error("[Nevermore] Nevermore was never given a name") end
if script.ClassName ~= "ModuleScript" then error("[Nevermore] Nevermore must be a ModuleScript") end
if script.Parent ~= ReplicatedStorage then error("[Nevermore] Nevermore must be parented to ReplicatedStorage") end
local function GetFirstChild(Parent, Name, Class) -- This is what allows the client / server to run the same code
local Object, Bool = Parent:FindFirstChild(Name)
if not Object then
Object = Instance.new(Class, Parent)
Object.Name = Name
Bool = true
end
return Object, Bool
end
local Retrieve = GetFirstChild
local function Error(Parent, Name, Class)
return Parent:FindFirstChild(Name) or error(("[Nevermore] %s \"%s\" is not installed."):format(Class, Name))
end
local Nevermore = {
__metatable = "[Nevermore] Nevermore's metatable is locked";
GetFirstChild = GetFirstChild;
}
local LocalResourcesLocation, CreateResourceManager
if not RunService:IsServer() then
LocalResourcesLocation = game:GetService("Players").LocalPlayer
GetFirstChild = game.WaitForChild
else
LocalResourcesLocation = ServerStorage
end
local function GetFolder() return GetFirstChild(ResourcesLocation, "Resources", "Folder") end
local function GetLocalFolder(...)
function GetLocalFolder()
return Retrieve(LocalResourcesLocation, "Resources", "Folder")
end
local Object, Bool = CreateResourceManager(Nevermore, "GetLocalFolder")(...)
GetLocalFolder = Nevermore.GetLocalFolder
return Object, Bool
end
function CreateResourceManager(Nevermore, Name, Data) -- Create methods called to Nevermore
if type(Name) == "string" then
local FullName, Local = Name
Name, Local = Name:gsub("^Get", ""):gsub("^Local", "")
local function Function(...)
local Class = Classes[Name] or Name
local GetFirstChild, Folder, Table = GetFirstChild
if Local == 0 then
Folder = GetFolder(Plurals[Class] or Class .. "s")
local Success, Table = pcall(Instance.new, Class)
if Success then
Table:Destroy()
else
if GetFirstChild == Retrieve then
GetFirstChild = Error
end
end
else
Folder = GetLocalFolder(Plurals[Class] or Class .. "s")
end
Table = Data or {}
function Function(self, Name, Parent)
if self ~= Nevermore then -- Enables functions to support calling by '.' or ':'
Name, Parent = self, Name
end
local Object, Bool = Table[Name]
if not Object then
Object, Bool = GetFirstChild(Parent or Folder, Name, Class)
if not Parent then
Table[Name] = Object
end
end
return Object, Bool
end
Nevermore[FullName] = Function
return Function(...)
end
Nevermore[FullName] = Function
return Function
end
end
Nevermore.__index = CreateResourceManager
setmetatable(Nevermore, Nevermore)
local Modules do -- Assembles table Modules
local Repository = CreateResourceManager(Nevermore, "GetFolder")("Modules") -- Grabs Module folder
GetFolder = Nevermore.GetFolder
if RunService:IsServer() then
local ServerModules = ServerScriptService:FindFirstChild(FolderName or "Nevermore") or error("Make sure your module repository is a descendant of ServerScriptService named " .. (FolderName or "Nevermore"))
ServerModules.Name = ""
local ServerRepository = GetLocalFolder("Modules")
local Boundaries = {}
local Count, BoundaryCount = 0, 0
local NumDescendants, CurrentBoundary = 1, 1
local LowerBoundary, SetsEnabled
Modules = {ServerModules}
repeat
Count = Count + 1
local Child = Modules[Count]
local Name = Child.Name
local GrandChildren = Child:GetChildren()
local NumGrandChildren = #GrandChildren
if SetsEnabled then
if not LowerBoundary and Count > Boundaries[CurrentBoundary] then
LowerBoundary = true
elseif LowerBoundary and Count > Boundaries[CurrentBoundary + 1] then
CurrentBoundary = CurrentBoundary + 2
local Boundary = Boundaries[CurrentBoundary]
if Boundary then
LowerBoundary = Count > Boundary
else
SetsEnabled = false
LowerBoundary = false
end
end
end
local Server = LowerBoundary or Name:lower():find("server")
if NumGrandChildren ~= 0 then
if Server then
SetsEnabled = true
Boundaries[BoundaryCount + 1] = NumDescendants
BoundaryCount = BoundaryCount + 2
Boundaries[BoundaryCount] = NumDescendants + NumGrandChildren
end
for a = 1, NumGrandChildren do
Modules[NumDescendants + a] = GrandChildren[a]
end
end
if Child.ClassName == "ModuleScript" then
if LowerBoundary or not Modules[Name] then
Modules[Name] = Child
Child.Parent = Server and ServerRepository or Repository
else
error("[Nevermore] Duplicate Module with name \"" .. Name .. "\"")
end
elseif Child.ClassName ~= "Folder" then
Child.Parent = GetLocalFolder("ServerStuff", ServerScriptService)
warn("[Nevermore] You shouldn't have", Child:GetFullName(), "in your modules Repository")
end
NumDescendants, Modules[Count] = NumDescendants + NumGrandChildren
until Count == NumDescendants
ServerModules:Destroy()
end
end
local GetModule = CreateResourceManager(Nevermore, "GetModule", Modules)
function Nevermore.LoadLibrary(self, Name) -- Custom Require function
Name = self ~= Nevermore and self or Name
return type(Name) ~= "string" and error("[Nevermore] ModuleName must be a string") or require(GetModule(Name))
end
Nevermore.__call = Nevermore.LoadLibrary
return Nevermore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment