Initial commit

This commit is contained in:
Tony Bark 2025-02-07 14:39:37 -05:00
commit df8714aa1d
171 changed files with 1686 additions and 0 deletions

111
mods/wislib/init.lua Normal file
View file

@ -0,0 +1,111 @@
--luarocks imports
local lfs = minetest or require("lfs")
--local luajson = minetest or require("json") --lua-json
local dkjson = minetest or require("dkjson")
--setup lib env
--context is always -eq to the highest possible subfolder in the mods dir, this can be ether the mod or modpack root folder.
local DIR_DELIM = debug.getinfo(1, "S").source:match("[\\/]")
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or "modpack"
local modpath = minetest and core.get_modpath(core.get_current_modname()) or debug.getinfo(1, "S").source:match("^(.+)[/\\]"):sub(2)
--declare stuff
local namespace = {} --this file creates the context, tested using lua 5.1 and via mt's built-in virtual lua sandbox env
namespace.mergeTables = function(firstTable, secondTable)
if firstTable == nil then firstTable = {} end
if secondTable == nil then return firstTable end
for k,v in pairs(secondTable) do firstTable[k] = v end
return firstTable
end
namespace.getCallerInfo = function(p1IntLookback)
p1IntLookback = p1IntLookback or 0
local info = debug.getinfo(2 + p1IntLookback, "Sl")
if info then
return info
end
end
namespace.parse = function(p1String, p2Default)
if minetest then
return core.parse_json(p1String)
else
return (dkjson.decode(p1String) or p2Default) end
end
namespace.stringify = function(p1Table, p2Pretty)
p2Pretty = p2Pretty or true
return minetest and core.write_json(p1Table, p2Pretty) or dkjson.encode(p1Table, { indent = p2Pretty })
end
namespace.log = function(...)
local info = namespace.getCallerInfo(1)
--console: none, error
--debug.txt:none, error, warning, action
--never?info, verbose, trace
--debug_log_level = action
if core then core.log("action", table.concat({"logged from: ", info.short_src,"@", info.currentline,";"})) end
for _, arg in ipairs({...}) do
arg = tostring(arg)
if type(arg) == "table" then
local _ = minetest and core.debug(namespace.stringify(arg)) or _G["io"]["write"](namespace.stringify(arg))
else
local _ = minetest and core.debug(arg) or _G["io"]["write"](arg)
end
end
_G["print"]("")
end
local print = namespace.log
--print("[", namespace.parse("[false]"))
--print("{", namespace.stringify({false}))
namespace.get_dir_list=minetest and core.get_dir_list or function (folder)
local returns = {}
for filePath in lfs.dir(folder) do
if filePath~= "." and filePath ~= ".." then
table.insert(returns, filePath)
end
end
return returns
end
namespace.dofolder = function(folder, todoFunc)
for _, filePath in ipairs(namespace.get_dir_list(folder..modpath:match("[\\/]"))) do
if todoFunc ~= nil then
todoFunc(filePath)
end
end
end
--add local to global context
_G[context] = {}
_G[context] = namespace.mergeTables(_G[context], namespace)
-- do the thing
dofile(table.concat({modpath,"string.lua"}, DIR_DELIM))
dofile(table.concat({modpath,"table.lua"}, DIR_DELIM))
-- DIR_DELIM 2345 < is 5 chars shorter, why must I be made to do things the hard way!
namespace.dofolder(modpath .. modpath:match("[\\/]") .. "lua5_1", function(filePath)
if filePath:match("^.+%.(.+)$") == "lua" then
dofile(modpath .. modpath:match("[\\/]") .. "lua5_1"..modpath:match("[\\/]")..filePath)
end
end)
if minetest or (core and luanti)then
--This was written before the name charge to match lexicographic order,
--I'm not renaming it cause you chose to have an internal vote
--Editors Note: yeah, get em blood child!
_G[context].dofolder(modpath .. modpath:match("[\\/]") .. "minetest", function(filePath)
if filePath:match("^.+%.(.+)$") == "lua" then
dofile(modpath .. modpath:match("[\\/]") .. "minetest"..modpath:match("[\\/]")..filePath)
end
end)
end
_G[context].dofolder(modpath .. modpath:match("[\\/]") .. "namespace", function(filePath)
if filePath:match("^.+%.(.+)$") == "lua" then
dofile(modpath .. modpath:match("[\\/]") .. "namespace"..modpath:match("[\\/]")..filePath)
end
end)
--return so dofile works correctly
return namespace

View file

@ -0,0 +1,126 @@
--[[
AND (&): Performs a bitwise AND operation.
OR (|): Performs a bitwise OR operation.
XOR (~): Performs a bitwise exclusive OR operation.
NOT (~): Performs a unary bitwise NOT operation.
Left Shift (<<): Shifts bits to the left.
Right Shift (>>): Shifts bits to the right12.
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67,
71, 73, 79, 83, 89, 97, 101,
103, 107, 109, 113, 127, 131,
137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191,
193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277,
281, 283, 293, 307, 311, 313,
317, 331, 337, 347, 349, 353,
359, 367, 373, 379, 383,
389, 397, 401, 409, 419, 421, 431, 433, 439,
443, 449, 457, 461, 463, 467, 479, 487, 491, 499,
503, 509, 521, 523, 541, 547, 557, 563, 569, 571,
577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
641, 643, 647, 653, 659, 661, 673, 677, 683, 691,
701, 709, 719, 727, 733, 739, 743, 751, 757, 761,
769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
911, 919, 929, 937, 941, 947, 953, 967, 971, 977,
983, 991, 997
--]]
-- Bitwise AND
function band(a, b)
local result = 0
local bitval = 1
while a > 0 and b > 0 do
local abit = a % 2
local bbit = b % 2
if abit == 1 and bbit == 1 then
result = result + bitval
end
a = math.floor(a / 2)
b = math.floor(b / 2)
bitval = bitval * 2
end
return result
end
-- Bitwise OR
function bor(a, b)
local result = 0
local bitval = 1
while a > 0 or b > 0 do
local abit = a % 2
local bbit = b % 2
if abit == 1 or bbit == 1 then
result = result + bitval
end
a = math.floor(a / 2)
b = math.floor(b / 2)
bitval = bitval * 2
end
return result
end
-- Bitwise XOR
function bxor(a, b)
local result = 0
local bitval = 1
while a > 0 or b > 0 do
local abit = a % 2
local bbit = b % 2
if abit ~= bbit then
result = result + bitval
end
a = math.floor(a / 2)
b = math.floor(b / 2)
bitval = bitval * 2
end
return result
end
-- Bitwise NOT
function bnot(a)
local result = 0
local bitval = 1
while a > 0 do
local abit = a % 2
if abit == 0 then
result = result + bitval
end
a = math.floor(a / 2)
bitval = bitval * 2
end
return result
end
-- Left shift
function lshift(x, by)
return x * 2 ^ by
end
-- Right shift
function rshift(x, by)
return math.floor(x / 2 ^ by)
end
local gen_bitwise_assert = function(a,b)
print("AND: ", band(a, b))
print("OR: ", bor(a, b))
print("XOR: ", bxor(a, b))
print("NOT: ", bnot(271))
print("Left Shift: ", lshift(a, 1))
print("Right Shift: ", rshift(a, 1))
end
local a, b = 127, 271
--gen_bitwise_assert(a,b)
assert(band(a, b) == 15)
assert(bor(a, b) == 383)
assert(bxor(a, b) == 368)
assert(bnot(b) == 240)
assert(lshift(a, 1) == 254)
assert(rshift(a, 1) == 63)

View file

125
mods/wislib/lua5_1/io.lua Normal file
View file

@ -0,0 +1,125 @@
--context is always -eq to the highest possible subfolder in the mods dir, this can be ether the mod or modpack root folder.
local DIR_DELIM = debug.getinfo(1, "S").source:match("[\\/]")
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or "context"
local cwdpath = minetest and (minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELIM .. "lua5_1") or debug.getinfo(1, "S").source:match("^(.+)[/\\]"):sub(2)
--setup lib env
local print = _G[context]["log"]
--some string function moved here, for more info see: string.lua
function string:trim()
return self:match("^%s*(.-)%s*$")
end
--[[
function string:split (p2Sep, p3Patern)
if p2Sep == nil then
p2Sep = "%s"
end
if p3Patern == nil then
p3Patern = table.concat({"([^", p2Sep, "]+)"}, "")
end
local returns = {}
for _ in string.gmatch(self, p3Patern) do
table.insert(returns, _)
end
return returns
end
--]]
function string:startsWith(p2Needle) -- self == haystack
return self:sub(1, #p2Needle) == p2Needle
end
function string:endsWith(p2Needle) -- self == haystack
return p2Needle == "" or self:sub(-#p2Needle) == p2Needle
end
function string:charCount(p2Char)
local count = 0
for _ in string.gmatch(self, p2Char) do
count = count + 1
end
return count
end
--end string.lua snipet
_G[context].colors ={
reset = "\27[0m",
red = "\27[31m",
green = "\27[32m",
yellow = "\27[33m",
blue = "\27[34m",
magenta = "\27[35m",
cyan = "\27[36m",
white= "\27[37m"
}
_G[context].forFileAsLines=function(filePath, funcHandle, ignoreReturn)
local file = io.open(filePath, "r")
--if file is context:open then
local returns = {}
if not file then error(_G[context].colors.red.."access error: reading non-existant file, @" .._G[context].colors.cyan ..filePath.._G[context].colors.reset) end
if file then
--itarate over each line and pass to funkyFunc
for line in file:lines() do
local linedata=line:trim()--:sub(1,-2) --remove spooky char at the end of a line. If file uses \r\n, it may require (1,-3)
linedata=funcHandle and (funcHandle(linedata)) or linedata --buggy:TODO
--this data subject to brakeages, test for errors here:
--print("<"..linedata..">")
if not ignoreReturn then --used for large files, to avoid memory bloat.
table.insert(returns, linedata)
end
end
file:close()
return returns
else
return {}
end
end
--
_G[context].forFileAsIniObj = function(filePath, ignoreHeaders)
local debug_print=false
local returns = {} --object to store data about ini file as a hashmap table
returns[""]={} --default object to store global values before a header tag('[' or ']') is found in the file stream
local rpointer = "" -- by default pointer set to "" by default
local _ = debug_print and print("<"..filePath..">")
local _ = _G[context].forFileAsLines(filePath, function (line)
--in ini, ';' may be used as a comment by default.
--in the future this may be abstracted into a larger function with more customization
if not line:startsWith(";") and string.charCount(line, " ") ~= #line and #line ~= 0 then --discard comments or empty lines
--if is header "[*]"
local _ = debug_print and print(line)
if line:match("^%[.*%]$") then
if not ignoreHeaders then
rpointer = line:sub(2,-2):trim() --remove [ and ] from the header and use as str:returnPointer
returns[rpointer]= returns[rpointer] or {}
end
--else if is key value pair "*=*"
elseif line:match("^.+=.+$") and line:charCount("=") == 1 then
local spointerarray = line:split("=")
spointerarray[1]=spointerarray[1]:trim()
spointerarray[2]=spointerarray[2]:trim()
--If parser fails due to missing '"', use raw string as a fall back.
--minetest.parse_json create an unmutable error with no way to prevent it,
--just return as string ill deal with this later. :(
--Upon reflection this function should always return a string,
--since it may be used in multiple use case and so should leave parsing decisions to the caller
--_G[context].parse(spointerarray[2]) or
returns[rpointer][spointerarray[1]] = spointerarray[2]
else --else is error
error(table.concat({"error reading: ", filePath, "@^", line, "$"},""))
end
end
end, true)
--if the global array table was never used, delete it.
if #returns[""] == 0 and true then
returns[""]=nil
end
return returns
end
--Why the fuck is "true" true in the context of a conditional, is lua just as bad as javascript?
assert(true == _G[context].parse(_G[context].forFileAsIniObj(cwdpath..DIR_DELIM.."test.ini", false)["testdata"]["success"]))

View file

View file

View file

@ -0,0 +1,30 @@
--[[
-- Original table
original_table = { 1, "hello", true }
-- Metatable to track reads
metatable = {
__index = function(t, key)
local value = rawget(t, key)
print("Key:", key, "Type:", type(value))
return value
end
}
-- Set metatable
setmetatable(original_table, metatable)
-- Access elements
print(original_table[1])
print(original_table[2])
print(original_table[3])
--]]
-- Function to check if a string is in the table
function table.contains(table, element)
for _, value in ipairs(table) do
if value == element then
return true
end
end
return false
end

View file

@ -0,0 +1,9 @@
; This file created to test io.lua's ability to read files
; If you modify this file, please restart your server to see changes take effect.
; Please note: built-in reader reads all data as type:string, then converts them as a json object with a string fallback
; Comments are denoted by a prefacing ; character,
; [headers] are denoted by enclosing a [a-zA-Z0-9%-_] string, with braces
; key value pairs are denoted by placing a key infront of = symbole folowed by a value, Note: spaces are not trimed
[testdata]
success = true

View file

View file

View file

View file

@ -0,0 +1,120 @@
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or error("They broke debug!")
-- core: /usr/share/games/core/builtin/game/chat.lua
local S = core.get_translator("__builtin")
--local T = core.get_translator("")
--core.unregister_chatcommand("kill")
local handle_kill_command = core.registered_chatcommands["kill"].func
core.override_chatcommand("kill", {
params = S("[<name>]"),
description = S("Kill player or yourself"),
privs = {server=false},
func = function(name, param)
if param == "" or param == name or core.get_player_privs(name).server then
return handle_kill_command(name, param)
else
return false, "You don't have permission to run this command (missing privileges: server)."
end
--return handle_kill_command(name, param == "" and name or param)
end,
})
local handle_giveme_command = core.registered_chatcommands["giveme"].func
core.override_chatcommand("giveme", {
params = S("<ItemString> [<count> [<wear>]]"),
description = S("Give item to yourself"),
privs = {give=not core.is_singleplayer()},
func = function(name, param)
local par=param:split(" ")
if #par >=1 and not par[1]:startsWith("mapgen_") and core.registered_aliases["mapgen_"..par[1]] then
par[1]="mapgen_"..par[1]
param=table.concat(par, " ")
end
return handle_giveme_command(name, param)
end,
})
local handle_give_command = core.registered_chatcommands["give"].func
core.override_chatcommand("give", {
params = S("<name> <ItemString> [<count> [<wear>]]"),
description = S("Give item to player"),
privs = {give=not core.is_singleplayer()},
func = function(name, param)
local par=param:split(" ")
if #par >=2 and not par[2]:startsWith("mapgen_") and core.registered_aliases["mapgen_"..par[2]] then
par[2]="mapgen_"..par[2]
param=table.concat(par, " ")
end
return handle_give_command(name, param)
end,
})
core.register_chatcommand("clear", {
params = "",
description = "clear screen",
privs = {},
func = function(name, param)
local count = 0
repeat
count = count + 1
minetest.chat_send_player(name, " ")
until count >= 20
end,
})
core.register_chatcommand("cls", {
params = core.registered_chatcommands["clear"].params,
description = core.registered_chatcommands["clear"].description,
privs = core.registered_chatcommands["clear"].privs,
func = core.registered_chatcommands["clear"].func,
})
core.register_chatcommand("items", {
params = "[metadata]",
description = "list all items or items with metadata",
privs = {},
func = function(name, param)
local items = {}
local nodes = minetest.registered_nodes
-- Populate the items table with all registered items
for name, def in pairs(minetest.registered_items) do
items[name] = def
end
-- Remove entries that are also in the nodes list
for name in pairs(nodes) do
items[name] = nil
end
-- Print the remaining items
for itemname, def in pairs(items) do
minetest.chat_send_player(name, "Registered item: " .. itemname)
end
end
})
core.register_chatcommand("nodes", {
params = "[metadata]",
description = "list all items or items with metadata",
privs = {},
func = function(name, param)
for item, def in pairs(minetest.registered_nodes) do
minetest.chat_send_player(name, "Registered node: " .. item)
end
end
})
core.register_chatcommand("biomes", {
params = "[metadata]",
description = "list all items or items with metadata",
privs = {},
func = function()
local biomes = minetest.registered_biomes
for name, biome in pairs(biomes) do
print("Biome name: " .. name)
end
end
})

View file

View file

View file

View file

View file

View file

View file

View file

View file

@ -0,0 +1,24 @@
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or error("They broke debug!")
local DIR_DELIM = debug.getinfo(1, "S").source:match("[\\/]")
_G[context] = _G[context] or {}
_G[context].init = function (path, patern)
path = path or "/src/"
patern = patern or "%.lua$"
local MOD_NAME =minetest.get_current_modname()
local MOD_PATH=minetest.get_modpath(MOD_NAME)
--Crate a array (of type table) of all files in the MOD_PATH
local files = minetest.get_dir_list(MOD_PATH .. DIR_DELIM .. path)
--Shuffle array to randomize load order and encurage stable coding practices, you know cause slow is good?
table.shuffle(files)
-- Process each filename using ipairs
for _, filename in ipairs(files) do
-- Check that the string ends with ".lua" and is not the init.lua file
if filename:match(patern) and filename ~= 'init.lua'then
--do the thing
dofile(MOD_PATH .. DIR_DELIM .. path .. DIR_DELIM .. filename)
--print logs for debuging ~~purposes~~
--minetest.log(filename)
end
end
end

View file

View file

View file

@ -0,0 +1,164 @@
local DIR_DELIM = debug.getinfo(1, "S").source:match("[\\/]")
local modname = core.get_current_modname()
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or "context"
local modpath = core.get_modpath(modname)
local cwdpath = minetest and (core.get_modpath(core.get_current_modname()) .. DIR_DELIM .. "src") or debug.getinfo(1, "S").source:match("^(.+)[/\\]"):sub(2)
--local print = _G[context].log
local registrateItemFromBlob = function(blob)
assert(blob["name"]~=nil)
if not blob["name"]:find(":") then
blob["name"] = table.concat({core.get_current_modname(),blob["name"]},":")
end
blob["type"]="none"
local localname = blob["name"]
blob["name"] = nil
if blob["tool_dig_groups"] then
blob["tool_capabilities"] = blob["tool_capabilities"] or {}
blob["tool_capabilities"]["groupcaps"] = blob["tool_capabilities"]["groupcaps"] or {}
for _, value in ipairs(blob["tool_dig_groups"] ) do
blob["tool_capabilities"]["groupcaps"][value]={
times = blob["tool_dig_times"] or nil,
uses = blob["tool_dig_uses"] or nil,
maxlevel = blob["tool_dig_maxlevel"] or nil
}
end
blob["tool_capabilities"]["damage_groups"] = blob["tool_capabilities"]["damage_groups"] or nil
end
--print(">>",blob["tool_damage_groups"])
minetest.register_item(localname, blob)
--print(">>", minetest.write_json({[1] = 0.00, [2] = 2.00, [3] = 3.0, [100] = 99.0}))
end
local registrateBiomeFromBlob = function(blob)
assert(blob["name"]~=nil)
if not blob["name"]:find(":") then
blob["name"] = table.concat({core.get_current_modname(),blob["name"]},":")
end
if blob["depth_top"]==nil and blob["node_top_depth"]~=nil then
blob["depth_top"] = blob["node_top_depth"]
--blob["node_top_depth"]=nil
end
if blob["depth_filler"]==nil and blob["node_filler_depth"]~=nil then
blob["depth_filler"] = blob["node_filler_depth"]
blob["node_filler_depth"]=nil
end
if blob["depth_riverbed"]==nil and blob["node_riverbed_depth"]~=nil then
blob["depth_riverbed"] = blob["node_riverbed_depth"]
blob["node_riverbed_depth"]=nil
end
local yMin = -31000
local yMax = 31000
local oMin = blob["y_min"] or yMin
local oMax = blob["y_max"] or yMax
local seaLevel = minetest.settings:get("water_level") or 1
blob["y_min"] = blob["dune_line"] or seaLevel
blob["y_max"] = oMax
if blob["node_riverbed"] ~= nil or blob["node_substratum"] ~= nil then
blob["node_riverbed"] = blob["node_riverbed"] or blob["node_substratum"] or nil
blob["node_substratum"] = blob["node_substratum"] or blob["node_riverbed"] or nil
end
if blob["node_riverbed"] == nil then
minetest.register_biome(blob)
else
minetest.register_biome(blob)
blob["name"] = table.concat({blob["name"],"_subterranean"},"")
--e3.s
blob["node_top"] = blob["node_riverbed"]
blob["depth_top"] = blob["depth_riverbed"] or 1
blob["node_filler"] = blob["node_substratum"]
blob["depth_filler"] = blob["node_substratum_depth"] or 1
blob["y_max"] = blob["y_min"] - 1
blob["y_min"] = oMin
--print(blob)
minetest.register_biome(blob)
end
--node_riverbed = "mapgen_sand"
--node_riverbed_depth = 3
--node_substratum="mapgen_sandstone"
--node_substratum_depth=1
end
local registrateToolFromBlob = function(blob)
assert(blob["name"]~=nil)
if not blob["name"]:find(":") then
blob["name"] = table.concat({core.get_current_modname(),blob["name"]},":")
end
blob["type"]="none"
local localname = blob["name"]
blob["type"]=nil
minetest.register_tool(localname, blob)
end
local registrateNodeFromBlob = function(blob)
local nodeName=blob["name"]
blob["name"]=nil
assert(nodeName~=nil)
if not nodeName:find(":") then
nodeName = table.concat({core.get_current_modname(), nodeName},":")
--print(nodeName)
end
local nodeAlias=blob["alias"]
blob["alias"]=nil
core.register_node(nodeName, blob)
if type(nodeAlias) == "string" then
core.register_alias(nodeAlias,nodeName)
elseif type(nodeAlias) == "table" then
for key, value in ipairs(nodeAlias) do
core.register_alias(value, nodeName)
end
else
end
local wah = minetest.registered_nodes[nodeName].groups
end
_G[context].registrate_from_file = function(filePath)
--print(filePath:match("^.+%.(.+)$"))
for header, data in pairs(_G[context].forFileAsIniObj(filePath, false)) do
--print("["..header.."]")
for k, v in pairs(data) do
data[k]=_G[context].parse(v)
--print("reg", data, k)
--assert (data[k]~=nil)
end
if data["type"] == nil then
error("expectation not met, missing type in file:".. filePath)
end
assert(type(data["type"])=="string")
local types={"node", "item", "tool", "biome", "craft"}
if not table.contains(types, data["type"]) then
error("expectation not met, invalid type in file:".. filePath)
end
if data["type"] == "node" then
data["type"]=nil
registrateNodeFromBlob(data)
end
if data["type"] == "item" then
data["type"]=nil
registrateItemFromBlob(data)
end
if data["type"] == "tool" then
data["type"]=nil
registrateToolFromBlob(data)
end
if data["type"] == "biome" then
data["type"]=nil
registrateBiomeFromBlob(data)
end
end
end
--_G[context].registrate_from_file("")
--_G[context].registrate_from_folder("")

View file

2
mods/wislib/mod.conf Normal file
View file

@ -0,0 +1,2 @@
#name is a uid that only allows characters [a-z0-9_]
name = wislib

View file

@ -0,0 +1,71 @@
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or error("They broke debug!")
local modname = minetest and minetest.get_current_modname()
local modpath = minetest and minetest.get_modpath(modname)
-- Table main_table
--registrate namespace aliases, shorthands, spelling errors, and A.R.G. hint declarations
--that will delegate the function call to _G[context]
--TODO:127 is the hint, stop asking!
_G[string.char(127+1)]={} -- Ç
setmetatable(_G[string.char(127+1)], { __index = _G[context] })
--_G[string.char(127)]={} -- ⌂
--setmetatable(_G[string.char(127)], { __index = _G[context] })
_G[string.char(99)]={} -- c
setmetatable(_G[string.char(99)], { __index = _G[context] })
_G[string.char(67)]={} -- C
setmetatable(_G[string.char(67)], { __index = _G[context] })
--[[
ALPHABET SOUP xD: Anise, Basil, Cilantro, Dill, Epazote, Fennel, Garlic,
Horehound, Italian parsley, Jasmine, Khorne (Pre-Seasoned),
Lemongrass, Mint, Nasturtium, Oregano, Parsley
Quinine, Rosemary, Sage, Thyme, Uva Ursi, Vietnamese coriander
Wasabi, Xylopia, Yuca, Zapote
--]]
--[[
--The Four Classical Elements:
--🜁 (Alchemical Symbol for Air) : Represents intellect, communication, and self-awareness.
--🜂 (Alchemical Symbol for Fire) : Symbolizes energy, transformation, passion, and self-motivation.
--🜃 (Alchemical Symbol for Earth) : Represents physical sensations and stability, and mastery over the flesh
--🜄 (Alchemical Symbol for Water) : Symbolizes intuition and emotional depth.
--The Three Primes (Tria Prima)
--☿ (Mercury) : Symbolizes the mind and volatility.
--🜔 (Salt) : Represents the body and solidity.
--🜍 (Sulfur) : Represents the soul and combustibility.
--The Seven Planetary Metals
--☉(Gold) : Associated with the Sun, symbolizes perfection and enlightenment.
--☽(Silver) : Associated with the Moon, represents purity and reflection.
--♂(Iron) : Associated with Mars, symbolizes strength and aggression.
--☿(Mercury) : Associated with Mercury, represents fluidity and adaptability.
--♃(Tin) : Associated with Jupiter, symbolizes wisdom and expansion.
--♀(Copper) : Associated with Venus, represents love and beauty.
--♄(Lead) : Associated with Saturn, symbolizes endurance and transformation.
--Other Alchemical Symbols
--🜔(Philosophers Stone) : Represents the ultimate goal of alchemy, transformation and enlightenment.
--🜓(Ouroboros) : Symbolizes infinity and the cyclical nature of life.
--🜇(Alchemical Flask) Represents the vessel used in alchemical processes.
--⚕(Staff of Asclepius) Symbolizes healing and balance. See also: Caduceus ☤
--Other Symbols
--☥ (Ankh)
--⚘ (Flower)
--⚖ (Scales)
--♾ (Infinity)
--☯ (Yin Yang)
--]]

59
mods/wislib/string.lua Normal file
View file

@ -0,0 +1,59 @@
--setup lib env
local print = minetest and minetest.debug or print
--context is always -eq to the highest possible subfolder in the mods dir, this can be ether the mod or modpack root folder.
local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or "pack"
function string:basename ()
return self:match("(.+)%..+")
end
function string:trim()
return self:match("^%s*(.-)%s*$")
end
--[[
function string:split (p2Sep, p3Patern)
if p2Sep == nil then
p2Sep = "%s"
end
if p3Patern == nil then
p3Patern = table.concat({"([^", p2Sep, "]+)"}, "")
end
local returns = {}
for _ in string.gmatch(self, p3Patern) do
table.insert(returns, _)
end
return returns
end
--]]
function string:startsWith(p2Needle) -- self == haystack
return self:sub(1, #p2Needle) == p2Needle
end
function string:endsWith(p2Needle) -- self == haystack
return p2Needle == "" or self:sub(-#p2Needle) == p2Needle
end
function string:charCount(p2Char)
local count = 0
for _ in string.gmatch(self, p2Char) do
count = count + 1
end
return count
end
_G[context]=_G[context] or {}
_G[context].colors=_G[context].colors or {}
_G[context].colors.linux={
reset = "\27[0m",
red = "\27[31m",
green = "\27[32m",
yellow = "\27[33m",
blue = "\27[34m",
magenta = "\27[35m",
cyan = "\27[36m",
white= "\27[37m"
}
--some string function required by other modues and so is always loaded first, as load order is random.
--should not effect anything that depends on this library.

9
mods/wislib/table.lua Normal file
View file

@ -0,0 +1,9 @@
-- Function to check if a string is in the table
function table.contains(table, element)
for _, value in ipairs(table) do
if value == element then
return true
end
end
return false
end