first commit

This commit is contained in:
FatalErr42O 2024-06-26 21:07:54 -07:00
commit 4d5ec74078
5 changed files with 153 additions and 0 deletions

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
"/modlib/" directory: Copright (c) respective owners, see License.txt within the "/modlib/" directory.
All files outside of the modlib directory fall under the following license:
MIT License
Copyright (c) 2023 FatalError42O, Trevor Pasquali.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

3
init.lua Normal file
View File

@ -0,0 +1,3 @@
local path = minetest.get_modpath("mtul-class")
dofile(path.."/proxy_table.lua")
dofile(path.."/new_class.lua")

4
mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = mtul_class
title = MTUL class lib
description = Simple class system for minetest, with a inbuilt read only table system
author = FatalError42O

62
new_class.lua Normal file
View File

@ -0,0 +1,62 @@
--- An instantiatable class to inherit for defining new instantiatble classes classes
-- the "base" class. To make a new class call `new_class:inherit(your_new_class)`
--
-- @classmod new_class
mtul.class.new_class = {
instance = false,
--__no_copy = true
}
--- new_class
-- @table new_class
-- @field instance defines wether the object is an instance, use this in construction to determine what changes to make
-- @field base_class only present for instances: the class from which this instance originates
-- @field parent_class the class from which this class was inherited from
--- creates a new base class. Calls all constructors in the chain with def.instance=true
-- @param def the table containing a new definition (where the class calling the method is the parent). The content of the definition will override the fields for it's children.
-- @return def a new base class
-- @function Guns4d.Instantiatable_class:inherit()
function mtul.class.new_class:inherit(def)
--construction chain for inheritance
--if not def then def = {} else def = table.shallow_copy(def) end
def.parent_class = self
def.instance = false
--def.__no_copy = true
def._construct_low = def.construct
--this effectively creates a construction chain by overwriting .construct
function def.construct(parameters)
--rawget because in a instance it may only be present in a hierarchy but not the table itself
if self.construct then
self.construct(parameters)
end
if rawget(def, "_construct_low") then
def._construct_low(parameters)
end
end
--iterate through table properties
setmetatable(def, {__index = self})
def.construct(def) --moved this to call after the setmetatable, it doesnt seem to break anything, and how it should be? I dont know when I changed it... hopefully not totally broken.
return def
end
--- construct
-- every parent constructor is called in order of inheritance, this is used to make changes to the child table. In self you will find base_class defining what class it is from, and the bool instance indicating (shocking) wether it is an instance.
-- @function construct where self is the definition (after all higher parent calls) of the table. This is the working object, no returns necessary to change it's fields/methods.
--- creates an instance of the base class. Calls all constructors in the chain with def.instance=true
-- @return def a new instance of the class.
-- @function Guns4d.Instantiatable_class:new(def)
function mtul.class.new_class:new(def)
--if not def then def = {} else def = table.shallow_copy(def) end
def.base_class = self
def.instance = true
--def.__no_copy = true
function def:inherit()
assert(false, "cannot inherit instantiated object")
end
setmetatable(def, {__index = self})
--call the construct chain for inherited objects, also important this is called after meta changes
self.construct(def)
return def
end

60
proxy_table.lua Normal file
View File

@ -0,0 +1,60 @@
--
local Proxy_table = mtul.classes.proxy_table
Proxy_table = {
registered_proxies = {},
proxy_children = {}
}
--this creates proxy tables in a structure of tables
--this is great if you want to prevent the change of a table
--but still want it to be viewable, such as with constants
function Proxy_table:new(og_table, parent)
local new = {}
self.registered_proxies[og_table] = new
if parent then
self.proxy_children[parent][og_table] = true
else
self.proxy_children[og_table] = {}
parent = og_table
end
--set the proxy's metatable
setmetatable(new, {
__index = function(t, key)
if type(og_table[key]) == "table" then
return Proxy_table:get_or_create(og_table[key], parent)
else
return og_table[key]
end
end,
__newindex = function(table, key)
assert(false, "attempt to edit immutable table, cannot edit a proxy table (MTUL-class)")
end,
})
--[[overwrite og_table meta to destroy the proxy aswell (but I realized it wont be GCed unless it's removed altogether, so this is pointless)
local mtable = getmetatable(og_table)
local old_gc = mtable.__gc
mtable.__gc = function(t)
self.registered_proxies[t] = nil
self.proxy_children[t] = nil
old_gc(t)
end
setmetatable(og_table, mtable)]]
--premake proxy tables
for i, v in pairs(og_table) do
if type(v) == "table" then
Proxy_table:get_or_create(v, parent)
end
end
return new
end
function Proxy_table:get_or_create(og_table, parent)
return self.registered_proxies[og_table] or Proxy_table:new(og_table, parent)
end
function Proxy_table:destroy_proxy(parent)
self.registered_proxies[parent] = nil
if self.proxy_children[parent] then
for i, v in pairs(self.proxy_children[parent]) do
Proxy_table:destroy_proxy(i)
end
end
self.proxy_children[parent] = nil
end