diff --git a/catalog.spec.lua b/catalog.spec.lua index 393a582..6000b42 100644 --- a/catalog.spec.lua +++ b/catalog.spec.lua @@ -20,6 +20,20 @@ mtt.register("read existing catalog", function(callback) assert(size.z == 1, "z-size match") assert(c:has_mapblock({x=0,y=0,z=0}), "mapblock exists") assert(not c:has_mapblock({x=0,y=0,z=1}), "mapblock does not exist") + + -- test get_node() accessor + local node = c:get_node({x=0,y=0,z=0}) + assert(node.name == "default:stone") + assert(node.param1 == 15) + assert(node.param2 == 0) + + node = c:get_node({x=15,y=15,z=15}) + assert(node.name == "air") + assert(node.param1 == 15) + assert(node.param2 == 0) + + assert(not c:get_node({x=0,y=16,z=0})) + callback() end) diff --git a/get_catalog.lua b/get_catalog.lua index 81d41fb..e30c52d 100644 --- a/get_catalog.lua +++ b/get_catalog.lua @@ -108,6 +108,52 @@ function Catalog:prepare(catalog_mapblock_pos, options) end end +-- mapblock area for index -> pos calculations +local mapblock_area = VoxelArea:new({MinEdge={x=0,y=0,z=0}, MaxEdge={x=15,y=15,z=15}}) + +function Catalog:get_node(pos) + local mb_pos = mapblock_lib.get_mapblock(pos) + if not self:has_mapblock(mb_pos) then + -- return fast + return + end + + local cache_key = minetest.pos_to_string(mb_pos) + local cache_entry = self.cache[cache_key] + if not cache_entry then + -- load and parse + local manifest, mapblock, err = read_manifest_mapblock(self.filename, mb_pos) + if err then + return nil, err + end + + local nodeid_name_mapping = {} + for name, id in pairs(manifest.node_mapping) do + nodeid_name_mapping[id] = name + end + + cache_entry = { + nodeid_name_mapping = nodeid_name_mapping, + manifest = manifest, + mapblock = mapblock + } + self.cache[cache_key] = cache_entry + end + + -- fetch relative node data + local mb_min_pos = mapblock_lib.get_mapblock_bounds_from_mapblock(mb_pos) + local rel_pos = vector.subtract(pos, mb_min_pos) + local index = mapblock_area:indexp(rel_pos) + + local nodeid = cache_entry.mapblock.node_ids[index] + + return { + param1 = cache_entry.mapblock.param1[index], + param2 = cache_entry.mapblock.param2[index], + name = cache_entry.nodeid_name_mapping[nodeid] + } +end + ------ -- Deserialize options -- @number delay for async mode: delay between deserialization-calls @@ -213,7 +259,9 @@ function mapblock_lib.get_catalog(filename) filename = filename, manifest = manifest, -- for lookups only - zip = z + zip = z, + -- cached mapblocks for get_node() + cache = {} } return setmetatable(self, Catalog_mt) end