Fix numerous scan-related bugs

This commit is contained in:
Hugues Ross 2020-04-11 14:02:12 -04:00
parent a5ded9bc11
commit 0f706533b6
4 changed files with 63 additions and 23 deletions

View File

@ -1,19 +1,21 @@
local MAXINT = 2147483647;
-- /map <detail> -- 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 = "[<detail>]",
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,
})

View File

@ -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

View File

@ -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)

View File

@ -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);