diff options
Diffstat (limited to 'replacer')
-rw-r--r-- | replacer/README.md | 45 | ||||
-rw-r--r-- | replacer/check_owner.lua | 37 | ||||
-rw-r--r-- | replacer/depends.txt | 2 | ||||
-rw-r--r-- | replacer/init.lua | 238 | ||||
-rw-r--r-- | replacer/inspect.lua | 412 | ||||
-rw-r--r-- | replacer/textures/replacer_inspect.png | bin | 0 -> 594 bytes | |||
-rw-r--r-- | replacer/textures/replacer_replacer.png | bin | 0 -> 461 bytes |
7 files changed, 734 insertions, 0 deletions
diff --git a/replacer/README.md b/replacer/README.md new file mode 100644 index 0000000..5f263f1 --- /dev/null +++ b/replacer/README.md @@ -0,0 +1,45 @@ + Replacement tool for creative building (Mod for MineTest) + +This tool is helpful for creative purposes (i.e. build a wall and "paint" windows into it). +It replaces nodes with a previously selected other type of node (i.e. places said windows +into a brick wall). + +Crafting: chest - - + - stick - + - - chest +Or just use /giveme replacer:replacer + +Usage: Right-click on a node of that type you want to replace other nodes with. + Left-click (normal usage) on any nodes you want to replace with the type you previously right-clicked on. + SHIFT-Right-click in order to store a new pattern. + +When in creative mode, the node will just be replaced. Your inventory will not be changed. + +When not in creative mode, digging will be simulated and you will get what was there. In return, the replacement node +will be taken from your inventory. + + +The second tool included in this mod is the inspector. + +Crafting: torch + stick + +Just wield it and click on any node or entity you want to know more about. A limited craft-guide is included. + + + + Copyright (C) 2013,2014,2015 Sokomine + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + diff --git a/replacer/check_owner.lua b/replacer/check_owner.lua new file mode 100644 index 0000000..f8e843f --- /dev/null +++ b/replacer/check_owner.lua @@ -0,0 +1,37 @@ +-- taken from Vanessa Ezekowitz' homedecor mod +-- see http://forum.minetest.net/viewtopic.php?pid=26061 or https://github.com/VanessaE/homedecor for details! +function replacer_homedecor_node_is_owned(pos, placer) + + if type( minetest.is_protected == "function") then + return minetest.is_protected( pos, placer:get_player_name() ); + end + + + local ownername = false + if type(IsPlayerNodeOwner) == "function" then -- node_ownership mod + if HasOwner(pos, placer) then -- returns true if the node is owned + if not IsPlayerNodeOwner(pos, placer:get_player_name()) then + if type(getLastOwner) == "function" then -- ...is an old version + ownername = getLastOwner(pos) + elseif type(GetNodeOwnerName) == "function" then -- ...is a recent version + ownername = GetNodeOwnerName(pos) + else + ownername = "someone" + end + end + end + + elseif type(isprotect)=="function" then -- glomie's protection mod + if not isprotect(5, pos, placer) then + ownername = "someone" + end + end + + if ownername ~= false then + minetest.chat_send_player( placer:get_player_name(), "Sorry, "..ownername.." owns that spot." ) + return true + else + return false + end +end + diff --git a/replacer/depends.txt b/replacer/depends.txt new file mode 100644 index 0000000..fef1434 --- /dev/null +++ b/replacer/depends.txt @@ -0,0 +1,2 @@ +default? +dye? diff --git a/replacer/init.lua b/replacer/init.lua new file mode 100644 index 0000000..6b7732c --- /dev/null +++ b/replacer/init.lua @@ -0,0 +1,238 @@ + + +--[[ + Replacement tool for creative building (Mod for MineTest) + Copyright (C) 2013 Sokomine + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +--]] + +-- Version 3.0 + +-- Changelog: +-- 02.10.2014 * Some more improvements for inspect-tool. Added craft-guide. +-- 01.10.2014 * Added inspect-tool. +-- 12.01.2013 * If digging the node was unsuccessful, then the replacement will now fail +-- (instead of destroying the old node with its metadata; i.e. chests with content) +-- 20.11.2013 * if the server version is new enough, minetest.is_protected is used +-- in order to check if the replacement is allowed +-- 24.04.2013 * param1 and param2 are now stored +-- * hold sneak + right click to store new pattern +-- * right click: place one of the itmes +-- * receipe changed +-- * inventory image added + +-- adds a function to check ownership of a node; taken from VanessaEs homedecor mod +dofile(minetest.get_modpath("replacer").."/check_owner.lua"); + +replacer = {}; + +-- adds a tool for inspecting nodes and entities +dofile(minetest.get_modpath("replacer").."/inspect.lua"); + +minetest.register_tool( "replacer:replacer", +{ + description = "Node replacement tool", + groups = {}, + inventory_image = "replacer_replacer.png", + wield_image = "", + wield_scale = {x=1,y=1,z=1}, + stack_max = 1, -- it has to store information - thus only one can be stacked + liquids_pointable = true, -- it is ok to painit in/with water + -- the tool_capabilities are of nearly no intrest here + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + groupcaps={ + -- For example: + fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, + snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, + choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0} + } + }, + node_placement_prediction = nil, + metadata = "default:dirt", -- default replacement: common dirt + + on_place = function(itemstack, placer, pointed_thing) + + if( placer == nil or pointed_thing == nil) then + return itemstack; -- nothing consumed + end + local name = placer:get_player_name(); + --minetest.chat_send_player( name, "You PLACED this on "..minetest.serialize( pointed_thing ).."."); + + local keys=placer:get_player_control(); + + -- just place the stored node if now new one is to be selected + if( not( keys["sneak"] )) then + + return replacer.replace( itemstack, placer, pointed_thing, 0 ); end + + + if( pointed_thing.type ~= "node" ) then + minetest.chat_send_player( name, " Error: No node selected."); + return nil; + end + + local pos = minetest.get_pointed_thing_position( pointed_thing, under ); + local node = minetest.get_node_or_nil( pos ); + + --minetest.chat_send_player( name, " Target node: "..minetest.serialize( node ).." at pos "..minetest.serialize( pos ).."."); + + local item = itemstack:to_table(); + -- make sure metadata is always set + if( node ~= nil and node.name ) then + item[ "metadata" ] = node.name..' '..node.param1..' '..node.param2; + else + item[ "metadata" ] = "default:dirt 0 0"; + end + itemstack:replace( item ); + + minetest.chat_send_player( name, "Node replacement tool set to: '"..item[ "metadata" ].."'."); + + return itemstack; -- nothing consumed but data changed + end, + + +-- on_drop = func(itemstack, dropper, pos), + + on_use = function(itemstack, user, pointed_thing) + + return replacer.replace( itemstack, user, pointed_thing, above ); + end, +}) + + +replacer.replace = function( itemstack, user, pointed_thing, mode ) + + if( user == nil or pointed_thing == nil) then + return nil; + end + local name = user:get_player_name(); + --minetest.chat_send_player( name, "You USED this on "..minetest.serialize( pointed_thing ).."."); + + if( pointed_thing.type ~= "node" ) then + minetest.chat_send_player( name, " Error: No node."); + return nil; + end + + local pos = minetest.get_pointed_thing_position( pointed_thing, mode ); + local node = minetest.get_node_or_nil( pos ); + + --minetest.chat_send_player( name, " Target node: "..minetest.serialize( node ).." at pos "..minetest.serialize( pos ).."."); + + if( node == nil ) then + + minetest.chat_send_player( name, "Error: Target node not yet loaded. Please wait a moment for the server to catch up."); + return nil; + end + + + local item = itemstack:to_table(); + + -- make sure it is defined + if( not( item[ "metadata"] ) or item["metadata"]=="" ) then + item["metadata"] = "default:dirt 0 0"; + end + + -- regain information about nodename, param1 and param2 + local daten = item[ "metadata"]:split( " " ); + -- the old format stored only the node name + if( #daten < 3 ) then + daten[2] = 0; + daten[3] = 0; + end + + -- if someone else owns that node then we can not change it + if( replacer_homedecor_node_is_owned(pos, user)) then + + return nil; + end + + -- do not replace if there is nothing to be done + if( node.name == daten[1] ) then + + -- the node itshelf remains the same, but the orientation was changed + if( node.param1 ~= daten[2] or node.param2 ~= daten[3] ) then + minetest.add_node( pos, { name = node.name, param1 = daten[2], param2 = daten[3] } ); + end + + return nil; + end + + + -- in survival mode, the player has to provide the node he wants to be placed + if( not(minetest.setting_getbool("creative_mode") )) then + + -- players usually don't carry dirt_with_grass around; it's safe to assume normal dirt here + -- fortionately, dirt and dirt_with_grass does not make use of rotation + if( daten[1] == "default:dirt_with_grass" ) then + daten[1] = "default:dirt"; + item["metadata"] = "default:dirt 0 0"; + end + + -- does the player carry at least one of the desired nodes with him? + if( not( user:get_inventory():contains_item("main", daten[1]))) then + + + minetest.chat_send_player( name, "You have no further '"..( daten[1] or "?" ).."'. Replacement failed."); + return nil; + end + + + + -- give the player the item by simulating digging if possible + if( node.name ~= "air" + and node.name ~= "ignore" + and node.name ~= "default:lava_source" + and node.name ~= "default:lava_flowing" + and node.name ~= "default:water_source" + and node.name ~= "default:water_flowing" ) then + + minetest.node_dig( pos, node, user ); + + local digged_node = minetest.get_node_or_nil( pos ); + if( not( digged_node ) + or digged_node.name == node.name ) then + + minetest.chat_send_player( name, "Replacing '"..( node.name or "air" ).."' with '"..( item[ "metadata"] or "?" ).."' failed. Unable to remove old node."); + return nil; + end + + end + + -- consume the item + user:get_inventory():remove_item("main", daten[1].." 1"); + + --user:get_inventory():add_item( "main", node.name.." 1"); + end + + --minetest.chat_send_player( name, "Replacing node '"..( node.name or "air" ).."' with '"..( item[ "metadata"] or "?" ).."'."); + + --minetest.place_node( pos, { name = item[ "metadata" ] } ); + minetest.add_node( pos, { name = daten[1], param1 = daten[2], param2 = daten[3] } ); + return nil; -- no item shall be removed from inventory + end + + +minetest.register_craft({ + output = 'replacer:replacer', + recipe = { + { 'default:chest', '', '' }, + { '', 'default:stick', '' }, + { '', '', 'default:chest' }, + } +}) + + diff --git a/replacer/inspect.lua b/replacer/inspect.lua new file mode 100644 index 0000000..6db5c74 --- /dev/null +++ b/replacer/inspect.lua @@ -0,0 +1,412 @@ + +replacer.image_replacements = {}; + +-- support for RealTest +if( minetest.get_modpath("trees") + and minetest.get_modpath("core") + and minetest.get_modpath("instruments") + and minetest.get_modpath("anvil") + and minetest.get_modpath("scribing_table")) then + replacer.image_replacements[ "group:planks" ] = "trees:pine_planks"; + replacer.image_replacements[ "group:plank" ] = "trees:pine_plank"; + replacer.image_replacements[ "group:wood" ] = "trees:pine_planks"; + replacer.image_replacements[ "group:tree" ] = "trees:pine_log"; + replacer.image_replacements[ "group:sapling"] = "trees:pine_sapling"; + replacer.image_replacements[ "group:leaves" ] = "trees:pine_leaves"; + replacer.image_replacements[ "default:furnace" ] = "oven:oven"; + replacer.image_replacements[ "default:furnace_active" ] = "oven:oven_active"; +end + +minetest.register_tool( "replacer:inspect", +{ + description = "Node inspection tool", + groups = {}, + inventory_image = "replacer_inspect.png", + wield_image = "", + wield_scale = {x=1,y=1,z=1}, + liquids_pointable = true, -- it is ok to request information about liquids + -- the tool_capabilities are of no intrest here; it is not for digging + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + groupcaps={ + fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, + snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1}, + choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0} + } + }, + node_placement_prediction = nil, + + on_use = function(itemstack, user, pointed_thing) + + return replacer.inspect( itemstack, user, pointed_thing, nil, true ); --false ); + end, + + on_place = function(itemstack, placer, pointed_thing) + + return replacer.inspect( itemstack, placer, pointed_thing, nil, true ); + end, +}) + + +replacer.inspect = function( itemstack, user, pointed_thing, mode, show_receipe ) + + if( user == nil or pointed_thing == nil) then + return nil; + end + local name = user:get_player_name(); + local keys = user:get_player_control(); + if( keys["sneak"] ) then + show_receipe = true; + end + + if( pointed_thing.type == 'object' ) then + local text = 'This is '; + local ref = pointed_thing.ref; + if( not( ref )) then + text = text..'a borken object. We have no further information about it. It is located'; + elseif( ref:is_player()) then + text = text..'your fellow player \"'..tostring( ref:get_player_name() )..'\"'; + else + local luaob = ref:get_luaentity(); + if( luaob ) then + text = text..'entity \"'..tostring( luaob.name )..'\"'; + local sdata = luaob:get_staticdata(); + if( sdata ) then + sdata = minetest.deserialize( sdata ); + if( sdata.itemstring ) then + text = text..' ['..tostring( sdata.itemstring )..']'; + if( show_receipe ) then + -- the fields part is used here to provide additional information about the entity + replacer.inspect_show_crafting( name, sdata.itemstring, { pos=pos, luaob=luaob} ); + end + end + if( sdata.age ) then + text = text..', dropped '..tostring( math.floor( sdata.age/60 ))..' minutes ago'; + end + end + else + text = text..'object \"'..tostring( ref:get_entity_name() )..'\"'; + end + + end + text = text..' at '..minetest.pos_to_string( ref:getpos() ); + minetest.chat_send_player( name, text ); + return nil; + elseif( pointed_thing.type ~= 'node' ) then + minetest.chat_send_player( name, 'Sorry. This is an unkown something of type \"'..tostring( pointed_thing.type )..'\". No information available.'); + return nil; + end + + local pos = minetest.get_pointed_thing_position( pointed_thing, mode ); + local node = minetest.get_node_or_nil( pos ); + + if( node == nil ) then + minetest.chat_send_player( name, "Error: Target node not yet loaded. Please wait a moment for the server to catch up."); + return nil; + end + + local text = ' ['..tostring( node.name )..'] with param2='..tostring( node.param2 )..' at '..minetest.pos_to_string( pos )..'.'; + if( not( minetest.registered_nodes[ node.name ] )) then + text = 'This node is an UNKOWN block'..text; + else + text = 'This is a \"'..tostring( minetest.registered_nodes[ node.name ].description or ' - no description provided -')..'\" block'..text; + end + local protected_info = ""; + if( minetest.is_protected( pos, name )) then + protected_info = 'WARNING: You can\'t dig this node. It is protected.'; + elseif( minetest.is_protected( pos, '_THIS_NAME_DOES_NOT_EXIST_' )) then + protected_info = 'INFO: You can dig this node, but others can\'t.'; + end + text = text..' '..protected_info; +-- no longer spam the chat; the craft guide is more informative +-- minetest.chat_send_player( name, text ); + + if( show_receipe ) then + -- get light of the node at the current time + local light = minetest.get_node_light(pos, nil); + if( light==0 ) then + light = minetest.get_node_light( {x=pos.x,y=pos.y+1,z=pos.z}); + end + -- the fields part is used here to provide additional information about the node + replacer.inspect_show_crafting( name, node.name, {pos=pos, param2=node.param2, light=light, protected_info=protected_info} ); + end + return nil; -- no item shall be removed from inventory +end + +-- some common groups +replacer.group_placeholder = {}; +replacer.group_placeholder[ 'group:wood' ] = 'default:wood'; +replacer.group_placeholder[ 'group:tree' ] = 'default:tree'; +replacer.group_placeholder[ 'group:sapling']= 'default:sapling'; +replacer.group_placeholder[ 'group:stick' ] = 'default:stick'; +replacer.group_placeholder[ 'group:stone' ] = 'default:cobble'; -- 'default:stone'; point people to the cheaper cobble +replacer.group_placeholder[ 'group:sand' ] = 'default:sand'; +replacer.group_placeholder[ 'group:leaves'] = 'default:leaves'; +replacer.group_placeholder[ 'group:wood_slab'] = 'stairs:slab_wood'; +replacer.group_placeholder[ 'group:wool' ] = 'wool:white'; + + +-- handle the standard dye color groups +if( minetest.get_modpath("dye") and dye and dye.basecolors) then + for i,color in ipairs( dye.basecolors ) do + local def = minetest.registered_items[ "dye:"..color ]; + if( def and def.groups ) then + for k,v in pairs( def.groups ) do + if( k ~= 'dye' ) then + replacer.group_placeholder[ 'group:dye,'..k ] = 'dye:'..color; + end + end + replacer.group_placeholder[ 'group:flower,color_'..color ] = 'dye:'..color; + end + end +end + +replacer.image_button_link = function( stack_string ) + local group = ''; + if( replacer.image_replacements[ stack_string ] ) then + stack_string = replacer.image_replacements[ stack_string ]; + end + if( replacer.group_placeholder[ stack_string ] ) then + stack_string = replacer.group_placeholder[ stack_string ]; + group = 'G'; + end +-- TODO: show information about other groups not handled above + local stack = ItemStack( stack_string ); + local new_node_name = stack_string; + if( stack and stack:get_name()) then + new_node_name = stack:get_name(); + end + return tostring( stack_string )..';'..tostring( new_node_name )..';'..group; +end + +replacer.add_circular_saw_receipe = function( node_name, receipes ) + if( not( node_name ) or not( minetest.get_modpath("moreblocks")) or not( circular_saw ) or not( circular_saw.names) or (node_name=='moreblocks:circular_saw')) then + return; + end + local help = node_name:split( ':' ); + if( not( help ) or #help ~= 2 or help[1]=='stairs') then + return; + end + help2 = help[2]:split('_'); + if( not( help2 ) or #help2 < 2 or (help2[1]~='micro' and help2[1]~='panel' and help2[1]~='stair' and help2[1]~='slab')) then + return; + end +-- for i,v in ipairs( circular_saw.names ) do +-- modname..":"..v[1].."_"..material..v[2] + +-- TODO: write better and more correct method of getting the names of the materials +-- TODO: make sure only nodes produced by the saw are listed here +help[1]='default'; + local basic_node_name = help[1]..':'..help2[2]; + -- node found that fits into the saw + receipes[ #receipes+1 ] = { method = 'saw', type = 'saw', items = { basic_node_name }, output = node_name}; + return receipes; +end + +replacer.add_colormachine_receipe = function( node_name, receipes ) + if( not( minetest.get_modpath("colormachine")) or not( colormachine )) then + return; + end + local res = colormachine.get_node_name_painted( node_name, "" ); + + if( not( res) or not( res.possible ) or #res.possible < 1 ) then + return; + end + -- paintable node found + receipes[ #receipes+1 ] = { method = 'colormachine', type = 'colormachine', items = { res.possible[1] }, output = node_name}; + return receipes; +end + + +replacer.inspect_show_crafting = function( name, node_name, fields ) + if( not( name )) then + return; + end + + local receipe_nr = 1; + if( not( node_name )) then + node_name = fields.node_name; + receipe_nr = tonumber(fields.receipe_nr); + end + -- turn it into an item stack so that we can handle dropped stacks etc + local stack = ItemStack( node_name ); + node_name = stack:get_name(); + + -- the player may ask for receipes of indigrents to the current receipe + if( fields ) then + for k,v in pairs( fields ) do + if( v and v=="" and (minetest.registered_items[ k ] + or minetest.registered_nodes[ k ] + or minetest.registered_craftitems[ k ] + or minetest.registered_tools[ k ] )) then + node_name = k; + receipe_nr = 1; + end + end + end + + local res = minetest.get_all_craft_recipes( node_name ); + if( not( res )) then + res = {}; + end + -- add special receipes for nodes created by machines + replacer.add_circular_saw_receipe( node_name, res ); + replacer.add_colormachine_receipe( node_name, res ); + + -- offer all alternate creafting receipes thrugh prev/next buttons + if( fields and fields.prev_receipe and receipe_nr > 1 ) then + receipe_nr = receipe_nr - 1; + elseif( fields and fields.next_receipe and receipe_nr < #res ) then + receipe_nr = receipe_nr + 1; + end + + local desc = nil; + if( minetest.registered_nodes[ node_name ] ) then + if( minetest.registered_nodes[ node_name ].description + and minetest.registered_nodes[ node_name ].description~= "") then + desc = "\""..minetest.registered_nodes[ node_name ].description.."\" block"; + elseif( minetest.registered_nodes[ node_name ].name ) then + desc = "\""..minetest.registered_nodes[ node_name ].name.."\" block"; + else + desc = " - no description provided - block"; + end + elseif( minetest.registered_items[ node_name ] ) then + if( minetest.registered_items[ node_name ].description + and minetest.registered_items[ node_name ].description~= "") then + desc = "\""..minetest.registered_items[ node_name ].description.."\" item"; + elseif( minetest.registered_items[ node_name ].name ) then + desc = "\""..minetest.registered_items[ node_name ].name.."\" item"; + else + desc = " - no description provided - item"; + end + end + if( not( desc ) or desc=="") then + desc = ' - no description provided - '; + end + + local formspec = "size[6,6]".. + "label[0,5.5;This is a "..minetest.formspec_escape( desc )..".]".. + "button_exit[5.0,4.3;1,0.5;quit;Exit]".. + "label[0,0;Name:]".. + "field[20,20;0.1,0.1;node_name;node_name;"..node_name.."]".. -- invisible field for passing on information + "field[21,21;0.1,0.1;receipe_nr;receipe_nr;"..tostring( receipe_nr ).."]".. -- another invisible field + "label[1,0;"..tostring( node_name ).."]".. + "item_image_button[5,2;1.0,1.0;"..tostring( node_name )..";normal;]"; + + -- provide additional information regarding the node in particular that has been inspected + if( fields.pos ) then + formspec = formspec.."label[0.0,0.3;Located at ".. + minetest.formspec_escape( minetest.pos_to_string( fields.pos )); + if( fields.param2 ) then + formspec = formspec.." with param2="..tostring( fields.param2 ); + end + if( fields.light ) then + formspec = formspec.." and receiving "..tostring( fields.light ).." light"; + end + formspec = formspec..".]"; + end + + -- show information about protection + if( fields.protected_info and fields.protected_info ~= "" ) then + formspec = formspec.."label[0.0,4.5;"..minetest.formspec_escape( fields.protected_info ).."]"; + end + + if( not( res ) or receipe_nr > #res or receipe_nr < 1 ) then + receipe_nr = 1; + end + if( res and receipe_nr > 1 ) then + formspec = formspec.."button[3.8,5;1,0.5;prev_receipe;prev]"; + end + if( res and receipe_nr < #res ) then + formspec = formspec.."button[5.0,5.0;1,0.5;next_receipe;next]"; + end + if( not( res ) or #res<1) then + formspec = formspec..'label[3,1;No receipes.]'; + if( minetest.registered_nodes[ node_name ] + and minetest.registered_nodes[ node_name ].drop ) then + local drop = minetest.registered_nodes[ node_name ].drop; + if( drop ) then + if( type( drop )=='string' and drop ~= node_name ) then + formspec = formspec.."label[2,1.6;Drops on dig:]".. + "item_image_button[2,2;1.0,1.0;"..replacer.image_button_link( drop ).."]"; + elseif( type( drop )=='table' and drop.items ) then + local droplist = {}; + for _,drops in ipairs( drop.items ) do + for _,item in ipairs( drops.items ) do + -- avoid duplicates; but include the item itshelf + droplist[ item ] = 1; + end + end + local i = 1; + formspec = formspec.."label[2,1.6;May drop on dig:]"; + for k,v in pairs( droplist ) do + formspec = formspec.. + "item_image_button["..(((i-1)%3)+1)..","..math.floor(((i-1)/3)+2)..";1.0,1.0;"..replacer.image_button_link( k ).."]"; + i = i+1; + end + end + end + end + else + formspec = formspec.."label[1,5;Alternate "..tostring( receipe_nr ).."/"..tostring( #res ).."]"; + -- reverse order; default receipes (and thus the most intresting ones) are usually the oldest + local receipe = res[ #res+1-receipe_nr ]; + if( receipe.type=='normal' and receipe.items) then + local width = receipe.width; + if( not( width ) or width==0 ) then + width = 3; + end + for i=1,9 do + if( receipe.items[i] ) then + formspec = formspec.."item_image_button["..(((i-1)%width)+1)..','..(math.floor((i-1)/width)+1)..";1.0,1.0;".. + replacer.image_button_link( receipe.items[i] ).."]"; + end + end + elseif( receipe.type=='cooking' and receipe.items and #receipe.items==1 + and receipe.output=="" ) then + formspec = formspec.."item_image_button[1,1;3.4,3.4;"..replacer.image_button_link( 'default:furnace_active' ).."]".. --default_furnace_front.png]".. + "item_image_button[2.9,2.7;1.0,1.0;"..replacer.image_button_link( receipe.items[1] ).."]".. + "label[1.0,0;"..tostring(receipe.items[1]).."]".. + "label[0,0.5;This can be used as a fuel.]"; + elseif( receipe.type=='cooking' and receipe.items and #receipe.items==1 ) then + formspec = formspec.."item_image_button[1,1;3.4,3.4;"..replacer.image_button_link( 'default:furnace' ).."]".. --default_furnace_front.png]".. + "item_image_button[2.9,2.7;1.0,1.0;"..replacer.image_button_link( receipe.items[1] ).."]"; + elseif( receipe.type=='colormachine' and receipe.items and #receipe.items==1 ) then + formspec = formspec.."item_image_button[1,1;3.4,3.4;"..replacer.image_button_link( 'colormachine:colormachine' ).."]".. --colormachine_front.png]".. + "item_image_button[2,2;1.0,1.0;"..replacer.image_button_link( receipe.items[1] ).."]"; + elseif( receipe.type=='saw' and receipe.items and #receipe.items==1 ) then + --formspec = formspec.."item_image[1,1;3.4,3.4;moreblocks:circular_saw]".. + formspec = formspec.."item_image_button[1,1;3.4,3.4;"..replacer.image_button_link( 'moreblocks:circular_saw' ).."]".. + "item_image_button[2,0.6;1.0,1.0;"..replacer.image_button_link( receipe.items[1] ).."]"; + else + formspec = formspec..'label[3,1;Error: Unkown receipe.]'; + end + -- show how many of the items the receipe will yield + local outstack = ItemStack( receipe.output ); + if( outstack and outstack:get_count() and outstack:get_count()>1 ) then + formspec = formspec..'label[5.5,2.5;'..tostring( outstack:get_count() )..']'; + end + end + minetest.show_formspec( name, "replacer:crafting", formspec ); +end + +-- translate general formspec calls back to specific calls +replacer.form_input_handler = function( player, formname, fields) + if( formname and formname == "replacer:crafting" and player and not( fields.quit )) then + replacer.inspect_show_crafting( player:get_player_name(), nil, fields ); + return; + end +end + +-- establish a callback so that input from the player-specific formspec gets handled +minetest.register_on_player_receive_fields( replacer.form_input_handler ); + + +minetest.register_craft({ + output = 'replacer:inspect', + recipe = { + { 'default:torch' }, + { 'default:stick' }, + } +}) diff --git a/replacer/textures/replacer_inspect.png b/replacer/textures/replacer_inspect.png Binary files differnew file mode 100644 index 0000000..ea47b56 --- /dev/null +++ b/replacer/textures/replacer_inspect.png diff --git a/replacer/textures/replacer_replacer.png b/replacer/textures/replacer_replacer.png Binary files differnew file mode 100644 index 0000000..0c5a4f8 --- /dev/null +++ b/replacer/textures/replacer_replacer.png |