Record heightmap when scanning
- Use heightmap value for more granular biome texture selection
This commit is contained in:
		
							
								
								
									
										3
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								init.lua
									
									
									
									
									
								
							| @@ -2,13 +2,12 @@ local mod_storage = minetest.get_mod_storage(); | |||||||
|  |  | ||||||
| -- The API object | -- The API object | ||||||
| cartographer = { | cartographer = { | ||||||
|     biome_lookup = {}, |  | ||||||
|     biome_heights = {}, |  | ||||||
|     scan_queue = {}, |     scan_queue = {}, | ||||||
| }; | }; | ||||||
| _cartographer = { | _cartographer = { | ||||||
|     CHUNK_SIZE = 16, |     CHUNK_SIZE = 16, | ||||||
|  |  | ||||||
|  |     biome_lookup = {}, | ||||||
|     maps = minetest.deserialize(mod_storage:get_string("maps")) or {}, |     maps = minetest.deserialize(mod_storage:get_string("maps")) or {}, | ||||||
|     next_map_id = mod_storage:get_int("next_map_id"), |     next_map_id = mod_storage:get_int("next_map_id"), | ||||||
|     last_deaths = minetest.deserialize(mod_storage:get_string("deaths")) or {}, |     last_deaths = minetest.deserialize(mod_storage:get_string("deaths")) or {}, | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								map_api.lua
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								map_api.lua
									
									
									
									
									
								
							| @@ -92,12 +92,20 @@ minetest.register_globalstep(function(dt) | |||||||
|     end |     end | ||||||
| end) | end) | ||||||
|  |  | ||||||
| function cartographer.register_biome(name, texture, height) | -- Register a biome with textures to display | ||||||
|     cartographer.biome_lookup[name] = texture; | -- name: A string containing the biome name | ||||||
|  | -- textures: A table of texture names. | ||||||
|     if height ~= nil and height ~= 0 then | --           These should correspond with detail levels, | ||||||
|         cartographer.biome_heights[name] = height; | --           any detail level past the length of the table will return the last texture | ||||||
|     end | -- (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 | end | ||||||
|  |  | ||||||
| function cartographer.is_filled(map, x, z) | 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)])); |     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; |     return map.fill[(x - map.x) + ((z - map.z) * map.w)] ~= nil; | ||||||
| end | 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 | ||||||
|   | |||||||
| @@ -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 |             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") |                 str = str..tile:format(fx, fy, scale, scale, "cartographer_unknown_biome." .. tostring(get_variant(random)) .. ".png") | ||||||
|             else |             else | ||||||
|                 local name = minetest.get_biome_name(column[j]); |                 local name = minetest.get_biome_name(column[j].biome); | ||||||
|                 local biome = cartographer.biome_lookup[name]; |                 local height = column[j].height; | ||||||
|                 local height = cartographer.biome_heights[name] or 0; |                 local biome = cartographer.get_biome_texture(name, math.floor(height + 0.5), detail); | ||||||
|  |  | ||||||
|                 if biome == nil then |                 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") |                     str = str..tile:format(fx, fy, scale, scale, "cartographer_unknown_biome." .. tostring(get_variant(random)) .. ".png") | ||||||
|                 else |                 else | ||||||
|                     if height > 0 then |                     if height > 0 then | ||||||
|                         str = str..tile:format(fx, fy, scale, scale, "cartographer_cliff.png") |                         str = str..tile:format(fx, fy, scale, scale, "cartographer_cliff.png") | ||||||
|                     end |                     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 |                 end | ||||||
|  |  | ||||||
|                 if i == player_x and j == player_y then |                 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 |                 -- elseif i == death_x and j == death_y then | ||||||
|                 --     str = str..marker:format(fx, fy - (height * 0.025), scale, scale, "dicon.png") |                 --     str = str..marker:format(fx, fy - (height * 0.025), scale, scale, "dicon.png") | ||||||
|                 -- elseif i == spawn_x and j == spawn_y then |                 -- elseif i == spawn_x and j == spawn_y then | ||||||
|   | |||||||
| @@ -62,16 +62,28 @@ cartographer.register_biome("Wasteland", { | |||||||
| cartographer.register_biome("Grassland Ocean", { | cartographer.register_biome("Grassland Ocean", { | ||||||
|     "cartographer_simple_water", |     "cartographer_simple_water", | ||||||
|     "cartographer_colored_water", |     "cartographer_colored_water", | ||||||
| }); | }, nil, 0); | ||||||
|  | cartographer.register_biome("Grassland Ocean", { | ||||||
|  |     "cartographer_simple_land", | ||||||
|  |     "cartographer_colored_sand", | ||||||
|  | }, 0); | ||||||
| cartographer.register_biome("Gravel Beach", { | cartographer.register_biome("Gravel Beach", { | ||||||
|     "cartographer_simple_land", |     "cartographer_simple_land", | ||||||
|     "cartographer_colored_sand", |     "cartographer_colored_sand", | ||||||
|     "cartographer_gravel", |     "cartographer_gravel", | ||||||
| }); | }, 0); | ||||||
|  | cartographer.register_biome("Gravel Beach", { | ||||||
|  |     "cartographer_simple_water", | ||||||
|  |     "cartographer_colored_water", | ||||||
|  | }, nil, 0); | ||||||
| cartographer.register_biome("Savanna Ocean", { | cartographer.register_biome("Savanna Ocean", { | ||||||
|     "cartographer_simple_water", |     "cartographer_simple_water", | ||||||
|     "cartographer_colored_water", |     "cartographer_colored_water", | ||||||
| }); | }, nil, 0); | ||||||
|  | cartographer.register_biome("Savanna Ocean", { | ||||||
|  |     "cartographer_simple_land", | ||||||
|  |     "cartographer_colored_sand", | ||||||
|  | }, 0); | ||||||
|  |  | ||||||
| -- Materials | -- Materials | ||||||
| cartographer.register_map_material_name("default:paper", "fiber", 5); | cartographer.register_map_material_name("default:paper", "fiber", 5); | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								scanner.lua
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								scanner.lua
									
									
									
									
									
								
							| @@ -1,12 +1,18 @@ | |||||||
| local CHUNK_SIZE = _cartographer.CHUNK_SIZE; | 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 |     if not data.generated[x] then | ||||||
|         data.generated[x] = { |         data.generated[x] = { | ||||||
|             [y] = biome, |             [y] = { | ||||||
|  |                 biome = biome, | ||||||
|  |                 height = height, | ||||||
|  |             } | ||||||
|         }; |         }; | ||||||
|     elseif not data.generated[x][y] then |     elseif not data.generated[x][y] then | ||||||
|         data.generated[x][y] = biome; |         data.generated[x][y] = { | ||||||
|  |                 biome = biome, | ||||||
|  |                 height = height, | ||||||
|  |             }; | ||||||
|     end |     end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -15,6 +21,7 @@ local function get_mapgen_biome(min, max, mmin, mmax) | |||||||
|     local DEFAULT = minetest.get_biome_id("default"); |     local DEFAULT = minetest.get_biome_id("default"); | ||||||
|  |  | ||||||
|     local biomes = minetest.get_mapgen_object("biomemap"); |     local biomes = minetest.get_mapgen_object("biomemap"); | ||||||
|  |     local heights = minetest.get_mapgen_object("heightmap"); | ||||||
|  |  | ||||||
|     local xx = max.x - min.x; |     local xx = max.x - min.x; | ||||||
|     local yy = max.y - min.y; |     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 startz = min.z - mmin.z; | ||||||
|      |      | ||||||
|     local scan_biomes = {}; |     local scan_biomes = {}; | ||||||
|  |     local scan_heights = {}; | ||||||
|  |  | ||||||
|     for i = startx,startx + xx,1 do |     for i = startx,startx + xx,1 do | ||||||
|         for k = startz,startz + zz,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 |             if b ~= nil and b ~= UNDERGROUND and b ~= DEFAULT then | ||||||
|                 scan_biomes[b] = (scan_biomes[b] or 0) + 1; |                 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 |         end | ||||||
|     end |     end | ||||||
| @@ -48,7 +57,12 @@ local function get_mapgen_biome(min, max, mmin, mmax) | |||||||
|         end |         end | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     return biome; |     local avg_height = 0; | ||||||
|  |     if high > 0 then | ||||||
|  |         avg_height = scan_heights[biome] / high; | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     return biome, avg_height; | ||||||
| end | end | ||||||
|  |  | ||||||
| local function get_biome(min, max) | local function get_biome(min, max) | ||||||
| @@ -61,6 +75,7 @@ local function get_biome(min, max) | |||||||
|     local zz = max.z - min.z; |     local zz = max.z - min.z; | ||||||
|  |  | ||||||
|     local scan_biomes = {}; |     local scan_biomes = {}; | ||||||
|  |     local scan_heights = {}; | ||||||
|  |  | ||||||
|     for i = min.x,max.x,1 do |     for i = min.x,max.x,1 do | ||||||
|         for j = min.y,max.y,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; |                     node = minetest.get_node(pos).name; | ||||||
|                     if node == "air" or node == WATER_SOURCE then |                     if node == "air" or node == WATER_SOURCE then | ||||||
|                         scan_biomes[b] = (scan_biomes[b] or 0) + 1; |                         scan_biomes[b] = (scan_biomes[b] or 0) + 1; | ||||||
|  |                         scan_heights[b] = (scan_heights[b] or 0) + j; | ||||||
|                     end |                     end | ||||||
|                 end |                 end | ||||||
|             end |             end | ||||||
| @@ -88,7 +104,12 @@ local function get_biome(min, max) | |||||||
|         end |         end | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     return biome; |     local avg_height = 0; | ||||||
|  |     if high > 0 then | ||||||
|  |         avg_height = scan_heights[biome] / high; | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     return biome, avg_height; | ||||||
| end | end | ||||||
|  |  | ||||||
| local function on_generated(min, max, blockseed) | local function on_generated(min, max, blockseed) | ||||||
| @@ -110,9 +131,9 @@ local function on_generated(min, max, blockseed) | |||||||
|                 y = max.y, |                 y = max.y, | ||||||
|                 z = j * CHUNK_SIZE + CHUNK_SIZE, |                 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 |             if  biome ~= nil then | ||||||
|                 register_mapchunk(i, j, biome) |                 register_mapchunk(i, j, biome, height) | ||||||
|             end |             end | ||||||
|  |  | ||||||
|         end |         end | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user