Zoomable maps ()

Reviewed-on: https://git.minetest.land/VoxeLibre/VoxeLibre/pulls/4699
Reviewed-by: teknomunk <teknomunk@protonmail.com>
This commit is contained in:
the-real-herowl 2025-03-01 16:01:44 +01:00
commit a54bff42b9
27 changed files with 571 additions and 242 deletions

View file

@ -1,6 +1,6 @@
mcl_cartography_table
-------------------
Cartography Tables, by PrairieWind
Cartography Tables, by PrairieWind, mirqf and AFCM
Adds Cartography Tables to VoxeLibre.

View file

@ -1,10 +1,209 @@
local S = minetest.get_translator(minetest.get_current_modname())
-- Cartography Table Code. Used to create and copy maps. TODO: Needs a GUI still.
local S = core.get_translator(core.get_current_modname())
local C = core.colorize
local F = core.formspec_escape
minetest.register_node("mcl_cartography_table:cartography_table", {
local formspec_name = "mcl_cartography_table:cartography_table"
-- Crafting patterns supported:
-- 1. Filled map + paper = zoomed out map, but only ONCE for now (too slow)
-- 2. Filled map + empty map = two copies of the map
-- 3. Filled map + glass pane = locked filled map
-- TODO: allow refreshing a map using the table?
local function update_cartography_table(player)
if not player or not player:is_player() then return end
local formspec = table.concat({
"formspec_version[4]",
"size[11.75,10.425]",
"label[0.375,0.375;" .. F(C(mcl_formspec.label_color, S("Cartography Table"))) .. "]",
-- First input slot
mcl_formspec.get_itemslot_bg_v4(1, 0.75, 1, 1),
"list[current_player;cartography_table_input;1,0.75;1,1;0]",
-- Cross icon
"image[1,2;1,1;mcl_anvils_inventory_cross.png]",
-- Second input slot
mcl_formspec.get_itemslot_bg_v4(1, 3.25, 1, 1),
"list[current_player;cartography_table_input;1,3.25;1,1;1]",
-- Arrow
"image[2.7,2;2,1;mcl_anvils_inventory_arrow.png]",
-- Output slot
mcl_formspec.get_itemslot_bg_v4(9.75, 2, 1, 1, 0.2),
"list[current_player;cartography_table_output;9.75,2;1,1;]",
-- Player inventory
"label[0.375,4.7;" .. F(C(mcl_formspec.label_color, S("Inventory"))) .. "]",
mcl_formspec.get_itemslot_bg_v4(0.375, 5.1, 9, 3),
"list[current_player;main;0.375,5.1;9,3;9]",
mcl_formspec.get_itemslot_bg_v4(0.375, 9.05, 9, 1),
"list[current_player;main;0.375,9.05;9,1;]",
})
local inv = player:get_inventory()
local map = inv:get_stack("cartography_table_input", 1)
local texture = not map:is_empty() and mcl_maps.load_map_item(map)
local addon = inv:get_stack("cartography_table_input", 2)
inv:set_stack("cartography_table_output", 1, nil)
if not map:is_empty() and addon:get_name() == "mcl_core:paper"
and map:get_meta():get_int("mcl_maps:zoom") < mcl_maps.max_zoom
and map:get_meta():get_int("mcl_maps:locked") ~= 1 then
---- Zoom a map
formspec = formspec .. "image[5.125,0.5;4,4;mcl_maps_map_background.png]"
-- TODO: show half size in appropriate position?
if texture then formspec = formspec .. "image[6.25,1.625;1.75,1.75;" .. texture .. "]" end
-- zoom will be really applied when taking from the stack
-- to not cause unnecessary map generation. But the tooltip should be right already:
map:get_meta():set_int("mcl_maps:zoom", map:get_meta():get_int("mcl_maps:zoom") + 1)
tt.reload_itemstack_description(map)
inv:set_stack("cartography_table_output", 1, map)
elseif not map:is_empty() and addon:get_name() == "mcl_maps:empty_map" then
---- Copy a map
if texture then
formspec = formspec .. table.concat({
"image[6.125,0.5;3,3;mcl_maps_map_background.png]",
"image[6.375,0.75;2.5,2.5;" .. texture .. "]",
"image[5.125,1.5;3,3;mcl_maps_map_background.png]",
"image[5.375,1.75;2.5,2.5;" .. texture .. "]"
})
else
formspec = formspec .. table.concat({
"image[6.125,0.5;3,3;mcl_maps_map_background.png]",
"image[5.125,1.5;3,3;mcl_maps_map_background.png]"
})
end
map:set_count(2)
inv:set_stack("cartography_table_output", 1, map)
elseif addon:get_name() == "xpanes:pane_natural_flat" and not map:is_empty() then
---- Lock a map
formspec = formspec .. "image[5.125,0.5;4,4;mcl_maps_map_background.png]"
if texture then formspec = formspec .. "image[5.375,0.75;3.5,3.5;" .. texture .. "]" end
if map:get_meta():get_int("mcl_maps:locked") == 1 then
formspec = formspec .. table.concat({
"image[3.2,2;1,1;mcl_core_barrier.png]",
"image[8.375,3.75;0.5,0.5;mcl_core_barrier.png]"
})
else
formspec = formspec .. "image[8.375,3.75;0.5,0.5;mcl_core_barrier.png]"
map:get_meta():set_int("mcl_maps:locked", 1)
inv:set_stack("cartography_table_output", 1, map)
end
else
---- Not supported
formspec = formspec .. "image[5.125,0.5;4,4;mcl_maps_map_background.png]"
if texture then formspec = formspec .. "image[5.375,0.75;3.5,3.5;" .. texture .. "]" end
end
core.show_formspec(player:get_player_name(), formspec_name, formspec)
end
core.register_on_joinplayer(function(player)
local inv = player:get_inventory()
inv:set_size("cartography_table_input", 2)
inv:set_size("cartography_table_output", 1)
--The player might have items remaining in the slots from the previous join; this is likely
--when the server has been shutdown and the server didn't clean up the player inventories.
mcl_util.move_player_list(player, "cartography_table_input")
player:get_inventory():set_list("cartography_table_output", {})
end)
core.register_on_leaveplayer(function(player)
mcl_util.move_player_list(player, "cartography_table_input")
player:get_inventory():set_list("cartography_table_output", {})
end)
function remove_from_input(player, inventory, count)
local meta = player:get_meta()
local astack = inventory:get_stack("cartography_table_input", 1)
if astack then
astack:set_count(math.max(0, astack:get_count() - count))
inventory:set_stack("cartography_table_input", 1, astack)
end
local bstack = inventory:get_stack("cartography_table_input", 2)
if bstack then
bstack:set_count(math.max(0, bstack:get_count() - count))
inventory:set_stack("cartography_table_input", 2, bstack)
end
end
core.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
-- Generate zoomed map
if (action == "move" or action == "take") and inventory_info.from_list == "cartography_table_output" and inventory_info.from_index == 1 then
local stack = inventory:get_stack("cartography_table_output", 1)
local addon = inventory:get_stack("cartography_table_input", 2)
if stack:get_name():find("mcl_maps:filled_map") and addon:get_name() == "mcl_core:paper" then
-- also send chat, as the actionbar may be hidden by the cartograph table
core.chat_send_player(player:get_player_name(), core.get_color_escape_sequence("gold")..S("Zooming a map may take several seconds to generate the world, please wait."))
mcl_title.set(player, "actionbar", {text=S("Zooming a map may take several seconds to generate the world, please wait."), color="gold", stay=5*20})
local callback = function(id, filename)
mcl_title.set(player, "actionbar", {text=S("The zoomed map is now ready."), color="green", stay=3*20})
end
mcl_maps.regenerate_map(stack, callback) -- new zoom level
inventory:set_stack("cartography_table_output", 1, stack)
end
end
-- TODO: also allow map texture refresh?
if action == "move" or action == "put" then
if inventory_info.to_list == "cartography_table_output" then return false end
if inventory_info.to_list == "cartograhy_table_input" then
local index = inventory_info.to_index
local stack = inventory:get_stack("cartography_table_input", index)
if index == 1 and stack:get_name() == "mcl_maps:empty_map" then return inventory_info.count end
if index == 1 and stack:get_name():find("mcl_maps:filled_map") then return inventory_info.count end
if index == 1 and stack:get_name() == "mcl_core:paper" then return inventory_info.count end
if index == 2 and stack:get_name() == "mcl_maps:empty_map" then return inventory_info.count end
if index == 2 and stack:get_name() == "xpanes:pane_natural_flat" then return inventory_info.count end
return false
end
if inventory_info.from_list == "cartography_table_output" and inventory_info.from_index == 1 then
return inventory_info.count
end
end
end)
core.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
if action == "move" then
if inventory_info.from_list == "cartography_table_output" then
remove_from_input(player, inventory, inventory_info.count)
end
if inventory_info.to_list == "cartography_table_input" or inventory_info.from_list == "cartography_table_input" then
update_cartography_table(player)
end
elseif action == "put" then
if inventory_info.listname == "cartography_table_input" then
update_cartography_table(player)
end
elseif action == "take" then
if inventory_info.listname == "cartography_table_output" then
remove_from_input(player, inventory, inventory_info.stack:get_count())
end
end
end)
core.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= formspec_name then return end
if fields.quit then
mcl_util.move_player_list(player, "cartography_table_input")
player:get_inventory():set_list("cartography_table_output", {})
return
end
end)
core.register_node("mcl_cartography_table:cartography_table", {
description = S("Cartography Table"),
_tt_help = S("Used to create or copy maps"),
_doc_items_longdesc = S("Is used to create or copy maps for use.."),
_tt_help = S("Used to copy, lock, and zoom maps"),
_doc_items_longdesc = S("A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact."),
tiles = {
"mcl_cartography_table_top.png", "mcl_cartography_table_side3.png",
"mcl_cartography_table_side3.png", "mcl_cartography_table_side2.png",
@ -14,11 +213,13 @@ minetest.register_node("mcl_cartography_table:cartography_table", {
groups = { axey = 2, handy = 1, deco_block = 1, material_wood = 1, flammable = 1 },
sounds = mcl_sounds.node_sound_wood_defaults(),
_mcl_blast_resistance = 2.5,
_mcl_hardness = 2.5
})
_mcl_hardness = 2.5,
on_rightclick = function(pos, node, player, itemstack)
if player and player:is_player() and not player:get_player_control().sneak then update_cartography_table(player) end
end,
})
minetest.register_craft({
core.register_craft({
output = "mcl_cartography_table:cartography_table",
recipe = {
{ "mcl_core:paper", "mcl_core:paper", "" },
@ -27,7 +228,7 @@ minetest.register_craft({
}
})
minetest.register_craft({
core.register_craft({
type = "fuel",
recipe = "mcl_cartography_table:cartography_table",
burntime = 15,

View file

@ -1,5 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=Kartentisch
Used to create or copy maps=Dient zum Erstellen und Kopieren von Karten
# choose one below
Is used to create or copy maps for use..=Dient dazu, Karten zu erstellen oder zu kopieren.
Inventory=Inventar
Zooming a map may take several seconds to generate the world, please wait.=Eine Karte zu vergrößern kann einige Sekunden benötigen, bitte warten.
The zoomed map is now ready.=Die vergrößerte Karte ist jetzt bereit.
Used to copy, lock, and zoom maps=Kann Karten kopieren, sperren und vergrößern.
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=Ein Kartentisch ermöglicht es, Karten zu kopieren, zu sperren, oder zu vergrößern. Sperren ist noch nicht nützlich, und der maximale Zoomlevel kann in den Servereinstellungen begrenzt sein, um die Rechenzeit zu begrenzen.

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=Table de cartographie
Used to create or copy maps=Utilisée pour créer ou copier des cartes
Is used to create or copy maps for use..=Est utilisée pour créer ou copier des cartes..
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=Mesa de Cartografia
Used to create or copy maps=Empregada para criar ou copiar mapas
Is used to create or copy maps for use..=É usada para criar ou copiar mapas para o seu uso..
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=製図台
Used to create or copy maps=地図の作成やコピーに使用
Is used to create or copy maps for use..=地図の作成やコピーに使用します。
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=Kartografbenk
Used to create or copy maps=Brukes for å opprette eller kopiere kart
Is used to create or copy maps for use..=Brukes for å opprette eller kopiere kart for ulikt bruk...
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=Mesa de Cartografia
Used to create or copy maps=Utilizada para criar ou copiar mapas
Is used to create or copy maps for use..=É usada para criar ou copiar mapas para uso..
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=Картографический стол
Used to create or copy maps=Используется для создания или копирования карт
Is used to create or copy maps for use..=Используется для создания или копирования карт.
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=制图台
Used to create or copy maps=用于制作或复制地图。
Is used to create or copy maps for use..=用于制作或复制供使用的地图。
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,7 @@
# textdomain: mcl_cartography_table
Cartography Table=
Used to create or copy maps=
Is used to create or copy maps for use..=
Inventory=
Zooming a map may take several seconds to generate the world, please wait.=
The zoomed map is now ready.=
Used to copy, lock, and zoom maps=
A cartography tables allows to copy, lock, and zoom maps. Locking is not yet useful, and the maximum zoom level may be restricted by server settings to limit the performance impact.=

View file

@ -1,4 +1,4 @@
name = mcl_cartography_table
author = PrairieWind
depends = mcl_core, mcl_sounds, mcl_tools
description = Adds the cartography table villager workstation to MineClone 2/5. Used to copy and create maps.
author = PrairieWind, mirqf, AFCM, kno10
depends = mcl_core, mcl_sounds, mcl_tools, mcl_formspec, tt, mcl_maps
description = Adds the cartography table villager workstation to Voxelibre. Used to copy and create maps.

View file

@ -1,189 +1,262 @@
-- TODO: improve support for larger zoom levels, benchmark raycasting, too?
-- TODO: only send texture to players that have the map
-- TODO: use ephemeral textures or base64 inline textures to eventually allow explorer maps?
-- TODO: show multiple players on the map
-- TODO: show banners on map
-- TODO: when the minimum supported Luanti version has core.get_node_raw, use it
-- Check for engine updates that allow improvements
mcl_maps = {}
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local S = minetest.get_translator(modname)
mcl_maps.max_zoom = (tonumber(core.settings:get("vl_maps_max_zoom")) or 4)
mcl_maps.enable_maps = core.settings:get_bool("enable_real_maps", true)
mcl_maps.allow_nether_maps = core.settings:get_bool("vl_maps_allow_nether", true)
mcl_maps.map_allow_overlap = core.settings:get_bool("vl_maps_allow_overlap", true) -- 50% overlap allowed in each level
local modname = core.get_current_modname()
local modpath = core.get_modpath(modname)
local S = core.get_translator(modname)
local math = math
local vector = vector
local table = table
local pairs = pairs
local min, max, round, floor, ceil = math.min, math.max, math.round, math.floor, math.ceil
local HALF_PI = math.pi * 0.5
local pos_to_string = minetest.pos_to_string
local string_to_pos = minetest.string_to_pos
local get_item_group = minetest.get_item_group
local dynamic_add_media = minetest.dynamic_add_media
local get_connected_players = minetest.get_connected_players
local pos_to_string = core.pos_to_string
local string_to_pos = core.string_to_pos
local get_item_group = core.get_item_group
local dynamic_add_media = core.dynamic_add_media
local get_connected_players = core.get_connected_players
local get_node_name_raw = mcl_vars.get_node_name_raw
local storage = minetest.get_mod_storage()
local worldpath = minetest.get_worldpath()
local map_textures_path = worldpath .. "/mcl_maps/"
--local last_finished_id = storage:get_int("next_id") - 1
local storage = core.get_mod_storage()
local worldpath = core.get_worldpath()
local map_textures_path = worldpath .. DIR_DELIM .. "mcl_maps" .. DIR_DELIM
minetest.mkdir(map_textures_path)
core.mkdir(map_textures_path)
local function load_json_file(name)
local file = assert(io.open(modpath .. "/" .. name .. ".json", "r"))
local data = minetest.parse_json(file:read("*all"))
local file = assert(io.open(modpath .. DIR_DELIM .. name .. ".json", "r"))
local data = core.parse_json(file:read("*all"))
file:close()
return data
end
local texture_colors = load_json_file("colors")
local creating_maps = {}
local loaded_maps = {}
local maps_generating, maps_loading = {}, {}
local c_air = minetest.get_content_id("air")
-- Main map generation function, called from emerge
local function do_generate_map(id, minp, maxp, callback, t1)
local t2 = os.clock()
-- Generate a (usually) 128x128 linear array for the image
local pixels = {}
local xsize, zsize = maxp.x - minp.x + 1, maxp.z - minp.z + 1
-- Step size, for zoom levels > 1
local xstep, zstep = ceil(xsize / 128), ceil(zsize / 128)
for z = zsize, 1, -zstep do
local map_z = minp.z + z - 1
local last_height
for x = 1, xsize, xstep do
local map_x = minp.x + x - 1
-- color aggregate and height information (for 3D effect)
local cagg, height = { 0, 0, 0, 0 }, nil
local solid_under_air = -1 -- anything but air, actually
for map_y = maxp.y, minp.y, -1 do
local nodename, _, param2 = get_node_name_raw(map_x, map_y, map_z)
if nodename ~= "air" then
local color = texture_colors[nodename]
-- use param2 if available:
if color and type(color[1]) == "table" then
color = color[param2 + 1] or color[1]
end
if color then
if solid_under_air == 0 then
cagg, height = { 0, 0, 0, 0 }, nil -- reset
solid_under_air = 1
end
local alpha = cagg[4] -- 0 (transparent) to 255 (opaque)
if alpha < 255 then
local a = (color[4] or 255) * (255 - alpha) / 255 -- 0 to 255
local f = a / 255 -- 0 to 1, color contribution
-- Alpha blend the colors:
cagg[1] = cagg[1] + f * color[1]
cagg[2] = cagg[2] + f * color[2]
cagg[3] = cagg[3] + f * color[3]
alpha = cagg[4] + a -- new alpha, 0 to 255
cagg[4] = alpha
end
function mcl_maps.create_map(pos)
local minp = vector.multiply(vector.floor(vector.divide(pos, 128)), 128)
local maxp = vector.add(minp, vector.new(127, 127, 127))
-- ground estimate with transparent blocks
if alpha > 140 and not height then height = map_y end
if alpha >= 250 and solid_under_air > 0 then
-- adjust color to give a 3d effect
if last_height and height then
local dheight = max(-48, min((height - last_height) * 8, 48))
cagg[1] = cagg[1] + dheight
cagg[2] = cagg[2] + dheight
cagg[3] = cagg[3] + dheight
end
cagg[4] = 255 -- make fully opaque
break
end
end
elseif solid_under_air == -1 then
solid_under_air = 0 -- first air
end
end
-- clamp colors values to 0:255 for PNG
-- because 3d height effect may exceed this range
cagg[1] = max(0, min(round(cagg[1]), 255))
cagg[2] = max(0, min(round(cagg[2]), 255))
cagg[3] = max(0, min(round(cagg[3]), 255))
cagg[4] = max(0, min(round(cagg[4]), 255))
pixels[#pixels + 1] = string.char(cagg[1], cagg[2], cagg[3], cagg[4])
last_height = height
end
end
-- Save as png texture
local t3 = os.clock()
local filename = map_textures_path .. "mcl_maps_map_" .. id .. ".png"
core.safe_file_write(filename, core.encode_png(xsize / xstep, zsize / zstep, table.concat(pixels)))
local t4 = os.clock()
--core.log("action", string.format("Completed map %s after %.2fms (%.2fms emerge, %.2fms map, %.2fms png)", id, (os.clock()-t1)*1000, (t2-t1)*1000, (t3-t2)*1000, (t4-t3)*1000))
maps_generating[id] = nil
if callback then callback(id, filename) end
end
-- Trigger map generation
local function emerge_generate_map(id, minp, maxp, callback)
if maps_generating[id] then return end
maps_generating[id] = true
local t1 = os.clock()
core.emerge_area(minp, maxp, function(blockpos, action, calls_remaining)
if calls_remaining > 0 then return end
-- do a DOUBLE emerge to give mapgen the chance to place structures triggered by the initial emerge
core.emerge_area(minp, maxp, function(blockpos, action, calls_remaining)
if calls_remaining > 0 then return end
do_generate_map(id, minp, maxp, callback, t1)
end)
end)
end
local function configure_map(itemstack, cx, dim, cz, zoom, callback)
zoom = max(zoom or 1, 1)
-- Texture size is 128
local size = 64 * (2^zoom)
local halfsize = size / 2
-- If enabled, round to halfsize grid, otherwise to size grid.
if mcl_maps.map_allow_overlap then
cx, cz = (floor(cx / halfsize) + 0.5) * halfsize, (floor(cz / halfsize) + 0.5) * halfsize
else
cx, cz = (floor(cx / size) + 0.5) * size, (floor(cz / size) + 0.5) * size
end
-- Y range to use for mapping. In nether, if we begin above bedrock, maps will be bedrock only, similar to MC
-- Prefer smaller ranges for performance!
local miny, maxy
if dim == "end" then
miny, maxy = mcl_vars.mg_end_min + 48, mcl_vars.mg_end_min + 127
elseif dim == "nether" then
if mcl_maps.allow_nether_maps then
miny, maxy = mcl_vars.mg_nether_min + 16, mcl_vars.mg_nether_deco_max
else
miny, maxy = mcl_vars.mg_nether_max, mcl_vars.mg_nether_max -- map the nether roof...
end
elseif dim == "overworld" then
miny, maxy = -32, 63
else
miny = tonumber(dim) - 32
maxy = miny + 63
end
-- File name conventions, including a unique number in case someone maps the same area twice (old and new)
local seq = storage:get_int("next_id")
storage:set_int("next_id", seq + 1)
local id = table.concat({cx, dim, cz, zoom, seq}, "_")
local minp = vector.new(cx - halfsize, miny, cz - halfsize)
local maxp = vector.new(cx + halfsize - 1, maxy, cz + halfsize - 1)
local itemstack = ItemStack("mcl_maps:filled_map")
local meta = itemstack:get_meta()
local next_id = storage:get_int("next_id")
storage:set_int("next_id", next_id + 1)
local id = tostring(next_id)
meta:set_string("mcl_maps:id", id)
meta:set_int("mcl_maps:cx", cx)
meta:set_string("mcl_maps:dim", dim)
meta:set_int("mcl_maps:cz", cz)
meta:set_int("mcl_maps:zoom", zoom)
meta:set_string("mcl_maps:minp", pos_to_string(minp))
meta:set_string("mcl_maps:maxp", pos_to_string(maxp))
tt.reload_itemstack_description(itemstack)
creating_maps[id] = true
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining)
if calls_remaining > 0 then
return
end
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(minp, maxp)
local data = vm:get_data()
local param2data = vm:get_param2_data()
local area = VoxelArea:new({ MinEdge = emin, MaxEdge = emax })
local pixels = {}
for z = 1, 128 do
local map_z = minp.z - 1 + z
local last_height
for x = 1, 128 do
local map_x = minp.x - 1 + x
local cagg, alpha, height = { 0, 0, 0 }, 0
for map_y = maxp.y, minp.y, -1 do
local index = area:index(map_x, map_y, map_z)
local c_id = data[index]
if c_id ~= c_air then
local color = texture_colors[minetest.get_name_from_content_id(c_id)]
-- use param2 if available:
if color and type(color[1]) == "table" then
color = color[param2data[index] + 1] or color[1]
end
if color then
local a = (color[4] or 255) / 255
local f = a * (1 - alpha)
cagg[1] = cagg[1] + f * color[1]
cagg[2] = cagg[2] + f * color[2]
cagg[3] = cagg[3] + f * color[3]
alpha = alpha + f
-- ground estimate with transparent blocks
if alpha > 0.70 and not height then height = map_y end
-- adjust color to give a 3d effect
if alpha >= 0.99 and last_height and height then
local dheight = math.min(math.max((height - last_height) * 8, -32), 32)
cagg = {
math.max(0, math.min(255, cagg[1] + dheight)),
math.max(0, math.min(255, cagg[2] + dheight)),
math.max(0, math.min(255, cagg[3] + dheight)),
}
end
if alpha >= 0.99 then break end
end
end
end
last_height = height
pixels[z] = pixels[z] or {}
pixels[z][x] = cagg or { 0, 0, 0 }
end
end
tga_encoder.image(pixels):save(map_textures_path .. "mcl_maps_map_texture_" .. id .. ".tga")
creating_maps[id] = nil
end)
emerge_generate_map(id, minp, maxp, callback)
return itemstack
end
function mcl_maps.load_map(id, callback)
if id == "" or creating_maps[id] then
return false
end
if id == "" or maps_generating[id] then return false end
local texture = "mcl_maps_map_texture_" .. id .. ".tga"
local result = true
if not loaded_maps[id] then
if not minetest.features.dynamic_add_media_table then
-- minetest.dynamic_add_media() blocks in
-- Luanti 5.3 and 5.4 until media loads
loaded_maps[id] = true
result = dynamic_add_media(map_textures_path .. texture, function()
end)
if callback then
callback(texture)
end
else
-- minetest.dynamic_add_media() never blocks
-- in Luanti 5.5, callback runs after load
result = dynamic_add_media(map_textures_path .. texture, function()
loaded_maps[id] = true
if callback then
callback(texture)
end
end)
end
end
if result == false then
return false
end
if loaded_maps[id] then
if callback then
callback(texture)
end
local texture = "mcl_maps_map_" .. id .. ".png"
if maps_loading[id] then
if callback then callback(texture) end
return texture
end
-- core.dynamic_add_media() never blocks in Minetest 5.5, callback runs after load
-- TODO: send only to the player that needs it!
dynamic_add_media(map_textures_path .. texture, function()
if not maps_loading[id] then -- avoid repeated callbacks
maps_loading[id] = true
if callback then callback(texture) end
end
end)
end
function mcl_maps.load_map_item(itemstack)
return mcl_maps.load_map(itemstack:get_meta():get_string("mcl_maps:id"))
function mcl_maps.create_map(pos, zoom, callback)
local dim = mcl_worlds.pos_to_dimension(pos)
if dim == "overworld" and pos.y >= 48 then dim = tostring(round(pos.y/64)*64) end -- for float islands
local itemstack = ItemStack("mcl_maps:filled_map")
configure_map(itemstack, pos.x, dim, pos.z, zoom, callback)
return itemstack
end
function mcl_maps.load_map_item(itemstack, callback)
return mcl_maps.load_map(itemstack:get_meta():get_string("mcl_maps:id"), callback)
end
function mcl_maps.regenerate_map(itemstack, callback)
local meta = itemstack:get_meta()
local cx, cz = meta:get_int("mcl_maps:cx"), meta:get_int("mcl_maps:cz")
local dim = meta:get_string("mcl_maps:dim")
local zoom = meta:get_int("mcl_maps:zoom")
if mcl_maps.enable_maps then
configure_map(itemstack, cx, dim, cz, zoom, callback)
end
end
local function fill_map(itemstack, placer, pointed_thing)
local new_stack = mcl_util.call_on_rightclick(itemstack, placer, pointed_thing)
if new_stack then
return new_stack
end
if new_stack then return new_stack end
if minetest.settings:get_bool("enable_real_maps", true) then
local new_map = mcl_maps.create_map(placer:get_pos())
itemstack:take_item()
if itemstack:is_empty() then
return new_map
else
local inv = placer:get_inventory()
if inv:room_for_item("main", new_map) then
inv:add_item("main", new_map)
else
minetest.add_item(placer:get_pos(), new_map)
end
return itemstack
if mcl_maps.enable_maps then
mcl_title.set(placer, "actionbar", {text=S("It may take a moment for the map to be ready."), color="gold", stay=5*20})
local callback = function(id, filename)
mcl_title.set(placer, "actionbar", {text=S("The new map is now ready."), color="green", stay=3*20})
end
local new_map = mcl_maps.create_map(placer:get_pos(), 0, callback)
itemstack:take_item()
if itemstack:is_empty() then return new_map end
local inv = placer:get_inventory()
if inv:room_for_item("main", new_map) then
inv:add_item("main", new_map)
else
core.add_item(placer:get_pos(), new_map)
end
return itemstack
end
end
minetest.register_craftitem("mcl_maps:empty_map", {
core.register_craftitem("mcl_maps:empty_map", {
description = S("Empty Map"),
_doc_items_longdesc = S("Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used."),
_doc_items_usagehelp = S("Rightclick to create a filled map (which can't be stacked anymore)."),
_doc_items_usagehelp = S("Rightclick to create a filled map (which cannot be stacked anymore)."),
inventory_image = "mcl_maps_map_empty.png",
on_place = fill_map,
on_secondary_use = fill_map,
@ -200,10 +273,10 @@ local filled_def = {
groups = { not_in_creative_inventory = 1, filled_map = 1, tool = 1 },
}
minetest.register_craftitem("mcl_maps:filled_map", filled_def)
core.register_craftitem("mcl_maps:filled_map", filled_def)
local filled_wield_def = table.copy(filled_def)
filled_wield_def.use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false
filled_wield_def.use_texture_alpha = core.features.use_texture_alpha_string_modes and "opaque" or false
filled_wield_def.visual_scale = 1
filled_wield_def.wield_scale = { x = 1, y = 1, z = 1 }
filled_wield_def.paramtype = "light"
@ -212,7 +285,7 @@ filled_wield_def.node_placement_prediction = ""
filled_wield_def.on_place = mcl_util.call_on_rightclick
filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map"
local mcl_skins_enabled = minetest.global_exists("mcl_skins")
local mcl_skins_enabled = core.global_exists("mcl_skins")
if mcl_skins_enabled then
-- Generate a node for every skin
@ -223,26 +296,26 @@ if mcl_skins_enabled then
female._mcl_hand_id = skin.id
female.mesh = "mcl_meshhand_female.b3d"
female.tiles = { skin.texture }
minetest.register_node("mcl_maps:filled_map_" .. skin.id, female)
core.register_node("mcl_maps:filled_map_" .. skin.id, female)
else
local male = table.copy(filled_wield_def)
male._mcl_hand_id = skin.id
male.mesh = "mcl_meshhand.b3d"
male.tiles = { skin.texture }
minetest.register_node("mcl_maps:filled_map_" .. skin.id, male)
core.register_node("mcl_maps:filled_map_" .. skin.id, male)
end
end
else
filled_wield_def._mcl_hand_id = "hand"
filled_wield_def.mesh = "mcl_meshhand.b3d"
filled_wield_def.tiles = { "character.png" }
minetest.register_node("mcl_maps:filled_map_hand", filled_wield_def)
core.register_node("mcl_maps:filled_map_hand", filled_wield_def)
end
local old_add_item = minetest.add_item
function minetest.add_item(pos, stack)
local old_add_item = core.add_item
function core.add_item(pos, stack)
if not pos then
minetest.log("warning", "Trying to add item with missing pos: " .. tostring(stack))
core.log("warning", "Trying to add item with missing pos: " .. tostring(stack))
return
end
stack = ItemStack(stack)
@ -254,23 +327,23 @@ end
tt.register_priority_snippet(function(itemstring, _, itemstack)
if itemstack and get_item_group(itemstring, "filled_map") > 0 then
local id = itemstack:get_meta():get_string("mcl_maps:id")
if id ~= "" then
return "#" .. id, mcl_colors.GRAY
local zoom = itemstack:get_meta():get_string("mcl_maps:zoom")
if zoom ~= "" then
return S("Level @1", zoom), mcl_colors.GRAY
end
end
end)
minetest.register_craft({
core.register_craft({
output = "mcl_maps:empty_map",
recipe = {
{ "mcl_core:paper", "mcl_core:paper", "mcl_core:paper" },
{ "mcl_core:paper", "group:compass", "mcl_core:paper" },
{ "mcl_core:paper", "group:compass", "mcl_core:paper" },
{ "mcl_core:paper", "mcl_core:paper", "mcl_core:paper" },
}
})
minetest.register_craft({
core.register_craft({
type = "shapeless",
output = "mcl_maps:filled_map 2",
recipe = { "group:filled_map", "mcl_maps:empty_map" },
@ -287,13 +360,13 @@ local function on_craft(itemstack, player, old_craft_grid, craft_inv)
end
end
minetest.register_on_craft(on_craft)
minetest.register_craft_predict(on_craft)
core.register_on_craft(on_craft)
core.register_craft_predict(on_craft)
local maps = {}
local huds = {}
minetest.register_on_joinplayer(function(player)
core.register_on_joinplayer(function(player)
local map_def = {
hud_elem_type = "image",
text = "blank.png",
@ -310,17 +383,17 @@ minetest.register_on_joinplayer(function(player)
}
end)
minetest.register_on_leaveplayer(function(player)
core.register_on_leaveplayer(function(player)
maps[player] = nil
huds[player] = nil
end)
minetest.register_globalstep(function(dtime)
core.register_globalstep(function(dtime)
for _, player in pairs(get_connected_players()) do
local wield = player:get_wielded_item()
local texture = mcl_maps.load_map_item(wield)
local hud = huds[player]
if texture then
local hud = huds[player]
local wield_def = wield:get_definition()
local hand_def = player:get_inventory():get_stack("hand", 1):get_definition()
@ -329,18 +402,21 @@ minetest.register_globalstep(function(dtime)
player:set_wielded_item(wield)
end
if texture ~= maps[player] then
-- change map only when necessary
if not maps[player] or texture ~= maps[player][1] then
player:hud_change(hud.map, "text", "[combine:140x140:0,0=mcl_maps_map_background.png:6,6=" .. texture)
maps[player] = texture
local meta = wield:get_meta()
local minp = string_to_pos(meta:get_string("mcl_maps:minp"))
local maxp = string_to_pos(meta:get_string("mcl_maps:maxp"))
maps[player] = {texture, minp, maxp}
end
local pos = vector.round(player:get_pos())
local meta = wield:get_meta()
local minp = string_to_pos(meta:get_string("mcl_maps:minp"))
local maxp = string_to_pos(meta:get_string("mcl_maps:maxp"))
-- map overlay with player position
local pos = player:get_pos() -- was: vector.round(player:get_pos())
local minp, maxp = maps[player][2], maps[player][3]
-- Use dots when outside of map, indicate direction
local marker = "mcl_maps_player_arrow.png"
if pos.x < minp.x then
marker = "mcl_maps_player_dot.png"
pos.x = minp.x
@ -358,13 +434,17 @@ minetest.register_globalstep(function(dtime)
end
if marker == "mcl_maps_player_arrow.png" then
local yaw = (math.floor(player:get_look_horizontal() * 180 / math.pi / 90 + 0.5) % 4) * 90
local yaw = (floor(player:get_look_horizontal() / HALF_PI + 0.5) % 4) * 90
marker = marker .. "^[transformR" .. yaw
end
-- Note the alignment and scale used above
local f = 2 * 128 / (maxp.x - minp.x + 1)
player:hud_change(hud.marker, "offset", { x = (pos.x - minp.x) * f - 128, y = (maxp.z - pos.z) * f - 256 })
player:hud_change(hud.marker, "text", marker)
player:hud_change(hud.marker, "offset", { x = (6 - 140 / 2 + pos.x - minp.x) * 2, y = (6 - 140 + maxp.z - pos.z) * 2 })
elseif maps[player] then
elseif maps[player] then -- disable map
local hud = huds[player]
player:hud_change(hud.map, "text", "blank.png")
player:hud_change(hud.marker, "text", "blank.png")
maps[player] = nil

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=Es kann einen Moment dauern, bis die Karte verfügbar ist.
The new map is now ready.=Die Karte ist jetzt fertig.
Empty Map=Leere Karte
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Leere Karten sind als Karten nicht nützlich, aber sie können gestapelt werden und zu benutzbaren Karten umgewandelt werden.
Rightclick to create a filled map (which can't be stacked anymore).=Rechtsklick, um die Karte zu füllen. Sie kann dann nicht mehr gestapelt werden.
Rightclick to create a filled map (which cannot be stacked anymore).=Rechtsklick, um die Karte zu füllen. Sie kann dann nicht mehr gestapelt werden.
Map=Karte
Shows a map image.=Zeigt ein Kartenbild.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Beim Erstellen speichert die Karte die Gegend in der Nähe als ein Bild, dass jederzeit durch halten der Karte angesehen werden kann.
Hold the map in your hand. This will display a map on your screen.=Halten Sie die Karte in Ihrer Hand. Eine Karte wird auf Ihrem Bildschirm angezeigt werden.
Level @1=Stufe @1

View file

@ -1,13 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Mapa vacio
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Los mapas vacíos no son útiles como mapas, pero se pueden apilar y convertir en mapas que se pueden usar.
Rightclick to create a filled map (which can't be stacked anymore).=
Rightclick to create a filled map (which cannot be stacked anymore).=
Map=Mapa
Shows a map image.=
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=
Hold the map in your hand. This will display a map on your screen.=
##### not used anymore #####
Rightclick to start using the map (which can't be stacked anymore).=Haga clic derecho para comenzar a usar el mapa (que ya no se puede apilar).
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Carte Vierge
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Les cartes vierges ne sont pas utiles en tant que cartes, mais elles peuvent être empilées et transformées en cartes utilisables.
Rightclick to create a filled map (which can't be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée).
Rightclick to create a filled map (which cannot be stacked anymore).=Clic droit pour créer une carte remplie (qui ne peut plus être empilée).
Map=Carte
Shows a map image.=Affiche une carte.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Lors de sa création, la carte sauvegarde le terrain proche sous forme d'image qui peut être consultée n'importe quand en tenant la carte dans la main.
Hold the map in your hand. This will display a map on your screen.=Tenez la carte dans votre main. Cela affichera la carte à l'écran.
Level @1=

View file

@ -1,8 +1,12 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Mapa baleiro
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Os mapas baleiros non son útiles como mapas, pero pódense apilar e converter en mapas que se poden usar.
Rightclick to create a filled map (which can't be stacked anymore).=Fai clic co botón dereito para crear un mapa cheo (que xa non se pode apilar).
##TODO: fuzzy matched - verify and remove the comment
Rightclick to create a filled map (which cannot be stacked anymore).=Fai clic co botón dereito para crear un mapa cheo (que xa non se pode apilar).
Map=Mapa
Shows a map image.=Mostra unha imaxe de mapa.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Cando se crea, o mapa garda a zona próxima como unha imaxe que se pode ver en calquera momento mantendo pulsado o mapa.
Hold the map in your hand. This will display a map on your screen.=Manteña o mapa na man. Isto amosará un mapa na súa pantalla.
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=白紙の地図
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=白紙の地図は地図として使えませんが、スタックしたり、使える地図に変えられます。
Rightclick to create a filled map (which can't be stacked anymore).=右クリックで塗りつぶしたマップを作成します(スタックはできなくなります)。
Rightclick to create a filled map (which cannot be stacked anymore).=右クリックで塗りつぶしたマップを作成します(スタックはできなくなります)。
Map=地図
Shows a map image.=地図画像を表示します。
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=作成すると、その付近の地図が画像として保存され、地図をかざすといつでも見ることができます。
Hold the map in your hand. This will display a map on your screen.=地図を手に持ってください。これで画面に地図が表示されます。
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Tomt kart
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Tomme kart er ikke nyttige som kart, men de kan stables og gjøres om til kart som kan brukes.
Rightclick to create a filled map (which can't be stacked anymore).=Høyreklikk for å lage et fylt kart (som ikke kan stables lenger).
Rightclick to create a filled map (which cannot be stacked anymore).=Høyreklikk for å lage et fylt kart (som ikke kan stables lenger).
Map=Kart
Shows a map image.=Viser et kartbilde.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Når kartet opprettes, lagres det nærliggende området som et bilde som kan vises når som helst ved å holde kartet.
Hold the map in your hand. This will display a map on your screen.=Hold kartet i hånden. Dette vil vise et kart på skjermen.
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Pusta mapa
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Puste mapy nie są tak użyteczne jak mapy ale mogą być grupowane i zamienione w mapy które już są pożyteczne.
Rightclick to create a filled map (which can't be stacked anymore).=Kliknij prawy przycisk aby stworzyć wypełnioną mapę (nie będzie już jej można grupować).
Rightclick to create a filled map (which cannot be stacked anymore).=Kliknij prawy przycisk aby stworzyć wypełnioną mapę (nie będzie już jej można grupować).
Map=Mapa
Shows a map image.=Pokazuje obraz mapy.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Gdy są utworzone mapy zapisują obszar okolicy jako obrazek, który może być oglądany przez trzymanie mapy w rękach.
Hold the map in your hand. This will display a map on your screen.=Weź mapę do ręki. To pokaże mapę na twoim ekranie.
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Mapa Vazio
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Mapas vazios não são úteis como mapas, mas eles podem ser empilhados e transfomados em mapas aos quais podem ser usados.
Rightclick to create a filled map (which can't be stacked anymore).=Clique com o botão direito para criar um mapa preenchido (ao qual não pode mais ser empilhado).
Rightclick to create a filled map (which cannot be stacked anymore).=Clique com o botão direito para criar um mapa preenchido (ao qual não pode mais ser empilhado).
Map=Mapa
Shows a map image.=Mostra uma imagem do mapa.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=Quando criado, o mapa salva a área próxima como uma imagem que pode ser visualizada sempre que você segurar o mapa.
Hold the map in your hand. This will display a map on your screen.=Segure o mapa em suas mãos. Isso mostrará um mapa em sua tela.
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=Пустая карта
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=Пустые карты не так полезны как карты, но могут складываться в стопки, а также могут быть превращены в полноценные карты.
Rightclick to create a filled map (which can't be stacked anymore).=Правый клик, чтобы заполнить карту (больше не может складываться в стопки).
Rightclick to create a filled map (which cannot be stacked anymore).=Правый клик, чтобы заполнить карту (больше не может складываться в стопки).
Map=Карта
Shows a map image.=Показать карту.
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=После создания карта сохраняет ближайшую местность которую можно посмотеть в любое время взяв карту в руки.
Hold the map in your hand. This will display a map on your screen.=Возьмите карту в руки. Так появится изображение карты на экране.
Level @1=

View file

@ -1,18 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=空白地图
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=空白地图作为地图本身没什么用处,但它们可以堆叠起来,并转化为能使用的地图。
Rightclick to create a filled map (which can't be stacked anymore).=
Rightclick to create a filled map (which cannot be stacked anymore).=
Map=地图
Shows a map image.=
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=
Hold the map in your hand. This will display a map on your screen.=
##### not used anymore #####
Rightclick to start using the map (which can't be stacked anymore).=右键点击开始使用地图(该地图不能再堆叠了)。
Maps show your surroundings as you explore the world.=在你探索世界时,地图会显示你周围的环境。
Hold the map in any of the hotbar slots. This allows you to access the minimap by pressing the minimap key (see controls settings).=将地图放在快捷栏的任意栏位中,这样你按下小地图键就能访问小地图了(见控制设置)。
In Creative Mode, you don't need this item; the minimap is always available.=在创造模式下,你不需要这个物品,小地图始终是可用的。
Enables minimap=启用小地图
Use the minimap key to show the map.=使用小地图键来显示地图。
Level @1=

View file

@ -1,18 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=空地圖
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=空的地圖作為地圖是沒有用的,但它們可以被疊加,並變成可以使用的地圖。
Rightclick to create a filled map (which can't be stacked anymore).=
Rightclick to create a filled map (which cannot be stacked anymore).=
Map=地圖
Shows a map image.=
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=
Hold the map in your hand. This will display a map on your screen.=
##### not used anymore #####
Rightclick to start using the map (which can't be stacked anymore).=右鍵單擊以開始使用地圖(該地圖無法再堆疊)。
Maps show your surroundings as you explore the world.=當您探索世界時,地圖會顯示您的周圍環境。
Hold the map in any of the hotbar slots. This allows you to access the minimap by pressing the minimap key (see controls settings).=在任何一個熱鍵槽中放置地圖。這允許你通過按小地圖鍵來訪問小地圖(見控制設置)。
In Creative Mode, you don't need this item; the minimap is always available.=在創造模式下,您不需要此項目; 小地圖始終可用。
Enables minimap=啓用小地圖
Use the minimap key to show the map.=使用小地圖鍵來顯示小地圖。
Level @1=

View file

@ -1,8 +1,11 @@
# textdomain: mcl_maps
It may take a moment for the map to be ready.=
The new map is now ready.=
Empty Map=
Empty maps are not useful as maps, but they can be stacked and turned to maps which can be used.=
Rightclick to create a filled map (which can't be stacked anymore).=
Rightclick to create a filled map (which cannot be stacked anymore).=
Map=
Shows a map image.=
When created, the map saves the nearby area as an image that can be viewed any time by holding the map.=
Hold the map in your hand. This will display a map on your screen.=
Level @1=

View file

@ -1,2 +1,3 @@
name = mcl_maps
depends = mcl_core, mcl_flowers, tga_encoder, tt, mcl_colors, mcl_skins, mcl_util
author = wuzzy, fleckenstein, kno10
depends = mcl_core, mcl_flowers, tt, mcl_colors, mcl_skins, mcl_util, mcl_title

View file

@ -320,6 +320,15 @@ fix_doubleplants (Mcimport double plant fixes) bool true
# Allow players to create Minecraft-like maps.
enable_real_maps (Enable Real Maps) bool true
# Make maps in the Nether show not only the bedrock.
vl_maps_allow_nether (Make maps in the Nether useful) bool true
# Allow maps to overlap 50% per level
vl_maps_allow_overlap (Allow overlapping maps by 50%) bool true
# Maximum map zoom level permitted (high zoom levels can take very long, do not increase on multiplayer servers)
vl_maps_max_zoom (Maximum Zoom Level) int 2 1 5
# Enable workarounds for faulty mob navigation.
# Hack 1: teleport golems home if they are very far from home
mcl_mob_allow_nav_hacks (Mob navigation hacks) bool false