local scale = 0.25; local variant_odds = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4 }; local function get_variant(random) return variant_odds[random:next(1, 12)]; end local map_formspec_prefix = [[ formspec_version[3] size[%f,%f] real_coordinates[true] style_type[image_button;border=false] ]]; local tile = "image[%f,%f;%f,%f;%s]"; local marker = "animated_image[%f,%f;%f,%f;;%s;%d;%d]"; -- Generate formspec markup for an unknown biome tile local function unknown_biome_tile(x, y, scale, variant) return tile:format(x, y, scale, scale, cartographer.skin.unknown_biome_texture .. "." .. tostring(variant) .. ".png"); end -- Generate formspec markup for a given map -- data: The mapping data -- x: The X position of the map (in map coordinates) -- y: The Z position of the map (in map coordinates) -- w: The width of the map (in map coordinates) -- h: The height of the map (in map coordinates) -- player_x: The X position of the player marker (in map coordinates) -- player_y: The Y position of the player marker (in map coordinates) -- detail: The detail level -- map_scale: Integer scaling factor for displaying a zoomed-out map -- (Optional) is_visible: Callback to determine if a tile should be drawn -- (Optional) get_marker: Callback to get the marker for any given tile -- (Optional) user: userdata passed to the is_visible/get_marker callbacks -- -- Returns a formspec string local function generate_map(data, x, y, w, h, player_x, player_y, detail, map_scale, is_visible, get_marker, user) local str = ""; local random = PcgRandom(x + y + w + h); -- TODO: Better seed player_x = math.floor(player_x / map_scale + 0.5); player_y = math.floor(player_y / map_scale + 0.5); for i = x,x + w,1 do local fx = (i - x) * (scale - 0.01); local column = data.generated[i * map_scale]; for j = y + h,y,-1 do local fy = (y + h - j) * (scale - 0.01); if column == nil or column[j * map_scale] == nil or (is_visible and not is_visible(user, i, j)) then str = str .. unknown_biome_tile(fx, fy, scale, get_variant(random)); else local name = minetest.get_biome_name(column[j * map_scale].biome); local height = column[j * map_scale].height; local biome = cartographer.get_biome_texture(name, math.floor(height + 0.5), detail); if biome then local depth = math.min(math.max(math.floor(height / 8), -8), 0) * -1 height = math.max(math.min(math.floor(height / 4), 8), 0) local mod = ""; if height > 0 then mod = "^[colorize:white:"..tostring(height * 10) height = height * 0.05; str = str..tile:format(fx, fy - height + (scale - 0.01), scale, height + 0.01, cartographer.skin.cliff_texture .. ".png"); elseif depth > 0 then mod = "^[colorize:#1f1f34:"..tostring(depth * 10) end str = str..tile:format(fx, fy - height, scale, scale, biome .. "." .. tostring(get_variant(random)) .. ".png" .. mod) if get_marker then local marker = cartographer.get_marker_texture(get_marker(user, i, j), detail); if marker then str = str..tile:format(fx, fy - height, scale, scale, marker .. ".png") end end if i == player_x and j == player_y then str = str..marker:format(fx, fy - height, scale, scale, cartographer.skin.player_icon.texture .. ".png", cartographer.skin.player_icon.frame_count, cartographer.skin.player_icon.frame_duration); end else str = str .. unknown_biome_tile(fx, fy, scale, get_variant(random)); end end end end return str; 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, 1); end function cartographer.get_map_formspec_map(data, map, x, y) return map_formspec_prefix:format(map.w * scale, map.h * scale)..generate_map(data, map.x, map.z, map.w, map.h, x, y, map.detail, map.scale, cartographer.is_filled, cartographer.get_marker, map); end