From 84b94eb19804484b689cec441e175628fd10335f Mon Sep 17 00:00:00 2001 From: Novatux Date: Sat, 11 Jan 2014 17:54:00 +0100 Subject: [PATCH] Add forceloading --- builtin/builtin.lua | 1 + builtin/forceloading.lua | 79 ++++++++++++++++++++++++++++++++++++ builtin/misc.lua | 10 +++++ doc/lua_api.txt | 9 ++++ minetest.conf.example | 2 + src/environment.cpp | 2 +- src/environment.h | 3 ++ src/script/lua_api/l_env.cpp | 23 +++++++++++ src/script/lua_api/l_env.h | 8 ++++ 9 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 builtin/forceloading.lua diff --git a/builtin/builtin.lua b/builtin/builtin.lua index 99242f3d2..dc428220a 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -34,3 +34,4 @@ dofile(modpath.."/falling.lua") dofile(modpath.."/features.lua") dofile(modpath.."/voxelarea.lua") dofile(modpath.."/vector.lua") +dofile(modpath.."/forceloading.lua") diff --git a/builtin/forceloading.lua b/builtin/forceloading.lua new file mode 100644 index 000000000..021de075b --- /dev/null +++ b/builtin/forceloading.lua @@ -0,0 +1,79 @@ +-- Prevent anyone else accessing those functions +local forceload_block = minetest.forceload_block +local forceload_free_block = minetest.forceload_free_block +minetest.forceload_block = nil +minetest.forceload_free_block = nil + +local blocks_forceloaded +local total_forceloaded = 0 + +local BLOCKSIZE = 16 +local function get_blockpos(pos) + return { + x = math.floor(pos.x/BLOCKSIZE), + y = math.floor(pos.y/BLOCKSIZE), + z = math.floor(pos.z/BLOCKSIZE)} +end + +function minetest.forceload_block(pos) + local blockpos = get_blockpos(pos) + local hash = minetest.hash_node_position(blockpos) + if blocks_forceloaded[hash] ~= nil then + blocks_forceloaded[hash] = blocks_forceloaded[hash] + 1 + return true + else + if total_forceloaded >= (minetest.setting_get("max_forceloaded_blocks") or 16) then + return false + end + total_forceloaded = total_forceloaded+1 + blocks_forceloaded[hash] = 1 + forceload_block(blockpos) + return true + end +end + +function minetest.forceload_free_block(pos) + local blockpos = get_blockpos(pos) + local hash = minetest.hash_node_position(blockpos) + if blocks_forceloaded[hash] == nil then return end + if blocks_forceloaded[hash] > 1 then + blocks_forceloaded[hash] = blocks_forceloaded[hash] - 1 + else + total_forceloaded = total_forceloaded-1 + blocks_forceloaded[hash] = nil + forceload_free_block(blockpos) + end +end + +-- Keep the forceloaded areas after restart +local wpath = minetest.get_worldpath() +local function read_file(filename) + local f = io.open(filename, "r") + if f==nil then return {} end + local t = f:read("*all") + f:close() + if t=="" or t==nil then return {} end + return minetest.deserialize(t) +end + +local function write_file(filename, table) + local f = io.open(filename, "w") + f:write(minetest.serialize(table)) + f:close() +end + +blocks_forceloaded = read_file(wpath.."/force_loaded.txt") +for _, __ in pairs(blocks_forceloaded) do + total_forceloaded = total_forceloaded + 1 +end + +minetest.after(5, function() + for hash, _ in pairs(blocks_forceloaded) do + local blockpos = minetest.get_position_from_hash(hash) + forceload_block(blockpos) + end +end) + +minetest.register_on_shutdown(function() + write_file(wpath.."/force_loaded.txt", blocks_forceloaded) +end) diff --git a/builtin/misc.lua b/builtin/misc.lua index fd80aacf6..1d5e146c6 100644 --- a/builtin/misc.lua +++ b/builtin/misc.lua @@ -64,6 +64,16 @@ function minetest.hash_node_position(pos) return (pos.z+32768)*65536*65536 + (pos.y+32768)*65536 + pos.x+32768 end +function minetest.get_position_from_hash(hash) + local pos = {} + pos.x = (hash%65536) - 32768 + hash = math.floor(hash/65536) + pos.y = (hash%65536) - 32768 + hash = math.floor(hash/65536) + pos.z = (hash%65536) - 32768 + return pos +end + function minetest.get_item_group(name, group) if not minetest.registered_items[name] or not minetest.registered_items[name].groups[group] then diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f4bc95786..4e73136de 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1590,6 +1590,15 @@ minetest.rotate_node(itemstack, placer, pointed_thing) the creative mode setting, and checks for "sneak" to set the invert_wall parameter. +minetest.forceload_block(pos) +^ forceloads the position pos. +^ returns true if area could be forceloaded + +minetest.forceload_free_block(pos) +^ stops forceloading the position pos. + +Please note that forceloaded areas are saved when the server restarts. + Global objects: minetest.env - EnvRef of the server environment and world. ^ Any function in the minetest namespace can be called using the syntax diff --git a/minetest.conf.example b/minetest.conf.example index e63bd70f7..1279e81d0 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -301,6 +301,8 @@ # This is a trade-off between sqlite transaction overhead and # memory consumption (4096=100MB, as a rule of thumb) #max_clearobjects_extra_loaded_blocks = 4096 +# Maximum number of forceloaded blocks +#max_forceloaded_blocks = 16 # Interval of sending time of day to clients #time_send_interval = 5 # Length of day/night cycle. 72=20min, 360=4min, 1=24hour, 0=day/night/whatever stays unchanged diff --git a/src/environment.cpp b/src/environment.cpp index 7fe5d356a..034db00d5 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -258,7 +258,7 @@ void ActiveBlockList::update(std::list &active_positions, /* Create the new list */ - std::set newlist; + std::set newlist = m_forceloaded_list; for(std::list::iterator i = active_positions.begin(); i != active_positions.end(); ++i) { diff --git a/src/environment.h b/src/environment.h index d9804e781..e439b2ef5 100644 --- a/src/environment.h +++ b/src/environment.h @@ -170,6 +170,7 @@ public: } std::set m_list; + std::set m_forceloaded_list; private: }; @@ -305,6 +306,8 @@ public: // is weather active in this environment? bool m_use_weather; + std::set* getForceloadedBlocks() { return &m_active_blocks.m_forceloaded_list; }; + private: /* diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index d01889401..f75334750 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -798,6 +798,27 @@ int ModApiEnvMod::l_get_humidity(lua_State *L) return 1; } +// minetest.forceload_block(blockpos) +// blockpos = {x=num, y=num, z=num} +int ModApiEnvMod::l_forceload_block(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 blockpos = read_v3s16(L, 1); + env->getForceloadedBlocks()->insert(blockpos); + return 0; +} + +// minetest.forceload_free_block(blockpos) +// blockpos = {x=num, y=num, z=num} +int ModApiEnvMod::l_forceload_free_block(lua_State *L) +{ + GET_ENV_PTR; + + v3s16 blockpos = read_v3s16(L, 1); + env->getForceloadedBlocks()->erase(blockpos); + return 0; +} void ModApiEnvMod::Initialize(lua_State *L, int top) { @@ -836,4 +857,6 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(transforming_liquid_add); API_FCT(get_heat); API_FCT(get_humidity); + API_FCT(forceload_block); + API_FCT(forceload_free_block); } diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 126349c6e..7e1cabe3f 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -151,6 +151,14 @@ private: static int l_get_heat(lua_State *L); static int l_get_humidity(lua_State *L); + // minetest.forceload_block(blockpos) + // forceloads a block + static int l_forceload_block(lua_State *L); + + // minetest.forceload_free_block(blockpos) + // stops forceloading a position + static int l_forceload_free_block(lua_State *L); + public: static void Initialize(lua_State *L, int top); };