init.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. --Todo make lift go up and down!
  2. doors.register_door("lifter:door", {
  3. tiles = {{ name = "lifter_door.png", backface_culling = true }},
  4. description = "Lift Door",
  5. inventory_image = "lifter_item_door.png",
  6. groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
  7. recipe = {
  8. {"group:stick", "group:stick", "group:stick"},
  9. {"group:stick", "doors:door_wood", "group:stick"},
  10. {"group:stick", "group:stick", "group:stick"},
  11. }
  12. })
  13. -- should only be ignore if there's not generated map
  14. local function get_far_node(pos)
  15. local node = minetest.get_node(pos)
  16. if node.name == "ignore" then
  17. minetest.get_voxel_manip():read_from_map(pos, pos)
  18. node = minetest.get_node(pos)
  19. end
  20. return node
  21. end
  22. local function fetch_lift(pos, node, clicker, rel, i, open_door, plus)
  23. local wnode = get_far_node({x=pos.x+1, y=pos.y+i, z=pos.z})
  24. local snode = get_far_node({x=pos.x-1, y=pos.y+i, z=pos.z})
  25. local anode = get_far_node({x=pos.x, y=pos.y+i, z=pos.z+1})
  26. local dnode = get_far_node({x=pos.x, y=pos.y+i, z=pos.z-1})
  27. if wnode.name ~= "lifter:lift" and snode.name ~= "lifter:lift" and
  28. anode.name ~= "lifter:lift" and dnode.name ~= "lifter:lift" then
  29. if wnode.name ~= "air" and snode.name ~= "air" and
  30. anode.name ~= "air" and dnode.name ~= "air" and
  31. wnode.name ~= "bones:bones" and snode.name ~= "bones:bones" and
  32. anode.name ~= "bones:bones" and dnode.name ~= "bones:bones" and
  33. wnode.name ~= "default:torch" and snode.name ~= "default:torch" and
  34. anode.name ~= "default:torch" and dnode.name ~= "default:torch" and
  35. wnode.name ~= "lifter:block" and snode.name ~= "lifter:block" and
  36. anode.name ~= "lifter:block" and dnode.name ~= "lifter:block" then
  37. print("lift not found, no air")
  38. return
  39. end
  40. local test = minetest.find_nodes_in_area({x=pos.x-1, y=pos.y+i, z=pos.z-1}, {x=pos.x+1, y=pos.y+i, z=pos.z+1}, "air")
  41. if #test == 9 then
  42. print( "lift not found, too much air")
  43. return
  44. end
  45. if i%20 == 0 then
  46. minetest.after(1, fetch_lift, pos, node, clicker, rel, i+plus, open_door, plus)
  47. else
  48. fetch_lift(pos, node, clicker, rel, i+plus, open_door, plus)
  49. end
  50. else
  51. local foundpos
  52. if wnode.name == "lifter:lift" then
  53. local name = minetest.get_node({x=pos.x+1, y=pos.y+rel, z=pos.z}).name
  54. if name == "air" or name == "ignore" or name == "bones:bones" then
  55. minetest.remove_node({x=pos.x+1, y=pos.y+i, z=pos.z})
  56. minetest.add_node({x=pos.x+1, y=pos.y+rel, z=pos.z}, {name="lifter:lift"})
  57. foundpos = {x=pos.x+1, y=pos.y+i, z=pos.z}
  58. else
  59. print("lift blocked")
  60. end
  61. end
  62. if snode.name == "lifter:lift" then
  63. local name = minetest.get_node({x=pos.x-1, y=pos.y+rel, z=pos.z}).name
  64. if name == "air" or name == "ignore" or name == "bones:bones" then
  65. minetest.remove_node({x=pos.x-1, y=pos.y+i, z=pos.z})
  66. minetest.add_node({x=pos.x-1, y=pos.y+rel, z=pos.z}, {name="lifter:lift"})
  67. foundpos = {x=pos.x-1, y=pos.y+i, z=pos.z}
  68. else
  69. print("lift blocked")
  70. end
  71. end
  72. if anode.name == "lifter:lift" then
  73. local name = minetest.get_node({x=pos.x, y=pos.y+rel, z=pos.z+1}).name
  74. if name == "air" or name == "ignore" or name == "bones:bones" then
  75. minetest.remove_node({x=pos.x, y=pos.y+i, z=pos.z+1})
  76. minetest.add_node({x=pos.x, y=pos.y+rel, z=pos.z+1}, {name="lifter:lift"})
  77. foundpos = {x=pos.x, y=pos.y+i, z=pos.z+1}
  78. else
  79. print("lift blocked")
  80. end
  81. end
  82. if dnode.name == "lifter:lift" then
  83. local name = minetest.get_node({x=pos.x, y=pos.y+rel, z=pos.z-1}).name
  84. if name == "air" or name == "ignore" or name == "bones:bones" then
  85. minetest.remove_node({x=pos.x, y=pos.y+i, z=pos.z-1})
  86. minetest.add_node({x=pos.x, y=pos.y+rel, z=pos.z-1}, {name="lifter:lift"})
  87. foundpos = {x=pos.x, y=pos.y+i, z=pos.z-1}
  88. else
  89. print("lift blocked")
  90. end
  91. end
  92. if foundpos ~= nil then
  93. foundpos.y = foundpos.y-1
  94. local name = minetest.get_node(foundpos).name
  95. if name == "lifter:block" then
  96. minetest.remove_node(foundpos)
  97. end
  98. end
  99. open_door(pos,node,clicker)
  100. end
  101. end
  102. local b1rc = minetest.registered_nodes["lifter:door_a"].on_rightclick
  103. --local t2rc = minetest.registered_nodes["lifter:door_t_2"].on_rightclick
  104. minetest.override_item("lifter:door_a", {
  105. on_rightclick = function(pos, node, clicker)
  106. if string.sub(node.name, -2) == "_a" then
  107. if clicker:is_player() then
  108. minetest.chat_send_player(clicker:get_player_name(), "You called for a lift...")
  109. end
  110. fetch_lift(pos, node, clicker, -1, 0, b1rc, 1)
  111. fetch_lift(pos, node, clicker, -1, 0, b1rc, -1)
  112. -- minetest.after(5, b1rc, pos, node, clicker)
  113. else
  114. b1rc(pos, node, clicker)
  115. end
  116. end
  117. })
  118. minetest.register_abm({
  119. nodenames = {"lifter:door_b"},
  120. interval = 8,
  121. chance = 1,
  122. catch_up = false,
  123. action = function(pos, node)
  124. minetest.after(1, b1rc, pos, node, nil)
  125. end
  126. })
  127. local b2rc = minetest.registered_nodes["lifter:door_b"].on_rightclick
  128. minetest.register_node("lifter:lift", {
  129. tiles = {"lifter.png"},
  130. description = "Lift",
  131. drawtype = "normal",
  132. paramtype = "light",
  133. groups = {crumbly=3},
  134. on_rightclick = function(pos, node, player, itemstack, pointed_thing)
  135. local obj = minetest.add_entity(pos, "lifter:travelling_lift")
  136. minetest.remove_node(pos)
  137. if not player then
  138. return
  139. end
  140. obj:get_luaentity().driver = player
  141. player:set_attach(obj, "", {x=0, y=15, z=0}, {x=0, y=0, z=0})
  142. player:set_eye_offset({x=0, y=6, z=0},{x=0, y=0, z=0})
  143. local door = minetest.find_node_near(pos, 2, "lifter:door_b")
  144. if door then
  145. b2rc(door, minetest.get_node(door), player)
  146. end
  147. local support = minetest.find_node_near(pos, 2, "lifter:block")
  148. if support then
  149. minetest.set_node(support, {name="air"})
  150. end
  151. end,
  152. })
  153. minetest.register_node("lifter:block", {
  154. tiles = {"default_wood.png"},
  155. description = "Lift Support",
  156. drawtype = "normal",
  157. paramtype = "light",
  158. groups = {crumbly=3},
  159. drop = "",
  160. })
  161. minetest.register_entity("lifter:travelling_lift", {
  162. physical = true,
  163. collide_with_objects = true,
  164. collisionbox = {-0.5,-0.5,-0.5, 0.5,2.5,0.5},
  165. visual = "cube",
  166. textures = {"lifter.png", "lifter.png", "lifter.png", "lifter.png", "lifter.png", "lifter.png"},
  167. --visual_size = {x=1, y=1},
  168. driver = nil,
  169. direction = 0,
  170. exiting = false,
  171. on_punch = function(self, dtime)
  172. end,
  173. on_step = function(self, dtime)
  174. local exit = false
  175. -- Turn to actual sand when collides to ground or just move
  176. local pos = self.object:get_pos()
  177. local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point
  178. local bcn = minetest.get_node(bcp)
  179. local bcd = minetest.registered_nodes[bcn.name]
  180. -- Note: walkable is in the node definition, not in item groups
  181. local np = {x=bcp.x, y=bcp.y+1, z=bcp.z}
  182. if not self.driver then
  183. print("lost driver!")
  184. minetest.add_node(np, {name="lifter:lift"})
  185. self.object:remove()
  186. --nodeupdate(np)
  187. return
  188. end
  189. local ctrl = self.driver:get_player_control()
  190. if ctrl.jump then
  191. self.direction = 1
  192. end
  193. if ctrl.sneak then
  194. self.direction = -1
  195. end
  196. if ctrl.aux1 then
  197. self.direction = 0
  198. self.object:set_velocity({x=0, y=0, z=0})
  199. end
  200. pos.y = pos.y+1
  201. local nex = 1
  202. local wnode = minetest.get_node({x=pos.x+1, y=pos.y, z=pos.z})
  203. local wbnode = minetest.get_node({x=pos.x+1, y=pos.y-nex, z=pos.z})
  204. local snode = minetest.get_node({x=pos.x-1, y=pos.y, z=pos.z})
  205. local sbnode = minetest.get_node({x=pos.x-1, y=pos.y-nex, z=pos.z})
  206. local anode = minetest.get_node({x=pos.x, y=pos.y, z=pos.z+1})
  207. local abnode = minetest.get_node({x=pos.x, y=pos.y-nex, z=pos.z+1})
  208. local dnode = minetest.get_node({x=pos.x, y=pos.y, z=pos.z-1})
  209. local dbnode = minetest.get_node({x=pos.x, y=pos.y-nex, z=pos.z-1})
  210. if self.direction ~= 0 and not ctrl.jump and not ctrl.sneak then
  211. if (wnode.name == "air" and wbnode.name ~= "air") or
  212. (snode.name == "air" and sbnode.name ~= "air") or
  213. (anode.name == "air" and abnode.name ~= "air") or
  214. (dnode.name == "air" and dbnode.name ~= "air") then
  215. self.direction = 0
  216. self.object:set_velocity({x=0, y=0, z=0})
  217. self.object:set_acceleration({x=0, y=0, z=0})
  218. end
  219. if (wnode.name:find("door") and not wbnode.name:find("door")) or
  220. (snode.name:find("door") and not sbnode.name:find("door")) or
  221. (anode.name:find("door") and not abnode.name:find("door")) or
  222. (dnode.name:find("door") and not dbnode.name:find("door")) then
  223. self.direction = 0
  224. self.object:set_velocity({x=0, y=0, z=0})
  225. self.object:set_acceleration({x=0, y=0, z=0})
  226. end
  227. end
  228. if wnode.name == "air" and snode.name == "air" and anode.name == "air" and dnode.name == "air" then
  229. if self.direction >= 0 then
  230. self.direction = 0
  231. self.object:set_velocity({x=0, y=0, z=0})
  232. else
  233. self.object:set_acceleration({x=0, y=-10, z=0})
  234. end
  235. end
  236. local vel = self.object:get_velocity()
  237. if vector.equals(vel, {x=0,y=0,z=0}) then
  238. if ctrl.up or ctrl.down or ctrl.left or ctrl.right then
  239. exit = true
  240. end
  241. local npos = self.object:get_pos()
  242. if self.direction == 1 then
  243. npos.y = npos.y+0.5
  244. if minetest.get_node({x=npos.x, y=npos.y+2.5, z=npos.z}).name ~= "air" then
  245. npos.y = npos.y-0.5
  246. end
  247. end
  248. if self.direction == -1 then
  249. npos.y = npos.y-1
  250. if minetest.get_node(npos).name ~= "air" then
  251. npos.y = npos.y+0.5
  252. end
  253. end
  254. self.object:set_pos(vector.round(npos))
  255. end
  256. if exit and not self.exiting then
  257. local door = minetest.find_node_near(np, 2, "lifter:door_a")
  258. if door then
  259. b1rc(door, minetest.get_node(door), self.driver)
  260. end
  261. -- Create node and remove entity
  262. minetest.add_node(np, {name="lifter:lift"})
  263. --nodeupdate(np)
  264. np.y = np.y-1
  265. if minetest.get_node(np).name == "air" then
  266. minetest.add_node(np, {name="lifter:block"})
  267. end
  268. self.exiting = true
  269. minetest.after(0.2, function(self)
  270. if self.driver then
  271. self.exiting = false
  272. self.driver:set_detach()
  273. self.driver:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
  274. pos.y = pos.y
  275. self.driver:set_pos(pos)
  276. self.object:remove()
  277. end
  278. end, self)
  279. return
  280. end
  281. if ctrl.jump or ctrl.sneak then
  282. -- Set gravity
  283. self.object:set_acceleration({x=0, y=self.direction*5, z=0})
  284. else
  285. self.object:set_acceleration({x=0, y=0, z=0})
  286. end
  287. end
  288. })
  289. minetest.register_craft({
  290. output = "lifter:lift",
  291. recipe = {
  292. {"group:wood", "group:stick", "group:wood"},
  293. {"group:wood", "default:mese", "group:wood"},
  294. {"group:wood", "group:stick", "group:wood"},
  295. },
  296. })