Skip to content

Instantly share code, notes, and snippets.

@appgurueu
Last active March 9, 2022 00:53
Show Gist options
  • Save appgurueu/b17f118c86545ce7f353a13fa68c3524 to your computer and use it in GitHub Desktop.
Save appgurueu/b17f118c86545ce7f353a13fa68c3524 to your computer and use it in GitHub Desktop.
modlib - init.lua - template
-- Table helpers
table_ext= {
tablecopy = function(t)
return table.copy(t)
end,
count = function(table)
local count = 0
for _ in pairs(table) do
count = count + 1
end
return count
end,
is_empty = function(table)
return next(table) == nil
end,
merge_tables = function(table1, table2)
local table1copy = table.copy(table1)
for key, value in pairs(table2) do
table1copy[key] = value
end
return table1copy
end,
add_all=function(dst, new)
for key, value in pairs(new) do
dst[key] = value
end
return dst
end,
get_value = function(table, key)
if type(key) == "table" then
for k, v in pairs(table) do
if key==k then
return v
end
end
return nil
end
return table[key]
end,
keys = function(table)
local keys = {}
for key, _ in pairs(table) do
table.insert(keys, key)
end
return keys
end,
values = function(table)
local values = {}
for key, _ in pairs(table) do
table.insert(values, key)
end
return values
end,
flip = function(table)
local flipped = {}
for key, val in pairs(table) do
flipped[val] = key
end
return flipped
end,
unique = function(table)
local lookup = {}
for val in ipairs(table) do
lookup[val] = true
end
return table_ext.keys(lookup)
end,
rpairs=function(t)
local i = #t
return function ()
if i >= 1 then
local v=t[i]
i = i-1
if v then
return i+1, v
end
end
end
end,
best_value=function(table, is_better_fnc)
if not table or not is_better_fnc then
return nil
end
local l=#table
if l==0 then
return nil
end
local m=table[1]
for i=2, l do
local v=table[i]
if is_better_fnc(v, m) then
m=v
end
end
return m
end,
min = function(table)
return table_ext.best_value(table, function(v, m) return v < m end)
end,
max = function(table)
return table_ext.best_value(table, function(v, m) return v > m end)
end
}
-- Number helpers - currently only round
number_ext={
round=function (number, steps) --Rounds a number
steps=steps or 1
return math.floor(number*steps+0.5)/steps
end
}
-- File helpers - reading, writing, appending, exists, create_if_not_exists
file_ext={
read=function(filename)
local file=io.open(filename,"r")
if file==nil then
return nil
end
local content=file:read("*a")
file:close()
return content
end,
write=function(filename, new_content)
local file=io.open(filename,"w")
if file==nil then
return false
end
file:write(new_content)
file:close()
return true
end,
append=function(filename, new_content)
local file=io.open(filename,"a")
if file==nil then
return false
end
file:write(new_content)
file:close()
return true
end,
exists=function(filename)
local file=io.open(filename, "r")
if file==nil then
return false
end
file:close()
return true
end,
create_if_not_exists=function(filename, content)
if not file_ext.exists(filename) then
file_ext.write(filename, content)
return true
end
return false
end,
create_if_not_exists_from_file=function(filename, src_filename)
return file_ext.create_if_not_exists(filename, file_ext.read(src_filename))
end
}
-- Minetest related helpers --
-- get modpath wrapper
function get_resource(modname, resource)
return minetest.get_modpath(modname).."/"..resource
end
-- get resource + dofile
function include(modname, file)
dofile(get_resource(modname, file))
end
-- dofile with table env
function include_class(classname, filename)
local file=io.open(filename, "r")
local class=classname.."={_G=_G, G=_G}\nsetfenv(1,setmetatable("..classname..", {__index=_G, __call=_G}))\n"..file:read("*a").."\n"
local fnc=assert(loadstring(class))
fnc()
file:close()
end
-- runs main.lua in table env
function include_mod(modname, config_constraints)
include_class(modname, get_resource(modname,"main.lua"))
if config_constraints then
end
end
-- Configuration helpers - load config, check constraints
minetest.mkdir(minetest.get_worldpath().."/config")
conf={
get_path=function(confname)
return minetest.get_worldpath().."/config/"..confname
end,
load=function (filename, constraints)
local config=minetest.parse_json(file_ext.read(filename))
if constraints then
local error_message=conf.check_constraints(config, constraints)
if error_message then
error("Configuration - "..confpath.." doesn't satisfy constraints : "..error_message)
end
end
return config
end,
load_or_create=function(filename, replacement_file, constraints)
file_ext.create_if_not_exists_from_file(filename, replacement_file)
return conf.load(filename, constraints)
end,
import=function(modname,constraints)
return conf.load_or_create(conf.get_path(modname)..".json",get_resource(modname, "default_config.json"),constraints)
end,
check_constraints=function(value, constraints)
local t=type(value)
if constraints.func then
local possible_errors=constraints.func(value)
if possible_errors then
return possible_errors
end
end
if constraints.type~=t then
return "Wrong type : Expected "..constraints.type..", found "..t
end
if (t == "number" or t == "string") and constraints.range then
if value < constraints.range[1] or value > constraints.range[2] then
return "Not inside range : Expected value >= "..constraints.range[1].." and <= "..constraints.range[1]..", found "..minetest.write_json(value)
end
end
if constraints.possible_values and not table_ext.get_value(constraints.possible_values,value) then
return "None of the possible values : Expected one of "..minetest.write_json(table_ext.keys(constraints.possible_values))..", found "..minetest.write_json(value)
end
if t == "table" then
if constraints.children then
for k, v in pairs(value) do
local child=constraints.children[k]
if not child then
return "Unexpected table entry : Expected one of "..minetest.write_json(table_ext.keys(constraints.children))..", found "..minetest.write_json(k)
else
local possible_errors=conf.check_constraints(v, child)
if possible_errors then
return possible_errors
end
end
end
for k, _ in pairs(constraints.children) do
if value[k] == nil then
return "Table entry missing : Expected key "..minetest.write_json(k).." to be present in table "..minetest.write_json(value)
end
end
end
if constraints.keys then
for k,_ in pairs(value) do
local possible_errors=conf.check_constraints(k, constraints.keys)
if possible_errors then
return possible_errors
end
end
end
if constraints.values then
for _,v in pairs(value) do
local possible_errors=conf.check_constraints(v, constraints.values)
if possible_errors then
return possible_errors
end
end
end
end
end
}
-- Log helpers - write to log, force writing to file
minetest.mkdir(minetest.get_worldpath().."/logs")
log={
channels={},
get_path=function(logname)
return minetest.get_worldpath().."/logs/"..logname
end,
create_channel=function(title)
log.channels[title]={filename=log.get_path(title),queue={}}
end,
write=function(channelname, msg)
table.insert(log.channels[channelname].queue, msg)
end,
write_to_file=function(name, channel, current_date)
if not channel then
channel=log.channels[name]
end
if #(channel.queue) > 0 then
local filename=channel.filename.."_"..(current_date or os.date("%Y-%m-%d"))..".txt"
local rope={}
for _, msg in ipairs(channel.queue) do
table.insert(rope, msg)
end
file_ext.append(filename, table.concat(rope, "\n").."\n")
log.channels[name].queue={}
end
end,
write_all_to_file=function()
local current_date=os.date("%Y-%m-%d")
for name, channel in pairs(log.channels) do
log.write_to_file(name, channel, current_date)
end
end
}
local timer=0
minetest.register_globalstep(function(dtime)
timer=timer+dtime
if timer > 5 then
log.write_all_to_file()
timer=0
end
end)
minetest.register_on_shutdown(log.write_all_to_file)
@appgurueu
Copy link
Author

Minetest mod

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