Page 1 of 1

Getting amount of drops

PostPosted: Wed Jan 08, 2014 16:35
by qwrwed
See most recent problem.
[spoiler=Original post]I am trying to make a pickaxe that automatically smelts whatever it mines, but am having trouble. I have typed this code in the minetest.register_tool:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
after_use = function(itemstack, user, node, digparams)
    local node = node.name
    print(node)
    local product = minetest.get_craft_result({method = "cooking", width = 1, items = {node}})
    print(product)
    user:get_inventory():add_item("main", (product))
    return itemstack
end

This just prints something similar to:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
default:stone
table: 0x0a828580

and does not add the smelted item.
I have also tried returning "product" instead of "itemstack", but this also does not work as intended; it just removes the tools.
How do I find out the name of the craft result?[/spoiler]

PostPosted: Wed Jan 08, 2014 16:50
by GreenTech
qwrwed wrote:I am trying to make a pickaxe that automatically smelts whatever it mines, but am having trouble. I have typed this code in the minetest.register_tool:
after_use = function(itemstack, user, node, digparams)
local node = node.name
print(node)
local product = minetest.get_craft_result({method = "cooking", width = 1, items = {node}})
print(product)
user:get_inventory():add_item("main", (product))
return itemstack
end
This just prints something similar to:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
default:stone
table: 0x0a828580

and does not add the smelted item.
I have also tried returning "product" instead of "itemstack", but this also does not work as intended; it just removes the tools.
How do I find out the name of the craft result?


Maybe on_dig?

PostPosted: Wed Jan 08, 2014 17:18
by qwrwed
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
on_dig = function(pos, node, digger)
    print("digged")
end

Nothing is printed.
On_dig only works for nodes; you can't dig a pickaxe.

PostPosted: Wed Jan 08, 2014 17:30
by LionsDen
Yeah, I don't think the print lua command works because there isn't any text display in the game (No specific area anyway). Type the chat message, that is what I use whenever I want to show information to myself. Here is an example:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.chat_send_player(user:get_player_name(), "Text you want to display here.")


As further information, I used this as part of a node's on_use so was able to use the user:get_player_name() function.

PostPosted: Wed Jan 08, 2014 17:47
by qwrwed
It does - it prints to the terminal.
[spoiler=Image]Image[/spoiler]
This screenshot also shows the "table: 0x0<string of random characters>" that is printed. I have just realised there is no cooking recipe for stone, but digging cobble or sand does not give stone or glass either.

PostPosted: Wed Jan 08, 2014 17:51
by kaeza

PostPosted: Wed Jan 08, 2014 18:02
by qwrwed
I looked at that code again and saw that had "cooked.item", whereas I just had "product". Adding .item meant that it worked almost as intended - digging cobble gives stone AND cobble - how do I prevent the item that is being dug from being added to the inventory?

PostPosted: Wed Jan 08, 2014 18:17
by rubenwardy
after_use = function(itemstack, user, node, digparams)
local node = node.name
print(node)
local product = minetest.get_craft_result({method = "cooking", width = 1, items = {node}})
print(dump(product))
user:get_inventory():add_item("main", (product))
return itemstack
end


Tried deleting local node = ...?

PostPosted: Wed Jan 08, 2014 21:54
by qwrwed
I have prevented more than one dug item from being added to the inventory (although the is a problem I will solve completely in the future) but is there a way to get the amount of drops? I have used this:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
after_use = function(itemstack, user, node, digparams)
        local drops = table.concat(minetest.get_node_drops(node.name, "default:pick_mese"))
        local product = minetest.get_craft_result({method = "cooking", width = 1, items = {drops}})
        local inv = user:get_inventory()
        print(product.name)
        inv:add_item("main", product.item)
        inv:remove_item("main", drops)
        return itemstack
    end,
It works perfectly when mining metals, but when mining clay, only 1 brick is added instead of 4. I have looked in doc/lua_api, but I didn't see anything for getting the amount of drops - how do I do this?

PostPosted: Thu Jan 09, 2014 08:09
by rubenwardy
You could read the drop definition from minetest.registered_nodes[name]

PostPosted: Thu Jan 09, 2014 19:29
by Krock
Well more than my codes I can't give because explaining could be hard:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local output_drops = {}
local drops = minetest.get_node_drops(node.name)
for _, item in ipairs(drops) do
    local stack = ItemStack(item)
    local item_name = stack:get_name()
    local item_count = stack:get_count()
    if(item_count == nil) then
        item_count = 1
    end
    if(output_drops[item_name] ~= nil) then
        output_drops[item_name] = output_drops[item_name] + item_count
    else
        output_drops[item_name] = item_count
    end
end

~ original source 'mining_plus' by Krock


EDIT: typos

PostPosted: Fri Jan 10, 2014 09:59
by prestidigitator
qwrwed wrote:I have prevented more than one dug item from being added to the inventory (although the is a problem I will solve completely in the future) but is there a way to get the amount of drops? I have used this:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
after_use = function(itemstack, user, node, digparams)
        local drops = table.concat(minetest.get_node_drops(node.name, "default:pick_mese"))
        local product = minetest.get_craft_result({method = "cooking", width = 1, items = {drops}})
        local inv = user:get_inventory()
        print(product.name)
        inv:add_item("main", product.item)
        inv:remove_item("main", drops)
        return itemstack
    end,
It works perfectly when mining metals, but when mining clay, only 1 brick is added instead of 4. I have looked in doc/lua_api, but I didn't see anything for getting the amount of drops - how do I do this?

There are a couple odd things about this code. Changing them MIGHT help.
  1. Using table.concat() on the list of ItemStacks returned by minetest.get_node_drops() will result in undefined behavior. It might be doing something right now, but note that the Lua 5.1 API only specifies the behavior of table.concat() when the elements are strings or numbers, not when they are references to tables or userdata (an ItemStack is one of those—not sure which). Fortunately, minetest.get_craft_result() takes a table whose 'items' property is an array of ItemStacks, so you shouldn't really have to do that table.concat() conversion anyway. You may want to iterate through the list of ItemStacks from minetest.get_node_drops() and deal with each individually, however, instead of just using the whole list.
  2. Since the result of the minetest.get_craft_result() call has an ItemStack, I believe you should actually be calling "product.item:get_name()" rather than just using the expression "product.name" on it. Likewise, you should be able to get the count of the cooked product using "product.item:get_count()". However, since you are using "inv:add_item(..., product.item)" which takes a whole ItemStack as its second parameter anyway, I think that logic should already be handling the item count just fine....
  3. Your call of "inv:remove_item(...)" will need to be dealt with in a way similar to how you will need to use ItemStacks for minetest.get_craft_result(), as I described above.
  4. You'll probably want to test whether the stack given by minetest.get_craft_result() is empty (meaning there is no craft recipe for the inputs you are describing). As it is this will remove any drop that doesn't get cooked into anything, rather than leaving it unchanged.

PostPosted: Fri Jan 10, 2014 12:07
by qwrwed
prestidigitator: Ah. Now I see why things such as coal weren't added to the inventory.

Thanks for the help of everyone who posted here - the problem with the original code isn't fixed, but kaeza has provided an alternate solution (overwriting minetest.handle_node_drops) which works fine.