diff --git a/api.txt b/api.txt index 691d3e3..a0273b0 100644 --- a/api.txt +++ b/api.txt @@ -1,4 +1,18 @@ -Function happens when a nodes constructer function is ran near by. +-- node_funcs +-- Function happens when a node's constructer function is ran in a 3x3x3 near by. on_construct_node_near_by(pos,other_pos) -Function happens when a nodes destructer function is ran near by. -on_destruct_node_near_by(pos,other_pos) \ No newline at end of file +-- Function happens when a node's destructer function is ran 3x3x3 near by. +on_destruct_node_near_by(pos,other_pos) +-- async +-- +minetest.async.priority(resting,maxtime) +-- +minetest.async.iterate(from,to,func,callback) +-- +minetest.async.foreach(array, func, callback) +-- +minetest.async.do_while(condition, func, callback) +-- +minetest.async.register_globalstep(func) +-- +minetest.async.queue_task(tasks,callback) \ No newline at end of file diff --git a/async.lua b/async.lua new file mode 100644 index 0000000..1834112 --- /dev/null +++ b/async.lua @@ -0,0 +1,167 @@ +minetest.async = {} + +minetest.async.threads = {} +minetest.async.globalstep_threads = {} +minetest.async.resting = 200 / 1000 +minetest.async.maxtime = 200 / 1000 +minetest.async.state = "suspended" + +function minetest.async.create_worker(func) + local thread = coroutine.create(func) + table.insert(minetest.async.threads, thread) +end + +function minetest.async.create_globalstep_worker(func) + local thread = coroutine.create(func) + table.insert(minetest.async.globalstep_threads, thread) +end + +function minetest.async.run_worker(index) + local thread = minetest.async.threads[index] + if thread == nil or coroutine.status(thread) == "dead" then + table.remove(minetest.async.threads, index) + minetest.after(0,minetest.async.schedule_worker) + return false + else + coroutine.resume(thread) + minetest.after(0,minetest.async.schedule_worker) + return true + end +end + +function minetest.async.run_globalstep_worker(index) + local thread = minetest.async.globalstep_threads[index] + if thread == nil or coroutine.status(thread) == "dead" then + table.remove(minetest.async.globalstep_threads, index) + minetest.after(0,minetest.async.schedule_globalstep_worker) + return false + else + coroutine.resume(thread) + minetest.after(0,minetest.async.schedule_globalstep_worker) + return true + end +end + +function minetest.async.schedule_worker() + minetest.async.state = "running" + for index,value in ipairs(minetest.async.threads) do + minetest.after(0,minetest.async.run_worker,index) + return true + end + minetest.async.state = "suspended" + minetest.after(minetest.async.resting,minetest.async.schedule_worker) + return false +end + +function minetest.async.schedule_globalstep_worker() + for index,value in ipairs(minetest.async.globalstep_threads) do + minetest.after(0,minetest.async.run_globalstep_worker,index) + return true + end + minetest.after(5,minetest.async.schedule_globalstep_worker) + return false +end + +function minetest.async.priority(resting,maxtime) + minetest.async.resting = resting / 1000 + minetest.async.maxtime = maxtime / 1000 +end + +function minetest.async.iterate(from,to,func,callback) + minetest.async.create_worker(function(t,mt) + local last_time = minetest.get_us_time() * 1000 + local maxtime = minetest.async.maxtime + for i = from, to do + func(i) + if minetest.get_us_time() * 1000 > last_time + maxtime then + coroutine.yield() + last_time = minetest.get_us_time() * 1000 + end + end + if callback then + callback() + end + end) + minetest.async.schedule_worker() +end + +function minetest.async.foreach(array, func, callback) + minetest.async.create_worker(function() + local last_time = minetest.get_us_time() * 1000 + local maxtime = minetest.async.maxtime + for k,v in ipairs(array) do + func(k,v) + if minetest.get_us_time() * 1000 > last_time + maxtime then + coroutine.yield() + last_time = minetest.get_us_time() * 1000 + end + end + if callback then + callback() + end + end) + minetest.async.schedule_worker() +end + +function minetest.async.do_while(condition, func, callback) + minetest.async.create_worker(function(t,mt) + local last_time = minetest.get_us_time() * 1000 + local maxtime = minetest.async.maxtime + while(condition) do + local c = func() + if c and c ~= condition then + break + end + if minetest.get_us_time() * 1000 > last_time + maxtime then + coroutine.yield() + last_time = minetest.get_us_time() * 1000 + end + end + if callback then + callback() + end + end) + minetest.async.schedule_worker() +end + +function minetest.async.register_globalstep(func) + minetest.async.create_globalstep_worker(function() + local last_time = minetest.get_us_time() * 1000 + local dtime = last_time + while(true) do + local c = func(dtime) + if c and c == false then + break + end + dtime = minetest.get_us_time() * 1000 + -- 0.05 seconds + if minetest.get_us_time() * 1000 > last_time + 50 then + coroutine.yield() + local last_time = minetest.get_us_time() * 1000 + end + end + end) + minetest.async.schedule_globalstep_worker() +end + +function minetest.async.queue_task(tasks,callback) + minetest.async.create_worker(function() + local pass_arg = {} + local last_time = minetest.get_us_time() * 1000 + local maxtime = minetest.async.maxtime + for index, task_func in pairs(tasks) do + local p = task_func(pass_arg) + if p then + pass_arg = p + end + if minetest.get_us_time() * 1000 > last_time + maxtime then + coroutine.yield() + last_time = minetest.get_us_time() * 1000 + end + end + if callback then + callback(pass_arg) + end + end) + minetest.async.schedule_worker() +end \ No newline at end of file diff --git a/init.lua b/init.lua index c64ddcd..77e6457 100644 --- a/init.lua +++ b/init.lua @@ -1,202 +1,3 @@ --- on_construct_node_near_by(pos,constructed_pos) -local function on_construct_override(pos) - local lpos = pos - local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} - local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} - - local vm = minetest.get_voxel_manip() - - local emin, emax = vm:read_from_map(pos1, pos2) - local a = VoxelArea:new{ - MinEdge = emin, - MaxEdge = emax - } - - local nx = lpos.x - local ny = lpos.y - local nz = lpos.z - - local n1x = pos1.x - local n1y = pos1.y - local n1z = pos1.z - - local n2x = pos2.x - local n2y = pos2.y - local n2z = pos2.z - - local data = vm:get_data() - for z = n1z, n2z do - for y = n1y, n2y do - for x = n1x, n2x do - if x ~= nx or y ~= ny or z ~= nz then - local vi = a:index(x, y, z) - local name = minetest.get_name_from_content_id(data[vi]) - local node = minetest.registered_nodes[name] - if node.on_construct_node_near_by then - node.on_construct_node_near_by({x=x,y=y,z=z},lpos) - end - end - end - end - end -end - -local function on_construct_override2(pos) - local lpos = pos - local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} - local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} - - local vm = minetest.get_voxel_manip() - - local emin, emax = vm:read_from_map(pos1, pos2) - local a = VoxelArea:new{ - MinEdge = emin, - MaxEdge = emax - } - - local nx = lpos.x - local ny = lpos.y - local nz = lpos.z - - local n1x = pos1.x - local n1y = pos1.y - local n1z = pos1.z - - local n2x = pos2.x - local n2y = pos2.y - local n2z = pos2.z - - local data = vm:get_data() - for z = n1z, n2z do - for y = n1y, n2y do - for x = n1x, n2x do - local vi = a:index(x, y, z) - local name = minetest.get_name_from_content_id(data[vi]) - local node = minetest.registered_nodes[name] - if x ~= nx or y ~= ny or z ~= nz then - if node.on_construct_node_near_by then - node.on_construct_node_near_by({x=x,y=y,z=z},lpos) - end - else - node.exa_old_on_construct(lpos) - end - end - end - end -end --- End - --- on_destruct_node_near_by(pos,destructed_pos) -local function on_destruct_override(pos) - local lpos = pos - local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} - local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} - - local vm = minetest.get_voxel_manip() - - local emin, emax = vm:read_from_map(pos1, pos2) - local a = VoxelArea:new{ - MinEdge = emin, - MaxEdge = emax - } - - local nx = lpos.x - local ny = lpos.y - local nz = lpos.z - - local n1x = pos1.x - local n1y = pos1.y - local n1z = pos1.z - - local n2x = pos2.x - local n2y = pos2.y - local n2z = pos2.z - - local data = vm:get_data() - for z = n1z, n2z do - for y = n1y, n2y do - for x = n1x, n2x do - if x ~= nx or y ~= ny or z ~= nz then - local vi = a:index(x, y, z) - local name = minetest.get_name_from_content_id(data[vi]) - local node = minetest.registered_nodes[name] - if node.on_destruct_node_near_by then - node.on_destruct_node_near_by({x=x,y=y,z=z},lpos) - end - end - end - end - end -end - -local function on_destruct_override2(pos) - local lpos = pos - local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} - local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} - - local vm = minetest.get_voxel_manip() - - local emin, emax = vm:read_from_map(pos1, pos2) - local a = VoxelArea:new{ - MinEdge = emin, - MaxEdge = emax - } - - local nx = lpos.x - local ny = lpos.y - local nz = lpos.z - - local n1x = pos1.x - local n1y = pos1.y - local n1z = pos1.z - - local n2x = pos2.x - local n2y = pos2.y - local n2z = pos2.z - - local data = vm:get_data() - for z = n1z, n2z do - for y = n1y, n2y do - for x = n1x, n2x do - local vi = a:index(x, y, z) - local name = minetest.get_name_from_content_id(data[vi]) - local node = minetest.registered_nodes[name] - if x ~= nx or y ~= ny or z ~= nz then - if node.on_destruct_node_near_by then - node.on_destruct_node_near_by({x=x,y=y,z=z},lpos) - end - else - node.exa_old_on_destruct(lpos) - end - end - end - end -end --- End - -minetest.after(0, -function() - for n, d in pairs(minetest.registered_nodes) do - local cn = {} - for k,v in pairs(minetest.registered_nodes[n]) do cn[k] = v end - -- on_construct_node_near_by(pos,other_pos) - local on_con = cn.on_construct - if on_con then - cn.exa_old_on_construct = on_con - on_con = on_construct_override2 - else - on_con = on_construct_override - end - cn.on_construct = on_con - -- on_destruct_node_near_by(pos,other_pos) - local on_dis = cn.on_destruct - if on_dis then - cn.exa_old_on_destruct = on_dis - on_dis = on_destruct_override2 - else - on_dis = on_destruct_override - end - cn.on_destruct = on_con - minetest.register_node(":"..n,cn) - end -end) \ No newline at end of file +modpath = minetest.get_modpath("extended_api") +dofile(string.format("%s/node_funcs.lua",modpath)) +dofile(string.format("%s/async.lua",modpath)) \ No newline at end of file diff --git a/node_funcs.lua b/node_funcs.lua new file mode 100644 index 0000000..c64ddcd --- /dev/null +++ b/node_funcs.lua @@ -0,0 +1,202 @@ +-- on_construct_node_near_by(pos,constructed_pos) +local function on_construct_override(pos) + local lpos = pos + local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} + local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} + + local vm = minetest.get_voxel_manip() + + local emin, emax = vm:read_from_map(pos1, pos2) + local a = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax + } + + local nx = lpos.x + local ny = lpos.y + local nz = lpos.z + + local n1x = pos1.x + local n1y = pos1.y + local n1z = pos1.z + + local n2x = pos2.x + local n2y = pos2.y + local n2z = pos2.z + + local data = vm:get_data() + for z = n1z, n2z do + for y = n1y, n2y do + for x = n1x, n2x do + if x ~= nx or y ~= ny or z ~= nz then + local vi = a:index(x, y, z) + local name = minetest.get_name_from_content_id(data[vi]) + local node = minetest.registered_nodes[name] + if node.on_construct_node_near_by then + node.on_construct_node_near_by({x=x,y=y,z=z},lpos) + end + end + end + end + end +end + +local function on_construct_override2(pos) + local lpos = pos + local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} + local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} + + local vm = minetest.get_voxel_manip() + + local emin, emax = vm:read_from_map(pos1, pos2) + local a = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax + } + + local nx = lpos.x + local ny = lpos.y + local nz = lpos.z + + local n1x = pos1.x + local n1y = pos1.y + local n1z = pos1.z + + local n2x = pos2.x + local n2y = pos2.y + local n2z = pos2.z + + local data = vm:get_data() + for z = n1z, n2z do + for y = n1y, n2y do + for x = n1x, n2x do + local vi = a:index(x, y, z) + local name = minetest.get_name_from_content_id(data[vi]) + local node = minetest.registered_nodes[name] + if x ~= nx or y ~= ny or z ~= nz then + if node.on_construct_node_near_by then + node.on_construct_node_near_by({x=x,y=y,z=z},lpos) + end + else + node.exa_old_on_construct(lpos) + end + end + end + end +end +-- End + +-- on_destruct_node_near_by(pos,destructed_pos) +local function on_destruct_override(pos) + local lpos = pos + local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} + local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} + + local vm = minetest.get_voxel_manip() + + local emin, emax = vm:read_from_map(pos1, pos2) + local a = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax + } + + local nx = lpos.x + local ny = lpos.y + local nz = lpos.z + + local n1x = pos1.x + local n1y = pos1.y + local n1z = pos1.z + + local n2x = pos2.x + local n2y = pos2.y + local n2z = pos2.z + + local data = vm:get_data() + for z = n1z, n2z do + for y = n1y, n2y do + for x = n1x, n2x do + if x ~= nx or y ~= ny or z ~= nz then + local vi = a:index(x, y, z) + local name = minetest.get_name_from_content_id(data[vi]) + local node = minetest.registered_nodes[name] + if node.on_destruct_node_near_by then + node.on_destruct_node_near_by({x=x,y=y,z=z},lpos) + end + end + end + end + end +end + +local function on_destruct_override2(pos) + local lpos = pos + local pos1 = {x=lpos.x-1,y=lpos.y-1,z=lpos.z-1} + local pos2 = {x=lpos.x+1,y=lpos.y+1,z=lpos.z+1} + + local vm = minetest.get_voxel_manip() + + local emin, emax = vm:read_from_map(pos1, pos2) + local a = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax + } + + local nx = lpos.x + local ny = lpos.y + local nz = lpos.z + + local n1x = pos1.x + local n1y = pos1.y + local n1z = pos1.z + + local n2x = pos2.x + local n2y = pos2.y + local n2z = pos2.z + + local data = vm:get_data() + for z = n1z, n2z do + for y = n1y, n2y do + for x = n1x, n2x do + local vi = a:index(x, y, z) + local name = minetest.get_name_from_content_id(data[vi]) + local node = minetest.registered_nodes[name] + if x ~= nx or y ~= ny or z ~= nz then + if node.on_destruct_node_near_by then + node.on_destruct_node_near_by({x=x,y=y,z=z},lpos) + end + else + node.exa_old_on_destruct(lpos) + end + end + end + end +end +-- End + +minetest.after(0, +function() + for n, d in pairs(minetest.registered_nodes) do + local cn = {} + for k,v in pairs(minetest.registered_nodes[n]) do cn[k] = v end + -- on_construct_node_near_by(pos,other_pos) + local on_con = cn.on_construct + if on_con then + cn.exa_old_on_construct = on_con + on_con = on_construct_override2 + else + on_con = on_construct_override + end + cn.on_construct = on_con + -- on_destruct_node_near_by(pos,other_pos) + local on_dis = cn.on_destruct + if on_dis then + cn.exa_old_on_destruct = on_dis + on_dis = on_destruct_override2 + else + on_dis = on_destruct_override + end + cn.on_destruct = on_con + minetest.register_node(":"..n,cn) + end +end) \ No newline at end of file