init.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. -- Minetest 0.4 mod: stairs
  2. -- See README.txt for licensing and other information.
  3. -- Global namespace for functions
  4. stairs = {}
  5. -- Register aliases for new pine node names
  6. minetest.register_alias("stairs:stair_pinewood", "stairs:stair_pine_wood")
  7. minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood")
  8. -- Get setting for replace ABM
  9. local replace = minetest.settings:get_bool("enable_stairs_replace_abm")
  10. local function rotate_and_place(itemstack, placer, pointed_thing)
  11. local p0 = pointed_thing.under
  12. local p1 = pointed_thing.above
  13. local param2 = 0
  14. if placer then
  15. local placer_pos = placer:get_pos()
  16. if placer_pos then
  17. param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
  18. end
  19. local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
  20. local fpos = finepos.y % 1
  21. if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)
  22. or (fpos < -0.5 and fpos > -0.999999999) then
  23. param2 = param2 + 20
  24. if param2 == 21 then
  25. param2 = 23
  26. elseif param2 == 23 then
  27. param2 = 21
  28. end
  29. end
  30. end
  31. return minetest.item_place(itemstack, placer, pointed_thing, param2)
  32. end
  33. -- Register stair
  34. -- Node will be called stairs:stair_<subname>
  35. function stairs.register_stair(subname, recipeitem, groups, images, description,
  36. sounds, worldaligntex)
  37. -- Set backface culling and world-aligned textures
  38. local stair_images = {}
  39. for i, image in ipairs(images) do
  40. if type(image) == "string" then
  41. stair_images[i] = {
  42. name = image,
  43. backface_culling = true,
  44. }
  45. if worldaligntex then
  46. stair_images[i].align_style = "world"
  47. end
  48. else
  49. stair_images[i] = table.copy(image)
  50. if stair_images[i].backface_culling == nil then
  51. stair_images[i].backface_culling = true
  52. end
  53. if worldaligntex and stair_images[i].align_style == nil then
  54. stair_images[i].align_style = "world"
  55. end
  56. end
  57. end
  58. local new_groups = table.copy(groups)
  59. new_groups.stair = 1
  60. minetest.register_node(":stairs:stair_" .. subname, {
  61. description = description,
  62. drawtype = "nodebox",
  63. tiles = stair_images,
  64. paramtype = "light",
  65. paramtype2 = "facedir",
  66. is_ground_content = false,
  67. groups = new_groups,
  68. sounds = sounds,
  69. node_box = {
  70. type = "fixed",
  71. fixed = {
  72. {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
  73. {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5},
  74. },
  75. },
  76. on_place = function(itemstack, placer, pointed_thing)
  77. if pointed_thing.type ~= "node" then
  78. return itemstack
  79. end
  80. return rotate_and_place(itemstack, placer, pointed_thing)
  81. end,
  82. })
  83. -- for replace ABM
  84. if replace then
  85. minetest.register_node(":stairs:stair_" .. subname .. "upside_down", {
  86. replace_name = "stairs:stair_" .. subname,
  87. groups = {slabs_replace = 1},
  88. })
  89. end
  90. if recipeitem then
  91. -- Recipe matches appearence in inventory
  92. minetest.register_craft({
  93. output = 'stairs:stair_' .. subname .. ' 8',
  94. recipe = {
  95. {"", "", recipeitem},
  96. {"", recipeitem, recipeitem},
  97. {recipeitem, recipeitem, recipeitem},
  98. },
  99. })
  100. -- Use stairs to craft full blocks again (1:1)
  101. minetest.register_craft({
  102. output = recipeitem .. ' 3',
  103. recipe = {
  104. {'stairs:stair_' .. subname, 'stairs:stair_' .. subname},
  105. {'stairs:stair_' .. subname, 'stairs:stair_' .. subname},
  106. },
  107. })
  108. -- Fuel
  109. local baseburntime = minetest.get_craft_result({
  110. method = "fuel",
  111. width = 1,
  112. items = {recipeitem}
  113. }).time
  114. if baseburntime > 0 then
  115. minetest.register_craft({
  116. type = "fuel",
  117. recipe = 'stairs:stair_' .. subname,
  118. burntime = math.floor(baseburntime * 0.75),
  119. })
  120. end
  121. end
  122. end
  123. -- Register slab
  124. -- Node will be called stairs:slab_<subname>
  125. function stairs.register_slab(subname, recipeitem, groups, images, description,
  126. sounds, worldaligntex)
  127. -- Set world-aligned textures
  128. local slab_images = {}
  129. for i, image in ipairs(images) do
  130. if type(image) == "string" then
  131. slab_images[i] = {
  132. name = image,
  133. }
  134. if worldaligntex then
  135. slab_images[i].align_style = "world"
  136. end
  137. else
  138. slab_images[i] = table.copy(image)
  139. if worldaligntex and image.align_style == nil then
  140. slab_images[i].align_style = "world"
  141. end
  142. end
  143. end
  144. local new_groups = table.copy(groups)
  145. new_groups.slab = 1
  146. minetest.register_node(":stairs:slab_" .. subname, {
  147. description = description,
  148. drawtype = "nodebox",
  149. tiles = slab_images,
  150. paramtype = "light",
  151. paramtype2 = "facedir",
  152. is_ground_content = false,
  153. groups = new_groups,
  154. sounds = sounds,
  155. node_box = {
  156. type = "fixed",
  157. fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
  158. },
  159. on_place = function(itemstack, placer, pointed_thing)
  160. local under = minetest.get_node(pointed_thing.under)
  161. local wield_item = itemstack:get_name()
  162. local player_name = placer and placer:get_player_name() or ""
  163. local creative_enabled = (creative and creative.is_enabled_for
  164. and creative.is_enabled_for(player_name))
  165. if under and under.name:find("^stairs:slab_") then
  166. -- place slab using under node orientation
  167. local dir = minetest.dir_to_facedir(vector.subtract(
  168. pointed_thing.above, pointed_thing.under), true)
  169. local p2 = under.param2
  170. -- Placing a slab on an upside down slab should make it right-side up.
  171. if p2 >= 20 and dir == 8 then
  172. p2 = p2 - 20
  173. -- same for the opposite case: slab below normal slab
  174. elseif p2 <= 3 and dir == 4 then
  175. p2 = p2 + 20
  176. end
  177. -- else attempt to place node with proper param2
  178. minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2)
  179. if not creative_enabled then
  180. itemstack:take_item()
  181. end
  182. return itemstack
  183. else
  184. return rotate_and_place(itemstack, placer, pointed_thing)
  185. end
  186. end,
  187. })
  188. -- for replace ABM
  189. if replace then
  190. minetest.register_node(":stairs:slab_" .. subname .. "upside_down", {
  191. replace_name = "stairs:slab_".. subname,
  192. groups = {slabs_replace = 1},
  193. })
  194. end
  195. if recipeitem then
  196. minetest.register_craft({
  197. output = 'stairs:slab_' .. subname .. ' 6',
  198. recipe = {
  199. {recipeitem, recipeitem, recipeitem},
  200. },
  201. })
  202. -- Use 2 slabs to craft a full block again (1:1)
  203. minetest.register_craft({
  204. output = recipeitem,
  205. recipe = {
  206. {'stairs:slab_' .. subname},
  207. {'stairs:slab_' .. subname},
  208. },
  209. })
  210. -- Fuel
  211. local baseburntime = minetest.get_craft_result({
  212. method = "fuel",
  213. width = 1,
  214. items = {recipeitem}
  215. }).time
  216. if baseburntime > 0 then
  217. minetest.register_craft({
  218. type = "fuel",
  219. recipe = 'stairs:slab_' .. subname,
  220. burntime = math.floor(baseburntime * 0.5),
  221. })
  222. end
  223. end
  224. end
  225. -- Optionally replace old "upside_down" nodes with new param2 versions.
  226. -- Disabled by default.
  227. if replace then
  228. minetest.register_abm({
  229. label = "Slab replace",
  230. nodenames = {"group:slabs_replace"},
  231. interval = 16,
  232. chance = 1,
  233. action = function(pos, node)
  234. node.name = minetest.registered_nodes[node.name].replace_name
  235. node.param2 = node.param2 + 20
  236. if node.param2 == 21 then
  237. node.param2 = 23
  238. elseif node.param2 == 23 then
  239. node.param2 = 21
  240. end
  241. minetest.set_node(pos, node)
  242. end,
  243. })
  244. end
  245. -- Register inner stair
  246. -- Node will be called stairs:stair_inner_<subname>
  247. function stairs.register_stair_inner(subname, recipeitem, groups, images,
  248. description, sounds, worldaligntex)
  249. -- Set backface culling and world-aligned textures
  250. local stair_images = {}
  251. for i, image in ipairs(images) do
  252. if type(image) == "string" then
  253. stair_images[i] = {
  254. name = image,
  255. backface_culling = true,
  256. }
  257. if worldaligntex then
  258. stair_images[i].align_style = "world"
  259. end
  260. else
  261. stair_images[i] = table.copy(image)
  262. if stair_images[i].backface_culling == nil then
  263. stair_images[i].backface_culling = true
  264. end
  265. if worldaligntex and stair_images[i].align_style == nil then
  266. stair_images[i].align_style = "world"
  267. end
  268. end
  269. end
  270. local new_groups = table.copy(groups)
  271. new_groups.stair = 1
  272. minetest.register_node(":stairs:stair_inner_" .. subname, {
  273. description = "Inner " .. description,
  274. drawtype = "nodebox",
  275. tiles = stair_images,
  276. paramtype = "light",
  277. paramtype2 = "facedir",
  278. is_ground_content = false,
  279. groups = new_groups,
  280. sounds = sounds,
  281. node_box = {
  282. type = "fixed",
  283. fixed = {
  284. {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
  285. {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5},
  286. {-0.5, 0.0, -0.5, 0.0, 0.5, 0.0},
  287. },
  288. },
  289. on_place = function(itemstack, placer, pointed_thing)
  290. if pointed_thing.type ~= "node" then
  291. return itemstack
  292. end
  293. return rotate_and_place(itemstack, placer, pointed_thing)
  294. end,
  295. })
  296. if recipeitem then
  297. minetest.register_craft({
  298. output = 'stairs:stair_inner_' .. subname .. ' 7',
  299. recipe = {
  300. {"", recipeitem, ""},
  301. {recipeitem, "", recipeitem},
  302. {recipeitem, recipeitem, recipeitem},
  303. },
  304. })
  305. -- Fuel
  306. local baseburntime = minetest.get_craft_result({
  307. method = "fuel",
  308. width = 1,
  309. items = {recipeitem}
  310. }).time
  311. if baseburntime > 0 then
  312. minetest.register_craft({
  313. type = "fuel",
  314. recipe = 'stairs:stair_inner_' .. subname,
  315. burntime = math.floor(baseburntime * 0.875),
  316. })
  317. end
  318. end
  319. end
  320. -- Register outer stair
  321. -- Node will be called stairs:stair_outer_<subname>
  322. function stairs.register_stair_outer(subname, recipeitem, groups, images,
  323. description, sounds, worldaligntex)
  324. -- Set backface culling and world-aligned textures
  325. local stair_images = {}
  326. for i, image in ipairs(images) do
  327. if type(image) == "string" then
  328. stair_images[i] = {
  329. name = image,
  330. backface_culling = true,
  331. }
  332. if worldaligntex then
  333. stair_images[i].align_style = "world"
  334. end
  335. else
  336. stair_images[i] = table.copy(image)
  337. if stair_images[i].backface_culling == nil then
  338. stair_images[i].backface_culling = true
  339. end
  340. if worldaligntex and stair_images[i].align_style == nil then
  341. stair_images[i].align_style = "world"
  342. end
  343. end
  344. end
  345. local new_groups = table.copy(groups)
  346. new_groups.stair = 1
  347. minetest.register_node(":stairs:stair_outer_" .. subname, {
  348. description = "Outer " .. description,
  349. drawtype = "nodebox",
  350. tiles = stair_images,
  351. paramtype = "light",
  352. paramtype2 = "facedir",
  353. is_ground_content = false,
  354. groups = new_groups,
  355. sounds = sounds,
  356. node_box = {
  357. type = "fixed",
  358. fixed = {
  359. {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5},
  360. {-0.5, 0.0, 0.0, 0.0, 0.5, 0.5},
  361. },
  362. },
  363. on_place = function(itemstack, placer, pointed_thing)
  364. if pointed_thing.type ~= "node" then
  365. return itemstack
  366. end
  367. return rotate_and_place(itemstack, placer, pointed_thing)
  368. end,
  369. })
  370. if recipeitem then
  371. minetest.register_craft({
  372. output = 'stairs:stair_outer_' .. subname .. ' 6',
  373. recipe = {
  374. {"", recipeitem, ""},
  375. {recipeitem, recipeitem, recipeitem},
  376. },
  377. })
  378. -- Fuel
  379. local baseburntime = minetest.get_craft_result({
  380. method = "fuel",
  381. width = 1,
  382. items = {recipeitem}
  383. }).time
  384. if baseburntime > 0 then
  385. minetest.register_craft({
  386. type = "fuel",
  387. recipe = 'stairs:stair_outer_' .. subname,
  388. burntime = math.floor(baseburntime * 0.625),
  389. })
  390. end
  391. end
  392. end
  393. -- Stair/slab registration function.
  394. -- Nodes will be called stairs:{stair,slab}_<subname>
  395. function stairs.register_stair_and_slab(subname, recipeitem, groups, images,
  396. desc_stair, desc_slab, sounds, worldaligntex)
  397. stairs.register_stair(subname, recipeitem, groups, images, desc_stair,
  398. sounds, worldaligntex)
  399. stairs.register_stair_inner(subname, recipeitem, groups, images, desc_stair,
  400. sounds, worldaligntex)
  401. stairs.register_stair_outer(subname, recipeitem, groups, images, desc_stair,
  402. sounds, worldaligntex)
  403. stairs.register_slab(subname, recipeitem, groups, images, desc_slab,
  404. sounds, worldaligntex)
  405. end