Update table material costs/values when items are placed/removed from them
This commit is contained in:
		
							
								
								
									
										229
									
								
								table.lua
									
									
									
									
									
								
							
							
						
						
									
										229
									
								
								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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user