Some changes:
- Extend data format to 2 byte content id and 1 byte param2 - add basic metadata support (just a table with the advantage that it is syncronized to ndb) - Remove leftovers from advtrainsmaster
parent
6bf400dd1a
commit
a44a507d0f
166
init.lua
166
init.lua
|
@ -8,8 +8,7 @@
|
|||
local mstore = minetest.get_mod_storage()
|
||||
|
||||
--serialization format:
|
||||
--(2byte z) (2byte y) (2byte x) (2byte contentid)
|
||||
--contentid := (14bit nodeid, 2bit param2)
|
||||
--(2byte z) (2byte y) (2byte x) (2byte contentid) (1byte param2)
|
||||
|
||||
local function int_to_bytes(i)
|
||||
local x=i+32768--clip to positive integers
|
||||
|
@ -17,6 +16,11 @@ local function int_to_bytes(i)
|
|||
local cL = math.floor(x ) % 256;
|
||||
return(string.char(cH, cL));
|
||||
end
|
||||
local function int_to_single_byte(i)
|
||||
local x=i
|
||||
local cL = math.floor(x ) % 256;
|
||||
return(string.char(cL));
|
||||
end
|
||||
local function bytes_to_int(bytes)
|
||||
local t={string.byte(bytes,1,-1)}
|
||||
local n =
|
||||
|
@ -24,20 +28,23 @@ local function bytes_to_int(bytes)
|
|||
t[2]
|
||||
return n-32768
|
||||
end
|
||||
local function l2b(x)
|
||||
return x%4
|
||||
end
|
||||
local function u14b(x)
|
||||
return math.floor(x/4)
|
||||
local function single_byte_to_int(bytes)
|
||||
local t={string.byte(bytes,1,-1)}
|
||||
local n =
|
||||
t[1]
|
||||
return n
|
||||
end
|
||||
local ndb={}
|
||||
|
||||
--local variables for performance
|
||||
local ndb_nodeids={}
|
||||
local ndb_nodes={}
|
||||
local ndb_nodecid={}
|
||||
local ndb_nodepar={}
|
||||
|
||||
local function ndbget(x,y,z)
|
||||
local ny=ndb_nodes[y]
|
||||
local ndb_nodemeta={}
|
||||
|
||||
local function ndbget(t,x,y,z)
|
||||
local ny=t[y]
|
||||
if ny then
|
||||
local nx=ny[x]
|
||||
if nx then
|
||||
|
@ -46,14 +53,14 @@ local function ndbget(x,y,z)
|
|||
end
|
||||
return nil
|
||||
end
|
||||
local function ndbset(x,y,z,v)
|
||||
if not ndb_nodes[y] then
|
||||
ndb_nodes[y]={}
|
||||
local function ndbset(t,x,y,z,v)
|
||||
if not t[y] then
|
||||
t[y]={}
|
||||
end
|
||||
if not ndb_nodes[y][x] then
|
||||
ndb_nodes[y][x]={}
|
||||
if not t[y][x] then
|
||||
t[y][x]={}
|
||||
end
|
||||
ndb_nodes[y][x][z]=v
|
||||
t[y][x][z]=v
|
||||
end
|
||||
|
||||
local path = minetest.get_worldpath().."/nplib_ndb"
|
||||
|
@ -61,12 +68,6 @@ local path = minetest.get_worldpath().."/nplib_ndb"
|
|||
local file, err = io.open(path, "r")
|
||||
if not file then
|
||||
minetest.log("error", "Couldn't load the node database: "..( err or "Unknown Error"))
|
||||
load_from_avt=true
|
||||
minetest.log("error", "Trying file: "..path_compat)
|
||||
file, err = io.open(path_compat, "r")
|
||||
if not file then
|
||||
minetest.log("error", "Couldn't load the node database from compatibility file: "..( err or "Unknown Error"))
|
||||
end
|
||||
end
|
||||
if file then
|
||||
local cnt=0
|
||||
|
@ -74,21 +75,26 @@ if file then
|
|||
local hst_y=file:read(2)
|
||||
local hst_x=file:read(2)
|
||||
local cid=file:read(2)
|
||||
local par=file:read(1)
|
||||
while hst_z and hst_y and hst_x and cid and #hst_z==2 and #hst_y==2 and #hst_x==2 and #cid==2 do
|
||||
ndbset(bytes_to_int(hst_x), bytes_to_int(hst_y), bytes_to_int(hst_z), bytes_to_int(cid))
|
||||
ndbset(ndb_nodecid, bytes_to_int(hst_x), bytes_to_int(hst_y), bytes_to_int(hst_z), bytes_to_int(cid))
|
||||
ndbset(ndb_nodepar, bytes_to_int(hst_x), bytes_to_int(hst_y), bytes_to_int(hst_z), single_byte_to_int(par))
|
||||
cnt=cnt+1
|
||||
hst_z=file:read(2)
|
||||
hst_y=file:read(2)
|
||||
hst_x=file:read(2)
|
||||
cid=file:read(2)
|
||||
par=file:read(1)
|
||||
end
|
||||
minetest.log("action", "[nplib] nodedb: read"..cnt.."nodes.")
|
||||
file:close()
|
||||
local mstorek = minetest.deserialize(mstore:get_string("nodeids"))
|
||||
if mstorek and not load_from_avt then then
|
||||
ndb_nodeids = mstorek
|
||||
local mstorek = minetest.deserialize(mstore:get_string("data"))
|
||||
if mstorek and mstorek.version==1 then
|
||||
ndb_nodeids = mstorek.ids
|
||||
ndb_meta = mstorek.meta
|
||||
else
|
||||
minetest.log("error", "[nplib] Could not load the node id's from the mod storage. To prevent a huge mess, the node database will be cleared.")
|
||||
minetest.log("error", "[nplib] Could not load the node ids and/or metadata from the mod storage (unreadable, unsupported version a.s.o.)")
|
||||
minetest.log("error", "[nplib] To prevent a huge mess, the node database will be cleared.")
|
||||
ndb_nodes={}
|
||||
ndb_nodeids={}
|
||||
end
|
||||
|
@ -97,6 +103,7 @@ end
|
|||
|
||||
function ndb.save_data()
|
||||
local file, err = io.open(path, "w")
|
||||
local par
|
||||
if not file then
|
||||
minetest.log("error", "Couldn't save the node database: "..( err or "Unknown Error"))
|
||||
else
|
||||
|
@ -107,19 +114,23 @@ function ndb.save_data()
|
|||
file:write(int_to_bytes(y))
|
||||
file:write(int_to_bytes(x))
|
||||
file:write(int_to_bytes(cid))
|
||||
par=ndbget(ndb_nodepar, x, y, z) or 0
|
||||
file:write(int_to_single_byte(par))
|
||||
end
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
mstore:set_string("nodeids", minetest.serialize(ndb_nodeids))
|
||||
local tmp = {
|
||||
version = 1,
|
||||
ids = ndb_nodeids,
|
||||
meta = ndb_nodemeta,
|
||||
}
|
||||
mstore:set_string("data", minetest.serialize(tmp))
|
||||
end
|
||||
|
||||
--function to get node.
|
||||
function ndb.get_node_or_nil(pos)
|
||||
-- FIX for bug found on linuxworks server:
|
||||
-- a loaded node might get read before the LBM has updated its state, resulting in wrongly set signals and switches
|
||||
-- -> Using the saved node prioritarily.
|
||||
local node = ndb.get_node_raw(pos)
|
||||
if node then
|
||||
return node
|
||||
|
@ -136,11 +147,12 @@ function ndb.get_node(pos)
|
|||
return n
|
||||
end
|
||||
function ndb.get_node_raw(pos)
|
||||
local cid=ndbget(pos.x, pos.y, pos.z)
|
||||
local cid=ndbget(ndb_nodecid, pos.x, pos.y, pos.z)
|
||||
if cid then
|
||||
local nodeid = ndb_nodeids[u14b(cid)]
|
||||
local nodeid = ndb_nodeids[cid]
|
||||
if nodeid then
|
||||
return {name=nodeid, param2 = l2b(cid)}
|
||||
local par=ndbget(ndb_nodepar, pos.x, pos.y, pos.z)
|
||||
return {name=nodeid, param2 = par}
|
||||
end
|
||||
end
|
||||
return nil
|
||||
|
@ -166,45 +178,45 @@ function ndb.update(pos, pnode)
|
|||
nid=#ndb_nodeids+1
|
||||
ndb_nodeids[nid]=node.name
|
||||
end
|
||||
ndbset(pos.x, pos.y, pos.z, (nid * 4) + (l2b(node.param2 or 0)) )
|
||||
ndbset(ndb_nodecid, pos.x, pos.y, pos.z, nid)
|
||||
ndbset(ndb_nodepar, pos.x, pos.y, pos.z, node.param2)
|
||||
else
|
||||
--at this position there is no longer a node that needs to be tracked.
|
||||
ndbset(pos.x, pos.y, pos.z, nil)
|
||||
ndb.clear(pos)
|
||||
end
|
||||
end
|
||||
|
||||
function ndb.clear(pos)
|
||||
ndbset(pos.x, pos.y, pos.z, nil)
|
||||
ndbset(ndb_nodecid, pos.x, pos.y, pos.z, nil)
|
||||
ndbset(ndb_nodepar, pos.x, pos.y, pos.z, nil)
|
||||
end
|
||||
|
||||
ndb.run_lbm = function(pos, node)
|
||||
return advtrains.pcall(function()
|
||||
local cid=ndbget(pos.x, pos.y, pos.z)
|
||||
if cid then
|
||||
--if in database, detect changes and apply.
|
||||
local nodeid = ndb_nodeids[u14b(cid)]
|
||||
local param2 = l2b(cid)
|
||||
if not nodeid then
|
||||
--something went wrong
|
||||
minetest.log("warning", "[nplib] Node Database corruption, couldn't determine node to set at "..minetest.pos_to_string(pos))
|
||||
ndb.update(pos, node)
|
||||
else
|
||||
if (nodeid~=node.name or param2~=node.param2) then
|
||||
minetest.swap_node(pos, {name=nodeid, param2 = param2})
|
||||
local ndef=minetest.registered_nodes[nodeid]
|
||||
if ndef and ndef.on_updated_from_nodedb then
|
||||
ndef.on_updated_from_nodedb(pos, node)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
--if not in database, take it.
|
||||
minetest.log("action", "[nplib] Node Database: "..minetest.pos_to_string(pos).." was not found in the database, have you used worldedit?")
|
||||
local cid=ndbget(ndb_nodecid, pos.x, pos.y, pos.z)
|
||||
if cid then
|
||||
--if in database, detect changes and apply.
|
||||
local nodeid = ndb_nodeids[cid]
|
||||
local param2 = ndbget(ndb_nodepar, pos.x, pos.y, pos.z)
|
||||
if not nodeid or not param2 then
|
||||
--something went wrong
|
||||
minetest.log("warning", "[nplib] Node Database corruption, couldn't determine node to set at "..minetest.pos_to_string(pos))
|
||||
ndb.update(pos, node)
|
||||
else
|
||||
if (nodeid~=node.name or param2~=node.param2) then
|
||||
minetest.swap_node(pos, {name=nodeid, param2 = param2})
|
||||
local ndef=minetest.registered_nodes[nodeid]
|
||||
if ndef and ndef.on_updated_from_nodedb then
|
||||
ndef.on_updated_from_nodedb(pos, node)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end)
|
||||
else
|
||||
--if not in database, take it.
|
||||
minetest.log("action", "[nplib] Node Database: "..minetest.pos_to_string(pos).." was not found in the database, have you used worldedit?")
|
||||
ndb.update(pos, node)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
@ -261,20 +273,34 @@ nplib=ndb
|
|||
|
||||
local ptime=0
|
||||
|
||||
--- METADATA
|
||||
|
||||
local pts = minetest.pos_to_string
|
||||
|
||||
function ndb.get_meta(pos)
|
||||
local p = pts(pos)
|
||||
return ndb_nodemeta[p]
|
||||
end
|
||||
|
||||
function ndb.set_meta(pos, meta)
|
||||
local p = pts(pos)
|
||||
ndb_nodemeta[p] = meta
|
||||
end
|
||||
|
||||
|
||||
|
||||
minetest.register_chatcommand("nplib_sync_ndb",
|
||||
{
|
||||
params = "", -- Short parameter description
|
||||
description = "Synchronize node database and map. Useful after using WorldEdit", -- Full description
|
||||
privs = {worldedit=true}, -- Require the "privs" privilege to run
|
||||
func = function(name, param)
|
||||
return advtrains.pcall(function()
|
||||
if not minetest.check_player_privs(name, {server=true}) and os.time() < ptime+30 then
|
||||
return false, "Please wait at least 30s from the previous execution of /nplib_sync_ndb!"
|
||||
end
|
||||
ndb.restore_all()
|
||||
ptime=os.time()
|
||||
return true
|
||||
end)
|
||||
if not minetest.check_player_privs(name, {server=true}) and os.time() < ptime+30 then
|
||||
return false, "Please wait at least 30s from the previous execution of /nplib_sync_ndb!"
|
||||
end
|
||||
ndb.restore_all()
|
||||
ptime=os.time()
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue