123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- --[[
- 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, key)
- 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 and node_key ~= "used" and node_key ~= "best_before" then
- if key == nil or (type(mem) == "table" and mem[key] ~= nil) then
- local pos = keys_to_pos(block_key, node_key)
- local node = tubelib2.get_node_lvm(pos)
- if key ~= nil then
- -- only specified 'key'
- clbk(pos, node, {[key] = mem[key]})
- else
- -- without specified 'key'
- clbk(pos, node, mem)
- end
- end
- end
- end
- end
- end
|