From 0f706533b67bb73e28ec3f5334bc02cc6660ec1a Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Sat, 11 Apr 2020 14:02:12 -0400 Subject: [PATCH] Fix numerous scan-related bugs --- commands.lua | 8 ++++--- map_api.lua | 22 ++++++++++++-------- map_formspec.lua | 2 +- scanner.lua | 54 +++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/commands.lua b/commands.lua index 9872810..f7185ff 100644 --- a/commands.lua +++ b/commands.lua @@ -1,19 +1,21 @@ local MAXINT = 2147483647; +-- /map -- Displays a regional map around the player +-- (Optional)detail: Specifies the map's detail level. Defaults to the highest +-- available detail. minetest.register_chatcommand("map", { params = "[]", func = function(name, detail) local player = minetest.get_player_by_name(name); local pos = player:get_pos(); - local player_x = tochunk(pos.x); - local player_y = tochunk(pos.z); + local player_x, player_z = cartographer.to_map_coordinates(nil, pos.x, pos.z); if detail == "" then detail = MAXINT; end - minetest.show_formspec(name, "map", cartographer.get_map_formspec(data, tochunk(pos.x), tochunk(pos.z), 40, 40, detail)); + minetest.show_formspec(name, "map", cartographer.get_map_formspec(data, player_x, player_z, 40, 40, detail)); end, }) diff --git a/map_api.lua b/map_api.lua index cec6198..5ed2afa 100644 --- a/map_api.lua +++ b/map_api.lua @@ -69,11 +69,17 @@ function cartographer.get_marker(map, x, z) return map.markers[x][z]; end +-- Fill in the local area of a map around a position +-- id: A map ID +-- x: The x position, in world coordinates +-- z: The z position, in world coordinates function cartographer.fill_local(id, x, z) local map = cartographer.get_map(id); - if map ~= nil and x >= map.x - 2 and x <= map.x + map.w + 1 and z >= map.z - 2 and z <= map.z + map.h + 1 then - -- minetest.chat_send_all("[" .. tostring(x) .. ", " .. tostring(z) .. "] - [" .. tostring(map.x - 2) .. ", " .. tostring(map.z - 2) .. "], [" .. tostring(map.x + map.w + 1) .. ", " .. tostring(map.z + map.h + 1) .. "]"); + x, z = cartographer.to_map_coordinates(map, x, z); + + -- TODO: Adjust size to match map scale + if map and x >= map.x - 2 and x <= map.x + map.w + 1 and z >= map.z - 2 and z <= map.z + map.h + 1 then cartographer.fill(map, x - 2, z - 2, 5, 5); end end @@ -93,8 +99,8 @@ function cartographer.to_map_coordinates(map, x, z) end local timer = 0; - minetest.register_globalstep(function(dt) + -- TODO: We need a better way to do this. minetest.after maybe? timer = timer - dt; if timer < 0 then timer = timer + 5; @@ -108,17 +114,15 @@ minetest.register_globalstep(function(dt) local stack = inventory:get_stack("main", i); if stack:get_name() == "cartographer:map" then - local player_x = tochunk(pos.x); - local player_y = tochunk(pos.z); - cartographer.fill_local(stack:get_meta():get_int("cartographer:map_id"), player_x, player_y); + cartographer.fill_local(stack:get_meta():get_int("cartographer:map_id"), pos.x, pos.y); end end for i = -2,2 do for j = -2,2 do local adjusted_pos = { - x = tochunk(pos.x + fromchunk(i)), - y = tochunk(pos.y), - z = tochunk(pos.z + fromchunk(j)), + x = pos.x + fromchunk(i), + y = pos.y, + z = pos.z + fromchunk(j), } cartographer.queue_region(adjusted_pos); end diff --git a/map_formspec.lua b/map_formspec.lua index e5bdd57..64ee169 100644 --- a/map_formspec.lua +++ b/map_formspec.lua @@ -94,7 +94,7 @@ local function generate_map(data, x, y, w, h, player_x, player_y, detail, map_sc end function cartographer.get_map_formspec(data, x, y, w, h, detail) - return map_formspec_prefix:format(w * scale, h * scale)..generate_map(data, x - (w * 0.5), y - (h * 0.5), w, h, x, y, detail, 4); + return map_formspec_prefix:format(w * scale, h * scale)..generate_map(data, x - (w * 0.5), y - (h * 0.5), w, h, x, y, detail, 1); end function cartographer.get_map_formspec_map(data, map, x, y) diff --git a/scanner.lua b/scanner.lua index a528a2c..6a4dcb8 100644 --- a/scanner.lua +++ b/scanner.lua @@ -1,6 +1,14 @@ local CHUNK_SIZE = _cartographer.CHUNK_SIZE; -local function register_mapchunk(x, y, biome, height) +-- Register a new tile in map data +-- x: The x position in map coordinates +-- y: The y position in map coordinates +-- biome: The tile's biome id +-- height: The tile's height +-- (Optional): manual_scan: Indicates if this was a 'manual' (non-generated) +-- scan. Manual scans are overridden by generated +-- scans under normal circumstances. +local function register_tile(x, y, biome, height, manual_scan) if not data.generated[x] then data.generated[x] = { [y] = { @@ -8,11 +16,17 @@ local function register_mapchunk(x, y, biome, height) height = height, } }; + if manual_scan ~= nil then + data.generated[x][y].manual_scan = manual_scan; + end elseif not data.generated[x][y] or data.generated[x][y].height < height then data.generated[x][y] = { biome = biome, height = height, }; + if manual_scan ~= nil or data.generated[x][y].manual_scan then + data.generated[x][y].manual_scan = manual_scan; + end end end @@ -133,21 +147,39 @@ local function on_generated(min, max, blockseed) }; local biome, height = get_mapgen_biome(sub_min, sub_max, min, max); if biome ~= nil then - register_mapchunk(i, j, biome, height) + register_tile(i, j, biome, height) end end end end +-- Is the scan of this position already handled? +-- x: The x position, in map coordinates +-- y: The y position, in world coordinates +-- x: The z position, in map coordinates +-- +-- Returns true if the position is handled by the current map data +local function is_scan_handled(x, y, z) + if not data.generated[x] then + return false; + end + + local tile = data.generated[x][z]; + + return tile and ((not tile.manual_scan and tile.height > 0) or tile.height >= y); +end + +-- Queue a tile for manual scanning +-- pos: The position as a table, in world coordinates function cartographer.queue_region(pos) local converted = { - x = tochunk(pos.x) * CHUNK_SIZE, - y = tochunk(pos.y) * CHUNK_SIZE, - z = tochunk(pos.z) * CHUNK_SIZE, + x = fromchunk(tochunk(pos.x)), + y = fromchunk(tochunk(pos.y)), + z = fromchunk(tochunk(pos.z)), }; - if data.generated[pos.x] ~= nil and data.generated[pos.x][pos.z] ~= nil then + if is_scan_handled(tochunk(pos.x), pos.y, tochunk(pos.z)) then return; end @@ -160,6 +192,7 @@ function cartographer.queue_region(pos) cartographer.scan_queue[#cartographer.scan_queue + 1] = converted; end +-- Scan the next tile on the queue, and remove it function cartographer.scan_regions() local len = #cartographer.scan_queue; @@ -167,23 +200,24 @@ function cartographer.scan_regions() return; end - local startpos = cartographer.scan_queue[len]; + local startpos = cartographer.scan_queue[1]; local endpos = { x = startpos.x + CHUNK_SIZE, y = startpos.y + CHUNK_SIZE, z = startpos.z + CHUNK_SIZE, }; - if data.generated[startpos.x] ~= nil and data.generated[startpos.x][startpos.z] ~= nil then + if is_scan_handled(tochunk(startpos.x), startpos.y, tochunk(startpos.z)) then + table.remove(cartographer.scan_queue, 1); return; end local biome,height = get_biome(startpos, endpos); if biome ~= nil then - register_mapchunk(startpos.x / CHUNK_SIZE, startpos.z / CHUNK_SIZE, biome, height) + register_tile(tochunk(startpos.x), tochunk(startpos.z), biome, height, true) end - cartographer.scan_queue[len] = nil; + table.remove(cartographer.scan_queue, 1); end minetest.register_on_generated(on_generated);