extendingladder.lua 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. local modpath = minetest.get_modpath(minetest.get_current_modname())
  2. local S, NS = dofile(modpath.."/intllib.lua")
  3. if ropes.extending_ladder_enabled then
  4. local wood_recipe = {
  5. {"group:stick", "group:stick", "group:stick"},
  6. {"group:stick", "", "group:stick"},
  7. {"group:stick", "", "group:stick"},
  8. }
  9. local wood_name = S("Wooden Extendable Ladder")
  10. local steel_recipe = {
  11. {"default:steel_ingot", "", "default:steel_ingot"},
  12. {"default:steel_ingot", "", "default:steel_ingot"},
  13. {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
  14. }
  15. local steel_name = S("Steel Extendable Ladder")
  16. if ropes.replace_default_ladders then
  17. minetest.unregister_item("default:ladder_wood")
  18. minetest.unregister_item("default:ladder_steel")
  19. minetest.clear_craft({output = "default:ladder_wood"})
  20. minetest.clear_craft({output = "default:ladder_steel"})
  21. local wallmounted_to_facedir =
  22. {[0] = 15, -- ceiling
  23. [1] = 13, -- floor
  24. [2] = 1, -- +X
  25. [3] = 3, -- -X
  26. [4] = 0, -- +Z
  27. [5] = 2, -- -Z
  28. }
  29. minetest.register_lbm({
  30. label = "Switch from wallmounted default ladders to rope mod extending ladders",
  31. name = "ropes:wallmounted_ladder_to_facedir_ladder",
  32. nodenames = {"default:ladder_wood", "default:ladder_steel"},
  33. run_at_every_load = false,
  34. action = function(pos, node)
  35. local new_node = {param2 = wallmounted_to_facedir[node.param2]}
  36. if (node.name == "default:ladder_wood") then
  37. new_node.name = "ropes:ladder_wood"
  38. else
  39. new_node.name = "ropes:ladder_steel"
  40. end
  41. minetest.set_node(pos, new_node)
  42. end,
  43. })
  44. wood_recipe = {
  45. {"group:stick", "", "group:stick"},
  46. {"group:stick", "group:stick", "group:stick"},
  47. {"group:stick", "", "group:stick"},
  48. }
  49. wood_name = S("Wooden Ladder")
  50. steel_recipe = {
  51. {'default:steel_ingot', '', 'default:steel_ingot'},
  52. {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'},
  53. {'default:steel_ingot', '', 'default:steel_ingot'},
  54. }
  55. steel_name = S("Steel Ladder")
  56. end
  57. minetest.register_craft({
  58. output = "ropes:ladder_wood 5",
  59. recipe = wood_recipe,
  60. })
  61. minetest.register_craft({
  62. output = 'ropes:ladder_steel 15',
  63. recipe = steel_recipe,
  64. })
  65. local ladder_extender = function(pos, node, clicker, itemstack, pointed_thing, ladder_node, standing_limit)
  66. -- on_rightclick can be called by other mods, make sure we have all the parameters we need
  67. if pointed_thing == nil or itemstack == nil then
  68. return itemstack
  69. end
  70. local clicked_stack = ItemStack(itemstack)
  71. -- true if we're pointing up at the ladder from below and there's a buildable space below it
  72. -- this check allows us to extend ladders downward
  73. local pointing_directly_below =
  74. pointed_thing.above.x == pos.x and
  75. pointed_thing.above.z == pos.z and
  76. pointed_thing.above.y == pos.y - 1 and
  77. minetest.registered_nodes[minetest.get_node(pointed_thing.above).name].buildable_to
  78. if clicked_stack:get_name() == ladder_node and not pointing_directly_below then
  79. local param2 = minetest.get_node(pos).param2
  80. local dir = minetest.facedir_to_dir(param2)
  81. local scan_limit = pos.y + 6 -- Only add ladder segments up to five nodes above the one clicked on
  82. pos.y = pos.y + 1
  83. while pos.y < scan_limit and minetest.get_node(pos).name == ladder_node do
  84. param2 = minetest.get_node(pos).param2
  85. pos.y = pos.y + 1
  86. end
  87. if pos.y < scan_limit and minetest.registered_nodes[minetest.get_node(pos).name].buildable_to then
  88. -- scan downward behind the ladder to find support
  89. local behind_pos = vector.add(pos, minetest.facedir_to_dir(param2))
  90. local target_height = pos.y - standing_limit - 1
  91. while behind_pos.y > target_height and minetest.registered_nodes[minetest.get_node(behind_pos).name].buildable_to do
  92. behind_pos.y = behind_pos.y - 1
  93. end
  94. -- If there's enough support, build a new ladder segment
  95. if behind_pos.y > target_height then
  96. if minetest.is_protected(pos, clicker:get_player_name()) then
  97. minetest.record_protection_violation(clicker:get_player_name())
  98. else
  99. minetest.set_node(pos, {name=ladder_node, param2=param2})
  100. if not minetest.settings:get_bool("creative_mode") then
  101. clicked_stack:take_item(1)
  102. end
  103. end
  104. end
  105. end
  106. elseif clicked_stack:get_definition().type == "node" then
  107. return minetest.item_place_node(itemstack, clicker, pointed_thing)
  108. end
  109. return clicked_stack
  110. end
  111. minetest.register_node("ropes:ladder_wood", {
  112. description = wood_name,
  113. _doc_items_longdesc = ropes.doc.ladder_longdesc,
  114. _doc_items_usagehelp = ropes.doc.ladder_usagehelp,
  115. tiles = {"default_wood.png","default_wood.png","default_wood.png^[transformR270","default_wood.png^[transformR270","default_ladder_wood.png"},
  116. inventory_image = "default_ladder_wood.png",
  117. wield_image = "default_ladder_wood.png",
  118. paramtype = "light",
  119. paramtype2 = "facedir",
  120. sunlight_propagates = true,
  121. walkable = false,
  122. climbable = true,
  123. is_ground_content = false,
  124. drawtype = "nodebox",
  125. paramtype = "light",
  126. node_box = {
  127. type = "fixed",
  128. fixed = {
  129. {-0.375, -0.5, 0.375, -0.25, 0.5, 0.5}, -- Upright1
  130. {0.25, -0.5, 0.375, 0.375, 0.5, 0.5}, -- Upright2
  131. {-0.4375, 0.3125, 0.4375, 0.4375, 0.4375, 0.5}, -- Rung_4
  132. {-0.4375, -0.1875, 0.4375, 0.4375, -0.0625, 0.5}, -- Rung_2
  133. {-0.4375, -0.4375, 0.4375, 0.4375, -0.3125, 0.5}, -- Rung_1
  134. {-0.4375, 0.0625, 0.4375, 0.4375, 0.1875, 0.5}, -- Rung_3
  135. }
  136. },
  137. groups = {choppy = 2, oddly_breakable_by_hand = 3, flammable = 2, flow_through = 1},
  138. sounds = default.node_sound_wood_defaults(),
  139. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  140. return ladder_extender(pos, node, clicker, itemstack, pointed_thing, "ropes:ladder_wood", ropes.extending_wood_ladder_limit)
  141. end,
  142. })
  143. minetest.register_node("ropes:ladder_steel", {
  144. description = steel_name,
  145. _doc_items_longdesc = ropes.doc.ladder_longdesc,
  146. _doc_items_usagehelp = ropes.doc.ladder_usagehelp,
  147. tiles = {"default_steel_block.png","default_steel_block.png","default_steel_block.png","default_steel_block.png","default_ladder_steel.png"},
  148. inventory_image = "default_ladder_steel.png",
  149. wield_image = "default_ladder_steel.png",
  150. paramtype = "light",
  151. paramtype2 = "facedir",
  152. sunlight_propagates = true,
  153. walkable = false,
  154. climbable = true,
  155. is_ground_content = false,
  156. drawtype = "nodebox",
  157. node_box = {
  158. type = "fixed",
  159. fixed = {
  160. {-0.4375, -0.5, 0.3125, -0.25, 0.5, 0.5}, -- Upright1
  161. {0.25, -0.5, 0.3125, 0.4375, 0.5, 0.5}, -- Upright2
  162. {-0.25, 0.3125, 0.375, 0.25, 0.4375, 0.5}, -- Rung_4
  163. {-0.25, -0.1875, 0.375, 0.25, -0.0625, 0.5}, -- Rung_2
  164. {-0.25, -0.4375, 0.375, 0.25, -0.3125, 0.5}, -- Rung_1
  165. {-0.25, 0.0625, 0.375, 0.25, 0.1875, 0.5}, -- Rung_3
  166. }
  167. },
  168. groups = {cracky = 2, flow_through = 1},
  169. sounds = default.node_sound_metal_defaults(),
  170. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  171. return ladder_extender(pos, node, clicker, itemstack, pointed_thing, "ropes:ladder_steel", ropes.extending_steel_ladder_limit)
  172. end,
  173. })
  174. else
  175. -- Table of possible wallmounted values
  176. local facedir_to_wallmounted = {
  177. 4, -- +Z
  178. 2, -- +X
  179. 5, -- -Z
  180. 3, -- -X
  181. 1, -- -Y
  182. 0, -- +Y
  183. }
  184. -- Mapping from facedir value to index in facedir_to_dir.
  185. local facedir_to_wallmounted_map = {
  186. [0]=1, 2, 3, 4,
  187. 5, 2, 6, 4,
  188. 6, 2, 5, 4,
  189. 1, 5, 3, 6,
  190. 1, 6, 3, 5,
  191. 1, 4, 3, 2,
  192. }
  193. minetest.register_lbm({
  194. label = "Switch from ropes ladders to wallmounted default ladders",
  195. name = "ropes:facedir_ladder_to_wallmounted_ladder",
  196. nodenames = {"ropes:ladder_wood", "ropes:ladder_steel"},
  197. run_at_every_load = false,
  198. action = function(pos, node)
  199. local new_node = {param2 = facedir_to_wallmounted[facedir_to_wallmounted_map[node.param2 % 32]]}
  200. if (node.name == "ropes:ladder_wood") then
  201. new_node.name = "default:ladder_wood"
  202. else
  203. new_node.name = "default:ladder_steel"
  204. end
  205. minetest.set_node(pos, new_node)
  206. end,
  207. })
  208. end