This commit is contained in:
sfan5 2019-09-09 17:03:36 +02:00
parent 3c5f6b9665
commit 5c06ae59ef
1 changed files with 51 additions and 70 deletions

View File

@ -85,19 +85,20 @@ function worldedit.serialize(pos1, pos2)
array[1] = first_value array[1] = first_value
return {first_value} return {first_value}
end end
local function match_try(array, cache, value) local function match_try(cache, prev_pushed, value)
local i = #cache local i = #cache
while i >= 1 do while i >= 1 do
if cache[i] == value then if cache[i] == value then
local ret = -(#cache - i + 1) local ret = -(#cache - i + 1)
return ret, array[#array] == ret local was_value = type(prev_pushed) ~= "number" or prev_pushed >= 0
return ret, (was_value and ret == -1) or prev_pushed == ret
end end
i = i - 1 i = i - 1
end end
return nil, false return nil, false
end end
local function match_push(array, cache, match, value) local function match_push(cache, match, value)
if match ~= nil then -- don't advance ringbuffer if match ~= nil then -- don't advance cache
return match return match
end end
local idx = #cache + 1 local idx = #cache + 1
@ -116,36 +117,36 @@ function worldedit.serialize(pos1, pos2)
data = {}, data = {},
param1 = {}, param1 = {},
param2 = {}, param2 = {},
meta = {},
} }
end end
local function cur_finish(result, cur) local function is_emptyish(t)
-- TODO: wouldn't be needed if param1, param2 supported omit (see below) -- returns true if <t> contains only one element and that one element is == 0
local i = #cur.param1 local seen = false
while i > 1 and cur.param1[i] == -1 do for _, value in ipairs(t) do
cur.param1[i] = nil if not seen then
i = i - 1 if value ~= 0 then
return false
end
seen = true
else
return false
end
end end
if i == 1 and cur.param1[1] == 0 then return true
end
local function cur_finish(result, cur)
if is_emptyish(cur.param1) then
cur.param1 = nil cur.param1 = nil
end end
if is_emptyish(cur.param2) then
i = #cur.param2
while i > 1 and cur.param2[i] == -1 do
cur.param2[i] = nil
i = i - 1
end
if i == 1 and cur.param2[1] == 0 then
cur.param2 = nil cur.param2 = nil
end end
-- Drop unneeded ref from data table (FIXME?) if next(cur.meta) == nil then
i = #cur.data cur.meta = nil
if cur.data[i] == -1 then
cur.data[i] = nil
end end
-- add to result table
result[#result + 1] = cur result[#result + 1] = cur
end end
local OMIT_MIN_LIMIT = 18
-- Serialize stuff -- Serialize stuff
local pos = {} local pos = {}
@ -153,7 +154,7 @@ function worldedit.serialize(pos1, pos2)
local result = {} local result = {}
local cur local cur
local cache_data, cache_param1, cache_param2 local cache_data, cache_param1, cache_param2
local is_omit -- applies to data only local prev_data, prev_param1, prev_param2
pos[other1] = pos1[other1] pos[other1] = pos1[other1]
while pos[other1] <= pos2[other1] do while pos[other1] <= pos2[other1] do
pos[other2] = pos1[other2] pos[other2] = pos1[other2]
@ -163,65 +164,46 @@ function worldedit.serialize(pos1, pos2)
local node = get_node(pos) local node = get_node(pos)
if node.name ~= "air" and node.name ~= "ignore" then if node.name ~= "air" and node.name ~= "ignore" then
local new_row = false if cur == nil then -- Start a new row
if cur == nil then cur = cur_new(pos, pos1, axis, other1, other2)
new_row = true
else -- See if we want to push to existing row cache_data = match_init(cur.data, node.name)
cache_param1 = match_init(cur.param1, node.param1)
cache_param2 = match_init(cur.param2, node.param2)
prev_data = cur.data[1]
prev_param1 = cur.param1[1]
prev_param2 = cur.param2[1]
else -- Append to existing row
local next_c = cur.c + 1 local next_c = cur.c + 1
cur.c = next_c cur.c = next_c
local value, m, can_omit local value, m, can_omit
value = node.name value = node.name
m, can_omit = match_try(cur.data, cache_data, node.name) m, can_omit = match_try(cache_data, prev_data, node.name)
if is_omit and not can_omit then if not can_omit then
-- we have omitted previous entries, but can't omit this one prev_data = match_push(cache_data, m, value)
if next_c - #cur.data > OMIT_MIN_LIMIT then cur.data[next_c] = prev_data
-- just starting a new row will take less space, do that
new_row = true
else
-- fill up omitted data and proceed as usual
local last = cur.data[#cur.data]
for i = #cur.data + 1, next_c - 1 do
cur.data[i] = last
end
cur.data[next_c] = match_push(cur.data, cache_data, m, value)
is_omit = false
end
elseif can_omit then
is_omit = true
else
cur.data[next_c] = match_push(cur.data, cache_data, m, value)
end end
-- TODO: implement omit for param1, param2 too value = node.param1
if not new_row then m, can_omit = match_try(cache_param1, prev_param1, value)
value = node.param1 if not can_omit then
m, can_omit = match_try(cur.param1, cache_param1, value) prev_param1 = match_push(cache_param1, m, value)
cur.param1[next_c] = match_push(cur.param1, cache_param1, m, value) cur.param1[next_c] = prev_param1
value = node.param2
m, can_omit = match_try(cur.param2, cache_param2, value)
cur.param2[next_c] = match_push(cur.param2, cache_param2, m, value)
else -- Undo changes and finish row
cur.c = next_c - 1
cur_finish(result, cur)
cur = nil
is_omit = false
end end
end
if new_row then -- Start a new row value = node.param2
cur = cur_new(pos, pos1, axis, other1, other2) m, can_omit = match_try(cache_param2, prev_param2, value)
cache_data = match_init(cur.data, node.name) if not can_omit then
cache_param1 = match_init(cur.param1, node.param1) prev_param2 = match_push(cache_param2, m, value)
cache_param2 = match_init(cur.param2, node.param2) cur.param2[next_c] = prev_param2
end
end end
count = count + 1 count = count + 1
else else
if cur ~= nil then -- Finish row if cur ~= nil then -- Finish row
cur_finish(result, cur) cur_finish(result, cur)
cur = nil cur = nil
is_omit = false
end end
end end
pos[axis] = pos[axis] + 1 pos[axis] = pos[axis] + 1
@ -230,7 +212,6 @@ function worldedit.serialize(pos1, pos2)
if cur ~= nil then -- Finish leftover row if cur ~= nil then -- Finish leftover row
cur_finish(result, cur) cur_finish(result, cur)
cur = nil cur = nil
is_omit = false
end end
pos[other2] = pos[other2] + 1 pos[other2] = pos[other2] + 1
end end