Initial completion

This commit is contained in:
Aaron Suen 2024-06-15 19:51:32 -04:00
commit f91d7157fa
19 changed files with 391 additions and 0 deletions

12
.luacheckrc Normal file

@ -0,0 +1,12 @@
globals = {
"minetest",
"vector",
"ItemStack",
"VoxelArea",
"vector",
"SecureRandom",
"PcgRandom
"profiler",
}
color = false
quiet = 1

7
.lualocals Normal file

@ -0,0 +1,7 @@
minetest
ItemStack
VoxelArea
vector
SecureRandom
PcgRandom
profiler

20
LICENSE Normal file

@ -0,0 +1,20 @@
Copyright (C)2024 Aaron Suen <warr1024@gmail.com>
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.

22
aaschemlib/alphabet.lua Normal file

@ -0,0 +1,22 @@
-- LUALOCALS < ---------------------------------------------------------
local string
= string
local string_sub
= string.sub
-- LUALOCALS > ---------------------------------------------------------
-- Define the chars that are allowed to be used in ascii art tables.
-- The size of the alphabet limits the maximum number of unique node
-- definition types that can be used in a single schematic.
local alphabet = {}
do
-- Only use printable 7-bit ascii characters that don't
-- require escaping in a lua string, for compatibility.
local chars = " .abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
.. "0123456789,/;'[]`-=<>?:{}|~!@#$%^&*()_+"
for i = 1, #chars do
alphabet[#alphabet + 1] = string_sub(chars, i, i)
end
end
return alphabet

@ -0,0 +1,60 @@
-- LUALOCALS < ---------------------------------------------------------
local dofile, ipairs, minetest, pairs, rawget, rawset, string, table
= dofile, ipairs, minetest, pairs, rawget, rawset, string, table
local string_format, table_concat
= string.format, table.concat
-- LUALOCALS > ---------------------------------------------------------
local alphabet = dofile(minetest.get_modpath(
minetest.get_current_modname()) .. "/alphabet.lua")
-- Dump an asciiart lua table in a format optimized for editing.
-- Use loadstring/dofile/etc to reverse.
local function asciiart_to_lua(aa)
local t = {
"return {",
"\tnodes = {",
}
for _, k in pairs(alphabet) do
local v = aa.nodes[k]
if v then
local u = {}
if v.name then u[#u + 1] = string_format("name = %q", v.name) end
if v.param2 then u[#u + 1] = string_format("param2 = %d", v.param2) end
if v.prob then u[#u + 1] = string_format("prob = %d", v.prob) end
if v.force then u[#u + 1] = "force = true" end
t[#t + 1] = string_format("\t\t[%q] = {%s},", k, table_concat(u, ", "))
end
end
t[#t + 1] = "\t},"
if aa.sliceprob then
t[#t + 1] = "\tsliceprob = {"
for y = 0, aa.size.y - 1 do
local p = aa.sliceprob[y]
if p then
t[#t + 1] = string_format("\t\t[%d] = %d,", y, p)
end
end
t[#t + 1] = "\t},"
end
t[#t + 1] = "\tlayers = {"
for _, layer in ipairs(aa.layers) do
t[#t + 1] = "\t\t{"
local row = 1
for _, row in ipairs(layer) do
t[#t + 1] = string_format("\t\t\t%q,", row)
end
t[#t + 1] = "\t\t},"
end
t[#t + 1] = "\t},"
t[#t + 1] = "}"
return table_concat(t, "\n")
end
------------------------------------------------------------------------
local modname = minetest.get_current_modname()
local api = rawget(_G, modname) or {}
rawset(_G, modname, api)
api.asciiart_to_lua = asciiart_to_lua

@ -0,0 +1,43 @@
-- LUALOCALS < ---------------------------------------------------------
local error, ipairs, minetest, pairs, rawget, rawset
= error, ipairs, minetest, pairs, rawget, rawset
-- LUALOCALS > ---------------------------------------------------------
-- Convert an asciiart lua table back into a minetest schematic one,
-- reversing schematic_to_asciiart.
local function asciiart_to_schematic(aa)
local schem = {
size = {y = #aa.layers},
data = {},
yslice_prob = {},
}
for y, ys in ipairs(aa.layers) do
if schem.size.z and schem.size.z ~= #ys then
error("inconsistent z size")
end
schem.size.z = #ys
for z, zs in ipairs(ys) do
if schem.size.x and schem.size.x ~= #zs then
error("inconsistent x size")
end
schem.size.x = #zs
for x = 1, zs:len() do
local node = aa.nodes[zs:sub(x, x)]
schem.data[(schem.size.z - z) * schem.size.x * schem.size.y
+ (y - 1) * schem.size.x + x] = node
end
end
end
for k, v in pairs(aa.sliceprob or {}) do
yslice_prob[#yslice_prob + 1] = {ypos = k, prob = v}
end
return schem
end
------------------------------------------------------------------------
local modname = minetest.get_current_modname()
local api = rawget(_G, modname) or {}
rawset(_G, modname, api)
api.asciiart_to_schematic = asciiart_to_schematic

@ -0,0 +1,103 @@
-- LUALOCALS < ---------------------------------------------------------
local dofile, error, minetest, next, pairs, rawget, rawset, string
= dofile, error, minetest, next, pairs, rawget, rawset, string
local string_sub
= string.sub
-- LUALOCALS > ---------------------------------------------------------
local alphabet = dofile(minetest.get_modpath(
minetest.get_current_modname()) .. "/alphabet.lua")
-- Convert a schematic lua table (in the format of minetest.read_schematic)
-- into an asciiart lua table. Use asciiart_to_schematic to reverse.
local function schematic_to_asciiart(mts)
local nodes = {
-- Reserve space for "void" (don't overwrite existing node)
[" "] = {prob = 0},
-- Reserve period for air (just remove existing node)
["."] = {name = "air"},
}
local alphaidx = 3
local usage = {}
local layers = {}
local function set(x, y, z, s)
x, y, z = x + 1, y + 1, mts.size.z - z
local l = layers[y]
if not l then
l = {}
layers[y] = l
end
local r = l[z] or ""
while (#r < x) do r = r .. " " end
l[z] = string_sub(r, 1, x - 1)
.. s .. string_sub(r, x + 2)
usage[s] = true
end
local i = 1
for z = 0, mts.size.z - 1 do
for y = 0, mts.size.y - 1 do
for x = 0, mts.size.x - 1 do
local v = mts.data[i]
i = i + 1
local t = {
name = v.name,
param2 = v.param2,
prob = v.prob,
force = v.force_place or nil
}
if t.param2 == 0 then t.param2 = nil end
if t.prob and t.prob >= 254 then t.prob = nil end
if t.prob and t.prob <= 0 then
t.name = nil
t.param2 = nil
end
local added
for nk, nv in pairs(nodes) do
if nv.name == t.name and nv.param2 == t.param2
and nv.prob == nv.prob and nv.force == t.force then
set(x, y, z, nk)
added = true
break
end
end
if not added then
local s = alphabet[alphaidx]
alphaidx = alphaidx + 1
if not s then error("too many unique nodes for chars") end
nodes[s] = t
set(x, y, z, s)
end
end
end
end
local t = {}
for k, v in pairs(mts) do t[k] = v end
t.size = nil
t.data = nil
t.layers = layers
t.nodes = {}
for k in pairs(usage) do
t.nodes[k] = nodes[k]
end
if t.yslice_prob and next(t.yslice_prob) then
local d = {}
for _, v in pairs(t.yslice_prob) do
d[v.ypos] = v.prob
end
t.sliceprob = d
end
t.yslice_prob = nil
return t
end
------------------------------------------------------------------------
local modname = minetest.get_current_modname()
local api = rawget(_G, modname) or {}
rawset(_G, modname, api)
api.schematic_to_asciiart = schematic_to_asciiart

11
aaschemlib/init.lua Normal file

@ -0,0 +1,11 @@
-- LUALOCALS < ---------------------------------------------------------
local dofile, ipairs, minetest
= dofile, ipairs, minetest
-- LUALOCALS > ---------------------------------------------------------
local modpath = minetest.get_modpath(minetest.get_current_modname())
for _, fn in ipairs({
"api_asciiart_to_lua",
"api_asciiart_to_schematic",
"api_schematic_to_asciiart",
}) do dofile(modpath .. "/" .. fn .. ".lua") end

3
aaschemlib/mod.conf Normal file

@ -0,0 +1,3 @@
name = aaschemlib
title = ASCII Art Schematic Library
description = Library for converting Minetest schematics to/from ASCII art

BIN
aaschemlib/screenshot.png Normal file

Binary file not shown.

After

(image error) Size: 38 KiB

@ -0,0 +1,53 @@
-- LUALOCALS < ---------------------------------------------------------
local io, minetest, pairs, pcall, rawget, rawset, string, unpack
= io, minetest, pairs, pcall, rawget, rawset, string, unpack
local io_open, string_format, string_sub
= io.open, string.format, string.sub
-- LUALOCALS > ---------------------------------------------------------
local function fileconv(func)
return function(_, param)
local src, dest = unpack(param:split(" "))
if (not src) or (src == "") or (not dest) or (dest == "") then
return false, "incorrect params"
end
-- Input pathnames can be prefixed with modname: to make the path
-- relative to a loaded mod. Input pathnames can be prefixed with
-- just a bare colon to make the path relative to the loaded world.
for _, n in pairs(minetest.get_modnames()) do
if string_sub(src, 1, #n + 1) == n .. ":" then
src = minetest.get_modpath(n) .. "/" .. string_sub(src, #n + 2)
end
end
if string_sub(src, 1, 1) == ":" then
src = minetest.get_worldpath() .. "/" .. string_sub(src, 2)
end
-- Output pathnames must always be relative to the world path.
dest = minetest.get_worldpath() .. "/" .. dest
-- Run the conversion process and check for errors.
local okay, result = pcall(func, src, dest)
if not okay then
return false, string_format("error convertin %q to %q: %s", src, dest, result)
end
-- Write the output
local f = io_open(dest, "wb")
if not f then
return false, string_format("failed to open %q for writing", dest)
end
f:write(result)
f:close()
return true, string_format("wrote %d bytes to %q", #result, dest)
end
end
------------------------------------------------------------------------
local modname = minetest.get_current_modname()
local api = rawget(_G, modname) or {}
rawset(_G, modname, api)
api.fileconv = fileconv

@ -0,0 +1,18 @@
-- LUALOCALS < ---------------------------------------------------------
local dofile, minetest, rawget
= dofile, minetest, rawget
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = rawget(_G, modname)
minetest.register_chatcommand("aa2mts", {
privs = {server = true},
description = "Convert Lua AA schematic to MTS (WARNING: Arbitrary Code Execution)",
params = "modname:path/to/file.lua output.mts",
func = api.fileconv(function(src, dest)
return minetest.serialize_schematic(
aaschemlib.asciiart_to_schematic(dofile(src)),
"mts", {})
end)
})

@ -0,0 +1,22 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, rawget
= minetest, rawget
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = rawget(_G, modname)
minetest.register_chatcommand("mts2aa", {
privs = {server = true},
description = "Convert MTS schematic to Lua AA",
params = "modname:path/to/file.mts output.lua",
func = api.fileconv(function(src, dest)
return aaschemlib.asciiart_to_lua(
aaschemlib.schematic_to_asciiart(
minetest.read_schematic(src, {
write_yslice_prob = "low"
})
)
)
end)
})

11
aaschemtools/init.lua Normal file

@ -0,0 +1,11 @@
-- LUALOCALS < ---------------------------------------------------------
local dofile, ipairs, minetest
= dofile, ipairs, minetest
-- LUALOCALS > ---------------------------------------------------------
local modpath = minetest.get_modpath(minetest.get_current_modname())
for _, fn in ipairs({
"api_fileconv",
"cmd_mts2aa",
"cmd_aa2mts",
}) do dofile(modpath .. "/" .. fn .. ".lua") end

4
aaschemtools/mod.conf Normal file

@ -0,0 +1,4 @@
name = aaschemtools
title = ASCII Art Schematic Tools
description = Developer tools for converting Minetest schematics to/from ASCII art
depends = aaschemlib

BIN
aaschemtools/screenshot.png Normal file

Binary file not shown.

After

(image error) Size: 38 KiB

BIN
cdb-screen.webp Normal file

Binary file not shown.

After

(image error) Size: 99 KiB

2
modpack.conf Normal file

@ -0,0 +1,2 @@
title = ASCII Art Schematics
description = Manage Minetest schematics as ASCII art

BIN
screenshot.png Normal file

Binary file not shown.

After

(image error) Size: 38 KiB