Add 6d facedir rotation prediction routine
authorVanessa Ezekowitz <vanessaezekowitz@gmail.com>
Tue, 5 Nov 2013 07:11:35 +0000 (02:11 -0500)
committerkwolekr <kwolekr@minetest.net>
Thu, 7 Nov 2013 02:08:36 +0000 (21:08 -0500)
builtin/misc_helpers.lua
doc/lua_api.txt

index 3a325e0d30d981c2adce85712229a66fcf841de8..d847db42c46687788d8cd7cd4afa76d8728106c3 100644 (file)
@@ -205,6 +205,84 @@ function tbl.formspec_escape(text)
        return text
 end
 
+--------------------------------------------------------------------------------
+
+if minetest then
+       local dirs1 = { 9, 18, 7, 12 }
+       local dirs2 = { 20, 23, 22, 21 }
+
+       function minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags)
+
+               local node = minetest.get_node(pointed_thing.under)
+               if not minetest.registered_nodes[node.name]
+                  or not minetest.registered_nodes[node.name].on_rightclick then
+
+                       local above = pointed_thing.above
+                       local under = pointed_thing.under
+                       local pitch = placer:get_look_pitch()
+                       local pname = minetest.get_node(under).name
+                       local node = minetest.get_node(above)
+                       local fdir = minetest.dir_to_facedir(placer:get_look_dir())
+                       local wield_name = itemstack:get_name()
+                       local reg_node = minetest.registered_nodes[pname]
+
+                       if not reg_node or not reg_node.on_rightclick then
+
+                               local iswall = (above.x ~= under.x) or (above.z ~= under.z)
+                               local isceiling = (above.x == under.x) and (above.z == under.z)
+                                                                 and (pitch > 0)
+                               local pos1 = above
+
+                               if reg_node and reg_node.buildable_to then
+                                       pos1 = under
+                                       iswall = false
+                               end
+
+                               reg_node = minetest.registered_nodes[minetest.get_node(pos1).name]
+                               if not reg_node or not reg_node.buildable_to then
+                                       return
+                               end
+
+                               if orient_flags.force_floor then
+                                       iswall = false
+                                       isceiling = false
+                               elseif orient_flags.force_ceiling then 
+                                       iswall = false
+                                       isceiling = true
+                               elseif orient_flags.force_wall then                                     
+                                       iswall = true
+                                       isceiling = false
+                               elseif orient_flags.invert_wall then
+                                       iswall = not iswall
+                               end
+
+                               if iswall then
+                                       minetest.add_node(pos1, {name = wield_name, param2 = dirs1[fdir+1] })
+                               elseif isceiling then
+                                       if orient_flags.force_facedir then
+                                               minetest.add_node(pos1, {name = wield_name, param2 = 20 })
+                                       else
+                                               minetest.add_node(pos1, {name = wield_name, param2 = dirs2[fdir+1] })
+                                       end
+                               else -- place right side up
+                                       if orient_flags.force_facedir then
+                                               minetest.add_node(pos1, {name = wield_name, param2 = 0 })
+                                       else
+                                               minetest.add_node(pos1, {name = wield_name, param2 = fdir })
+                                       end
+                               end
+
+                               if not infinitestacks then
+                                       itemstack:take_item()
+                                       return itemstack
+                               end
+                       end
+               else
+                       minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack)
+               end
+       end
+end
+
 --------------------------------------------------------------------------------
 -- mainmenu only functions
 --------------------------------------------------------------------------------
index 689496e22c1994776b249ee65a468b6ae91c1513..122fbde9938cd6ad8c63f065582030317c963e28 100644 (file)
@@ -1543,6 +1543,23 @@ minetest.is_protected(pos, name) -> bool
 minetest.record_protection_violation(pos, name)
 ^ This function calls functions registered with
   minetest.register_on_protection_violation.
+minetest.rotate_and_place(itemstack, placer, pointed_thing, infinitestacks, orient_flags)
+^ Attempt to predict the desired orientation of the facedir-capable node
+  defined by itemstack, and place it accordingly (on-wall, on the floor, or
+  hanging from the ceiling). Stacks are handled normally if the infinitestacks
+  field is false or omitted (else, the itemstack is not changed). orient_flags
+  is an optional table containing extra tweaks to the placement code:
+  invert_wall:         if true, place wall-orientation on the ground and ground-
+                                       orientation on the wall.
+  force_wall:          if true, always place the node in wall orientation.
+  force_ceiling:       if true, always place on the ceiling.
+  force_floor:         if true, always place the node on the floor.
+
+  The above four options are mutually-exclusive; the last in the list takes
+  precedence over the first.
+
+  force_facedir:       if true, forcably reset the facedir to north when placing on
+                                       the floor or ceiling
 
 Global objects:
 minetest.env - EnvRef of the server environment and world.