Use VoxelManipulators for get_node_force.

A VoxelManipulator, when asked to read a mapblock, in addition to making
that mapblock available to the caller, also pulls it into the server’s
map cache, thus making get_node calls in the immediate future succeed.

This has the dual advantages that not every mapblock containing a
Mesecons circuit need remain loaded at all times (rather mapblocks can
be loaded on demand as signals are sent), and that the server need not
bother running ABMs and ticking entities within those mapblocks that are
loaded due to Mesecons signalling.
This commit is contained in:
Christopher Head 2016-08-20 21:48:18 -07:00
parent 912f17f335
commit 564cee346a
No known key found for this signature in database
GPG Key ID: E3188720C4CCDD7E

@ -236,43 +236,25 @@ local function unhash_blockpos(hash)
return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE) return vector.multiply(minetest.get_position_from_hash(hash), BLOCKSIZE)
end end
mesecon.forceloaded_blocks = {}
-- get node and force-load area -- get node and force-load area
function mesecon.get_node_force(pos) function mesecon.get_node_force(pos)
local hash = hash_blockpos(pos) local node = minetest.get_node_or_nil(pos)
if node == nil then
if mesecon.forceloaded_blocks[hash] == nil then -- Node is not currently loaded; use a VoxelManipulator to prime
-- if no more forceload spaces are available, try again next time -- the mapblock cache and try again.
if minetest.forceload_block(pos) then minetest.get_voxel_manip(pos, pos)
mesecon.forceloaded_blocks[hash] = 0 node = minetest.get_node_or_nil(pos)
end end
else return node
mesecon.forceloaded_blocks[hash] = 0
end
return minetest.get_node_or_nil(pos)
end end
minetest.register_globalstep(function (dtime) -- Un-forceload any forceloaded mapblocks from older versions of Mesecons which
for hash, time in pairs(mesecon.forceloaded_blocks) do -- used forceloading instead of VoxelManipulators.
-- unload forceloaded blocks after 10 minutes without usage local old_forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
if (time > mesecon.setting("forceload_timeout", 600)) then for hash, _ in pairs(old_forceloaded_blocks) do
minetest.forceload_free_block(unhash_blockpos(hash)) minetest.forceload_free_block(unhash_blockpos(hash))
mesecon.forceloaded_blocks[hash] = nil end
else os.remove(wpath..DIR_DELIM.."mesecon_forceloaded")
mesecon.forceloaded_blocks[hash] = time + dtime
end
end
end)
-- Store and read the forceloaded blocks to / from a file
-- so that those blocks are remembered when the game
-- is restarted
mesecon.forceloaded_blocks = mesecon.file2table("mesecon_forceloaded")
minetest.register_on_shutdown(function()
mesecon.table2file("mesecon_forceloaded", mesecon.forceloaded_blocks)
end)
-- Autoconnect Hooks -- Autoconnect Hooks
-- Nodes like conductors may change their appearance and their connection rules -- Nodes like conductors may change their appearance and their connection rules