Instantly share code, notes, and snippets.
Last active
October 19, 2024 15:10
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save Pyseph/8f1d6b2499f5eb0aa7be2712f8ea9922 to your computer and use it in GitHub Desktop.
Custom Enum class for Roblox
This file contains hidden or 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
--[[ | |
EXAMPLE USAGE: | |
local BaseState = CustomEnum.Class.new("BaseState", { | |
"Dead", | |
"Alive", | |
"Walking", | |
}) | |
local SubState = CustomEnum.Class.New("CombatStates", { | |
"Attacking", | |
"Dodging", | |
"Blocking", | |
}) | |
BaseState:AddItem(SubState) | |
SubState.Attacking:IsA(BaseState) -- true | |
BaseState.Dead:IsA(SubState) -- false | |
print(BaseState.SubState.Attacking) -- "Attacking" | |
]] | |
local EnumConstructor = { | |
Class = {}, | |
Item = {}, | |
} | |
local EnumItem = {} | |
local EnumClass = {} | |
function EnumItem.__index(self, key) | |
local FoundValue = rawget(EnumItem, key) | |
if not FoundValue then | |
error(`{key} is not a valid member of "{self._MainParent.Name}.{self.Name}"`) | |
end | |
return FoundValue | |
end | |
function EnumClass.__index(self, key) | |
local FoundValue = rawget(self._Items, key) or rawget(EnumClass, key) | |
if not FoundValue then | |
error(`{key} is not a valid member of "{self.Name}"`) | |
end | |
return FoundValue | |
end | |
function EnumClass.__tostring(self) | |
local HasParent = rawget(self, "_MainParent") ~= nil | |
local Prefix = HasParent and `{self._MainParent.Name}.` or `` | |
return `{Prefix}{self.Name}` | |
end | |
function EnumItem:IsA(Class) | |
if typeof(Class) == "table" and Class.Type == "EnumClass" then | |
Class = Class.Name | |
end | |
assert(typeof(Class) == "string", `invalid argument #2 to 'IsA' (string expected, got {typeof(Class)})`) | |
for ParentName, ParentClass in self._Parents do | |
if ParentName == Class or ParentClass:IsA(Class) then | |
return true | |
end | |
end | |
return self._Parents[Class] ~= nil | |
end | |
function EnumItem:GetFullName() | |
local FullName = self.Name | |
local Parent = rawget(self, "_MainParent") | |
while Parent do | |
FullName = `{Parent.Name}.{FullName}` | |
Parent = rawget(Parent, "_MainParent") | |
end | |
return FullName | |
end | |
EnumItem.__tostring = EnumItem.GetFullName | |
function EnumClass:GetEnumItems() | |
return self._Items | |
end | |
function EnumClass:IsA(Class) | |
if typeof(Class) == "table" and Class.Type == "EnumClass" then | |
Class = Class.Name | |
end | |
assert(typeof(Class) == "string", `invalid argument #2 to 'IsA' (string expected, got {typeof(Class)})`) | |
for ParentName, ParentClass in self._Parents do | |
if ParentName == Class or ParentClass:IsA(Class) then | |
return true | |
end | |
end | |
return self._Parents[Class] ~= nil | |
end | |
function EnumClass:AddItem(EnumObject) | |
assert( | |
type(EnumObject) == "table", | |
`invalid argument #1 to 'AddItem' (EnumItem or EnumClass expected, got {typeof(EnumObject)})` | |
) | |
assert( | |
EnumObject.Type == "EnumItem" or EnumObject.Type == "EnumClass", | |
`invalid argument #1 to 'AddItem' (EnumItem or EnumClass expected, got {typeof(EnumObject)})` | |
) | |
self._Items[EnumObject.Name] = EnumObject | |
EnumObject._Parents[self.Name] = self | |
if rawget(EnumObject, "_MainParent") == nil then | |
EnumObject._MainParent = self | |
end | |
end | |
function EnumClass:GetFullName() | |
local FullName = self.Name | |
local Parent = rawget(self, "_MainParent") | |
while Parent do | |
FullName = `{Parent.Name}.{FullName}` | |
Parent = rawget(Parent, "_MainParent") | |
end | |
return FullName | |
end | |
EnumClass.__tostring = EnumClass.GetFullName | |
function EnumConstructor.Item.new(ParentClass, ItemName) | |
assert( | |
type(ParentClass) == "table" and ParentClass.Type == "EnumClass", | |
`invalid argument #1 to 'EnumItem.new' (EnumClass expected, got {typeof(ParentClass)})` | |
) | |
assert( | |
type(ItemName) == "string", | |
`invalid argument #2 to EnumItem.new (string expected, got {typeof(ItemName)})` | |
) | |
local Item = setmetatable({ | |
Name = ItemName, | |
Type = "EnumItem", | |
_Parents = {}, | |
_MainParent = ParentClass, | |
}, EnumItem) | |
ParentClass:AddItem(Item) | |
return Item | |
end | |
function EnumConstructor.Class.new(ClassName, Items) | |
local ItemsHolder = {} | |
local Class = setmetatable({ | |
Name = ClassName, | |
Type = "EnumClass", | |
_Items = ItemsHolder, | |
_Parents = {}, | |
_MainParent = nil, | |
}, EnumClass) | |
if Items ~= nil then | |
assert( | |
type(Items) == "table", | |
`invalid argument #2 to EnumClass.new (table expected, got {type(Items)})` | |
) | |
for _, Item in Items do | |
if typeof(Item) == "string" then | |
EnumConstructor.Item.new(Class, Item) | |
elseif typeof(Item) == "table" and (Item.Type == "EnumItem" or Item.Type == "EnumClass") then | |
Class:AddItem(Item) | |
end | |
end | |
end | |
return Class | |
end | |
return EnumConstructor |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thats working nice! Thanks :D