147 lines
3.7 KiB
Lua
147 lines
3.7 KiB
Lua
|
--[[
|
||
|
|
||
|
Tube Library 2
|
||
|
==============
|
||
|
|
||
|
Copyright (C) 2017-2020 Joachim Stolberg
|
||
|
|
||
|
LGPLv2.1+
|
||
|
See LICENSE.txt for more information
|
||
|
|
||
|
storage.lua
|
||
|
|
||
|
]]--
|
||
|
|
||
|
--
|
||
|
-- Data maintenance
|
||
|
--
|
||
|
local MemStore = {}
|
||
|
local storage = minetest.get_mod_storage()
|
||
|
|
||
|
local function update_mod_storage()
|
||
|
local gametime = minetest.get_gametime()
|
||
|
for k,v in pairs(MemStore) do
|
||
|
if v.used then
|
||
|
v.used = false
|
||
|
v.best_before = gametime + (60 * 30) -- 30 min
|
||
|
storage:set_string(k, minetest.serialize(v))
|
||
|
elseif v.best_before < gametime then
|
||
|
storage:set_string(k, minetest.serialize(v))
|
||
|
MemStore[k] = nil -- remove from memory
|
||
|
end
|
||
|
end
|
||
|
-- run every 10 minutes
|
||
|
minetest.after(600, update_mod_storage)
|
||
|
end
|
||
|
|
||
|
minetest.register_on_shutdown(function()
|
||
|
for k,v in pairs(MemStore) do
|
||
|
storage:set_string(k, minetest.serialize(v))
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
minetest.after(600, update_mod_storage)
|
||
|
|
||
|
local function empty_block(block)
|
||
|
local empty = true
|
||
|
local tbl = minetest.deserialize(block)
|
||
|
for k,v in pairs(tbl) do
|
||
|
if k ~= "used" and k ~= "best_before" then
|
||
|
empty = false
|
||
|
end
|
||
|
end
|
||
|
return empty
|
||
|
end
|
||
|
|
||
|
minetest.after(1, function()
|
||
|
local tbl = storage:to_table()
|
||
|
for k,v in pairs(tbl.fields) do
|
||
|
if empty_block(v) then
|
||
|
storage:set_string(k, "")
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
--
|
||
|
-- Local helper functions
|
||
|
--
|
||
|
local function new_block(block_key)
|
||
|
local data = storage:get_string(block_key)
|
||
|
if data == nil or data == "" then -- TODO: change for v5
|
||
|
MemStore[block_key] = {}
|
||
|
else
|
||
|
MemStore[block_key] = minetest.deserialize(data)
|
||
|
end
|
||
|
return MemStore[block_key]
|
||
|
end
|
||
|
|
||
|
local function new_node(block, node_key)
|
||
|
block[node_key] = {}
|
||
|
return block[node_key]
|
||
|
end
|
||
|
|
||
|
local function unlock(pos)
|
||
|
local block_key = math.floor((pos.z+32768)/16)*4096*4096 +
|
||
|
math.floor((pos.y+32768)/16)*4096 + math.floor((pos.x+32768)/16)
|
||
|
local node_key = (pos.z%16)*16*16 + (pos.y%16)*16 + (pos.x%16)
|
||
|
local block = MemStore[block_key] or new_block(block_key)
|
||
|
block.used = true
|
||
|
return block, node_key
|
||
|
end
|
||
|
|
||
|
local function keys_to_pos(block_key, node_key)
|
||
|
local f = math.floor
|
||
|
block_key = tonumber(block_key) or 0
|
||
|
node_key = tonumber(node_key) or 0
|
||
|
local x = ((f(block_key % 0x1000) * 0x10) - 32768) + (node_key % 0x10)
|
||
|
block_key, node_key = f(block_key / 0x1000), f(node_key / 0x10)
|
||
|
local y = ((f(block_key % 0x1000) * 0x10) - 32768) + (node_key % 0x10)
|
||
|
block_key, node_key = f(block_key / 0x1000), f(node_key / 0x10)
|
||
|
local z = ((f(block_key % 0x1000) * 0x10) - 32768) + (node_key % 0x10)
|
||
|
return {x = x, y = y, z = z}
|
||
|
end
|
||
|
|
||
|
-------------------------------------------------------------------------------
|
||
|
-- API functions for a node related and high efficient storage table
|
||
|
-- for all kind of node data.
|
||
|
-------------------------------------------------------------------------------
|
||
|
|
||
|
-- To be called when a node is placed
|
||
|
function tubelib2.init_mem(pos)
|
||
|
local block, node_key = unlock(pos)
|
||
|
return new_node(block, node_key)
|
||
|
end
|
||
|
|
||
|
-- To get the node data table
|
||
|
function tubelib2.get_mem(pos)
|
||
|
local block, node_key = unlock(pos)
|
||
|
return block[node_key] or new_node(block, node_key)
|
||
|
end
|
||
|
|
||
|
-- To be called when a node is removed
|
||
|
function tubelib2.del_mem(pos)
|
||
|
local block, node_key = unlock(pos)
|
||
|
block[node_key] = nil
|
||
|
end
|
||
|
|
||
|
-- Read a value, or return the default value if not available
|
||
|
function tubelib2.get_mem_data(pos, key, default)
|
||
|
return tubelib2.get_mem(pos)[key] or default
|
||
|
end
|
||
|
|
||
|
function tubelib2.walk_over_all(clbk)
|
||
|
local data = storage:to_table()
|
||
|
for block_key,sblock in pairs(data.fields) do
|
||
|
local block = minetest.deserialize(sblock)
|
||
|
for node_key,mem in pairs(block) do
|
||
|
if mem then
|
||
|
if node_key ~= "used" and node_key ~= "best_before" then
|
||
|
local pos = keys_to_pos(block_key, node_key)
|
||
|
local node = tubelib2.get_node_lvm(pos)
|
||
|
clbk(pos, node, mem)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|