mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 15:23:48 +01:00
Use tabs not spaces
This commit is contained in:
parent
a86b24eef5
commit
daa0251632
80
Readme.md
80
Readme.md
@ -44,21 +44,21 @@ Binary Lua object notation. **Experimental.** Handling of subnormal numbers (ver
|
|||||||
|
|
||||||
```lua
|
```lua
|
||||||
def = {
|
def = {
|
||||||
aux_is_valid = function(object)
|
aux_is_valid = function(object)
|
||||||
return is_valid
|
return is_valid
|
||||||
end,
|
end,
|
||||||
aux_len = function(object)
|
aux_len = function(object)
|
||||||
return length_in_bytes
|
return length_in_bytes
|
||||||
end,
|
end,
|
||||||
-- read type byte, stream providing :read(count), map of references -> id
|
-- read type byte, stream providing :read(count), map of references -> id
|
||||||
aux_read = function(type, stream, references)
|
aux_read = function(type, stream, references)
|
||||||
... = stream:read(...)
|
... = stream:read(...)
|
||||||
return object
|
return object
|
||||||
end,
|
end,
|
||||||
-- object to be written, stream providing :write(text), list of references
|
-- object to be written, stream providing :write(text), list of references
|
||||||
aux_write = function(object, stream, references)
|
aux_write = function(object, stream, references)
|
||||||
stream:write(...)
|
stream:write(...)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -128,22 +128,22 @@ assert(modlib.bluon:read(object, rope) == true)
|
|||||||
```lua
|
```lua
|
||||||
-- Serializes all userdata to a constant string:
|
-- Serializes all userdata to a constant string:
|
||||||
local custom_bluon = bluon.new{
|
local custom_bluon = bluon.new{
|
||||||
aux_is_valid = function(object)
|
aux_is_valid = function(object)
|
||||||
return type(object) == "userdata"
|
return type(object) == "userdata"
|
||||||
end,
|
end,
|
||||||
aux_len = function(object)
|
aux_len = function(object)
|
||||||
return 1 + ("userdata"):len())
|
return 1 + ("userdata"):len())
|
||||||
end,
|
end,
|
||||||
aux_read = function(type, stream, references)
|
aux_read = function(type, stream, references)
|
||||||
assert(type == 100, "unsupported type")
|
assert(type == 100, "unsupported type")
|
||||||
assert(stream:read(("userdata"):len()) == "userdata")
|
assert(stream:read(("userdata"):len()) == "userdata")
|
||||||
return userdata()
|
return userdata()
|
||||||
end,
|
end,
|
||||||
-- object to be written, stream providing :write(text), list of references
|
-- object to be written, stream providing :write(text), list of references
|
||||||
aux_write = function(object, stream, references)
|
aux_write = function(object, stream, references)
|
||||||
assert(type(object) == "userdata")
|
assert(type(object) == "userdata")
|
||||||
stream:write"\100userdata"
|
stream:write"\100userdata"
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
-- Write to text
|
-- Write to text
|
||||||
local rope = modlib.table.rope{}
|
local rope = modlib.table.rope{}
|
||||||
@ -255,21 +255,21 @@ A schematic format with support for metadata and baked light data. **Experimenta
|
|||||||
|
|
||||||
* Fixes
|
* Fixes
|
||||||
* Colorspec
|
* Colorspec
|
||||||
* Stricter patterns in `colorspec:from_string`
|
* Stricter patterns in `colorspec:from_string`
|
||||||
* `colorspec:to_string` works now
|
* `colorspec:to_string` works now
|
||||||
* Lua log file
|
* Lua log file
|
||||||
* Patched memory leaks
|
* Patched memory leaks
|
||||||
* Added option to not reference strings
|
* Added option to not reference strings
|
||||||
* Handling of circular tables
|
* Handling of circular tables
|
||||||
* Additions
|
* Additions
|
||||||
* `luon`: Configurable serialization to and from Lua with circular and string reference support
|
* `luon`: Configurable serialization to and from Lua with circular and string reference support
|
||||||
* `minetest.luon` even supports `ItemStack` and `AreaStore`
|
* `minetest.luon` even supports `ItemStack` and `AreaStore`
|
||||||
* `vector.rotate3`
|
* `vector.rotate3`
|
||||||
* `table.deep_foreach_any`
|
* `table.deep_foreach_any`
|
||||||
* `func`:
|
* `func`:
|
||||||
* `func.iterate`
|
* `func.iterate`
|
||||||
* `func.aggregate`
|
* `func.aggregate`
|
||||||
* Functional wrappers for operators
|
* Functional wrappers for operators
|
||||||
* Improvements
|
* Improvements
|
||||||
* Code quality
|
* Code quality
|
||||||
* Performance
|
* Performance
|
||||||
|
80
hashlist.lua
80
hashlist.lua
@ -9,82 +9,82 @@ list.metatable = metatable
|
|||||||
|
|
||||||
-- Takes a list
|
-- Takes a list
|
||||||
function list:new()
|
function list:new()
|
||||||
self.head = 0
|
self.head = 0
|
||||||
self.length = #self
|
self.length = #self
|
||||||
return setmetatable(self, metatable)
|
return setmetatable(self, metatable)
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:in_bounds(index)
|
function list:in_bounds(index)
|
||||||
return index >= 1 and index <= self.length
|
return index >= 1 and index <= self.length
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:get(index)
|
function list:get(index)
|
||||||
return self[self.head + index]
|
return self[self.head + index]
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:set(index, value)
|
function list:set(index, value)
|
||||||
assert(value ~= nil)
|
assert(value ~= nil)
|
||||||
self[self.head + index] = value
|
self[self.head + index] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:len()
|
function list:len()
|
||||||
return self.length
|
return self.length
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:ipairs()
|
function list:ipairs()
|
||||||
local index = 1
|
local index = 1
|
||||||
return function()
|
return function()
|
||||||
if index > self.length then
|
if index > self.length then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
return index, self[self.head + index]
|
return index, self[self.head + index]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:rpairs()
|
function list:rpairs()
|
||||||
local index = self.length
|
local index = self.length
|
||||||
return function()
|
return function()
|
||||||
if index < 1 then
|
if index < 1 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
return index, self[self.head + index]
|
return index, self[self.head + index]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:push_tail(value)
|
function list:push_tail(value)
|
||||||
assert(value ~= nil)
|
assert(value ~= nil)
|
||||||
self.length = self.length + 1
|
self.length = self.length + 1
|
||||||
self[self.head + self.length] = value
|
self[self.head + self.length] = value
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:get_tail()
|
function list:get_tail()
|
||||||
return self[self.head + self.length]
|
return self[self.head + self.length]
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:pop_tail()
|
function list:pop_tail()
|
||||||
if self.length == 0 then return end
|
if self.length == 0 then return end
|
||||||
local value = self:get_tail()
|
local value = self:get_tail()
|
||||||
self[self.head + self.length] = nil
|
self[self.head + self.length] = nil
|
||||||
self.length = self.length - 1
|
self.length = self.length - 1
|
||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:push_head(value)
|
function list:push_head(value)
|
||||||
self[self.head] = value
|
self[self.head] = value
|
||||||
self.head = self.head - 1
|
self.head = self.head - 1
|
||||||
self.length = self.length + 1
|
self.length = self.length + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:get_head()
|
function list:get_head()
|
||||||
return self[self.head + 1]
|
return self[self.head + 1]
|
||||||
end
|
end
|
||||||
|
|
||||||
function list:pop_head()
|
function list:pop_head()
|
||||||
if self.length == 0 then return end
|
if self.length == 0 then return end
|
||||||
local value = self:get_head()
|
local value = self:get_head()
|
||||||
self.head = self.head + 1
|
self.head = self.head + 1
|
||||||
self[self.head] = nil
|
self[self.head] = nil
|
||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
return list
|
return list
|
279
luon.lua
279
luon.lua
@ -1,16 +1,16 @@
|
|||||||
local assert, next, pairs, pcall, error, type, table_insert, table_concat, string_format, string_match, setmetatable, select, setfenv, math_huge, loadfile, loadstring
|
local assert, next, pairs, pcall, error, type, table_insert, table_concat, string_format, string_match, setmetatable, select, setfenv, math_huge, loadfile, loadstring
|
||||||
= assert, next, pairs, pcall, error, type, table.insert, table.concat, string.format, string.match, setmetatable, select, setfenv, math.huge, loadfile, loadstring
|
= assert, next, pairs, pcall, error, type, table.insert, table.concat, string.format, string.match, setmetatable, select, setfenv, math.huge, loadfile, loadstring
|
||||||
|
|
||||||
local count_objects = modlib.table.count_objects
|
local count_objects = modlib.table.count_objects
|
||||||
|
|
||||||
-- Build a table with the succeeding character from A-Z
|
-- Build a table with the succeeding character from A-Z
|
||||||
local succ = {}
|
local succ = {}
|
||||||
for char = ("A"):byte(), ("Z"):byte() - 1 do
|
for char = ("A"):byte(), ("Z"):byte() - 1 do
|
||||||
succ[string.char(char)] = string.char(char + 1)
|
succ[string.char(char)] = string.char(char + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function quote(string)
|
local function quote(string)
|
||||||
return string_format("%q", string)
|
return string_format("%q", string)
|
||||||
end
|
end
|
||||||
|
|
||||||
local _ENV = {}
|
local _ENV = {}
|
||||||
@ -19,169 +19,170 @@ local metatable = {__index = _ENV}
|
|||||||
_ENV.metatable = metatable
|
_ENV.metatable = metatable
|
||||||
|
|
||||||
function new(self)
|
function new(self)
|
||||||
return setmetatable(self, metatable)
|
return setmetatable(self, metatable)
|
||||||
end
|
end
|
||||||
|
|
||||||
function aux_write(_self, _object)
|
function aux_write(_self, _object)
|
||||||
-- returns reader, arguments
|
-- returns reader, arguments
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
aux_read = {}
|
aux_read = {}
|
||||||
|
|
||||||
function write(self, value, write)
|
function write(self, value, write)
|
||||||
local reference = {"A"}
|
local reference = {"A"}
|
||||||
local function increment_reference(place)
|
local function increment_reference(place)
|
||||||
if not reference[place] then
|
if not reference[place] then
|
||||||
reference[place] = "B"
|
reference[place] = "B"
|
||||||
elseif reference[place] == "Z" then
|
elseif reference[place] == "Z" then
|
||||||
reference[place] = "A"
|
reference[place] = "A"
|
||||||
return increment_reference(place + 1)
|
return increment_reference(place + 1)
|
||||||
else
|
else
|
||||||
reference[place] = succ[reference[place]]
|
reference[place] = succ[reference[place]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local references = {}
|
local references = {}
|
||||||
local to_fill = {}
|
local to_fill = {}
|
||||||
-- TODO sort objects by count, give frequently referenced objects shorter references
|
-- TODO sort objects by count, give frequently referenced objects shorter references
|
||||||
for object, count in pairs(count_objects(value)) do
|
for object, count in pairs(count_objects(value)) do
|
||||||
local type_ = type(object)
|
local type_ = type(object)
|
||||||
if count >= 2 and (type_ ~= "string" or #reference + 2 < #object) then
|
if count >= 2 and (type_ ~= "string" or #reference + 2 < #object) then
|
||||||
local ref = table_concat(reference)
|
local ref = table_concat(reference)
|
||||||
write(ref)
|
write(ref)
|
||||||
write"="
|
write"="
|
||||||
write(type_ == "table" and "{}" or quote(object))
|
write(type_ == "table" and "{}" or quote(object))
|
||||||
write";"
|
write";"
|
||||||
references[object] = ref
|
references[object] = ref
|
||||||
if type_ == "table" then
|
if type_ == "table" then
|
||||||
to_fill[object] = ref
|
to_fill[object] = ref
|
||||||
end
|
end
|
||||||
increment_reference(1)
|
increment_reference(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function is_short_key(key)
|
local function is_short_key(key)
|
||||||
return not references[key] and type(key) == "string" and string_match(key, "^[%a_][%a%d_]*$")
|
return not references[key] and type(key) == "string" and string_match(key, "^[%a_][%a%d_]*$")
|
||||||
end
|
end
|
||||||
local function dump(value)
|
local function dump(value)
|
||||||
-- Primitive types
|
-- Primitive types
|
||||||
if value == nil then
|
if value == nil then
|
||||||
return write"nil"
|
return write"nil"
|
||||||
end
|
end
|
||||||
if value == true then
|
if value == true then
|
||||||
return write"true"
|
return write"true"
|
||||||
end
|
end
|
||||||
if value == false then
|
if value == false then
|
||||||
return write"false"
|
return write"false"
|
||||||
end
|
end
|
||||||
local type_ = type(value)
|
local type_ = type(value)
|
||||||
if type_ == "number" then
|
if type_ == "number" then
|
||||||
return write(string_format("%.17g", value))
|
return write(string_format("%.17g", value))
|
||||||
end
|
end
|
||||||
-- Reference types: table and string
|
-- Reference types: table and string
|
||||||
local ref = references[value]
|
local ref = references[value]
|
||||||
if ref then
|
if ref then
|
||||||
-- Referenced
|
-- Referenced
|
||||||
return write(ref)
|
return write(ref)
|
||||||
elseif type_ == "string" then
|
elseif type_ == "string" then
|
||||||
return write(quote(value))
|
return write(quote(value))
|
||||||
elseif type_ == "table" then
|
elseif type_ == "table" then
|
||||||
local first = true
|
local first = true
|
||||||
write"{"
|
write"{"
|
||||||
local len = #value
|
local len = #value
|
||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
if not first then write";" end
|
if not first then write";" end
|
||||||
dump(value[i])
|
dump(value[i])
|
||||||
first = false
|
first = false
|
||||||
end
|
end
|
||||||
for k, v in next, value do
|
for k, v in next, value do
|
||||||
if type(k) ~= "number" or k % 1 ~= 0 or k < 1 or k > len then
|
if type(k) ~= "number" or k % 1 ~= 0 or k < 1 or k > len then
|
||||||
if not first then write";" end
|
if not first then write";" end
|
||||||
if is_short_key(k) then
|
if is_short_key(k) then
|
||||||
write(k)
|
write(k)
|
||||||
else
|
else
|
||||||
write"["
|
write"["
|
||||||
dump(k)
|
dump(k)
|
||||||
write"]"
|
write"]"
|
||||||
end
|
end
|
||||||
write"="
|
write"="
|
||||||
dump(v)
|
dump(v)
|
||||||
first = false
|
first = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
write"}"
|
write"}"
|
||||||
else
|
else
|
||||||
-- TODO move aux_write to start, to allow dealing with metatables etc.?
|
-- TODO move aux_write to start, to allow dealing with metatables etc.?
|
||||||
(function(func, ...)
|
(function(func, ...)
|
||||||
-- functions are the only way to deal with varargs
|
-- functions are the only way to deal with varargs
|
||||||
if not func then
|
if not func then
|
||||||
return error("unsupported type: " .. type_)
|
return error("unsupported type: " .. type_)
|
||||||
end
|
end
|
||||||
write(func)
|
write(func)
|
||||||
write"("
|
write"("
|
||||||
local n = select("#", ...)
|
local n = select("#", ...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
for i = 1, n - 1 do
|
for i = 1, n - 1 do
|
||||||
dump(args[i])
|
dump(args[i])
|
||||||
write","
|
write","
|
||||||
end
|
end
|
||||||
if n > 0 then
|
if n > 0 then
|
||||||
write(args[n])
|
write(args[n])
|
||||||
end
|
end
|
||||||
write")"
|
write")"
|
||||||
end)(self:aux_write(value))
|
end)(self:aux_write(value))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for table, ref in pairs(to_fill) do
|
for table, ref in pairs(to_fill) do
|
||||||
for k, v in pairs(table) do
|
for k, v in pairs(table) do
|
||||||
write(ref)
|
write(ref)
|
||||||
if is_short_key(k) then
|
if is_short_key(k) then
|
||||||
write"."
|
write"."
|
||||||
write(k)
|
write(k)
|
||||||
else
|
else
|
||||||
write"["
|
write"["
|
||||||
dump(k)
|
dump(k)
|
||||||
write"]"
|
write"]"
|
||||||
end
|
end
|
||||||
write"="
|
write"="
|
||||||
dump(v)
|
dump(v)
|
||||||
write";"
|
write";"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
write"return "
|
write"return "
|
||||||
dump(value)
|
dump(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
function write_file(self, value, file)
|
function write_file(self, value, file)
|
||||||
return self:write(value, function(text)
|
return self:write(value, function(text)
|
||||||
file:write(text)
|
file:write(text)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function write_string(self, value)
|
function write_string(self, value)
|
||||||
local rope = {}
|
local rope = {}
|
||||||
self:write(value, function(text)
|
self:write(value, function(text)
|
||||||
table_insert(rope, text)
|
table_insert(rope, text)
|
||||||
end)
|
end)
|
||||||
return table_concat(rope)
|
return table_concat(rope)
|
||||||
end
|
end
|
||||||
|
|
||||||
function read(self, ...)
|
function read(self, ...)
|
||||||
local read = assert(...)
|
local read = assert(...)
|
||||||
-- math.huge is serialized to inf, 0/0 is serialized to -nan
|
-- math.huge is serialized to inf, 0/0 is serialized to -nan
|
||||||
|
-- TODO verify this is actually the case, see https://en.wikipedia.org/wiki/Printf_format_string
|
||||||
setfenv(read, setmetatable({inf = math_huge, nan = 0/0}, {__index = self.aux_read}))
|
setfenv(read, setmetatable({inf = math_huge, nan = 0/0}, {__index = self.aux_read}))
|
||||||
local success, value_or_err = pcall(read)
|
local success, value_or_err = pcall(read)
|
||||||
if success then
|
if success then
|
||||||
return value_or_err
|
return value_or_err
|
||||||
end
|
end
|
||||||
return nil, value_or_err
|
return nil, value_or_err
|
||||||
end
|
end
|
||||||
|
|
||||||
function read_file(self, path)
|
function read_file(self, path)
|
||||||
return self:read(loadfile(path))
|
return self:read(loadfile(path))
|
||||||
end
|
end
|
||||||
|
|
||||||
function read_string(self, string)
|
function read_string(self, string)
|
||||||
return self:read(loadstring(string))
|
return self:read(loadstring(string))
|
||||||
end
|
end
|
||||||
|
|
||||||
return _ENV
|
return _ENV
|
@ -1,6 +1,6 @@
|
|||||||
local _ENV = setmetatable({}, {__index = _G})
|
local _ENV = setmetatable({}, {__index = _G})
|
||||||
local function load(filename)
|
local function load(filename)
|
||||||
assert(loadfile(modlib.mod.get_resource(modlib.modname, "minetest", filename .. ".lua")))(_ENV)
|
assert(loadfile(modlib.mod.get_resource(modlib.modname, "minetest", filename .. ".lua")))(_ENV)
|
||||||
end
|
end
|
||||||
load"misc"
|
load"misc"
|
||||||
load"collisionboxes"
|
load"collisionboxes"
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
-- Localize globals
|
-- Localize globals
|
||||||
local getmetatable, AreaStore, ItemStack
|
local getmetatable, AreaStore, ItemStack
|
||||||
= getmetatable, AreaStore, ItemStack
|
= getmetatable, AreaStore, ItemStack
|
||||||
|
|
||||||
-- Metatable lookup for classes specified in lua_api.txt, section "Class reference"
|
-- Metatable lookup for classes specified in lua_api.txt, section "Class reference"
|
||||||
local AreaStoreMT = getmetatable(AreaStore())
|
local AreaStoreMT = getmetatable(AreaStore())
|
||||||
local ItemStackMT = getmetatable(ItemStack"")
|
local ItemStackMT = getmetatable(ItemStack"")
|
||||||
local metatables = {
|
local metatables = {
|
||||||
[AreaStoreMT] = {name = "AreaStore", method = AreaStoreMT.to_string},
|
[AreaStoreMT] = {name = "AreaStore", method = AreaStoreMT.to_string},
|
||||||
[ItemStackMT] = {name = "ItemStack", method = ItemStackMT.to_table},
|
[ItemStackMT] = {name = "ItemStack", method = ItemStackMT.to_table},
|
||||||
-- TODO expand
|
-- TODO expand
|
||||||
}
|
}
|
||||||
|
|
||||||
(...).luon = modlib.luon.new{
|
(...).luon = modlib.luon.new{
|
||||||
aux_write = function(_, value)
|
aux_write = function(_, value)
|
||||||
local type = metatables[getmetatable(value)]
|
local type = metatables[getmetatable(value)]
|
||||||
if type then
|
if type then
|
||||||
return type.name, type.method(value)
|
return type.name, type.method(value)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
aux_read = {
|
aux_read = {
|
||||||
AreaStore = function(...)
|
AreaStore = function(...)
|
||||||
local store = AreaStore()
|
local store = AreaStore()
|
||||||
store:from_string(...)
|
store:from_string(...)
|
||||||
return store
|
return store
|
||||||
end,
|
end,
|
||||||
ItemStack = ItemStack
|
ItemStack = ItemStack
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
-- Localize globals
|
-- Localize globals
|
||||||
local VoxelArea, ItemStack, assert, error, io, ipairs, math, minetest, modlib, next, pairs, setmetatable, string, table, type, vector
|
local VoxelArea, ItemStack, assert, error, io, ipairs, math, minetest, modlib, next, pairs, setmetatable, string, table, type, vector
|
||||||
= VoxelArea, ItemStack, assert, error, io, ipairs, math, minetest, modlib, next, pairs, setmetatable, string, table, type, vector
|
= VoxelArea, ItemStack, assert, error, io, ipairs, math, minetest, modlib, next, pairs, setmetatable, string, table, type, vector
|
||||||
|
|
||||||
-- Set environment
|
-- Set environment
|
||||||
local _ENV = ...
|
local _ENV = ...
|
||||||
@ -10,179 +10,179 @@ schematic = {}
|
|||||||
local metatable = {__index = schematic}
|
local metatable = {__index = schematic}
|
||||||
|
|
||||||
function schematic.setmetatable(self)
|
function schematic.setmetatable(self)
|
||||||
return setmetatable(self, metatable)
|
return setmetatable(self, metatable)
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic.create(self, pos_min, pos_max)
|
function schematic.create(self, pos_min, pos_max)
|
||||||
self.size = vector.subtract(pos_max, pos_min)
|
self.size = vector.subtract(pos_max, pos_min)
|
||||||
local voxelmanip = minetest.get_voxel_manip(pos_min, pos_max)
|
local voxelmanip = minetest.get_voxel_manip(pos_min, pos_max)
|
||||||
local emin, emax = voxelmanip:read_from_map(pos_min, pos_max)
|
local emin, emax = voxelmanip:read_from_map(pos_min, pos_max)
|
||||||
local voxelarea = VoxelArea:new{ MinEdge = emin, MaxEdge = emax }
|
local voxelarea = VoxelArea:new{ MinEdge = emin, MaxEdge = emax }
|
||||||
local nodes, light_values, param2s = {}, self.light_values and {}, {}
|
local nodes, light_values, param2s = {}, self.light_values and {}, {}
|
||||||
local vm_nodes, vm_light_values, vm_param2s = voxelmanip:get_data(), light_values and voxelmanip:get_light_data(), voxelmanip:get_param2_data()
|
local vm_nodes, vm_light_values, vm_param2s = voxelmanip:get_data(), light_values and voxelmanip:get_light_data(), voxelmanip:get_param2_data()
|
||||||
local node_names, node_ids = {}, {}
|
local node_names, node_ids = {}, {}
|
||||||
local i = 0
|
local i = 0
|
||||||
for index in voxelarea:iterp(pos_min, pos_max) do
|
for index in voxelarea:iterp(pos_min, pos_max) do
|
||||||
if nodes[index] == minetest.CONTENT_UNKNOWN or nodes[index] == minetest.CONTENT_IGNORE then
|
if nodes[index] == minetest.CONTENT_UNKNOWN or nodes[index] == minetest.CONTENT_IGNORE then
|
||||||
error("unknown or ignore node at " .. minetest.pos_to_string(voxelarea:position(index)))
|
error("unknown or ignore node at " .. minetest.pos_to_string(voxelarea:position(index)))
|
||||||
end
|
end
|
||||||
local name = minetest.get_name_from_content_id(vm_nodes[index])
|
local name = minetest.get_name_from_content_id(vm_nodes[index])
|
||||||
local id = node_ids[name]
|
local id = node_ids[name]
|
||||||
if not id then
|
if not id then
|
||||||
table.insert(node_names, name)
|
table.insert(node_names, name)
|
||||||
id = #node_names
|
id = #node_names
|
||||||
node_ids[name] = id
|
node_ids[name] = id
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
nodes[i] = id
|
nodes[i] = id
|
||||||
if self.light_values then
|
if self.light_values then
|
||||||
light_values[i] = vm_light_values[index]
|
light_values[i] = vm_light_values[index]
|
||||||
end
|
end
|
||||||
param2s[i] = vm_param2s[index]
|
param2s[i] = vm_param2s[index]
|
||||||
end
|
end
|
||||||
local metas = self.metas
|
local metas = self.metas
|
||||||
if metas or metas == nil then
|
if metas or metas == nil then
|
||||||
local indexing = vector.add(self.size, 1)
|
local indexing = vector.add(self.size, 1)
|
||||||
metas = {}
|
metas = {}
|
||||||
for _, pos in ipairs(minetest.find_nodes_with_meta(pos_min, pos_max)) do
|
for _, pos in ipairs(minetest.find_nodes_with_meta(pos_min, pos_max)) do
|
||||||
local meta = minetest.get_meta(pos):to_table()
|
local meta = minetest.get_meta(pos):to_table()
|
||||||
if next(meta.fields) ~= nil or next(meta.inventory) ~= nil then
|
if next(meta.fields) ~= nil or next(meta.inventory) ~= nil then
|
||||||
local relative = vector.subtract(pos, pos_min)
|
local relative = vector.subtract(pos, pos_min)
|
||||||
metas[((relative.z * indexing.y) + relative.y) * indexing.x + relative.x] = meta
|
metas[((relative.z * indexing.y) + relative.y) * indexing.x + relative.x] = meta
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.node_names = node_names
|
self.node_names = node_names
|
||||||
self.nodes = nodes
|
self.nodes = nodes
|
||||||
self.light_values = light_values
|
self.light_values = light_values
|
||||||
self.param2s = param2s
|
self.param2s = param2s
|
||||||
self.metas = metas
|
self.metas = metas
|
||||||
return schematic.setmetatable(self)
|
return schematic.setmetatable(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic:write_to_voxelmanip(voxelmanip, pos_min)
|
function schematic:write_to_voxelmanip(voxelmanip, pos_min)
|
||||||
local pos_max = vector.add(pos_min, self.size)
|
local pos_max = vector.add(pos_min, self.size)
|
||||||
local emin, emax = voxelmanip:read_from_map(pos_min, pos_max)
|
local emin, emax = voxelmanip:read_from_map(pos_min, pos_max)
|
||||||
local voxelarea = VoxelArea:new{ MinEdge = emin, MaxEdge = emax }
|
local voxelarea = VoxelArea:new{ MinEdge = emin, MaxEdge = emax }
|
||||||
local nodes, light_values, param2s, metas = self.nodes, self.light_values, self.param2s, self.metas
|
local nodes, light_values, param2s, metas = self.nodes, self.light_values, self.param2s, self.metas
|
||||||
local vm_nodes, vm_lights, vm_param2s = voxelmanip:get_data(), light_values and voxelmanip:get_light_data(), voxelmanip:get_param2_data()
|
local vm_nodes, vm_lights, vm_param2s = voxelmanip:get_data(), light_values and voxelmanip:get_light_data(), voxelmanip:get_param2_data()
|
||||||
for _, pos in ipairs(minetest.find_nodes_with_meta(pos_min, pos_max)) do
|
for _, pos in ipairs(minetest.find_nodes_with_meta(pos_min, pos_max)) do
|
||||||
-- Clear all metadata. Due to an engine bug, nodes will actually have empty metadata.
|
-- Clear all metadata. Due to an engine bug, nodes will actually have empty metadata.
|
||||||
minetest.get_meta(pos):from_table{}
|
minetest.get_meta(pos):from_table{}
|
||||||
end
|
end
|
||||||
local content_ids = {}
|
local content_ids = {}
|
||||||
for index, name in ipairs(self.node_names) do
|
for index, name in ipairs(self.node_names) do
|
||||||
content_ids[index] = assert(minetest.get_content_id(name), ("unknown node %q"):format(name))
|
content_ids[index] = assert(minetest.get_content_id(name), ("unknown node %q"):format(name))
|
||||||
end
|
end
|
||||||
local i = 0
|
local i = 0
|
||||||
for index in voxelarea:iterp(pos_min, pos_max) do
|
for index in voxelarea:iterp(pos_min, pos_max) do
|
||||||
i = i + 1
|
i = i + 1
|
||||||
vm_nodes[index] = content_ids[nodes[i]]
|
vm_nodes[index] = content_ids[nodes[i]]
|
||||||
if light_values then
|
if light_values then
|
||||||
vm_lights[index] = light_values[i]
|
vm_lights[index] = light_values[i]
|
||||||
end
|
end
|
||||||
vm_param2s[index] = param2s[i]
|
vm_param2s[index] = param2s[i]
|
||||||
end
|
end
|
||||||
voxelmanip:set_data(vm_nodes)
|
voxelmanip:set_data(vm_nodes)
|
||||||
if light_values then
|
if light_values then
|
||||||
voxelmanip:set_light_data(vm_lights)
|
voxelmanip:set_light_data(vm_lights)
|
||||||
end
|
end
|
||||||
voxelmanip:set_param2_data(vm_param2s)
|
voxelmanip:set_param2_data(vm_param2s)
|
||||||
if metas then
|
if metas then
|
||||||
local indexing = vector.add(self.size, 1)
|
local indexing = vector.add(self.size, 1)
|
||||||
for index, meta in pairs(metas) do
|
for index, meta in pairs(metas) do
|
||||||
local floored = math.floor(index / indexing.x)
|
local floored = math.floor(index / indexing.x)
|
||||||
local relative = {
|
local relative = {
|
||||||
x = index % indexing.x,
|
x = index % indexing.x,
|
||||||
y = floored % indexing.y,
|
y = floored % indexing.y,
|
||||||
z = math.floor(floored / indexing.y)
|
z = math.floor(floored / indexing.y)
|
||||||
}
|
}
|
||||||
minetest.get_meta(vector.add(relative, pos_min)):from_table(meta)
|
minetest.get_meta(vector.add(relative, pos_min)):from_table(meta)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic:place(pos_min)
|
function schematic:place(pos_min)
|
||||||
local pos_max = vector.add(pos_min, self.size)
|
local pos_max = vector.add(pos_min, self.size)
|
||||||
local voxelmanip = minetest.get_voxel_manip(pos_min, pos_max)
|
local voxelmanip = minetest.get_voxel_manip(pos_min, pos_max)
|
||||||
self:write_to_voxelmanip(voxelmanip, pos_min)
|
self:write_to_voxelmanip(voxelmanip, pos_min)
|
||||||
voxelmanip:write_to_map(not self.light_values)
|
voxelmanip:write_to_map(not self.light_values)
|
||||||
return voxelmanip
|
return voxelmanip
|
||||||
end
|
end
|
||||||
|
|
||||||
local function table_to_byte_string(tab)
|
local function table_to_byte_string(tab)
|
||||||
if not tab then return end
|
if not tab then return end
|
||||||
return table.concat(modlib.table.map(tab, string.char))
|
return table.concat(modlib.table.map(tab, string.char))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function write_bluon(self, stream)
|
local function write_bluon(self, stream)
|
||||||
local metas, light_values, param2s = self.metas, self.light_values, self.param2s
|
local metas, light_values, param2s = self.metas, self.light_values, self.param2s
|
||||||
self.metas = modlib.table.copy(metas)
|
self.metas = modlib.table.copy(metas)
|
||||||
for _, meta in pairs(self.metas) do
|
for _, meta in pairs(self.metas) do
|
||||||
for _, list in pairs(meta.inventory) do
|
for _, list in pairs(meta.inventory) do
|
||||||
for index, stack in pairs(list) do
|
for index, stack in pairs(list) do
|
||||||
list[index] = stack:to_string()
|
list[index] = stack:to_string()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.light_values, self.param2s = table_to_byte_string(light_values), table_to_byte_string(param2s)
|
self.light_values, self.param2s = table_to_byte_string(light_values), table_to_byte_string(param2s)
|
||||||
modlib.bluon:write(self, stream)
|
modlib.bluon:write(self, stream)
|
||||||
self.metas, self.light_values, self.param2s = metas, light_values, param2s
|
self.metas, self.light_values, self.param2s = metas, light_values, param2s
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic:write_bluon(path)
|
function schematic:write_bluon(path)
|
||||||
local file = io.open(path, "wb")
|
local file = io.open(path, "wb")
|
||||||
-- Header, short for "ModLib Bluon Schematic"
|
-- Header, short for "ModLib Bluon Schematic"
|
||||||
file:write"MLBS"
|
file:write"MLBS"
|
||||||
write_bluon(self, file)
|
write_bluon(self, file)
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function byte_string_to_table(self, field)
|
local function byte_string_to_table(self, field)
|
||||||
local byte_string = self[field]
|
local byte_string = self[field]
|
||||||
if not byte_string then return end
|
if not byte_string then return end
|
||||||
local tab = {}
|
local tab = {}
|
||||||
for i = 1, #byte_string do
|
for i = 1, #byte_string do
|
||||||
tab[i] = byte_string:byte(i)
|
tab[i] = byte_string:byte(i)
|
||||||
end
|
end
|
||||||
self[field] = tab
|
self[field] = tab
|
||||||
end
|
end
|
||||||
|
|
||||||
local function read_bluon(file)
|
local function read_bluon(file)
|
||||||
local self = modlib.bluon:read(file)
|
local self = modlib.bluon:read(file)
|
||||||
assert(not file:read(1), "expected EOF")
|
assert(not file:read(1), "expected EOF")
|
||||||
for _, meta in pairs(self.metas) do
|
for _, meta in pairs(self.metas) do
|
||||||
for _, list in pairs(meta.inventory) do
|
for _, list in pairs(meta.inventory) do
|
||||||
for index, itemstring in pairs(list) do
|
for index, itemstring in pairs(list) do
|
||||||
assert(type(itemstring) == "string")
|
assert(type(itemstring) == "string")
|
||||||
list[index] = ItemStack(itemstring)
|
list[index] = ItemStack(itemstring)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
byte_string_to_table(self, "light_values")
|
byte_string_to_table(self, "light_values")
|
||||||
byte_string_to_table(self, "param2s")
|
byte_string_to_table(self, "param2s")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic.read_bluon(path)
|
function schematic.read_bluon(path)
|
||||||
local file = io.open(path, "rb")
|
local file = io.open(path, "rb")
|
||||||
assert(file:read(4) == "MLBS", "not a modlib bluon schematic")
|
assert(file:read(4) == "MLBS", "not a modlib bluon schematic")
|
||||||
return schematic.setmetatable(read_bluon(file))
|
return schematic.setmetatable(read_bluon(file))
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic:write_zlib_bluon(path, compression)
|
function schematic:write_zlib_bluon(path, compression)
|
||||||
local file = io.open(path, "wb")
|
local file = io.open(path, "wb")
|
||||||
-- Header, short for "ModLib Zlib-compressed-bluon Schematic"
|
-- Header, short for "ModLib Zlib-compressed-bluon Schematic"
|
||||||
file:write"MLZS"
|
file:write"MLZS"
|
||||||
local rope = modlib.table.rope{}
|
local rope = modlib.table.rope{}
|
||||||
write_bluon(self, rope)
|
write_bluon(self, rope)
|
||||||
local text = rope:to_text()
|
local text = rope:to_text()
|
||||||
file:write(minetest.compress(text, "deflate", compression or 9))
|
file:write(minetest.compress(text, "deflate", compression or 9))
|
||||||
file:close()
|
file:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function schematic.read_zlib_bluon(path)
|
function schematic.read_zlib_bluon(path)
|
||||||
local file = io.open(path, "rb")
|
local file = io.open(path, "rb")
|
||||||
assert(file:read(4) == "MLZS", "not a modlib zlib compressed bluon schematic")
|
assert(file:read(4) == "MLZS", "not a modlib zlib compressed bluon schematic")
|
||||||
return schematic.setmetatable(read_bluon(modlib.text.inputstream(minetest.decompress(file:read"*a", "deflate"))))
|
return schematic.setmetatable(read_bluon(modlib.text.inputstream(minetest.decompress(file:read"*a", "deflate"))))
|
||||||
end
|
end
|
26
table.lua
26
table.lua
@ -339,25 +339,25 @@ end
|
|||||||
|
|
||||||
-- Recursively counts occurences of objects (non-primitives including strings) in a table.
|
-- Recursively counts occurences of objects (non-primitives including strings) in a table.
|
||||||
function count_objects(value)
|
function count_objects(value)
|
||||||
local counts = {}
|
local counts = {}
|
||||||
if value == nil then
|
if value == nil then
|
||||||
-- Early return for nil
|
-- Early return for nil
|
||||||
return counts
|
return counts
|
||||||
end
|
end
|
||||||
local function count_values(value)
|
local function count_values(value)
|
||||||
local type_ = type(value)
|
local type_ = type(value)
|
||||||
if type_ == "boolean" or type_ == "number" then return end
|
if type_ == "boolean" or type_ == "number" then return end
|
||||||
local count = counts[value]
|
local count = counts[value]
|
||||||
counts[value] = (count or 0) + 1
|
counts[value] = (count or 0) + 1
|
||||||
if not count and type_ == "table" then
|
if not count and type_ == "table" then
|
||||||
for k, v in pairs(value) do
|
for k, v in pairs(value) do
|
||||||
count_values(k)
|
count_values(k)
|
||||||
count_values(v)
|
count_values(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
count_values(value)
|
count_values(value)
|
||||||
return counts
|
return counts
|
||||||
end
|
end
|
||||||
|
|
||||||
function foreach_value(table, func)
|
function foreach_value(table, func)
|
||||||
|
Loading…
Reference in New Issue
Block a user