Skip to content

Instantly share code, notes, and snippets.

@Pyseph
Last active October 19, 2024 15:10
Show Gist options
  • Save Pyseph/8f1d6b2499f5eb0aa7be2712f8ea9922 to your computer and use it in GitHub Desktop.
Save Pyseph/8f1d6b2499f5eb0aa7be2712f8ea9922 to your computer and use it in GitHub Desktop.
Custom Enum class for Roblox
--[[
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
@PatoFlamejanteTV
Copy link

Thats working nice! Thanks :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment