v0.9 storage added

This commit is contained in:
Joachim Stolberg 2019-02-09 11:04:42 +01:00
parent 68e9abcd93
commit 5cd7ea6f3d
6 changed files with 197 additions and 106 deletions

@ -70,4 +70,5 @@ Textures: CC0
- 2018-12-20 v0.6 * intllib support added, max tube length bugfix
- 2019-01-06 v0.7 * API function replace_tube_line added, bug fixed
- 2019-01-11 v0.8 * dir_to_facedir bugfix
- 2019-02-09 v0.9 * storage.lua added, code partly restructured

@ -7,5 +7,6 @@ dofile(MP .. "/intllib.lua")
dofile(MP .. "/internal2.lua")
dofile(MP .. "/internal1.lua")
dofile(MP .. "/tube_api.lua")
dofile(MP .. "/storage.lua")
-- Only for testing/demo purposes
--dofile(MP .. "/tube_test.lua")

@ -21,24 +21,17 @@ local M = minetest.get_meta
-- Load support for intllib.
local MP = minetest.get_modpath("tubelib2")
local I,IS = dofile(MP.."/intllib.lua")
local I,_ = dofile(MP.."/intllib.lua")
local Tube = tubelib2.Tube
local Turn180Deg = tubelib2.Turn180Deg
local Dir6dToVector = tubelib2.Dir6dToVector
local encode_param2 = tubelib2.encode_param2
local tValidNum = {[0] = true, true, true} -- 0..2 are valid
local function get_pos(pos, dir)
return vector.add(pos, Dir6dToVector[dir or 0])
end
-- format and return given data as table
local function get_tube_data(pos, dir1, dir2, num_tubes)
local param2, tube_type = encode_param2(dir1, dir2, num_tubes)
return pos, param2, tube_type, num_tubes
end
local function fdir(self, player)
local pitch = player:get_look_pitch()
if pitch > 1.0 and self.valid_dirs[6] then -- up?
@ -70,7 +63,7 @@ end
function Tube:get_primary_dir(pos)
-- Check all valid positions
for dir = 1,6 do
if self:primary_node(pos, dir) then
if self:is_primary_node(pos, dir) then
return dir
end
end
@ -148,7 +141,7 @@ function Tube:update_after_place_node(pos, dirs)
for _,dir in ipairs(dirs) do
local npos, d1, d2, num = self:add_tube_dir(pos, dir)
if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num]then
self.clbk_after_place_tube(get_tube_data(npos, d1, d2, num))
self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
lRes[#lRes+1] = dir
end
end
@ -162,7 +155,7 @@ function Tube:update_after_dig_node(pos, dirs)
for _,dir in ipairs(dirs) do
local npos, d1, d2, num = self:del_tube_dir(pos, dir)
if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num]then
self.clbk_after_place_tube(get_tube_data(npos, d1, d2, num))
self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
lRes[#lRes+1] = dir
end
end
@ -176,20 +169,20 @@ function Tube:update_after_place_tube(pos, placer, pointed_thing)
return false
end
if self.valid_dirs[dir1] and self.valid_dirs[dir2] and tValidNum[num_tubes]then
self.clbk_after_place_tube(get_tube_data(pos, dir1, dir2, num_tubes))
self.clbk_after_place_tube(self:get_tube_data(pos, dir1, dir2, num_tubes))
end
if num_tubes >= 1 then
local npos, d1, d2, num = self:add_tube_dir(pos, dir1)
if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num]then
self.clbk_after_place_tube(get_tube_data(npos, d1, d2, num))
self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
end
end
if num_tubes >= 2 then
local npos, d1, d2, num = self:add_tube_dir(pos, dir2)
if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num]then
self.clbk_after_place_tube(get_tube_data(npos, d1, d2, num))
self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
end
end
return true, dir1, dir2, num_tubes
@ -200,14 +193,14 @@ function Tube:update_after_dig_tube(pos, param2)
local npos, d1, d2, num = self:del_tube_dir(pos, dir1)
if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num]then
self.clbk_after_place_tube(get_tube_data(npos, d1, d2, num))
self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
else
dir1 = nil
end
npos, d1, d2, num = self:del_tube_dir(pos, dir2)
if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num]then
self.clbk_after_place_tube(get_tube_data(npos, d1, d2, num))
self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
else
dir2 = nil
end
@ -217,12 +210,12 @@ end
-- Used by chat commands, when tubes are placed e.g. via WorldEdit
function Tube:replace_nodes(pos1, pos2, dir1, dir2)
self.clbk_after_place_tube(get_tube_data(pos1, dir1, dir2, 1))
self.clbk_after_place_tube(self:get_tube_data(pos1, dir1, dir2, 1))
local pos = get_pos(pos1, dir1)
while not vector.equals(pos, pos2) do
self.clbk_after_place_tube(get_tube_data(pos, dir1, dir2, 2))
self.clbk_after_place_tube(self:get_tube_data(pos, dir1, dir2, 2))
pos = get_pos(pos, dir1)
end
self.clbk_after_place_tube(get_tube_data(pos2, dir1, dir2, 1))
self.clbk_after_place_tube(self:get_tube_data(pos2, dir1, dir2, 1))
end

@ -21,9 +21,10 @@ local M = minetest.get_meta
local MP = minetest.get_modpath("tubelib2")
local I,IS = dofile(MP.."/intllib.lua")
local Tube = {}
local Turn180Deg = {[0]=0,3,4,1,2,6,5}
tubelib2.Turn180Deg = Turn180Deg
tubelib2.Tube = {}
-- To calculate param2 based on dir6d information
local DirToParam2 = {
@ -62,8 +63,6 @@ local Dir6dToVector = {[0] =
{x=0, y=1, z=0},
}
tubelib2.Dir6dToVector = Dir6dToVector
local VectorToDir6d = {
[{x=0, y=0, z=1}] = 1,
[{x=1, y=0, z=0}] = 2,
@ -74,11 +73,19 @@ local VectorToDir6d = {
}
tubelib2.Tube = Tube
tubelib2.Turn180Deg = Turn180Deg
tubelib2.DirToParam2 = DirToParam2
tubelib2.Param2ToDir = Param2ToDir
tubelib2.Dir6dToVector = Dir6dToVector
tubelib2.VectorToDir6d = VectorToDir6d
--
-- Local Functions
-- Tubelib2 Methods
--
local function get_node_lvm(pos)
function Tube:get_node_lvm(pos)
local node = minetest.get_node_or_nil(pos)
if node then
return node
@ -96,65 +103,32 @@ local function get_node_lvm(pos)
return node
end
local function get_next_tube(self, pos, dir)
-- Read param2 from a primary node at the given position.
-- If dir == nil then node_pos = pos
-- Function returns param2, new_pos or nil
function Tube:get_primary_node_param2(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0])
local node = get_node_lvm(npos)
local node = self:get_node_lvm(npos)
if self.primary_node_names[node.name] then
-- decode param2
local val = Param2ToDir[node.param2 % 32]
if val then
local dir1, dir2 = math.floor(val / 10), val % 10
local num_conn = math.floor(node.param2 / 32)
if Turn180Deg[dir] == dir1 then
return npos, dir2, num_conn
else
return npos, dir1, num_conn
end
end
end
return self:get_next_teleport_node(pos, dir)
end
local function repair_tube(self, pos, dir)
local node = get_node_lvm(pos, dir)
if self.primary_node_names[node.name] then
local dir1, dir2 = self:decode_param2(pos, node.param2)
local param2, tube_type = tubelib2.encode_param2(dir1, dir2, 2)
self.clbk_after_place_tube(pos, param2, tube_type, 2)
return node.param2, npos
end
end
-- Return param2 and tube type ("A"/"S")
function tubelib2.encode_param2(dir1, dir2, num_conn)
if dir1 > dir2 then
dir1, dir2 = dir2, dir1
end
local param2, _type = unpack(DirToParam2[dir1 * 10 + dir2] or {0, "S"})
return (num_conn * 32) + param2, _type
end
--
-- Tubelib2 Methods
--
local Tube = tubelib2.Tube
-- Check if node at given position is a tube node
-- If dir == nil then node_pos = pos
-- Function returns the new pos or nil
function Tube:primary_node(pos, dir)
local npos, node = self:get_node(pos, dir)
if self.primary_node_names[node.name] then
return npos, node
end
-- Function returns true/false
function Tube:is_primary_node(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0])
local node = self:get_node_lvm(npos)
return self.primary_node_names[node.name]
end
-- Check if node at given position is a secondary node
-- If dir == nil then node_pos = pos
-- Function returns the new pos or nil
function Tube:secondary_node(pos, dir)
local npos, node = self:get_node(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0])
local node = self:get_node_lvm(npos)
if self.secondary_node_names[node.name] then
return npos
end
@ -162,12 +136,34 @@ end
-- Check if node has a connection on the given dir
function Tube:connected(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0])
local node = get_node_lvm(npos)
return self.primary_node_names[node.name]
or self.secondary_node_names[node.name]
return self:is_primary_node(pos, dir) or self:secondary_node(pos, dir)
end
function Tube:get_next_tube(pos, dir)
local param2, npos = self:get_primary_node_param2(pos, dir)
if param2 then
local val = Param2ToDir[param2 % 32]
local dir1, dir2 = math.floor(val / 10), val % 10
local num_conn = math.floor(param2 / 32)
if Turn180Deg[dir] == dir1 then
return npos, dir2, num_conn
else
return npos, dir1, num_conn
end
end
return self:get_next_teleport_node(pos, dir)
end
-- Return param2 and tube type ("A"/"S")
function Tube:encode_param2(dir1, dir2, num_conn)
if dir1 > dir2 then
dir1, dir2 = dir2, dir1
end
local param2, _type = unpack(DirToParam2[dir1 * 10 + dir2] or {0, "S"})
return (num_conn * 32) + param2, _type
end
-- Return dir1, dir2, num_conn
function Tube:decode_param2(pos, param2)
local val = Param2ToDir[param2 % 32]
@ -178,17 +174,32 @@ function Tube:decode_param2(pos, param2)
end
end
function Tube:repair_tube(pos, dir)
local param2 = self:get_primary_node_param2(pos, dir)
if param2 then
local dir1, dir2 = self:decode_param2(pos, param2)
local param2, tube_type = self:encode_param2(dir1, dir2, 2)
self.clbk_after_place_tube(pos, param2, tube_type, 2)
end
end
-- Return node next to pos in direction 'dir'
function Tube:get_node(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0])
return npos, get_node_lvm(npos)
return npos, self:get_node_lvm(npos)
end
-- format and return given data as table
function Tube:get_tube_data(pos, dir1, dir2, num_tubes)
local param2, tube_type = self:encode_param2(dir1, dir2, num_tubes)
return pos, param2, tube_type, num_tubes
end
-- Return pos for a primary_node and true if num_conn < 2, else false
function Tube:friendly_primary_node(pos, dir)
local npos, node = self:get_node(pos, dir)
if self.primary_node_names[node.name] then
local _,_,num_conn = self:decode_param2(npos, node.param2)
local param2, npos = self:get_primary_node_param2(pos, dir)
if param2 then
local _,_,num_conn = self:decode_param2(npos, param2)
-- tube node with max one connection?
return npos, (num_conn or 2) < 2
end
@ -290,9 +301,9 @@ end
-- and return the new data to be able to update the node:
-- new_pos, dir1, dir2, num_connections (1, 2)
function Tube:add_tube_dir(pos, dir)
local npos, node = self:get_node(pos, dir)
if self.primary_node_names[node.name] then
local d1, d2, num = self:decode_param2(npos, node.param2)
local param2, npos = self:get_primary_node_param2(pos, dir)
if param2 then
local d1, d2, num = self:decode_param2(npos, param2)
if not num then return end
-- not already connected to the new tube?
dir = Turn180Deg[dir]
@ -316,9 +327,9 @@ end
-- and return the new data to be able to update the node:
-- new_pos, dir1, dir2, num_connections (0, 1)
function Tube:del_tube_dir(pos, dir)
local npos, node = self:get_node(pos, dir)
if self.primary_node_names[node.name] then
local d1, d2, num = self:decode_param2(npos, node.param2)
local param2, npos = self:get_primary_node_param2(pos, dir)
if param2 then
local d1, d2, num = self:decode_param2(npos, param2)
-- check if node is connected to the given pos
dir = Turn180Deg[dir]
if d1 == dir or dir == d2 then
@ -339,14 +350,16 @@ end
-- Jump over the teleport nodes to the next tube node
function Tube:get_next_teleport_node(pos, dir)
local npos = vector.add(pos, Dir6dToVector[dir or 0])
local meta = M(npos)
local s = meta:get_string("tele_pos")
if s ~= "" then
local tele_pos = P(s)
local tube_dir = M(tele_pos):get_int("tube_dir")
if tube_dir ~= 0 then
return tele_pos, tube_dir
if pos then
local npos = vector.add(pos, Dir6dToVector[dir or 0])
local meta = M(npos)
local s = meta:get_string("tele_pos")
if s ~= "" then
local tele_pos = P(s)
local tube_dir = M(tele_pos):get_int("tube_dir")
if tube_dir ~= 0 then
return tele_pos, tube_dir
end
end
end
end
@ -365,10 +378,10 @@ function Tube:walk_tube_line(pos, dir)
local cnt = 0
if dir then
while cnt <= self.max_tube_length do
local new_pos, new_dir, num = get_next_tube(self, pos, dir)
if not new_dir then break end
if cnt > 0 and num ~= 2 and self:primary_node(new_pos, new_dir) then
repair_tube(self, new_pos, new_dir)
local new_pos, new_dir, num = self:get_next_tube(pos, dir)
if not new_pos then break end
if cnt > 0 and num ~= 2 and self:is_primary_node(new_pos, new_dir) then
self:repair_tube(new_pos, new_dir)
end
pos, dir = new_pos, new_dir
cnt = cnt + 1

61
storage.lua Normal file

@ -0,0 +1,61 @@
--[[
Tube Library 2
==============
Copyright (C) 2017-2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
storage.lua
]]--
local MemStore = {}
local storage = minetest.get_mod_storage()
local function new_block(block_key)
MemStore[block_key] = minetest.deserialize(storage:get(block_key) or "return {}")
return MemStore[block_key]
end
local function new_node(block, node_key)
block[node_key] = {used = true}
return block[node_key]
end
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 + 10
storage:set_string(k, minetest.serialize(v))
elseif v.best_before < gametime then
storage:set_string(k, minetest.serialize(v))
MemStore[k] = nil
end
end
-- run every minute
minetest.after(60, update_mod_storage)
end
minetest.register_on_shutdown(function()
for k,v in ipairs(MemStore) do
storage:set_string(k, minetest.serialize(v))
end
end)
minetest.after(60, update_mod_storage)
-- API function for a node related and high efficient storage table
-- for all kind of node data.
function tubelib2.mem_load(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] or new_node(block, node_key)
end

@ -13,7 +13,7 @@
]]--
-- Version for compatibility checks, see readme.md/history
tubelib2.version = 0.8
tubelib2.version = 0.9
-- for lazy programmers
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
@ -21,7 +21,7 @@ local M = minetest.get_meta
-- Load support for intllib.
local MP = minetest.get_modpath("tubelib2")
local I,IS = dofile(MP.."/intllib.lua")
local I,_ = dofile(MP.."/intllib.lua")
local Dir2Str = {"north", "east", "south", "west", "down", "up"}
@ -112,6 +112,28 @@ local function update3(self, pos, dir1, dir2)
end
end
local function update4(self, pos, dirs)
dirs = dirs or self.dirs_to_check
for _,dir in ipairs(dirs) do
local npos = self:secondary_node(pos, dir)
if npos then
self:update_secondary_node(npos, Turn180Deg[dir], pos, dir)
self:update_secondary_node(pos, dir, npos, Turn180Deg[dir])
end
end
end
local function update5(self, pos, dirs)
dirs = dirs or self.dirs_to_check
for _,dir in ipairs(dirs) do
local npos = self:secondary_node(pos, dir)
if npos then
self:update_secondary_node(npos, Turn180Deg[dir])
self:update_secondary_node(pos, dir)
end
end
end
--
-- API Functions
--
@ -158,10 +180,9 @@ function Tube:after_place_node(pos, dirs)
for _,dir in ipairs(self:update_after_place_node(pos, dirs)) do
if pos and dir then
update1(self, pos, dir)
else
print("after_place_node", dump(pos), dir)
end
end
update4(self, pos, dirs)
end
-- To be called after a tube/primary node is placed.
@ -182,6 +203,7 @@ function Tube:after_dig_node(pos, dirs)
for _,dir in ipairs(self:update_after_dig_node(pos, dirs)) do
update1(self, pos, dir)
end
update5(self, pos, dirs)
end
-- To be called after a tube/primary node is removed.
@ -224,17 +246,17 @@ end
-- To be called from a repair tool in the case of a "WorldEdit" or with
-- legacy nodes corrupted tube line.
function Tube:tool_repair_tube(pos)
local _, node = self:primary_node(pos)
if node then
local dir1, dir2 = self:decode_param2(pos, node.param2)
local param2 = self:get_primary_node_param2(pos)
if param2 then
local dir1, dir2 = self:decode_param2(pos, param2)
return update3(self, pos, dir1, dir2)
end
end
-- To be called from a repair tool in the case, tube nodes are "unbreakable".
function Tube:tool_remove_tube(pos, sound)
local _,node = self:get_node(pos)
if self.primary_node_names[node.name] then
if self:is_primary_node(pos) then
local _,node = self:get_node(pos)
minetest.sound_play({name=sound},{
pos=pos,
gain=1,