forked from VoxeLibre/VoxeLibre
add block post processing support, start adding L2/L3/L4 node count indexing, add simple shim for vl_scheduler functionality
This commit is contained in:
parent
6e5c47ac59
commit
66854baf47
|
@ -3,11 +3,16 @@ local modpath = minetest.get_modpath(modname)
|
|||
|
||||
-- Make sure the API is available everywhere
|
||||
dofile(modpath.."/api.lua")
|
||||
if not minetest.get_modpath("vl_scheduler") then
|
||||
dofile(modpath.."/scheduler.lua")
|
||||
end
|
||||
local mod = vl_map_index
|
||||
mod.indexer_dofile(modpath.."/node_counter.lua")
|
||||
|
||||
|
||||
-- Imports
|
||||
local call_async = minetest.handle_async or function(a,b,...) b(a(...)) end
|
||||
local scheduler = mod.scheduler
|
||||
|
||||
-- Constants
|
||||
local DIRTY_BLOCK_HOLDOFF = 2
|
||||
|
@ -17,9 +22,11 @@ local MINETEST_BLOCK_SIZE = 16
|
|||
local storage = minetest.get_mod_storage()
|
||||
local dirty_blocks = minetest.deserialize(storage:get_string("dirty_blocks")) or {}
|
||||
local processing_block = minetest.deserialize(storage:get_string("processing_block")) or false
|
||||
local post_process_blocks = minetest.deserialize(storage:get_string("post_process_blocks")) or {}
|
||||
minetest.register_on_shutdown(function()
|
||||
storage:set_string("dirty_blocks", minetest.serialize(dirty_blocks))
|
||||
storage:set_string("processing_block",minetest.serialize(processing_block))
|
||||
storage:set_string("pos_process_blocks",minetest.serialize(post_process_blocks))
|
||||
end)
|
||||
|
||||
-- Map block processor
|
||||
|
@ -76,6 +83,11 @@ local function process_dirty_block()
|
|||
storage:set_string(mod.indexers[indexer].name..vector.to_string(minetest.get_position_from_hash(map_block_hash)),tostring(result))
|
||||
index_in_process = false
|
||||
decompress_queue[#decompress_queue + 1] = {map_block_hash, indexer, result}
|
||||
|
||||
-- Flag the map block for post processing
|
||||
if mod.indexers[indexer].post_process then
|
||||
post_process_blocks[map_block_hash] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Run the indexer
|
||||
|
@ -114,7 +126,8 @@ end
|
|||
-- Returns true if all indexes have been generated for map_block
|
||||
function mod.has_index(map_block)
|
||||
for i = 1,#mod.indexers do
|
||||
if not storage:contains(mod.indexers[i].name..vector.to_string(map_block)) then
|
||||
local idx = mod.indexers[i].name..vector.to_string(map_block)
|
||||
if not storage:contains(idx) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -131,7 +144,7 @@ function mod.index_around_entity(pos, distance)
|
|||
local blocks = math.ceil(distance / MINETEST_BLOCK_SIZE)
|
||||
|
||||
for z = -blocks,blocks do
|
||||
for y = -blocks,blocks do
|
||||
for y = -2,1 do
|
||||
for x = -blocks,blocks do
|
||||
mod.ensure_indexed(vector.add(center, vector.new(x,y,z)))
|
||||
end
|
||||
|
@ -170,7 +183,7 @@ local function run_indexer()
|
|||
|
||||
local last_player_block = last_player_blocks[player_name]
|
||||
if not last_player_block or last_player_block ~= map_block then
|
||||
print("Indexing around "..player_name)
|
||||
--print("Indexing around "..player_name)
|
||||
mod.index_around_entity(player_pos, 128)
|
||||
end
|
||||
last_player_blocks[player_name] = map_block
|
||||
|
@ -194,14 +207,16 @@ local function run_indexer()
|
|||
local item = decompress_queue[idx]
|
||||
decompress_queue[idx] = nil
|
||||
if item then
|
||||
mod.cache_map_index(item[1], item[2], mod.unpack_index(item[3]))
|
||||
local map_block_hash = item[1]
|
||||
local indexer = item[2]
|
||||
mod.cache_map_index(map_block_hash, indexer, mod.unpack_index(item[3]))
|
||||
if post_process_blocks[item[1]] then
|
||||
mod.indexers[indexer].post_process(map_block_hash)
|
||||
post_process_blocks[item[1]] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if minetest.get_modpath("vl_scheduler") then
|
||||
-- Run the indexer
|
||||
vl_scheduler.register_periodic_task("vl_map_index:indexer", 0.25, 4, run_indexer)
|
||||
else
|
||||
-- Globalstep to handle reindexing map blocks
|
||||
minetest.register_globalstep(run_indexer)
|
||||
end
|
||||
|
||||
-- Run the indexer
|
||||
scheduler.register_periodic_task("vl_map_index:indexer", 0.25, 4, run_indexer)
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
-- Imports
|
||||
local vl_map_index = vl_map_index
|
||||
local mod = vl_map_index
|
||||
local scheduler = mod.scheduler
|
||||
|
||||
-- Constants
|
||||
local MIN_SEARCH_SIZE = 1000
|
||||
|
@ -15,7 +16,11 @@ local function block_pos_hash(min, x, y, z)
|
|||
(z - min.z)
|
||||
end
|
||||
|
||||
vl_map_index.register_indexer("node_counter",{
|
||||
local l2_tasks = {}
|
||||
local l3_tasks = {}
|
||||
local l4_task = nil
|
||||
|
||||
mod.register_indexer("node_counter",{
|
||||
index = function(data)
|
||||
local min = data.map_block.min
|
||||
local max = data.map_block.max
|
||||
|
@ -79,51 +84,93 @@ vl_map_index.register_indexer("node_counter",{
|
|||
--print(dump(index))
|
||||
return index
|
||||
end,
|
||||
post_process = function(map_block_hash)
|
||||
local pos = minetest.get_position_from_hash(map_block_hash)
|
||||
---- Schedule tasks for updating heirarchial indexes
|
||||
|
||||
-- L2 index (256x256x256 blocks)
|
||||
local l2_block = mod.map_block(pos)
|
||||
local l2_block_hash = minetest.hash_node_position(l2_block)
|
||||
if l2_tasks[l2_block_hash] then
|
||||
l2_tasks[l2_block_hash]:cancel()
|
||||
end
|
||||
l2_tasks[l2_block_hash] = scheduler.add_cancelable_task("vl_map_index:node_counter_l2_index", 2, 4, {l2_block_hash})
|
||||
|
||||
-- L3 index (4096*4096*4096 blocks)
|
||||
local l3_block = mod.map_block(l2_block)
|
||||
local l3_block_hash = minetest.hash_node_position(l3_block)
|
||||
if l3_tasks[l3_block_hash] then
|
||||
l3_tasks[l3_block_hash]:cancel()
|
||||
end
|
||||
l3_tasks[l3_block_hash] = scheduler.add_cancelable_task("vl_map_index:node_counter_l3_index", 2, 4, {l3_block_hash})
|
||||
print("L3 block = "..vector.to_string(l3_block))
|
||||
|
||||
-- L4 (whole world, 65536x65536x65536 block)
|
||||
if l4_task then
|
||||
l4_task:cancel()
|
||||
end
|
||||
l4_task = scheduler.add_cancelable_task("vl_map_index:node_counter_l4_index", 2, 4, {})
|
||||
end,
|
||||
})
|
||||
|
||||
if not mod.main_thread then return end
|
||||
|
||||
-- Scheduler tasks
|
||||
scheduler.register_function("vl_map_index:node_counter_l2_index",function(l2_block_hash)
|
||||
print("TODO: update L2 index")
|
||||
l2_tasks[l2_block_hash] = nil
|
||||
end)
|
||||
scheduler.register_function("vl_map_index:node_counter_l3_index",function(l3_block_hash)
|
||||
print("TODO: update L3 index")
|
||||
l3_tasks[l3_block_hash] = nil
|
||||
end)
|
||||
scheduler.register_function("vl_map_index:node_counter_l4_index",function()
|
||||
print("TODO: update L4 index")
|
||||
l4_task = nil
|
||||
end)
|
||||
|
||||
-- Public-facing API
|
||||
if vl_map_index.main_thread then
|
||||
function vl_map_index.find_nodes_in_area(pos1, pos2, nodenames, grouped)
|
||||
local size = math.abs(pos1.x - pos2.x) * math.abs(pos1.y - pos2.y) * math.abs(pos1.z - pos2.z)
|
||||
if size >= MIN_SEARCH_SIZE then
|
||||
local indexes = vl_map_index.get_indexes_for_area(pos1, pos2, "node_counter")
|
||||
if indexes then
|
||||
for i=1,#indexes do
|
||||
-- TODO: find nodes in area
|
||||
end
|
||||
function mod.find_nodes_in_area(pos1, pos2, nodenames, grouped)
|
||||
local size = math.abs(pos1.x - pos2.x) * math.abs(pos1.y - pos2.y) * math.abs(pos1.z - pos2.z)
|
||||
if size >= MIN_SEARCH_SIZE then
|
||||
local indexes = mod.get_indexes_for_area(pos1, pos2, "node_counter")
|
||||
if indexes then
|
||||
for i=1,#indexes do
|
||||
-- TODO: find nodes in area
|
||||
end
|
||||
end
|
||||
|
||||
-- Otherwize, fallback onto minetest builtin function
|
||||
return minetest.find_nodes_in_area(pos1, pos2, nodenames, grouped)
|
||||
end
|
||||
function vl_map_index.find_node_near(pos, radius, nodenames, search_center)
|
||||
local size = radius * radius * radius
|
||||
if size >= MIN_SEARCH_SIZE then
|
||||
local indexes = vl_map_index.get_indexes_near(pos, radius, "node_counter")
|
||||
if indexes then
|
||||
for i=1,#indexes do
|
||||
-- TODO: find nodes in area
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Otherwize, fallback onto minetest builtin function
|
||||
return minetest.find_node_near(pos, radius, nodenames, search_center)
|
||||
end
|
||||
function vl_map_index.find_nodes_in_area_under_air(pos1, pos2, nodenames)
|
||||
local size = math.abs(pos1.x - pos2.x) * math.abs(pos1.y - pos2.y) * math.abs(pos1.z - pos2.z)
|
||||
if size >= MIN_SEARCH_SIZE then
|
||||
local indexes = vl_map_index.get_indexes_for_area(pos1, pos2, "node_counter")
|
||||
if indexes then
|
||||
for i=1,#indexes do
|
||||
-- TODO: find nodes under air in area
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Otherwize, fallback onto minetest builtin function
|
||||
return minetest.find_nodes_in_area_under_air(pos1, pos2, nodenames)
|
||||
end
|
||||
-- Otherwize, fallback onto minetest builtin function
|
||||
return minetest.find_nodes_in_area(pos1, pos2, nodenames, grouped)
|
||||
end
|
||||
function mod.find_node_near(pos, radius, nodenames, search_center)
|
||||
local size = radius * radius * radius
|
||||
if size >= MIN_SEARCH_SIZE then
|
||||
local indexes = mod.get_indexes_near(pos, radius, "node_counter")
|
||||
if indexes then
|
||||
for i=1,#indexes do
|
||||
-- TODO: find nodes in area
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Otherwize, fallback onto minetest builtin function
|
||||
return minetest.find_node_near(pos, radius, nodenames, search_center)
|
||||
end
|
||||
function mod.find_nodes_in_area_under_air(pos1, pos2, nodenames)
|
||||
local size = math.abs(pos1.x - pos2.x) * math.abs(pos1.y - pos2.y) * math.abs(pos1.z - pos2.z)
|
||||
if size >= MIN_SEARCH_SIZE then
|
||||
local indexes = mod.get_indexes_for_area(pos1, pos2, "node_counter")
|
||||
if indexes then
|
||||
for i=1,#indexes do
|
||||
-- TODO: find nodes under air in area
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Otherwize, fallback onto minetest builtin function
|
||||
return minetest.find_nodes_in_area_under_air(pos1, pos2, nodenames)
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
local mod = vl_map_index
|
||||
|
||||
-- Adapter for when no vl_scheduler is not available
|
||||
local periodic = {}
|
||||
local tasks = {}
|
||||
local functions = {}
|
||||
|
||||
local scheduler = {
|
||||
register_periodic_task = function(name,period,priority,func)
|
||||
periodic[#periodic + 1] = {
|
||||
func = func,
|
||||
period = period,
|
||||
time = 0
|
||||
}
|
||||
local time = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
time = time + dtime
|
||||
if time >= period then
|
||||
func()
|
||||
time = time - period
|
||||
end
|
||||
end)
|
||||
end,
|
||||
register_function = function(name, func, default_time, default_priority)
|
||||
functions[name] = func
|
||||
end,
|
||||
add_task = function(name, time, priority, args)
|
||||
local func = functions[name]
|
||||
if not func then return end
|
||||
|
||||
local task = {
|
||||
func = func,
|
||||
time = time,
|
||||
args = args,
|
||||
}
|
||||
tasks[#tasks + 1] = task
|
||||
end,
|
||||
add_cancelable_task = function(name, time, priority, args)
|
||||
local func = functions[name]
|
||||
if not func then return end
|
||||
|
||||
local task = {
|
||||
func = func,
|
||||
time = time,
|
||||
args = args,
|
||||
}
|
||||
function task:cancel()
|
||||
task.canceled = true
|
||||
end
|
||||
tasks[#tasks + 1] = task
|
||||
end
|
||||
}
|
||||
mod.scheduler = scheduler
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
-- Run periodic tasks
|
||||
for i = 1,#periodic do
|
||||
local task = periodic[i]
|
||||
local time,period = task.time,task.period
|
||||
time = time + dtime
|
||||
if time >= period then
|
||||
time = time - period
|
||||
task.func()
|
||||
end
|
||||
task.time = time
|
||||
end
|
||||
|
||||
-- Run tasks
|
||||
local new_tasks = {}
|
||||
for i = 1,#tasks do
|
||||
local task = tasks[i]
|
||||
local time = task.time
|
||||
time = time - dtime
|
||||
if time <= 0 then
|
||||
if not task.canceled then
|
||||
task.func(unpack(task.args))
|
||||
end
|
||||
else
|
||||
task.time = time
|
||||
new_tasks[#new_tasks + 1] = task
|
||||
end
|
||||
end
|
||||
tasks = new_tasks
|
||||
end)
|
Loading…
Reference in New Issue