diff --git a/table.lua b/table.lua index 0b993c4..c15bd99 100644 --- a/table.lua +++ b/table.lua @@ -45,7 +45,11 @@ local function get_material_cost(size, detail) }; end -local function get_full_material_cost(meta) +-- Get the material cost of the craft settings from the given table metadata +-- meta: The metadata to read +-- +-- Returns a table with the material costs +local function get_craft_material_cost(meta) local cost = get_material_cost(meta:get_int("size") or SIZE_SMALL, meta:get_int("detail") or 0); local stack = meta:get_inventory():get_stack("output", 1); @@ -61,6 +65,62 @@ local function get_full_material_cost(meta) return cost; end +-- Get the material cost of the copy settings from the given table metadata +-- meta: The metadata to read +-- +-- Returns a table with the material costs +local function get_copy_material_cost(meta) + local inv = meta:get_inventory(); + local in_stack = inv:get_stack("copy_input", 1); + local out_stack = inv:get_stack("copy_output", 1); + + + if out_stack:is_empty() and in_stack:get_name() == "cartographer:map" then + local smeta = in_stack:get_meta(); + local size = smeta:get_int("cartographer:size") or SIZE_SMALL; + local detail = smeta:get_int("cartographer:detail") or 1; + + return get_material_cost(size, detail - 1); + end + + return { + paper = 0, + pigment = 0, + }; +end + +-- Get the converted material value of the given itemstack +-- stack: The itemstack to convert +-- +-- Returns a table with the material values +function cartographer.get_material_value(stack) + local item_name = stack:get_name(); + local item_count = stack:get_count(); + + for name,mats in pairs(_cartographer.materials_by_name) do + if name == item_name then + return { + paper = (mats.paper or 0) * item_count, + pigment = (mats.pigment or 0) * item_count, + } + end + end + + for group,mats in pairs(_cartographer.materials_by_group) do + if minetest.get_item_group(item_name, group) ~= 0 then + return { + paper = (mats.paper or 0) * item_count, + pigment = (mats.pigment or 0) * item_count, + } + end + end + + return { + paper = 0, + pigment = 0, + }; +end + local fs = {}; -- Draw a 1px thick horizontal separator formspec element @@ -144,12 +204,14 @@ end -- -- Returns a formspec string function fs.convert(x, y, pos, skin) + local meta = minetest.get_meta(pos); + return string.format("container[%f,%f]", x, y) .. "formspec_version[3]" .. inventory_bg(0, 0, 1, 1, skin.slot) .. string.format("list[nodemeta:%d,%d,%d;input;0,0;1,1;]", pos.x, pos.y, pos.z) .. "button[1.25,0.5;2,0.5;convert;Convert Materials]" - .. fs.cost(1.25, 0.125, { Paper = 0, Pigment = 0, }, skin) + .. fs.cost(1.25, 0.125, cartographer.get_material_value(meta:get_inventory():get_stack("input", 1)), skin) .. "container_end[]"; end @@ -168,7 +230,7 @@ function fs.craft(x, y, pos, rank, meta, skin) .. inventory_bg(0, 0.75, 1, 1, skin.slot) .. string.format("list[nodemeta:%d,%d,%d;output;0,0.75;1,1;]", pos.x, pos.y, pos.z) .. "button[1.25,1.25;2,0.5;craft;Craft Map]" - .. fs.cost(1.25, 0.875, get_full_material_cost(meta), skin); + .. fs.cost(1.25, 0.875, get_craft_material_cost(meta), skin); if rank > 1 then local size = "s"; @@ -213,12 +275,14 @@ end -- -- Returns a formspec string function fs.copy(x, y, pos, skin) + local meta = minetest.get_meta(pos); + return string.format("container[%f,%f]", x, y) .. "formspec_version[3]" .. inventory_bg(0, 0, 1, 1, skin.slot) .. string.format("list[nodemeta:%d,%d,%d;copy_input;0,0;1,1;]", pos.x, pos.y, pos.z) .. "button[1.25,0.5;2,0.5;copy;Copy Map]" - .. fs.cost(1.25, 0.125, { Paper = 0, Pigment = 0, }, skin) + .. fs.cost(1.25, 0.125, get_copy_material_cost(meta), skin) .. inventory_bg(8.75, 0, 1, 1, skin.slot) .. string.format("list[nodemeta:%d,%d,%d;copy_output;8.75,0;1,1;]", pos.x, pos.y, pos.z) .. "container_end[]"; @@ -244,10 +308,10 @@ local player_tables = {}; -- The player must be recorded in player_tables in order to receive -- a formspec. -- --- player: A string containing the player's name --- tab: Which tab of the interface to display -local function table_formspec(player, tab) - local pos = player_tables[player]; +-- player: The player's name +local function table_formspec(player) + local data = player_tables[player]; + local pos = data.pos; if not pos then return; @@ -266,27 +330,27 @@ local function table_formspec(player, tab) skin = cartographer.skin.table_skins.advanced_table; end - if tab == 1 then + if data.tab == 1 then minetest.show_formspec(player, "simple_table", - fs.header(10.25, 7.375, rank, tab, skin) .. + fs.header(10.25, 7.375, rank, data.tab, skin) .. fs.materials(0.25, 0.1875, meta, skin) .. fs.separator(0.6875, skin.separator) .. fs.convert(0.25, 0.875, pos, skin) .. fs.separator(2.125, skin.separator) .. fs.inv(0.25, 2.375, skin) ); - elseif tab == 2 then + elseif data.tab == 2 then minetest.show_formspec(player, "simple_table", - fs.header(10.25, 8.0, rank, tab, skin) .. + fs.header(10.25, 8.0, rank, data.tab, skin) .. fs.materials(0.25, 0.1875, meta, skin) .. fs.separator(0.6875, skin.separator) .. fs.craft(0.25, 0.875, pos, rank, meta, skin) .. fs.separator(2.75, skin.separator) .. fs.inv(0.25, 3, skin) ); - elseif tab == 3 then + elseif data.tab == 3 then minetest.show_formspec(player, "simple_table", - fs.header(10.25, 7.375, rank, tab, skin) .. + fs.header(10.25, 7.375, rank, data.tab, skin) .. fs.materials(0.25, 0.1875, meta, skin) .. fs.separator(0.6875, skin.separator) .. fs.copy(0.25, 0.875, pos, skin) .. @@ -304,52 +368,20 @@ end minetest.register_on_player_receive_fields(function(player, name, fields) if name == "simple_table" then minetest.chat_send_all(name..": "); - for k,v in pairs(fields) do - minetest.chat_send_all(tostring(k).." - "..tostring(v)); - end + local meta = minetest.get_meta(player_tables[player:get_player_name()].pos); - local meta = minetest.get_meta(player_tables[player:get_player_name()]); - - if fields["convert"] ~= nil then + if fields["convert"] then local inv = meta:get_inventory(); local stack = inv:get_stack("input", 1); - local paper = meta:get_int("paper"); - local pigment = meta:get_int("pigment"); + local value = cartographer.get_material_value(stack); - local item_name = stack:get_name(); - local item_count = stack:get_count(); - local found_match = false; - - for name,mats in pairs(_cartographer.materials_by_name) do - if name == item_name then - paper = paper + ((mats.paper or 0) * item_count); - pigment = pigment + ((mats.pigment or 0) * item_count); - found_match = true; - break; - end - end - - if not found_match then - for group,mats in pairs(_cartographer.materials_by_group) do - if minetest.get_item_group(item_name, group) ~= 0 then - paper = paper + ((mats.paper or 0) * item_count); - pigment = pigment + ((mats.pigment or 0) * item_count); - found_match = true; - break; - end - end - end - - if found_match then + if value.paper + value.pigment > 0 then + meta:set_int("paper", meta:get_int("paper") + value.paper); + meta:set_int("pigment", meta:get_int("pigment") + value.pigment); inv:set_stack("input", 1, ItemStack(nil)); end - - meta:set_int("paper", paper); - meta:set_int("pigment", pigment); - - table_formspec(player:get_player_name(), 1) - elseif fields["craft"] ~= nil then + elseif fields["craft"] then local size = meta:get_int("size"); local detail = meta:get_int("detail"); local scale = meta:get_int("scale"); @@ -360,7 +392,7 @@ minetest.register_on_player_receive_fields(function(player, name, fields) local inv = meta:get_inventory(); local stack = inv:get_stack("output", 1); - local cost = get_full_material_cost(meta); + local cost = get_craft_material_cost(meta); if stack:is_empty() then if paper >= cost.paper and pigment >= cost.pigment then @@ -386,16 +418,14 @@ minetest.register_on_player_receive_fields(function(player, name, fields) cartographer.resize_map_item(smeta, size); local map = cartographer.get_map(smeta:get_int("cartographer:map_id")); - if map ~= nil then + if map then map.detail = 1 + detail; end cartographer.map_sound("cartographer_write", player); inv:set_stack("output", 1, stack); end end - - table_formspec(player:get_player_name(), 2) - elseif fields["copy"] ~= nil then + elseif fields["copy"] then local paper = meta:get_int("paper"); local pigment = meta:get_int("pigment"); @@ -420,41 +450,35 @@ minetest.register_on_player_receive_fields(function(player, name, fields) inv:set_stack("copy_output", 1, cartographer.copy_map_item(in_stack)); end end - - table_formspec(player:get_player_name(), 3) - elseif fields["s"] ~= nil then + elseif fields["s"] then meta:set_int("size", SIZE_SMALL); - table_formspec(player:get_player_name(), 2) - elseif fields["l"] ~= nil then + elseif fields["l"] then meta:set_int("size", SIZE_LARGE); - table_formspec(player:get_player_name(), 2) - elseif fields["1"] ~= nil then + elseif fields["1"] then meta:set_int("detail", 0); - table_formspec(player:get_player_name(), 2) - elseif fields["2"] ~= nil then + elseif fields["2"] then meta:set_int("detail", 1); - table_formspec(player:get_player_name(), 2) - elseif fields["3"] ~= nil then + elseif fields["3"] then meta:set_int("detail", 2); - table_formspec(player:get_player_name(), 2) - elseif fields["4"] ~= nil then + elseif fields["4"] then meta:set_int("detail", 3); - table_formspec(player:get_player_name(), 2) - elseif fields["1x"] ~= nil then + elseif fields["1x"] then meta:set_int("scale", SCALE_SMALL); - table_formspec(player:get_player_name(), 2) - elseif fields["4x"] ~= nil then + elseif fields["4x"] then meta:set_int("scale", SCALE_LARGE); - table_formspec(player:get_player_name(), 2) - elseif fields["tab1"] ~= nil then + elseif fields["tab1"] then + player_tables[player:get_player_name()].tab = 1; cartographer.map_sound("cartographer_turn_page", player); - table_formspec(player:get_player_name(), 1); - elseif fields["tab2"] ~= nil then + elseif fields["tab2"] then + player_tables[player:get_player_name()].tab = 2; cartographer.map_sound("cartographer_turn_page", player); - table_formspec(player:get_player_name(), 2); - elseif fields["tab3"] ~= nil then + elseif fields["tab3"] then + player_tables[player:get_player_name()].tab = 3; cartographer.map_sound("cartographer_turn_page", player); - table_formspec(player:get_player_name(), 3); + end + + if not fields["quit"] then + table_formspec(player:get_player_name()); end end end); @@ -507,6 +531,20 @@ local function table_can_move(_, _, _, to_list, _, count, _) return count; end +-- Called when a change occurs in a table's inventory +-- pos: The node's position +-- listname: The name of the changed inventory list +local function table_on_items_changed(pos, listname, _, _, _) + for player, data in pairs(player_tables) do + if vector.equals(pos, data.pos) and ( + (data.tab == 1 and listname == "input") + or (data.tab == 2 and listname == "output") + or (data.tab == 3 and listname == "copy_input")) then + table_formspec(player); + end + end +end + minetest.register_node("cartographer:simple_table", { description = "Shabby Cartographer's Table", drawtype = "mesh", @@ -530,16 +568,21 @@ minetest.register_node("cartographer:simple_table", { }, }, on_rightclick = function(pos, node, player, itemstack, pointed_thing) - player_tables[player:get_player_name()] = minetest.get_pointed_thing_position(pointed_thing); + player_tables[player:get_player_name()] = { + pos = minetest.get_pointed_thing_position(pointed_thing), + tab = 1, + }; cartographer.map_sound("cartographer_open_map", player); - table_formspec(player:get_player_name(), 1) + table_formspec(player:get_player_name()) end, after_place_node = setup_table_node, allow_metadata_inventory_move = table_can_move, allow_metadata_inventory_put = table_can_put, + on_metadata_inventory_put = table_on_items_changed, + on_metadata_inventory_take = table_on_items_changed, }); minetest.register_node("cartographer:standard_table", { @@ -565,16 +608,21 @@ minetest.register_node("cartographer:standard_table", { }, }, on_rightclick = function(pos, node, player, itemstack, pointed_thing) - player_tables[player:get_player_name()] = minetest.get_pointed_thing_position(pointed_thing); + player_tables[player:get_player_name()] = { + pos = minetest.get_pointed_thing_position(pointed_thing), + tab = 1, + }; cartographer.map_sound("cartographer_open_map", player); - table_formspec(player:get_player_name(), 1) + table_formspec(player:get_player_name()) end, after_place_node = setup_table_node, allow_metadata_inventory_move = table_can_move, allow_metadata_inventory_put = table_can_put, + on_metadata_inventory_put = table_on_items_changed, + on_metadata_inventory_take = table_on_items_changed, }); minetest.register_node("cartographer:advanced_table", { @@ -600,16 +648,21 @@ minetest.register_node("cartographer:advanced_table", { }, }, on_rightclick = function(pos, node, player, itemstack, pointed_thing) - player_tables[player:get_player_name()] = minetest.get_pointed_thing_position(pointed_thing); + player_tables[player:get_player_name()] = { + pos = minetest.get_pointed_thing_position(pointed_thing), + tab = 1, + }; cartographer.map_sound("cartographer_open_map", player); - table_formspec(player:get_player_name(), 1) + table_formspec(player:get_player_name()) end, after_place_node = setup_table_node, allow_metadata_inventory_move = table_can_move, allow_metadata_inventory_put = table_can_put, + on_metadata_inventory_put = table_on_items_changed, + on_metadata_inventory_take = table_on_items_changed, }); function cartographer.register_map_material_name(name, material, value)