First draft marker editor in the map formspec

This commit is contained in:
Hugues Ross 2020-03-28 09:51:38 -04:00
parent bda796c101
commit ade84c374d
4 changed files with 119 additions and 34 deletions

View File

@ -8,6 +8,7 @@ _cartographer = {
CHUNK_SIZE = 16,
biome_lookup = {},
marker_count = 0,
marker_lookup = {},
maps = minetest.deserialize(mod_storage:get_string("maps")) or {},
next_map_id = mod_storage:get_int("next_map_id"),
@ -54,6 +55,7 @@ dofile(modpath .. "/commands.lua");
dofile(modpath .. "/scanner.lua");
dofile(modpath .. "/map_api.lua");
dofile(modpath .. "/map_formspec.lua");
dofile(modpath .. "/marker_formspec.lua");
dofile(modpath .. "/items.lua");
dofile(modpath .. "/table.lua");

121
items.lua
View File

@ -1,4 +1,31 @@
local function map_from_meta(meta, player_x, player_y)
-- The list of players looking at maps, and the map IDs that they're looking at
local player_maps = {};
-- Show a map to a player from the ID
-- id: The map ID
-- player_x: The X position (in map coordinates)
-- player_z: The Z position (in map coordinates)
-- player_name: The name of the player to show to
local function show_map_id_formspec(id, player_x, player_z, player_name)
cartographer.fill_local(id, player_x, player_z);
player_maps[player_name] = id;
local map = cartographer.get_map(id);
local formspec = cartographer.get_map_formspec_map(data, map, player_x, player_z);
if _cartographer.marker_count > 0 then
formspec = formspec .. string.format("style_type[button,image_button;noclip=true;border=true] container[%f,0.5]", map.w * 0.25) -- TODO: Don't assume map.w * 0.25
.. _cartographer.generate_marker_formspec(cartographer.get_marker(map, player_x, player_z), map.detail)
.. "container_end[]";
end
minetest.show_formspec(player_name, "cartographer:map", formspec);
end
-- Create a map from metadata, and assign the ID to the metadata
-- meta: A metadata object containing the map ID
-- player_x: The X position (in map coordinates)
-- player_z: The Z position (in map coordinates)
local function map_from_meta(meta, player_x, player_z)
local size = meta:get_int("cartographer:size") or 10;
local detail = meta:get_int("cartographer:detail") or 1;
local scale = meta:get_int("cartographer:scale") or 1;
@ -6,7 +33,7 @@ local function map_from_meta(meta, player_x, player_y)
local total_size = size * scale;
local map_x = math.floor((player_x + 10)/total_size) * total_size - 10
local map_y = math.floor((player_y + 10)/total_size) * total_size - 10;
local map_y = math.floor((player_z + 10)/total_size) * total_size - 10;
local id = cartographer.create_map(map_x, map_y, size, size, false, detail, scale);
@ -16,6 +43,51 @@ local function map_from_meta(meta, player_x, player_y)
return id;
end
-- Show a map to a player from metadata, creating it if possible
-- meta: A metadata object containing the map ID
-- player: The player to show the map to
local function show_map_meta(meta, player)
local pos = player:get_pos();
local player_x = tochunk(pos.x);
local player_z = tochunk(pos.z);
local id = meta:get_int("cartographer:map_id");
if id == 0 then
id = map_from_meta(meta, player_x, player_z);
end
show_map_id_formspec(id, player_x, player_z, player:get_player_name());
end
-- Called when a player sends input to the server from a formspec
-- This callback handles player input in the map formspec, for editing markers
-- player: The player who sent the input
-- name: The formspec name
-- fields: A table containing the input
minetest.register_on_player_receive_fields(function(player, name, fields)
if name == "cartographer:map" then
local map = cartographer.get_map(player_maps[player:get_player_name()]);
if not map then
return;
end
for k,v in pairs(fields) do
local marker = k:match("marker%-(.+)");
minetest.chat_send_all(k .. ": " .. tostring(marker));
if marker or k == "clear_marker" then
local pos = player:get_pos();
local player_x = tochunk(pos.x);
local player_z = tochunk(pos.z);
cartographer.set_marker(map, player_x, player_z, marker);
show_map_id_formspec(player_maps[player:get_player_name()], player_x, player_z, player:get_player_name());
elseif k == "quit" then
player_maps[player:get_player_name()] = nil;
end
end
end
end);
-- The map item/node
minetest.register_node("cartographer:map", {
description = "Map",
@ -33,25 +105,6 @@ minetest.register_node("cartographer:map", {
{-0.5, -0.5, -0.5, 0.5, -7 / 16, 0.5},
},
},
on_use = function(stack, player, _)
local pos = player:get_pos();
local name = player:get_player_name();
local player_x = tochunk(pos.x);
local player_y = tochunk(pos.z);
local meta = stack:get_meta();
local id = meta:get_int("cartographer:map_id");
if id == 0 then
id = map_from_meta(meta, player_x, player_y);
end
cartographer.fill_local(id, player_x, player_y);
minetest.show_formspec(player:get_player_name(), "map", cartographer.get_map_formspec_map(data, cartographer.get_map(id), player_x, player_y));
return stack;
end,
-- Called when this node is placed in the world. Copies map data from the
-- item to the node.
@ -68,20 +121,20 @@ minetest.register_node("cartographer:map", {
return false;
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local meta = minetest.get_meta(pos);
-- Called when a player right-clicks this node. Display's the map's
-- content, creating it if it doesn't exist.
-- pos: The position of the node
-- player: The player that right-clicked the node
on_rightclick = function(pos, _, player)
show_map_meta(minetest.get_meta(pos), player);
end,
local player_x = tochunk(pos.x);
local player_y = tochunk(pos.z);
local id = meta:get_int("cartographer:map_id");
if id == 0 then
id = map_from_meta(meta, player_x, player_y);
end
cartographer.fill_local(id, player_x, player_y);
minetest.show_formspec(player:get_player_name(), "map", cartographer.get_map_formspec_map(data, cartographer.get_map(id), player_x, player_y));
-- Called when a player uses this item. Displays the map's content,
-- creating it if it doesn't exist.
-- stack: The itemstack
-- player: The player that used the item
on_use = function(stack, player)
show_map_meta(stack:get_meta(), player);
end,
});

View File

@ -141,6 +141,10 @@ end
-- These should correspond with detail levels,
-- any detail level past the length of the table will return the last texture
function cartographer.register_marker(id, name, textures)
if not _cartographer.marker_lookup then
_cartographer.marker_count = _cartographer.marker_count + 1;
end
_cartographer.marker_lookup[id] = {
name = name,
textures = textures,

26
marker_formspec.lua Normal file
View File

@ -0,0 +1,26 @@
-- Generates formspec data for the map marker editor
-- selected_id: The id of the currently selected marker, or nil if no marker is
-- selected
-- detail: The map's detail level
--
-- Returns a formspec string for use in containers
function _cartographer.generate_marker_formspec(selected_id, detail)
local fs = "button[0,0;0.5,0.5;clear_marker;x]";
if selected_id then
fs = fs .. string.format("style[marker-%s;bgcolor=blue]", selected_id);
end
-- TODO: Support pagination if _cartographer.marker_count is too high
local i = 0;
for id in pairs(_cartographer.marker_lookup) do
fs = fs .. string.format("image_button[%f,%f;0.5,0.5;%s.png;marker-%s;]",
i % 5 * 0.5,
math.floor(i / 5) * 0.5 + 0.5,
cartographer.get_marker_texture(id, detail),
id);
i = i + 1;
end
return fs;
end