Created
April 12, 2024 21:35
-
-
Save AlphaTechNinja/a757bd790b53d23f49df3bd78ab79ea6 to your computer and use it in GitHub Desktop.
A refined version of my class library (now supports multi class inheritance, search tree, and loading) WARNING: this is written for cc: tweaked (to make it compatible with other engines you will have to change the “fs library to match the ones of your program”)
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
| --refined class library | |
| local classes = {} | |
| classes.__index = classes | |
| classes.path = package.path | |
| classes._tree = {} | |
| classes.loaded = {} | |
| local weakTab = {__mode = "k"} | |
| local function multiclass(parents) | |
| local fast = {} | |
| setmetatable(fast,weakTab) | |
| return function (k) | |
| if fast[k] then | |
| return fast[k] | |
| end | |
| --return function (k) | |
| for _,parent in pairs(parents) do | |
| if parent[k] then | |
| fast[k] = parent[k] | |
| return parent[k] | |
| end | |
| end | |
| end | |
| end | |
| function classes.create(name,...) | |
| local args = {...} | |
| if #args == 0 then | |
| local class = setmetatable({},classes) | |
| class.__name = name | |
| table.insert(classes._tree,class) | |
| class.__index = class | |
| return class | |
| end | |
| if #args < 2 then | |
| local class = setmetatable({},args[1] or classes) | |
| class.__name = name | |
| table.insert(classes._tree,class) | |
| class.__index = class | |
| return class | |
| end | |
| local class = {} | |
| class.__name = name | |
| table.insert(classes._tree,class) | |
| setmetatable(class,{__index = multiclass(args),__parents = args}) | |
| class.__index = class | |
| return class | |
| end | |
| setmetatable(classes,{__call = function (_,...) return classes.create(...) end}) | |
| -- private allows addition specification of external methods | |
| function classes.private(name,private,...) | |
| local base = classes.create(name,...) | |
| local old = getmetatable(base) | |
| if type(old) == "function" then | |
| setmetatable(base,{__index = function (_,k) local v = old(k) if v then return v else return private[k] end end}) | |
| else | |
| setmetatable(base,{__index = multiclass(old,private)}) | |
| end | |
| return base | |
| end | |
| --methods | |
| function classes:new(...) | |
| if self.constructor then | |
| return self:constructor(...) | |
| else | |
| return setmetatable({...},self) | |
| end | |
| end | |
| function classes:__call(...) | |
| return self:new(...) | |
| end | |
| function classes:isOf(parent,direct) | |
| if direct then | |
| return getmetatable(self) == parent | |
| elseif getmetatable(self).__parents then | |
| else | |
| if getmetatable(self) == parent then | |
| return true | |
| else | |
| return getmetatable(self):isOf(parent) | |
| end | |
| end | |
| end | |
| --the tree allows classes to persist entire removed | |
| function classes:remove() | |
| for i,class in ipairs(classes._tree) do | |
| if class == self then | |
| table.remove(classes._tree,i) | |
| return | |
| end | |
| end | |
| end | |
| function classes.getClass(name) | |
| for i,class in ipairs(classes._tree) do | |
| if class.__name == name then | |
| return class | |
| end | |
| end | |
| end | |
| local env = {} | |
| env.require = require | |
| env.package = package | |
| --load classes | |
| function classes.loadClass(name,class) | |
| --classes can be required seperate from standard require | |
| --used to insert a class | |
| if class then | |
| assert(not classes.loaded[name],"class has already been defined") | |
| classes.loaded[name] = class | |
| return true | |
| end | |
| --normal | |
| local errmsg = {} | |
| local function err(str) | |
| table.insert(errmsg,str) | |
| end | |
| err(("failed to load class '%s':"):format(name)) | |
| --check for class | |
| if classes.loaded[name] then | |
| return classes.loaded[name] | |
| end | |
| --search | |
| --make name a normal path | |
| local normal = name:gsub("%.","%/") | |
| local found | |
| for path in classes.path:gmatch("[^;]+") do | |
| --substitute wild card | |
| path = path:gsub("%?",normal) | |
| if path:sub(1,1) == "/" then | |
| --absolute path | |
| if fs.exists(path) then | |
| found = path | |
| break | |
| end | |
| else | |
| --relitive | |
| --append relitive path | |
| path = fs.combine(fs.getDir(shell.getRunningProgram()),path) | |
| if fs.exists(path) then | |
| found = path | |
| break | |
| end | |
| end | |
| --add to errors | |
| err(("%s not found in %s"):format(name,path)) | |
| end | |
| if found then | |
| classes.loaded[name] = loadfile(found,setmetatable({},{__index = function (_,k) if _G[k] then return _G[k] else return env[k] end end}))(classes) | |
| return classes.loaded[name] | |
| end | |
| error(table.concat(errmsg,"\n"),2) | |
| end | |
| return classes |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment