mirror of
https://github.com/HybridDog/we_undo.git
synced 2024-12-12 17:13:16 +01:00
Move common functions and support /luatransform
This commit is contained in:
parent
23eb83778c
commit
293308cf84
@ -28,6 +28,7 @@ Supported chatcommands:
|
||||
* /spiral
|
||||
* /load
|
||||
* /mtschemplace
|
||||
* /luatransform (nodes and metadata changes inside the selected area)
|
||||
* /y
|
||||
* /n
|
||||
|
||||
@ -68,7 +69,6 @@ Not yet implemented:
|
||||
* /restore
|
||||
* /allocate
|
||||
* /deleteblocks
|
||||
* /luatransform
|
||||
|
||||
|
||||
|
||||
|
549
init.lua
549
init.lua
@ -461,6 +461,300 @@ local function decompress_nodedata(ccontent)
|
||||
return result
|
||||
end
|
||||
|
||||
-- tells if the metadata is that dummy
|
||||
local function is_meta_empty(metatabl)
|
||||
if metatabl.inventory
|
||||
and next(metatabl.inventory) ~= nil then
|
||||
return false
|
||||
end
|
||||
if metatabl.fields
|
||||
and next(metatabl.fields) ~= nil then
|
||||
return false
|
||||
end
|
||||
for k in pairs(metatabl) do
|
||||
if k ~= "inventory"
|
||||
and k ~= "fields" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Gets information about meta if it is set, otherwise returns nil
|
||||
-- the format of the information is the same as in WorldEdit
|
||||
local function get_meta_serializable(pos)
|
||||
if not minetest.find_nodes_with_meta(pos, pos)[1] then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local metat = meta:to_table()
|
||||
if is_meta_empty(metat) then
|
||||
-- FIXME: is this case covered by minetest.find_nodes_with_meta?
|
||||
minetest.log("error", "metadata should be inexistent")
|
||||
return
|
||||
end
|
||||
for _, inventory in pairs(metat.inventory) do
|
||||
for index = 1,#inventory do
|
||||
local itemstack = inventory[index]
|
||||
if itemstack.to_string then
|
||||
inventory[index] = itemstack:to_string()
|
||||
end
|
||||
end
|
||||
end
|
||||
return metat, meta
|
||||
end
|
||||
|
||||
-- Collects all metadata in a serialized format inside the given area
|
||||
-- This may be a slow function, thus should only be used when needed
|
||||
local function get_metadatas_in_area(pos1, pos2)
|
||||
local meta_ps = minetest.find_nodes_with_meta(pos1, pos2)
|
||||
local meta_tables_list = {}
|
||||
local ystride = pos2.x - pos1.x + 1
|
||||
local zstride = (pos2.y - pos1.y + 1) * ystride
|
||||
for i = 1, #meta_ps do
|
||||
local pos = meta_ps[i]
|
||||
local meta = minetest.get_meta(pos)
|
||||
local metat = meta:to_table()
|
||||
if is_meta_empty(metat) then
|
||||
-- FIXME: is this case covered by minetest.find_nodes_with_meta?
|
||||
minetest.log("error", "metadata should be inexistent")
|
||||
else
|
||||
-- Make metat serializable
|
||||
for _, inventory in pairs(metat.inventory) do
|
||||
for index = 1,#inventory do
|
||||
local itemstack = inventory[index]
|
||||
if itemstack.to_string then
|
||||
inventory[index] = itemstack:to_string()
|
||||
end
|
||||
end
|
||||
end
|
||||
local rpos = vector.subtract(pos, pos1)
|
||||
meta_tables_list[#meta_tables_list+1] = {
|
||||
rpos.z * zstride + rpos.y * ystride + rpos.x,
|
||||
metat
|
||||
}
|
||||
end
|
||||
end
|
||||
table.sort(meta_tables_list, function(a, b)
|
||||
return a[1] < b[1]
|
||||
end)
|
||||
local indices_m = {}
|
||||
local metastrings = {}
|
||||
for i = 1, #meta_tables_list do
|
||||
indices_m[i] = meta_tables_list[i][1]
|
||||
metastrings[i] = minetest.serialize(meta_tables_list[i][2])
|
||||
end
|
||||
return indices_m, metastrings
|
||||
end
|
||||
|
||||
-- A generic function to collect the changed nodes and metadata
|
||||
-- (if collect_meta is true) between the times before and after executing func
|
||||
local function run_and_capture_changes(func, pos1, pos2, collect_meta)
|
||||
-- Get the node ids, param1s and param2s (before)
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local e1, e2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
|
||||
local nodeids_before = manip:get_data()
|
||||
local param1s_before = manip:get_light_data()
|
||||
local param2s_before = manip:get_param2_data()
|
||||
|
||||
local indices_m_before, metastrings_before
|
||||
if collect_meta then
|
||||
indices_m_before, metastrings_before = get_metadatas_in_area(pos1, pos2)
|
||||
end
|
||||
|
||||
-- Run the actual function
|
||||
local rvs = {func()}
|
||||
|
||||
-- Get the node ids, param1s and param2s (after)
|
||||
manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
local nodeids_after = manip:get_data()
|
||||
local param1s_after = manip:get_light_data()
|
||||
local param2s_after = manip:get_param2_data()
|
||||
|
||||
local indices_m_after, metastrings_after
|
||||
if collect_meta then
|
||||
indices_m_after, metastrings_after = get_metadatas_in_area(pos1, pos2)
|
||||
end
|
||||
|
||||
-- Collect the changed nodes
|
||||
local ystride = pos2.x - pos1.x + 1
|
||||
local zstride = (pos2.y - pos1.y + 1) * ystride
|
||||
local indices_n = {}
|
||||
local indices_p1 = {}
|
||||
local indices_p2 = {}
|
||||
local nodeids = {}
|
||||
local param1s = {}
|
||||
local param2s = {}
|
||||
for z = pos1.z, pos2.z do
|
||||
for y = pos1.y, pos2.y do
|
||||
for x = pos1.x, pos2.x do
|
||||
local vi_vm = area:index(x,y,z)
|
||||
local vi_my = (z - pos1.z) * zstride
|
||||
+ (y - pos1.y) * ystride
|
||||
+ x - pos1.x
|
||||
if nodeids_after[vi_vm] ~= nodeids_before[vi_vm] then
|
||||
indices_n[#indices_n+1] = vi_my
|
||||
nodeids[#nodeids+1] = nodeids_before[vi_vm]
|
||||
end
|
||||
if param1s_after[vi_vm] ~= param1s_before[vi_vm] then
|
||||
indices_p1[#indices_p1+1] = vi_my
|
||||
param1s[#param1s+1] = param1s_before[vi_vm]
|
||||
end
|
||||
if param2s_after[vi_vm] ~= param2s_before[vi_vm] then
|
||||
indices_p2[#indices_p2+1] = vi_my
|
||||
param2s[#param2s+1] = param2s_before[vi_vm]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local indices_m = {}
|
||||
local metastrings = {}
|
||||
if collect_meta then
|
||||
-- Collect all metadata changes
|
||||
local i_after = 1
|
||||
for i_before = 1, #indices_m_before do
|
||||
local vi_before = indices_m_before[i_before]
|
||||
local vi_after = indices_m_after[i_after]
|
||||
if vi_before < vi_after then
|
||||
-- Metadata has been removed at vi_before
|
||||
indices_m[#indices_m+1] = vi_before
|
||||
metastrings[#metastrings+1] = metastrings_before[i_before]
|
||||
elseif vi_before == vi_after then
|
||||
-- Metadata exists before and after
|
||||
if metastrings_before[i_before]
|
||||
~= metastrings_after[i_after] then
|
||||
indices_m[#indices_m+1] = vi_before
|
||||
metastrings[#metastrings+1] = metastrings_before[i_before]
|
||||
end
|
||||
i_after = i_after + 1
|
||||
if i_after > #indices_m_after then
|
||||
break
|
||||
end
|
||||
else
|
||||
while vi_before > vi_after do
|
||||
-- Metadata has been added at vi_after
|
||||
indices_m[#indices_m+1] = vi_after
|
||||
metastrings[#metastrings+1] = "return nil"
|
||||
i_after = i_after + 1
|
||||
if i_after > #indices_m_after then
|
||||
break
|
||||
end
|
||||
vi_after = indices_m_after[i_after]
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = i_after, #indices_m_after do
|
||||
-- Metadata has been added at i
|
||||
indices_m[#indices_m+1] = indices_m_after[i]
|
||||
metastrings[#metastrings+1] = "return nil"
|
||||
end
|
||||
end
|
||||
|
||||
local changes = {
|
||||
indices_n = indices_n,
|
||||
indices_p1 = indices_p1,
|
||||
indices_p2 = indices_p2,
|
||||
indices_m = indices_m,
|
||||
nodeids = nodeids,
|
||||
param1s = param1s,
|
||||
param2s = param2s,
|
||||
metastrings = metastrings,
|
||||
-- index_bytes is needed later for compression
|
||||
index_bytes = math.ceil(math.log(worldedit.volume(pos1, pos2)) /
|
||||
math.log(0x100)),
|
||||
}
|
||||
return rvs, changes
|
||||
end
|
||||
|
||||
undo_funcs.nodes = function(name, data)
|
||||
local pos1 = data.pos1
|
||||
local pos2 = data.pos2
|
||||
local ylen = pos2.y - pos1.y + 1
|
||||
local ystride = pos2.x - pos1.x + 1
|
||||
|
||||
local decompressed_data = decompress_nodedata{
|
||||
compressed_data = data.compressed_data,
|
||||
nodeids_cnt = data.count_n,
|
||||
param1s_cnt = data.count_p1,
|
||||
param2s_cnt = data.count_p2,
|
||||
metaens_cnt = data.count_m,
|
||||
index_bytes = data.index_bytes
|
||||
}
|
||||
local indices_n = decompressed_data.indices_n
|
||||
local indices_p1 = decompressed_data.indices_p1
|
||||
local indices_p2 = decompressed_data.indices_p2
|
||||
local nodeids = decompressed_data.nodeids
|
||||
local param1s = decompressed_data.param1s
|
||||
local param2s = decompressed_data.param2s
|
||||
|
||||
-- swap the nodes, param1s and param2s in the world and history data
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local e1, e2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
|
||||
local m_nodes = manip:get_data()
|
||||
local m_param1s = manip:get_light_data()
|
||||
local m_param2s = manip:get_param2_data()
|
||||
|
||||
local mts = {m_nodes, m_param1s, m_param2s}
|
||||
local indiceses = {indices_n, indices_p1, indices_p2}
|
||||
local contentses = {nodeids, param1s, param2s}
|
||||
for mtsi = 1,3 do
|
||||
local mt = mts[mtsi]
|
||||
local indices = indiceses[mtsi]
|
||||
local contents = contentses[mtsi]
|
||||
for k = 1,#indices do
|
||||
local i = indices[k]
|
||||
local x = i % ystride
|
||||
local y = math.floor(i / ystride) % ylen
|
||||
local z = math.floor(i / (ystride * ylen))
|
||||
local vi = area:index(pos1.x + x, pos1.y + y, pos1.z + z)
|
||||
contents[k], mt[vi] = mt[vi], contents[k]
|
||||
end
|
||||
end
|
||||
|
||||
manip:set_data(m_nodes)
|
||||
manip:set_light_data(m_param1s)
|
||||
manip:set_param2_data(m_param2s)
|
||||
manip:write_to_map()
|
||||
|
||||
-- swap metaens strings
|
||||
local indices_m = decompressed_data.indices_m
|
||||
local metastrings = decompressed_data.metastrings
|
||||
for k = 1,#indices_m do
|
||||
local i = indices_m[k]
|
||||
local pos = vector.add(pos1, {
|
||||
x = i % ystride,
|
||||
y = math.floor(i / ystride) % ylen,
|
||||
z = math.floor(i / (ystride * ylen))
|
||||
})
|
||||
local metat, meta = get_meta_serializable(pos)
|
||||
meta = meta or minetest.get_meta(pos)
|
||||
meta:from_table(minetest.deserialize(metastrings[k]))
|
||||
metastrings[k] = minetest.serialize(metat)
|
||||
end
|
||||
|
||||
-- update history entry
|
||||
data.compressed_data = compress_nodedata{
|
||||
indices_n = indices_n,
|
||||
indices_p1 = indices_p1,
|
||||
indices_p2 = indices_p2,
|
||||
indices_m = indices_m,
|
||||
nodeids = nodeids,
|
||||
param1s = param1s,
|
||||
param2s = param2s,
|
||||
metastrings = metastrings,
|
||||
index_bytes = data.index_bytes,
|
||||
}
|
||||
data.mem_usage = #data.compressed_data
|
||||
|
||||
worldedit.player_notify(name, data.count_n .. " nodes set, " ..
|
||||
data.count_p1 .. " param1s set, " .. data.count_p2 ..
|
||||
" param2s set and " .. #indices_m .. " metaens changed")
|
||||
end
|
||||
|
||||
|
||||
----------------------- World changing commands --------------------------------
|
||||
|
||||
@ -771,52 +1065,12 @@ override_cc_with_confirm("/spiral",
|
||||
)
|
||||
|
||||
|
||||
-- tells if the metadata is that dummy
|
||||
local function is_meta_empty(metatabl)
|
||||
if metatabl.inventory
|
||||
and next(metatabl.inventory) ~= nil then
|
||||
return false
|
||||
end
|
||||
if metatabl.fields
|
||||
and next(metatabl.fields) ~= nil then
|
||||
return false
|
||||
end
|
||||
for k in pairs(metatabl) do
|
||||
if k ~= "inventory"
|
||||
and k ~= "fields" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Gets information about meta if it is set, otherwise returns nil
|
||||
-- the format of the information is the same as in WorldEdit
|
||||
local function get_meta_serializable(pos)
|
||||
if not minetest.find_nodes_with_meta(pos, pos) then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local metat = meta:to_table()
|
||||
if is_meta_empty(metat) then
|
||||
-- For some reason minetest.find_nodes_with_meta can find empty
|
||||
-- metadata
|
||||
return
|
||||
end
|
||||
for _, inventory in pairs(metat.inventory) do
|
||||
for index = 1,#inventory do
|
||||
local itemstack = inventory[index]
|
||||
if itemstack.to_string then
|
||||
inventory[index] = itemstack:to_string()
|
||||
end
|
||||
end
|
||||
end
|
||||
return metat, meta
|
||||
end
|
||||
|
||||
local we_deserialize = worldedit.deserialize
|
||||
local function my_we_deserialize(pos_base, ...)
|
||||
-- remember the previous nodes and meta
|
||||
-- Collect the changes by overriding minetest.add_node since this is
|
||||
-- probably faster than loading the whole area including metadata before
|
||||
-- and after worldedit's operation
|
||||
local nodes = {}
|
||||
local metaens = {}
|
||||
local add_node = minetest.add_node
|
||||
@ -995,92 +1249,6 @@ override_cc_with_confirm("/load",
|
||||
end
|
||||
)
|
||||
|
||||
undo_funcs.nodes = function(name, data)
|
||||
local pos1 = data.pos1
|
||||
local pos2 = data.pos2
|
||||
local ylen = pos2.y - pos1.y + 1
|
||||
local ystride = pos2.x - pos1.x + 1
|
||||
|
||||
local decompressed_data = decompress_nodedata{
|
||||
compressed_data = data.compressed_data,
|
||||
nodeids_cnt = data.count_n,
|
||||
param1s_cnt = data.count_p1,
|
||||
param2s_cnt = data.count_p2,
|
||||
metaens_cnt = data.count_m,
|
||||
index_bytes = data.index_bytes
|
||||
}
|
||||
local indices_n = decompressed_data.indices_n
|
||||
local indices_p1 = decompressed_data.indices_p1
|
||||
local indices_p2 = decompressed_data.indices_p2
|
||||
local nodeids = decompressed_data.nodeids
|
||||
local param1s = decompressed_data.param1s
|
||||
local param2s = decompressed_data.param2s
|
||||
|
||||
-- swap the nodes, param1s and param2s in the world and history data
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local e1, e2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
|
||||
local m_nodes = manip:get_data()
|
||||
local m_param1s = manip:get_light_data()
|
||||
local m_param2s = manip:get_param2_data()
|
||||
|
||||
local mts = {m_nodes, m_param1s, m_param2s}
|
||||
local indiceses = {indices_n, indices_p1, indices_p2}
|
||||
local contentses = {nodeids, param1s, param2s}
|
||||
for mtsi = 1,3 do
|
||||
local mt = mts[mtsi]
|
||||
local indices = indiceses[mtsi]
|
||||
local contents = contentses[mtsi]
|
||||
for k = 1,#indices do
|
||||
local i = indices[k]
|
||||
local x = i % ystride
|
||||
local y = math.floor(i / ystride) % ylen
|
||||
local z = math.floor(i / (ystride * ylen))
|
||||
local vi = area:index(pos1.x + x, pos1.y + y, pos1.z + z)
|
||||
contents[k], mt[vi] = mt[vi], contents[k]
|
||||
end
|
||||
end
|
||||
|
||||
manip:set_data(m_nodes)
|
||||
manip:set_light_data(m_param1s)
|
||||
manip:set_param2_data(m_param2s)
|
||||
manip:write_to_map()
|
||||
|
||||
-- swap metaens strings
|
||||
local indices_m = decompressed_data.indices_m
|
||||
local metastrings = decompressed_data.metastrings
|
||||
for k = 1,#indices_m do
|
||||
local i = indices_m[k]
|
||||
local pos = vector.add(pos1, {
|
||||
x = i % ystride,
|
||||
y = math.floor(i / ystride) % ylen,
|
||||
z = math.floor(i / (ystride * ylen))
|
||||
})
|
||||
local metat, meta = get_meta_serializable(pos)
|
||||
meta = meta or minetest.get_meta(pos)
|
||||
meta:from_table(minetest.deserialize(metastrings[k]))
|
||||
metastrings[k] = minetest.serialize(metat)
|
||||
end
|
||||
|
||||
-- update history entry
|
||||
data.compressed_data = compress_nodedata{
|
||||
indices_n = indices_n,
|
||||
indices_p1 = indices_p1,
|
||||
indices_p2 = indices_p2,
|
||||
indices_m = indices_m,
|
||||
nodeids = nodeids,
|
||||
param1s = param1s,
|
||||
param2s = param2s,
|
||||
metastrings = metastrings,
|
||||
index_bytes = data.index_bytes,
|
||||
}
|
||||
data.mem_usage = #data.compressed_data
|
||||
|
||||
worldedit.player_notify(name, data.count_n .. " nodes set, " ..
|
||||
data.count_p1 .. " param1s set, " .. data.count_p2 ..
|
||||
" param2s set and " .. #indices_m .. " metaens changed")
|
||||
end
|
||||
|
||||
|
||||
local original_place_schematic = minetest.place_schematic
|
||||
local function my_place_schematic(pos, schematic_path, rotation, replacements,
|
||||
@ -1100,86 +1268,29 @@ local function my_place_schematic(pos, schematic_path, rotation, replacements,
|
||||
local pos1 = pos
|
||||
local pos2 = vector.subtract(vector.add(pos1, schem.size), 1)
|
||||
|
||||
-- Get the node ids, param1s and param2s (before)
|
||||
-- Note: schematic placement doesn't change the metadata
|
||||
local manip = minetest.get_voxel_manip()
|
||||
local e1, e2 = manip:read_from_map(pos1, pos2)
|
||||
local area = VoxelArea:new{MinEdge=e1, MaxEdge=e2}
|
||||
local nodeids_before = manip:get_data()
|
||||
local param1s_before = manip:get_light_data()
|
||||
local param2s_before = manip:get_param2_data()
|
||||
|
||||
-- Do the schematic placement
|
||||
local rv = original_place_schematic(pos, schematic_path, rotation,
|
||||
replacements, force_placement, flags)
|
||||
|
||||
-- Get the node ids, param1s and param2s (after)
|
||||
manip = minetest.get_voxel_manip()
|
||||
manip:read_from_map(pos1, pos2)
|
||||
local nodeids_after = manip:get_data()
|
||||
local param1s_after = manip:get_light_data()
|
||||
local param2s_after = manip:get_param2_data()
|
||||
|
||||
-- Collect the changed nodes
|
||||
local ystride = pos2.x - pos1.x + 1
|
||||
local zstride = (pos2.y - pos1.y + 1) * ystride
|
||||
local indices_n = {}
|
||||
local indices_p1 = {}
|
||||
local indices_p2 = {}
|
||||
local nodeids = {}
|
||||
local param1s = {}
|
||||
local param2s = {}
|
||||
for z = pos1.z, pos2.z do
|
||||
for y = pos1.y, pos2.y do
|
||||
for x = pos1.x, pos2.x do
|
||||
local vi_vm = area:index(x,y,z)
|
||||
local vi_my = (z - pos1.z) * zstride
|
||||
+ (y - pos1.y) * ystride
|
||||
+ x - pos1.x
|
||||
if nodeids_after[vi_vm] ~= nodeids_before[vi_vm] then
|
||||
indices_n[#indices_n+1] = vi_my
|
||||
nodeids[#nodeids+1] = nodeids_before[vi_vm]
|
||||
end
|
||||
if param1s_after[vi_vm] ~= param1s_before[vi_vm] then
|
||||
indices_p1[#indices_p1+1] = vi_my
|
||||
param1s[#param1s+1] = param1s_before[vi_vm]
|
||||
end
|
||||
if param2s_after[vi_vm] ~= param2s_before[vi_vm] then
|
||||
indices_p2[#indices_p2+1] = vi_my
|
||||
param2s[#param2s+1] = param2s_before[vi_vm]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local rvs, changes = run_and_capture_changes(function()
|
||||
-- Do the schematic placement
|
||||
return original_place_schematic(pos, schematic_path, rotation,
|
||||
replacements, force_placement, flags)
|
||||
end, pos1, pos2, false)
|
||||
|
||||
-- Compress the collected changes and add it to history
|
||||
local index_bytes = math.ceil(math.log(worldedit.volume(pos1, pos2)) /
|
||||
math.log(0x100))
|
||||
local compressed_data = compress_nodedata{
|
||||
indices_n = indices_n,
|
||||
indices_p1 = indices_p1,
|
||||
indices_p2 = indices_p2,
|
||||
indices_m = {},
|
||||
nodeids = nodeids,
|
||||
param1s = param1s,
|
||||
param2s = param2s,
|
||||
metastrings = {},
|
||||
index_bytes = index_bytes,
|
||||
}
|
||||
local compressed_data = compress_nodedata(changes)
|
||||
add_to_history({
|
||||
type = "nodes",
|
||||
mem_use = #compressed_data,
|
||||
pos1 = pos1,
|
||||
pos2 = pos2,
|
||||
count_n = #nodeids,
|
||||
count_p1 = #param1s,
|
||||
count_p2 = #param2s,
|
||||
count_n = #changes.nodeids,
|
||||
count_p1 = #changes.param1s,
|
||||
count_p2 = #changes.param2s,
|
||||
count_m = 0,
|
||||
index_bytes = index_bytes,
|
||||
index_bytes = changes.index_bytes,
|
||||
compressed_data = compressed_data
|
||||
}, command_invoker)
|
||||
|
||||
return rv
|
||||
return unpack(rvs)
|
||||
end
|
||||
override_cc_with_confirm("/mtschemplace",
|
||||
function()
|
||||
@ -1191,6 +1302,50 @@ override_cc_with_confirm("/mtschemplace",
|
||||
)
|
||||
|
||||
|
||||
local we_luatransform = worldedit.luatransform
|
||||
local function my_luatransform(pos1_actual, pos2_actual, code)
|
||||
local pos1_further, pos2_further = worldedit.sort_pos(pos1_actual,
|
||||
pos2_actual)
|
||||
-- For safety, add a bit extra space since players can do arbitrary
|
||||
-- things at arbitrary positions with luatransform
|
||||
pos1_further = vector.subtract(pos1_further, 5)
|
||||
pos2_further = vector.add(pos2_further, 5)
|
||||
|
||||
-- Use the generic (but not necessarily fast) function to capture the
|
||||
-- changes
|
||||
local rvs, changes = run_and_capture_changes(function()
|
||||
return we_luatransform(pos1_actual, pos2_actual, code)
|
||||
end, pos1_further, pos2_further, true)
|
||||
|
||||
-- Compress the collected changes and add it to history
|
||||
local compressed_data = compress_nodedata(changes)
|
||||
add_to_history({
|
||||
type = "nodes",
|
||||
mem_use = #compressed_data,
|
||||
pos1 = pos1_further,
|
||||
pos2 = pos2_further,
|
||||
count_n = #changes.nodeids,
|
||||
count_p1 = #changes.param1s,
|
||||
count_p2 = #changes.param2s,
|
||||
count_m = 0,
|
||||
index_bytes = changes.index_bytes,
|
||||
compressed_data = compressed_data
|
||||
}, command_invoker)
|
||||
|
||||
return unpack(rvs)
|
||||
end
|
||||
override_cc_with_confirm("/luatransform",
|
||||
function()
|
||||
worldedit.luatransform = my_luatransform
|
||||
end,
|
||||
function()
|
||||
worldedit.luatransform = we_luatransform
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
local time = (minetest.get_us_time() - load_time_start) / 1000000
|
||||
local msg = "[we_undo] loaded after ca. " .. time .. " seconds."
|
||||
if time > 0.01 then
|
||||
|
Loading…
Reference in New Issue
Block a user