Page 1 of 1

on_place = minetest.rotate_node -- No callbacks are called

PostPosted: Sat Oct 25, 2014 10:36
by DuDraig
I ran into this crating a mod that automatically creates stair corners when stair straights are appropriately placed.

The default value of the on_place field in a minetest.register_node def is minetest.item_place that is implemented in the builtin mods. It calls minetest.item_place_node that uses the undocumented (in the Wiki) minetest.add_node method to add the node to the world, and then calls the node on_place and globally registered on_placenode callbacks.

The example in the Minetest Wiki minetest.rotate_node page shows in a minetest.register_node def
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_place = minetest.rotate_node

Many mod nodes and almost all stairs use this assignment. The problem is that minetest.rotate_node calls minetest.rotate_and_place that uses minetest.add_node to place the node. It DOES NOT call any callbacks.

This means that there are many nodes registered by mods that will not call the node on_place or the global registered on_placenode callbacks.

The solution to this is to override the desired nodes with on_place replaced by a function that calls minetest.rotate_node but then also calls the callbacks in the same manner as minetest.item_place_node.
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.override_item(stairName, {
   -- Stairs normally have on_place set to minetest.rotate_node but that means the after_place_node
   -- is never called. Replace that with a function that calls minetest.rotate_node and also calls
   -- the callbacks as does minetest.item_place().
   on_place = function(itemstack, placer, pointed_thing)
      local oldnode      = minetest.get_node(pointed_thing.above)
      local newItemstack = minetest.rotate_node(itemstack, placer, pointed_thing)
      
      -- Perform callbacks. Copy any arguments that the callback might change.
      local def      = itemstack:get_definition()
      local takeItem = true
      
      if def.after_place_node then
         if def.after_place_node(
            vector.new(pointed_thing.above),
            placer,
            itemstack,
            copyPointedThing(pointed_thing)
         ) then takeItem = false end
      end
   
      for _, callback in ipairs(minetest.registered_on_placenodes) do
         if callback(
            vector.new(pointed_thing.above),
            copyNode(minetest.get_node(pointed_thing.above)),
            placer,
            copyNode(oldnode),
            itemstack,
            copyPointedThing(pointed_thing)
         ) then takeItem = false end
      end
      
      if takeItem then return itemstack
      else             return newItemstack
      end
   end,

   after_place_node = function(pos, placer, itemstack, pointed_thing)
      -- Code for after a node is placed.
   end,
})
(No Lua syntax coloring in BBCode Code blocks, really?)

This corrects the current bad behavior of the overridden nodes and re-enables the on_place and global registered on_placenode callbacks.

I suggest that the example in the Wiki minetest.rotate_node page be updated to reflect this with this or a better solution that does not break the callbacks. I have not done so yet because someone may come up with a better solution.

I hope someone finds this helpful.

Re: on_place = minetest.rotate_node -- No callbacks are call

PostPosted: Fri Nov 07, 2014 12:08
by 4aiman
The thing is, one shouldn't have assigned on_place = minetest.rotate_node but actually DO call the minetest.rotate_node with some params.

The same goes for the minetest.on_eat.
If one would write on_use = minetest.on_eat then nothing would happen.
But if there would be on_use=minetest.on_eat(2), then every on_use the minetest.on_eat with a single parametr of '2' would be called.