mirror of
https://github.com/Uberi/Minetest-WorldEdit.git
synced 2024-12-25 02:00:39 +01:00
//metasave and //metaload are now superceded by //save and //load's new functionality. worldedit.deserialize now supports every version of the WorldEdit format that has ever existed, and the new worldedit.valueversion uses file characteristics to determine which type of file format a given file uses. The new WorldEdit file format is the same as the one used by MineTest for serializing data, and is capable of storing arbitrary data, as well as leaving fields for future improvements. In other words, this is the last forward-compatibility breaking change that will be made to the file format.
This commit is contained in:
parent
34c4475d06
commit
9209d81d20
@ -235,20 +235,6 @@ Load nodes from "(world folder)/schems/<file>.we" with position 1 of the current
|
||||
//load some random filename
|
||||
//load huge_base
|
||||
|
||||
### //metasave <file>
|
||||
|
||||
Save the current WorldEdit region including metadata to "(world folder)/schems/<file>.wem".
|
||||
|
||||
//metasave some random filename
|
||||
//metasave huge_base
|
||||
|
||||
### //metaload <file>
|
||||
|
||||
Load nodes and metadata from "(world folder)/schems/<file>.wem" with position 1 of the current WorldEdit region as the origin.
|
||||
|
||||
//metaload some random filename
|
||||
//metaload huge_base
|
||||
|
||||
### //lua <code>
|
||||
|
||||
Executes <code> as a Lua chunk in the global namespace.
|
||||
|
@ -152,6 +152,12 @@ Serialization
|
||||
-------------
|
||||
Contained in serialization.lua, this module allows regions of nodes to be serialized and deserialized to formats suitable for use outside MineTest.
|
||||
|
||||
### version = worldedit.valueversion(value)
|
||||
|
||||
Determines the version of serialized data `value`.
|
||||
|
||||
Returns the version as a positive integer or 0 for unknown versions.
|
||||
|
||||
### data, count = worldedit.serialize(pos1, pos2)
|
||||
|
||||
Converts the region defined by positions `pos1` and `pos2` into a single string.
|
||||
@ -170,26 +176,6 @@ Loads the nodes represented by string `value` at position `originpos`.
|
||||
|
||||
Returns the number of nodes deserialized.
|
||||
|
||||
### count = worldedit.deserialize_old(originpos, value)
|
||||
|
||||
Loads the nodes represented by string `value` at position `originpos`, using the older table-based WorldEdit format.
|
||||
|
||||
This function is deprecated, and should not be used unless there is a need to support legacy WorldEdit save files.
|
||||
|
||||
Returns the number of nodes deserialized.
|
||||
|
||||
### count = worldedit.metasave(pos1, pos2, file)
|
||||
|
||||
Saves the nodes and meta defined by positions `pos1` and `pos2` into a file.
|
||||
|
||||
Returns the number of nodes saved.
|
||||
|
||||
### count = worldedit.metaload(pos1, file)
|
||||
|
||||
Loads the nodes and meta from `file` to position `pos1`.
|
||||
|
||||
Returns the number of nodes loaded.
|
||||
|
||||
Code
|
||||
----
|
||||
Contained in code.lua, this module allows arbitrary Lua code to be used with WorldEdit.
|
||||
|
17
worldedit/compatibility.lua
Normal file
17
worldedit/compatibility.lua
Normal file
@ -0,0 +1,17 @@
|
||||
worldedit.allocate_old = worldedit.allocate
|
||||
worldedit.deserialize_old = worldedit.deserialize
|
||||
worldedit.metasave = function(pos1, pos2, filename)
|
||||
local file, err = io.open(filename, "wb")
|
||||
if err then return 0 end
|
||||
local data, count = worldedit.serialize(pos1, pos2)
|
||||
file:write(data)
|
||||
file:close()
|
||||
return count
|
||||
end
|
||||
worldedit.metaload = function(originpos, filename)
|
||||
filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem"
|
||||
local file, err = io.open(filename, "wb")
|
||||
if err then return 0 end
|
||||
local data = file:read("*a")
|
||||
return worldedit.deserialize(originpos, data)
|
||||
end
|
@ -1,7 +1,5 @@
|
||||
worldedit = worldedit or {}
|
||||
|
||||
dofile(minetest.get_modpath("worldedit") .. "/table_save.lua") --wip: remove dependency
|
||||
|
||||
--modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
|
||||
worldedit.sort_pos = function(pos1, pos2)
|
||||
pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
|
||||
@ -18,175 +16,23 @@ worldedit.sort_pos = function(pos1, pos2)
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
--determines the version of serialized data `value`, returning the version as a positive integer or 0 for unknown versions
|
||||
worldedit.valueversion = function(value)
|
||||
if value:find("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)") and not value:find("%{") then --previous list format
|
||||
return 3
|
||||
elseif value:find("^[^\"']+%{%d+%}") then
|
||||
if value:find("%[\"meta\"%]") then --previous meta flat table format
|
||||
return 2
|
||||
end
|
||||
return 1 --original flat table format
|
||||
elseif value:find("%{") then --current nested table format
|
||||
return 4
|
||||
end
|
||||
return 0 --unknown format
|
||||
end
|
||||
|
||||
--converts the region defined by positions `pos1` and `pos2` into a single string, returning the serialized data and the number of nodes serialized
|
||||
worldedit.serialize = function(pos1, pos2)
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local count = 0
|
||||
local result = {}
|
||||
local env = minetest.env
|
||||
while pos.x <= pos2.x do
|
||||
pos.y = pos1.y
|
||||
while pos.y <= pos2.y do
|
||||
pos.z = pos1.z
|
||||
while pos.z <= pos2.z do
|
||||
local node = env:get_node(pos)
|
||||
if node.name ~= "air" and node.name ~= "ignore" then
|
||||
count = count + 1
|
||||
result[count] = pos.x - pos1.x .. " " .. pos.y - pos1.y .. " " .. pos.z - pos1.z .. " " .. node.name .. " " .. node.param1 .. " " .. node.param2
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
result = table.concat(result, "\n") --join all node entries into single string
|
||||
return result, count
|
||||
end
|
||||
|
||||
--determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes
|
||||
worldedit.allocate = function(originpos, value)
|
||||
local huge = math.huge
|
||||
local pos1 = {x=huge, y=huge, z=huge}
|
||||
local pos2 = {x=-huge, y=-huge, z=-huge}
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
local count = 0
|
||||
for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries
|
||||
x, y, z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z)
|
||||
if x < pos1.x then
|
||||
pos1.x = x
|
||||
end
|
||||
if y < pos1.y then
|
||||
pos1.y = y
|
||||
end
|
||||
if z < pos1.z then
|
||||
pos1.z = z
|
||||
end
|
||||
if x > pos2.x then
|
||||
pos2.x = x
|
||||
end
|
||||
if y > pos2.y then
|
||||
pos2.y = y
|
||||
end
|
||||
if z > pos2.z then
|
||||
pos2.z = z
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
return pos1, pos2, count
|
||||
end
|
||||
|
||||
--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized
|
||||
worldedit.deserialize = function(originpos, value)
|
||||
local pos = {x=0, y=0, z=0}
|
||||
local node = {name="", param1=0, param2=0}
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
local count = 0
|
||||
local env = minetest.env
|
||||
for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries
|
||||
pos.x = originx + tonumber(x)
|
||||
pos.y = originy + tonumber(y)
|
||||
pos.z = originz + tonumber(z)
|
||||
node.name = name
|
||||
node.param1 = param1
|
||||
node.param2 = param2
|
||||
env:add_node(pos, node)
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
--determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes
|
||||
--based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible)
|
||||
worldedit.allocate_old = function(originpos, value)
|
||||
--obtain the node table
|
||||
local count = 0
|
||||
local get_tables = loadstring(value)
|
||||
if get_tables == nil then --error loading value
|
||||
return count
|
||||
end
|
||||
local tables = get_tables()
|
||||
|
||||
--transform the node table into an array of nodes
|
||||
for i = 1, #tables do
|
||||
for j, v in pairs(tables[i]) do
|
||||
if type(v) == "table" then
|
||||
tables[i][j] = tables[v[1]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local huge = math.huge
|
||||
local pos1 = {x=huge, y=huge, z=huge}
|
||||
local pos2 = {x=-huge, y=-huge, z=-huge}
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
|
||||
--load the node array
|
||||
for i, v in ipairs(tables[1]) do
|
||||
local pos = v[1]
|
||||
local x, y, z = originx - pos.x, originy - pos.y, originz - pos.z
|
||||
if x < pos1.x then
|
||||
pos1.x = x
|
||||
end
|
||||
if y < pos1.y then
|
||||
pos1.y = y
|
||||
end
|
||||
if z < pos1.z then
|
||||
pos1.z = z
|
||||
end
|
||||
if x > pos2.x then
|
||||
pos2.x = x
|
||||
end
|
||||
if y > pos2.y then
|
||||
pos2.y = y
|
||||
end
|
||||
if z > pos2.z then
|
||||
pos2.z = z
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
return pos1, pos2, count
|
||||
end
|
||||
|
||||
--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized
|
||||
--based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible)
|
||||
worldedit.deserialize_old = function(originpos, value)
|
||||
--obtain the node table
|
||||
local count = 0
|
||||
local get_tables = loadstring(value)
|
||||
if get_tables == nil then --error loading value
|
||||
return count
|
||||
end
|
||||
local tables = get_tables()
|
||||
|
||||
--transform the node table into an array of nodes
|
||||
for i = 1, #tables do
|
||||
for j, v in pairs(tables[i]) do
|
||||
if type(v) == "table" then
|
||||
tables[i][j] = tables[v[1]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--load the node array
|
||||
local env = minetest.env
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
for i, v in ipairs(tables[1]) do
|
||||
local pos = v[1]
|
||||
pos.x, pos.y, pos.z = originx - pos.x, originy - pos.y, originz - pos.z
|
||||
env:add_node(pos, v[2])
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
--saves the nodes and meta defined by positions `pos1` and `pos2` into a file, returning the number of nodes saved
|
||||
worldedit.metasave = function(pos1, pos2, file) --wip: simply work with strings instead of doing IO
|
||||
local path = minetest.get_worldpath() .. "/schems"
|
||||
local filename = path .. "/" .. file .. ".wem"
|
||||
os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist
|
||||
local rows = {}
|
||||
worldedit.serialize = function(pos1, pos2) --wip: check for ItemStacks and whether they can be serialized
|
||||
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
|
||||
local pos = {x=pos1.x, y=0, z=0}
|
||||
local count = 0
|
||||
@ -201,23 +47,15 @@ worldedit.metasave = function(pos1, pos2, file) --wip: simply work with strings
|
||||
if node.name ~= "air" and node.name ~= "ignore" then
|
||||
count = count + 1
|
||||
local meta = env:get_meta(pos):to_table()
|
||||
|
||||
--convert metadata itemstacks to itemstrings
|
||||
for i, v in pairs(meta.inventory) do
|
||||
for index, items in ipairs(v) do
|
||||
v[index] = items:to_string()
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(rows, {
|
||||
x = pos.x-pos1.x,
|
||||
y = pos.y-pos1.y,
|
||||
z = pos.z-pos1.z,
|
||||
result[count] = {
|
||||
x = pos.x - pos1.x,
|
||||
y = pos.y - pos1.y,
|
||||
z = pos.z - pos1.z,
|
||||
name = node.name,
|
||||
param1 = node.param1,
|
||||
param2 = node.param2,
|
||||
meta = meta,
|
||||
})
|
||||
}
|
||||
end
|
||||
pos.z = pos.z + 1
|
||||
end
|
||||
@ -225,30 +63,157 @@ worldedit.metasave = function(pos1, pos2, file) --wip: simply work with strings
|
||||
end
|
||||
pos.x = pos.x + 1
|
||||
end
|
||||
local err = table.save(rows, filename)
|
||||
if err then return _, err end
|
||||
return count
|
||||
result = minetest.serialize(result) --convert entries to a string
|
||||
return result, count
|
||||
end
|
||||
|
||||
--loads the nodes and meta from `file` to position `pos1`, returning the number of nodes loaded
|
||||
worldedit.metaload = function(pos1, file) --wip: simply work with strings instead of doing IO
|
||||
local filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem"
|
||||
local rows, err = table.load(filename)
|
||||
if err then return _,err end
|
||||
local pos = {x=0, y=0, z=0}
|
||||
local node = {name="", param1=0, param2=0}
|
||||
--determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes
|
||||
--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible)
|
||||
worldedit.allocate = function(originpos, value)
|
||||
local huge = math.huge
|
||||
local pos1x, pos1y, pos1z = huge, huge, huge
|
||||
local pos2x, pos2y, pos2z = -huge, -huge, -huge
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
local count = 0
|
||||
local version = worldedit.valueversion(value)
|
||||
if version == 1 or version == 2 then --flat table format
|
||||
--obtain the node table
|
||||
local get_tables = loadstring(value)
|
||||
if get_tables then --error loading value
|
||||
return originpos, originpos, count
|
||||
end
|
||||
local tables = get_tables()
|
||||
|
||||
--transform the node table into an array of nodes
|
||||
for i = 1, #tables do
|
||||
for j, v in pairs(tables[i]) do
|
||||
if type(v) == "table" then
|
||||
tables[i][j] = tables[v[1]]
|
||||
end
|
||||
end
|
||||
end
|
||||
local nodes = tables[1]
|
||||
|
||||
--check the node array
|
||||
count = #nodes
|
||||
if version == 1 then --original flat table format
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
local pos = entry[1]
|
||||
local x, y, z = originx - pos.x, originy - pos.y, originz - pos.z
|
||||
if x < pos1x then pos1x = x end
|
||||
if y < pos1y then pos1y = y end
|
||||
if z < pos1z then pos1z = z end
|
||||
if x > pos2x then pos2x = x end
|
||||
if y > pos2y then pos2y = y end
|
||||
if z > pos2z then pos2z = z end
|
||||
end
|
||||
else --previous meta flat table format
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
local x, y, z = originx - entry.x, originy - entry.y, originz - entry.z
|
||||
if x < pos1x then pos1x = x end
|
||||
if y < pos1y then pos1y = y end
|
||||
if z < pos1z then pos1z = z end
|
||||
if x > pos2x then pos2x = x end
|
||||
if y > pos2y then pos2y = y end
|
||||
if z > pos2z then pos2z = z end
|
||||
end
|
||||
end
|
||||
elseif version == 3 then --previous list format
|
||||
for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries
|
||||
x, y, z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z)
|
||||
if x < pos1x then pos1x = x end
|
||||
if y < pos1y then pos1y = y end
|
||||
if z < pos1z then pos1z = z end
|
||||
if x > pos2x then pos2x = x end
|
||||
if y > pos2y then pos2y = y end
|
||||
if z > pos2z then pos2z = z end
|
||||
count = count + 1
|
||||
end
|
||||
elseif version == 4 then --current nested table format
|
||||
local nodes = minetest.deserialize(value)
|
||||
count = #nodes
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
x, y, z = originx + entry.x, originy + entry.y, originz + entry.z
|
||||
if x < pos1x then pos1x = x end
|
||||
if y < pos1y then pos1y = y end
|
||||
if z < pos1z then pos1z = z end
|
||||
if x > pos2x then pos2x = x end
|
||||
if y > pos2y then pos2y = y end
|
||||
if z > pos2z then pos2z = z end
|
||||
end
|
||||
end
|
||||
local pos1 = {x=pos1x, y=pos1y, z=pos1z}
|
||||
local pos2 = {x=pos2x, y=pos2y, z=pos2z}
|
||||
return pos1, pos2, count
|
||||
end
|
||||
|
||||
--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized
|
||||
--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible)
|
||||
worldedit.deserialize = function(originpos, value)
|
||||
local originx, originy, originz = originpos.x, originpos.y, originpos.z
|
||||
local count = 0
|
||||
local env = minetest.env
|
||||
for i,row in pairs(rows) do
|
||||
pos.x = pos1.x + tonumber(row.x)
|
||||
pos.y = pos1.y + tonumber(row.y)
|
||||
pos.z = pos1.z + tonumber(row.z)
|
||||
node.name = row.name
|
||||
node.param1 = row.param1
|
||||
node.param2 = row.param2
|
||||
env:add_node(pos, node)
|
||||
env:get_meta(pos):from_table(row.meta)
|
||||
count = count + 1
|
||||
local version = worldedit.valueversion(value)
|
||||
if version == 1 or version == 2 then --original flat table format
|
||||
--obtain the node table
|
||||
local get_tables = loadstring(value)
|
||||
if not get_tables then --error loading value
|
||||
return count
|
||||
end
|
||||
local tables = get_tables()
|
||||
|
||||
--transform the node table into an array of nodes
|
||||
for i = 1, #tables do
|
||||
for j, v in pairs(tables[i]) do
|
||||
if type(v) == "table" then
|
||||
tables[i][j] = tables[v[1]]
|
||||
end
|
||||
end
|
||||
end
|
||||
local nodes = tables[1]
|
||||
|
||||
--load the node array
|
||||
count = #nodes
|
||||
if version == 1 then --original flat table format
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
local pos = entry[1]
|
||||
pos.x, pos.y, pos.z = originx - pos.x, originy - pos.y, originz - pos.z
|
||||
env:add_node(pos, entry[2])
|
||||
end
|
||||
else --previous meta flat table format
|
||||
for index = 1, #nodes do
|
||||
local entry = nodes[index]
|
||||
entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z
|
||||
env:add_node(entry, entry) --entry acts both as position and as node
|
||||
env:get_meta(entry):from_table(entry.meta)
|
||||
end
|
||||
end
|
||||
elseif version == 3 then --previous list format
|
||||
local pos = {x=0, y=0, z=0}
|
||||
local node = {name="", param1=0, param2=0}
|
||||
for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries
|
||||
pos.x = originx + tonumber(x)
|
||||
pos.y = originy + tonumber(y)
|
||||
pos.z = originz + tonumber(z)
|
||||
node.name = name
|
||||
node.param1 = param1
|
||||
node.param2 = param2
|
||||
env:add_node(pos, node)
|
||||
count = count + 1
|
||||
end
|
||||
elseif version == 4 then --current nested table format
|
||||
local nodes = minetest.deserialize(value)
|
||||
count = #nodes
|
||||
for index = 1, count do
|
||||
local entry = nodes[index]
|
||||
entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z
|
||||
env:add_node(entry, entry) --entry acts both as position and as node
|
||||
env:get_meta(entry):from_table(entry.meta)
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
@ -1,15 +0,0 @@
|
||||
serialize_meta = function(pos)
|
||||
local insert, format, concat = table.insert, string.format, table.concat
|
||||
--wip: do recursive serialize
|
||||
|
||||
local meta = env:get_meta(pos):to_table()
|
||||
local fields = {}
|
||||
for key, value in pairs(meta.fields) do
|
||||
insert(fields, format("%q", key) .. format("%q", value))
|
||||
end
|
||||
return concat(meta.inventory, ",") .. concat(fields)
|
||||
end
|
||||
|
||||
deserialize_meta = function(value)
|
||||
--wip
|
||||
end
|
@ -1,133 +0,0 @@
|
||||
--[[
|
||||
Save Table to File
|
||||
Load Table from File
|
||||
v 1.0
|
||||
|
||||
Lua 5.2 compatible
|
||||
|
||||
Only Saves Tables, Numbers and Strings
|
||||
Insides Table References are saved
|
||||
Does not save Userdata, Metatables, Functions and indices of these
|
||||
----------------------------------------------------
|
||||
table.save( table , filename )
|
||||
|
||||
on failure: returns an error msg
|
||||
|
||||
----------------------------------------------------
|
||||
table.load( filename or stringtable )
|
||||
|
||||
Loads a table that has been saved via the table.save function
|
||||
|
||||
on success: returns a previously saved table
|
||||
on failure: returns as second argument an error msg
|
||||
----------------------------------------------------
|
||||
|
||||
Licensed under the same terms as Lua itself.
|
||||
]]--
|
||||
do
|
||||
-- declare local variables
|
||||
--// exportstring( string )
|
||||
--// returns a "Lua" portable version of the string
|
||||
local function exportstring( s )
|
||||
return string.format("%q", s)
|
||||
end
|
||||
|
||||
--// The Save Function
|
||||
function table.save( tbl,filename )
|
||||
local charS,charE = " ","\n"
|
||||
local file,err = io.open( filename, "wb" )
|
||||
if err then return err end
|
||||
|
||||
-- initiate variables for save procedure
|
||||
local tables,lookup = { tbl },{ [tbl] = 1 }
|
||||
file:write( "return {"..charE )
|
||||
|
||||
for idx,t in ipairs( tables ) do
|
||||
file:write( "-- Table: {"..idx.."}"..charE )
|
||||
file:write( "{"..charE )
|
||||
local thandled = {}
|
||||
|
||||
for i,v in ipairs( t ) do
|
||||
thandled[i] = true
|
||||
local stype = type( v )
|
||||
-- only handle value
|
||||
if stype == "table" then
|
||||
if not lookup[v] then
|
||||
table.insert( tables, v )
|
||||
lookup[v] = #tables
|
||||
end
|
||||
file:write( charS.."{"..lookup[v].."},"..charE )
|
||||
elseif stype == "string" then
|
||||
file:write( charS..exportstring( v )..","..charE )
|
||||
elseif stype == "number" then
|
||||
file:write( charS..tostring( v )..","..charE )
|
||||
end
|
||||
end
|
||||
|
||||
for i,v in pairs( t ) do
|
||||
-- escape handled values
|
||||
if (not thandled[i]) then
|
||||
|
||||
local str = ""
|
||||
local stype = type( i )
|
||||
-- handle index
|
||||
if stype == "table" then
|
||||
if not lookup[i] then
|
||||
table.insert( tables,i )
|
||||
lookup[i] = #tables
|
||||
end
|
||||
str = charS.."[{"..lookup[i].."}]="
|
||||
elseif stype == "string" then
|
||||
str = charS.."["..exportstring( i ).."]="
|
||||
elseif stype == "number" then
|
||||
str = charS.."["..tostring( i ).."]="
|
||||
end
|
||||
|
||||
if str ~= "" then
|
||||
stype = type( v )
|
||||
-- handle value
|
||||
if stype == "table" then
|
||||
if not lookup[v] then
|
||||
table.insert( tables,v )
|
||||
lookup[v] = #tables
|
||||
end
|
||||
file:write( str.."{"..lookup[v].."},"..charE )
|
||||
elseif stype == "string" then
|
||||
file:write( str..exportstring( v )..","..charE )
|
||||
elseif stype == "number" then
|
||||
file:write( str..tostring( v )..","..charE )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
file:write( "},"..charE )
|
||||
end
|
||||
file:write( "}" )
|
||||
file:close()
|
||||
end
|
||||
|
||||
--// The Load Function
|
||||
function table.load( sfile )
|
||||
local ftables,err = loadfile( sfile )
|
||||
if err then return _,err end
|
||||
local tables = ftables()
|
||||
for idx = 1,#tables do
|
||||
local tolinki = {}
|
||||
for i,v in pairs( tables[idx] ) do
|
||||
if type( v ) == "table" then
|
||||
tables[idx][i] = tables[v[1]]
|
||||
end
|
||||
if type( i ) == "table" and tables[i[1]] then
|
||||
table.insert( tolinki,{ i,tables[i[1]] } )
|
||||
end
|
||||
end
|
||||
-- link indices
|
||||
for _,v in ipairs( tolinki ) do
|
||||
tables[idx][v[2]],tables[idx][v[1]] = tables[idx][v[1]],nil
|
||||
end
|
||||
end
|
||||
return tables[1]
|
||||
end
|
||||
-- close do
|
||||
end
|
||||
-- ChillCode
|
@ -750,12 +750,11 @@ minetest.register_chatcommand("/allocate", {
|
||||
local value = file:read("*a")
|
||||
file:close()
|
||||
|
||||
local nodepos1, nodepos2, count
|
||||
if value:find("{") then --old WorldEdit format
|
||||
nodepos1, nodepos2, count = worldedit.allocate_old(pos1, value)
|
||||
else --new WorldEdit format
|
||||
nodepos1, nodepos2, count = worldedit.allocate(pos1, value)
|
||||
if worldedit.valueversion(value) == 0 then --unknown version
|
||||
minetest.chat_send_player(name, "Invalid file: file is invalid or created with newer version of WorldEdit")
|
||||
return
|
||||
end
|
||||
local nodepos1, nodepos2, count = worldedit.allocate(pos1, value)
|
||||
|
||||
worldedit.pos1[name] = nodepos1
|
||||
worldedit.mark_pos1(name)
|
||||
@ -768,7 +767,7 @@ minetest.register_chatcommand("/allocate", {
|
||||
|
||||
minetest.register_chatcommand("/load", {
|
||||
params = "<file>",
|
||||
description = "Load nodes from \"(world folder)/schems/<file>.we\" with position 1 of the current WorldEdit region as the origin",
|
||||
description = "Load nodes from \"(world folder)/schems/<file>[.we[m]]\" with position 1 of the current WorldEdit region as the origin",
|
||||
privs = {worldedit=true},
|
||||
func = function(name, param)
|
||||
local pos1 = worldedit.pos1[name]
|
||||
@ -782,72 +781,36 @@ minetest.register_chatcommand("/load", {
|
||||
return
|
||||
end
|
||||
|
||||
local filename = minetest.get_worldpath() .. "/schems/" .. param .. ".we"
|
||||
local file, err = io.open(filename, "rb")
|
||||
if err ~= nil then
|
||||
minetest.chat_send_player(name, "Could not open file \"" .. filename .. "\"")
|
||||
--find the file in the world path
|
||||
local testpaths = {
|
||||
minetest.get_worldpath() .. "/schems/" .. param,
|
||||
minetest.get_worldpath() .. "/schems/" .. param .. ".we",
|
||||
minetest.get_worldpath() .. "/schems/" .. param .. ".wem",
|
||||
}
|
||||
local file, err
|
||||
for index, path in ipairs(testpaths) do
|
||||
file, err = io.open(path, "rb")
|
||||
if not err then
|
||||
break
|
||||
end
|
||||
end
|
||||
if err then
|
||||
minetest.chat_send_player(name, "Could not open file \"" .. param .. "\"")
|
||||
return
|
||||
end
|
||||
local value = file:read("*a")
|
||||
file:close()
|
||||
|
||||
local count
|
||||
if value:find("{") then --old WorldEdit format
|
||||
count = worldedit.deserialize_old(pos1, value)
|
||||
else --new WorldEdit format
|
||||
count = worldedit.deserialize(pos1, value)
|
||||
if worldedit.valueversion(value) == 0 then --unknown version
|
||||
minetest.chat_send_player(name, "Invalid file: file is invalid or created with newer version of WorldEdit")
|
||||
return
|
||||
end
|
||||
local count = worldedit.deserialize(pos1, value)
|
||||
|
||||
minetest.chat_send_player(name, count .. " nodes loaded")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/metasave", {
|
||||
params = "<file>",
|
||||
description = "Save the current WorldEdit region to \"(world folder)/schems/<file>.wem\"",
|
||||
privs = {worldedit=true},
|
||||
func = function(name, param)
|
||||
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
|
||||
if pos1 == nil or pos2 == nil then
|
||||
minetest.chat_send_player(name, "No WorldEdit region selected")
|
||||
return
|
||||
end
|
||||
if param == "" then
|
||||
minetest.chat_send_player(name, "Invalid usage: " .. param)
|
||||
return
|
||||
end
|
||||
local count, err = worldedit.metasave(pos1, pos2, param)
|
||||
if err then
|
||||
minetest.chat_send_player(name, "error loading file: " .. err)
|
||||
else
|
||||
minetest.chat_send_player(name, count .. " nodes saved")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/metaload", {
|
||||
params = "<file>",
|
||||
description = "Load nodes from \"(world folder)/schems/<file>.wem\" with position 1 of the current WorldEdit region as the origin",
|
||||
privs = {worldedit=true},
|
||||
func = function(name, param)
|
||||
local pos1 = worldedit.pos1[name]
|
||||
if pos1 == nil then
|
||||
minetest.chat_send_player(name, "No WorldEdit region selected")
|
||||
return
|
||||
end
|
||||
if param == "" then
|
||||
minetest.chat_send_player(name, "Invalid usage: " .. param)
|
||||
return
|
||||
end
|
||||
local count, err = worldedit.metaload(pos1, param)
|
||||
if err then
|
||||
minetest.chat_send_player(name, "Error loading file: " .. err)
|
||||
else
|
||||
minetest.chat_send_player(name, count .. " nodes loaded")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("/lua", {
|
||||
params = "<code>",
|
||||
description = "Executes <code> as a Lua chunk in the global namespace",
|
||||
|
Loading…
Reference in New Issue
Block a user