diff --git a/init.lua b/init.lua index 4647037..8c0b49d 100644 --- a/init.lua +++ b/init.lua @@ -2,13 +2,12 @@ local mod_storage = minetest.get_mod_storage(); -- The API object cartographer = { - biome_lookup = {}, - biome_heights = {}, scan_queue = {}, }; _cartographer = { CHUNK_SIZE = 16, + biome_lookup = {}, maps = minetest.deserialize(mod_storage:get_string("maps")) or {}, next_map_id = mod_storage:get_int("next_map_id"), last_deaths = minetest.deserialize(mod_storage:get_string("deaths")) or {}, diff --git a/map_api.lua b/map_api.lua index 13fa962..3f6a94c 100644 --- a/map_api.lua +++ b/map_api.lua @@ -92,12 +92,20 @@ minetest.register_globalstep(function(dt) end end) -function cartographer.register_biome(name, texture, height) - cartographer.biome_lookup[name] = texture; - - if height ~= nil and height ~= 0 then - cartographer.biome_heights[name] = height; - end +-- Register a biome with textures to display +-- name: A string containing the biome name +-- textures: A table of texture names. +-- These should correspond with detail levels, +-- any detail level past the length of the table will return the last texture +-- (Optional) min_height: The minimum Y position where this biome data should be used +-- (Optional) max_height: The maximum Y position where this biome data should be used +function cartographer.register_biome(name, textures, min_height, max_height) + _cartographer.biome_lookup[#_cartographer.biome_lookup + 1] = { + name = name, + textures = textures, + min_height = min_height, + max_height = max_height, + }; end function cartographer.is_filled(map, x, z) @@ -108,3 +116,18 @@ function cartographer.is_filled(map, x, z) minetest.chat_send_all(tostring(x).. ", " .. tostring(z) .. "(" .. tostring(x + (z * map.w)) .."): " .. tostring(map.fill[x + (z * map.w)])); return map.fill[(x - map.x) + ((z - map.z) * map.w)] ~= nil; end + +-- Get the texture name (minus index/extension) for the given biome, height, and detail level. +-- name: A string containing the biome name +-- height: A number representing the Y position of the biome +-- detail: The detail level +-- Returns a string with a texture name, or nil if no matching biome entry was found. +function cartographer.get_biome_texture(name, height, detail) + for _,biome in ipairs(_cartographer.biome_lookup) do + if biome.name == name and (biome.min_height == nil or height >= biome.min_height) and (biome.max_height == nil or height <= biome.max_height) then + return biome.textures[math.min(detail, #biome.textures)]; + end + end + + return nil; +end diff --git a/map_formspec.lua b/map_formspec.lua index 4c30a56..e9348f2 100644 --- a/map_formspec.lua +++ b/map_formspec.lua @@ -26,23 +26,23 @@ local function generate_map(data, x, y, w, h, player_x, player_y, spawn_x, spawn if column == nil or column[j] == nil or (is_visible and not is_visible(user, i, j)) then str = str..tile:format(fx, fy, scale, scale, "cartographer_unknown_biome." .. tostring(get_variant(random)) .. ".png") else - local name = minetest.get_biome_name(column[j]); - local biome = cartographer.biome_lookup[name]; - local height = cartographer.biome_heights[name] or 0; + local name = minetest.get_biome_name(column[j].biome); + local height = column[j].height; + local biome = cartographer.get_biome_texture(name, math.floor(height + 0.5), detail); if biome == nil then - minetest.chat_send_all(name); + -- minetest.chat_send_all(name); str = str..tile:format(fx, fy, scale, scale, "cartographer_unknown_biome." .. tostring(get_variant(random)) .. ".png") else if height > 0 then str = str..tile:format(fx, fy, scale, scale, "cartographer_cliff.png") end - str = str..tile:format(fx, fy - (height * 0.025), scale, scale, biome[math.min(detail, #biome)] .. "." .. tostring(get_variant(random)) .. ".png") + str = str..tile:format(fx, fy, scale, scale, biome .. "." .. tostring(get_variant(random)) .. ".png") end if i == player_x and j == player_y then - str = str..marker:format(fx, fy - (height * 0.025), scale, scale, "cartographer_player_icon.png", 2, 500) + str = str..marker:format(fx, fy, scale, scale, "cartographer_player_icon.png", 2, 500) -- elseif i == death_x and j == death_y then -- str = str..marker:format(fx, fy - (height * 0.025), scale, scale, "dicon.png") -- elseif i == spawn_x and j == spawn_y then diff --git a/repixture.lua b/repixture.lua index 6f70678..7938b95 100644 --- a/repixture.lua +++ b/repixture.lua @@ -62,16 +62,28 @@ cartographer.register_biome("Wasteland", { cartographer.register_biome("Grassland Ocean", { "cartographer_simple_water", "cartographer_colored_water", -}); +}, nil, 0); +cartographer.register_biome("Grassland Ocean", { + "cartographer_simple_land", + "cartographer_colored_sand", +}, 0); cartographer.register_biome("Gravel Beach", { "cartographer_simple_land", "cartographer_colored_sand", "cartographer_gravel", -}); +}, 0); +cartographer.register_biome("Gravel Beach", { + "cartographer_simple_water", + "cartographer_colored_water", +}, nil, 0); cartographer.register_biome("Savanna Ocean", { "cartographer_simple_water", "cartographer_colored_water", -}); +}, nil, 0); +cartographer.register_biome("Savanna Ocean", { + "cartographer_simple_land", + "cartographer_colored_sand", +}, 0); -- Materials cartographer.register_map_material_name("default:paper", "fiber", 5); diff --git a/scanner.lua b/scanner.lua index 794af75..e8eb5b0 100644 --- a/scanner.lua +++ b/scanner.lua @@ -1,12 +1,18 @@ local CHUNK_SIZE = _cartographer.CHUNK_SIZE; -local function register_mapchunk(x, y, biome) +local function register_mapchunk(x, y, biome, height) if not data.generated[x] then data.generated[x] = { - [y] = biome, + [y] = { + biome = biome, + height = height, + } }; elseif not data.generated[x][y] then - data.generated[x][y] = biome; + data.generated[x][y] = { + biome = biome, + height = height, + }; end end @@ -15,6 +21,7 @@ local function get_mapgen_biome(min, max, mmin, mmax) local DEFAULT = minetest.get_biome_id("default"); local biomes = minetest.get_mapgen_object("biomemap"); + local heights = minetest.get_mapgen_object("heightmap"); local xx = max.x - min.x; local yy = max.y - min.y; @@ -29,12 +36,14 @@ local function get_mapgen_biome(min, max, mmin, mmax) local startz = min.z - mmin.z; local scan_biomes = {}; + local scan_heights = {}; for i = startx,startx + xx,1 do for k = startz,startz + zz,1 do - local b = biomes[i + (k * (xxx + 1))] + local b = biomes[i + (k * (xxx + 1))]; if b ~= nil and b ~= UNDERGROUND and b ~= DEFAULT then scan_biomes[b] = (scan_biomes[b] or 0) + 1; + scan_heights[b] = (scan_heights[b] or 0) + heights[i + (k * (xxx + 1))]; end end end @@ -48,7 +57,12 @@ local function get_mapgen_biome(min, max, mmin, mmax) end end - return biome; + local avg_height = 0; + if high > 0 then + avg_height = scan_heights[biome] / high; + end + + return biome, avg_height; end local function get_biome(min, max) @@ -61,6 +75,7 @@ local function get_biome(min, max) local zz = max.z - min.z; local scan_biomes = {}; + local scan_heights = {}; for i = min.x,max.x,1 do for j = min.y,max.y,1 do @@ -73,6 +88,7 @@ local function get_biome(min, max) node = minetest.get_node(pos).name; if node == "air" or node == WATER_SOURCE then scan_biomes[b] = (scan_biomes[b] or 0) + 1; + scan_heights[b] = (scan_heights[b] or 0) + j; end end end @@ -88,7 +104,12 @@ local function get_biome(min, max) end end - return biome; + local avg_height = 0; + if high > 0 then + avg_height = scan_heights[biome] / high; + end + + return biome, avg_height; end local function on_generated(min, max, blockseed) @@ -110,9 +131,9 @@ local function on_generated(min, max, blockseed) y = max.y, z = j * CHUNK_SIZE + CHUNK_SIZE, }; - local biome = get_mapgen_biome(sub_min, sub_max, min, max); + local biome, height = get_mapgen_biome(sub_min, sub_max, min, max); if biome ~= nil then - register_mapchunk(i, j, biome) + register_mapchunk(i, j, biome, height) end end