summaryrefslogtreecommitdiff
path: root/replacer
diff options
context:
space:
mode:
Diffstat (limited to 'replacer')
-rw-r--r--replacer/README.md45
-rw-r--r--replacer/check_owner.lua37
-rw-r--r--replacer/depends.txt2
-rw-r--r--replacer/init.lua238
-rw-r--r--replacer/inspect.lua412
-rw-r--r--replacer/textures/replacer_inspect.pngbin0 -> 594 bytes
-rw-r--r--replacer/textures/replacer_replacer.pngbin0 -> 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
new file mode 100644
index 0000000..ea47b56
--- /dev/null
+++ b/replacer/textures/replacer_inspect.png
Binary files differ
diff --git a/replacer/textures/replacer_replacer.png b/replacer/textures/replacer_replacer.png
new file mode 100644
index 0000000..0c5a4f8
--- /dev/null
+++ b/replacer/textures/replacer_replacer.png
Binary files differ