init.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. -- Minetest 0.4 mod: stairs
  2. -- See README.txt for licensing and other information.
  3. -- Global namespace for functions
  4. local S = function(str) return str end
  5. stairs = {}
  6. circular_saw = circular_saw or {}
  7. circular_saw.known_nodes = circular_saw.known_nodes or {}
  8. -- Also used by walls.
  9. function stairs.setup_nodedef_callbacks(subname, def)
  10. if string.find(subname, "ice") or string.find(subname, "snow") then
  11. assert(not def.on_construct)
  12. def.on_construct = function(pos)
  13. if rc.ice_melts_at_pos(pos) then
  14. minetest.get_node_timer(pos):start(math.random(ice.minmax_time()))
  15. end
  16. end
  17. assert(not def.on_timer)
  18. def.on_timer = function(pos, elapsed)
  19. if rc.ice_melts_at_pos(pos) then
  20. minetest.add_node(pos, {name="default:water_flowing"})
  21. end
  22. end
  23. end
  24. end
  25. function stairs.rotate_and_place(itemstack, placer, pt)
  26. if pt.type == "node" then
  27. local node = minetest.get_node(pt.under)
  28. if node.name == itemstack:get_name() then
  29. local param2 = node.param2
  30. return minetest.item_place(itemstack, placer, pt, param2)
  31. end
  32. end
  33. return minetest.rotate_node(itemstack, placer, pt)
  34. end
  35. dofile(minetest.get_modpath("stairs") .. "/slopes.lua")
  36. local slabs_defs = {
  37. ["_quarter"] = {num=4, light=0.25, is_flat=true},
  38. ["_three_quarter"] = {num=12, light=0.75, is_flat=true},
  39. ["_1"] = {num=1, light=1/16, is_flat=true},
  40. ["_2"] = {num=2, light=2/16, is_flat=true},
  41. ["_14"] = {num=14, light=14/16, is_flat=true},
  42. ["_15"] = {num=15, light=15/16, is_flat=true},
  43. ["_two_sides"] = {
  44. nodebox = {
  45. { -0.5, -0.5, -0.5, 0.5, -7/16, 7/16 },
  46. { -0.5, -0.5, 7/16, 0.5, 0.5, 0.5 },
  47. }
  48. },
  49. ["_three_sides"] = {
  50. nodebox = {
  51. { -7/16, -0.5, -0.5, 0.5, -7/16, 7/16 },
  52. { -7/16, -0.5, 7/16, 0.5, 0.5, 0.5 },
  53. { -0.5, -0.5, -0.5, -7/16, 0.5, 0.5 },
  54. }
  55. },
  56. ["_three_sides_u"] = {
  57. nodebox = {
  58. { -0.5, -0.5, -0.5, 0.5, 0.5, -7/16 },
  59. { -0.5, -0.5, -7/16, 0.5, -7/16, 7/16 },
  60. { -0.5, -0.5, 7/16, 0.5, 0.5, 0.5 },
  61. }
  62. },
  63. ["_four_sides"] = {
  64. nodebox = {
  65. { -0.5, -0.5, -0.5, 0.5, 0.5, -7/16 },
  66. { -0.5, -0.5, -7/16, 0.5, -7/16, 7/16 },
  67. { -0.5, -0.5, 7/16, 0.5, 0.5, 0.5 },
  68. { -0.5, -7/16, -7/16, -7/16, 0.5, 7/16 },
  69. }
  70. },
  71. ["_hole"] = {
  72. nodebox = {
  73. {-0.5, -0.5, -0.5, 0.5, 0.5, -7/16},
  74. {-0.5, -0.5, 0.5, 0.5, 0.5, 7/16},
  75. {-0.5, -0.5, -7/16, -7/16, 0.5, 7/16},
  76. {0.5, -0.5, -7/16, 7/16, 0.5, 7/16},
  77. }
  78. },
  79. ["_two_opposite"] = {
  80. nodebox = {
  81. {-0.5, -0.5, -0.5, 0.5, 0.5, -7/16},
  82. {-0.5, -0.5, 0.5, 0.5, 0.5, 7/16},
  83. }
  84. },
  85. ["_pit"] = {
  86. nodebox = {
  87. { -0.5, -0.5, -0.5, 0.5, 0.5, -7/16 },
  88. { -0.5, -0.5, -7/16, 0.5, -7/16, 7/16 },
  89. { -0.5, -0.5, 7/16, 0.5, 0.5, 0.5 },
  90. { -0.5, -7/16, -7/16, -7/16, 0.5, 7/16 },
  91. { -7/16, 0.5, -7/16, 0.5, 7/16, 7/16 },
  92. }
  93. },
  94. ["_pit_half"] = {
  95. nodebox = {
  96. { -0.5, -0.5, -0.5, 0.0, 0.5, -7/16 },
  97. { -0.5, -0.5, -7/16, 0.0, -7/16, 7/16 },
  98. { -0.5, -0.5, 7/16, 0.0, 0.5, 0.5 },
  99. { -0.5, -7/16, -7/16, -7/16, 0.5, 7/16 },
  100. { -7/16, 0.5, -7/16, 0.0, 7/16, 7/16 },
  101. }
  102. },
  103. ["_hole_half"] = {
  104. nodebox = {
  105. {-0.5, -0.5, -0.5, 0.5, 0, -7/16},
  106. {-0.5, -0.5, 0.5, 0.5, 0, 7/16},
  107. {-0.5, -0.5, -7/16, -7/16, 0, 7/16},
  108. {0.5, -0.5, -7/16, 7/16, 0, 7/16},
  109. }
  110. },
  111. }
  112. function stairs.register_extra_slabs(subname, recipeitem, groups, images, description, sounds)
  113. local stair_images = {}
  114. for i, image in ipairs(images) do
  115. if type(image) == "string" then
  116. stair_images[i] = {
  117. name = image,
  118. backface_culling = true,
  119. }
  120. elseif image.backface_culling == nil then -- override using any other value
  121. stair_images[i] = table.copy(image)
  122. stair_images[i].backface_culling = true
  123. end
  124. end
  125. local defs = table.copy(slabs_defs)
  126. -- Do not modify function argument.
  127. local groups = table.copy(groups)
  128. groups.not_in_craft_guide = 1
  129. groups.stairs_slab = 1
  130. groups.stairs_node = 1
  131. local ndef = minetest.registered_items[recipeitem]
  132. assert(ndef)
  133. for alternate, num in pairs(defs) do
  134. local def
  135. if num.num then
  136. def = {
  137. node_box = {
  138. type = "fixed",
  139. fixed = {-0.5, -0.5, -0.5, 0.5, (num.num/16)-0.5, 0.5},
  140. }
  141. }
  142. elseif num.nodebox then
  143. def = {
  144. node_box = {
  145. type = "fixed",
  146. fixed = num.nodebox,
  147. }
  148. }
  149. end
  150. def.drawtype = "nodebox"
  151. def.paramtype = "light"
  152. def.paramtype2 = "facedir"
  153. def.on_place = function(...) return stairs.rotate_and_place(...) end
  154. def.groups = groups
  155. def.sounds = sounds
  156. def.description = description
  157. def.tiles = stair_images
  158. def.light_source = math.ceil(ndef.light_source*(num.light or 0))
  159. -- Only for flat slabs.
  160. if num.is_flat then
  161. def.movement_speed_depends = recipeitem
  162. end
  163. stairs.setup_nodedef_callbacks(subname, def)
  164. minetest.register_node(":stairs:slab_" .. subname .. alternate, def)
  165. end
  166. if recipeitem then
  167. circular_saw.known_nodes[recipeitem] = {"stairs", subname}
  168. end
  169. end
  170. local stairs_defs = {
  171. ["_half"] = {
  172. node_box = {
  173. type = "fixed",
  174. fixed = {
  175. {-0.5, -0.5, -0.5, 0, 0, 0.5},
  176. {-0.5, 0, 0, 0, 0.5, 0.5},
  177. },
  178. },
  179. light=3/8,
  180. },
  181. ["_right_half" ]= {
  182. node_box = {
  183. type = "fixed",
  184. fixed = {
  185. {0, -0.5, -0.5, 0.5, 0, 0.5},
  186. {0, 0, 0, 0.5, 0.5, 0.5},
  187. },
  188. },
  189. light=3/8,
  190. },
  191. ["_half_1"] = {
  192. node_box = {
  193. type = "fixed",
  194. fixed = {
  195. {-0.5, -0.5, -0.5, -7/16, 0, 0.5},
  196. {-0.5, 0, 0, -7/16, 0.5, 0.5},
  197. },
  198. },
  199. light=1/8,
  200. },
  201. ["_right_half_1" ]= {
  202. node_box = {
  203. type = "fixed",
  204. fixed = {
  205. {7/16, -0.5, -0.5, 0.5, 0, 0.5},
  206. {7/16, 0, 0, 0.5, 0.5, 0.5},
  207. },
  208. },
  209. light=1/8,
  210. },
  211. ["_inner"] = {
  212. node_box = {
  213. type = "fixed",
  214. fixed = {
  215. {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
  216. {-0.5, 0, 0, 0.5, 0.5, 0.5},
  217. {-0.5, 0, -0.5, 0, 0.5, 0},
  218. },
  219. },
  220. light=7/8,
  221. },
  222. ["_outer"] = {
  223. node_box = {
  224. type = "fixed",
  225. fixed = {
  226. {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
  227. {-0.5, 0, 0, 0, 0.5, 0.5},
  228. },
  229. },
  230. light=5/8,
  231. },
  232. ["_alt"] = {
  233. node_box = {
  234. type = "fixed",
  235. fixed = {
  236. {-0.5, -0.5, -0.5, 0.5, 0, 0},
  237. {-0.5, 0, 0, 0.5, 0.5, 0.5},
  238. },
  239. },
  240. light=1/2,
  241. },
  242. ["_alt_1"] = {
  243. node_box = {
  244. type = "fixed",
  245. fixed = {
  246. {-0.5, -0.0625, -0.5, 0.5, 0, 0},
  247. {-0.5, 0.4375, 0, 0.5, 0.5, 0.5},
  248. },
  249. },
  250. light=1/16,
  251. },
  252. ["_alt_5"] = {
  253. node_box = {
  254. type = "fixed",
  255. fixed = {
  256. {-0.5, -0.0625, 0.0, 0.5, 0, 0.5},
  257. {-0.5, 0.4375, 0, 0.5, 0.5, 0.5},
  258. },
  259. },
  260. light=1/16,
  261. },
  262. ["_alt_6"] = {
  263. node_box = {
  264. type = "fixed",
  265. fixed = {
  266. {-0.5, -0.0625, -0.5, 0.5, 0, 0.5},
  267. {-0.5, 0.4375, -0.5, 0.5, 0.5, 0.5},
  268. },
  269. },
  270. light=1/16,
  271. },
  272. ["_alt_2"] = {
  273. node_box = {
  274. type = "fixed",
  275. fixed = {
  276. {-0.5, -0.125, -0.5, 0.5, 0, 0},
  277. {-0.5, 0.375, 0, 0.5, 0.5, 0.5},
  278. },
  279. },
  280. light=2/16,
  281. },
  282. ["_alt_4"] = {
  283. node_box = {
  284. type = "fixed",
  285. fixed = {
  286. {-0.5, -0.25, -0.5, 0.5, 0, 0},
  287. {-0.5, 0.25, 0, 0.5, 0.5, 0.5},
  288. },
  289. },
  290. light=4/16,
  291. },
  292. }
  293. function stairs.register_extra_stairs(subname, recipeitem, groups, images, description, sounds)
  294. local stair_images = {}
  295. for i, image in ipairs(images) do
  296. if type(image) == "string" then
  297. stair_images[i] = {
  298. name = image,
  299. backface_culling = true,
  300. }
  301. elseif image.backface_culling == nil then -- override using any other value
  302. stair_images[i] = table.copy(image)
  303. stair_images[i].backface_culling = true
  304. end
  305. end
  306. local defs = table.copy(stairs_defs)
  307. -- Do not modify function argument.
  308. local groups = table.copy(groups)
  309. groups.not_in_craft_guide = 1
  310. groups.stairs_stair = 1
  311. groups.stairs_node = 1
  312. local ndef = minetest.registered_items[recipeitem]
  313. assert(ndef)
  314. for alternate, def in pairs(defs) do
  315. def.drawtype = "nodebox"
  316. def.paramtype = "light"
  317. def.paramtype2 = "facedir"
  318. def.on_place = function(...) return stairs.rotate_and_place(...) end
  319. def.groups = groups
  320. def.sounds = sounds
  321. def.description = description
  322. def.tiles = stair_images
  323. def.light_source = math.ceil(ndef.light_source*def.light)
  324. def.light = nil
  325. stairs.setup_nodedef_callbacks(subname, def)
  326. minetest.register_node(":stairs:stair_" ..subname..alternate, def)
  327. if recipeitem then
  328. if alternate == "_inner" then
  329. minetest.register_craft({
  330. output = "stairs:stair_" .. subname .. alternate .. ' 8',
  331. recipe = {
  332. {recipeitem, recipeitem, recipeitem},
  333. {recipeitem, recipeitem, ''},
  334. {recipeitem, '', recipeitem},
  335. },
  336. })
  337. elseif alternate == "_outer" then
  338. minetest.register_craft({
  339. output = "stairs:stair_" .. subname .. alternate .. ' 8',
  340. recipe = {
  341. {recipeitem, recipeitem, recipeitem},
  342. {recipeitem, '', ''},
  343. {recipeitem, '', ''},
  344. },
  345. })
  346. end
  347. end
  348. end
  349. minetest.register_alias("stairs:stair_" ..subname.. "_bottom", "stairs:stair_" ..subname)
  350. if recipeitem then
  351. circular_saw.known_nodes[recipeitem] = {"stairs", subname}
  352. end
  353. end
  354. local panels_defs = {
  355. [""] = {
  356. node_box = {
  357. type = "fixed",
  358. fixed = {-0.5, -0.5, 0, 0.5, 0, 0.5},
  359. },
  360. light=1/4,
  361. },
  362. ["_1"] = {
  363. node_box = {
  364. type = "fixed",
  365. fixed = {-0.5, -0.5, 0, 0.5, -0.4375, 0.5},
  366. },
  367. light=1/32,
  368. },
  369. ["_2"] = {
  370. node_box = {
  371. type = "fixed",
  372. fixed = {-0.5, -0.5, 0, 0.5, -0.375, 0.5},
  373. },
  374. light=2/32,
  375. },
  376. ["_4"] = {
  377. node_box = {
  378. type = "fixed",
  379. fixed = {-0.5, -0.5, 0, 0.5, -0.25, 0.5},
  380. },
  381. light=4/32,
  382. },
  383. ["_12"] = {
  384. node_box = {
  385. type = "fixed",
  386. fixed = {-0.5, -0.5, 0, 0.5, 0.25, 0.5},
  387. },
  388. light=12/32,
  389. },
  390. ["_14"] = {
  391. node_box = {
  392. type = "fixed",
  393. fixed = {-0.5, -0.5, 0, 0.5, 0.375, 0.5},
  394. },
  395. light=14/32,
  396. },
  397. ["_15"] = {
  398. node_box = {
  399. type = "fixed",
  400. fixed = {-0.5, -0.5, 0, 0.5, 0.4375, 0.5},
  401. },
  402. light=15/32,
  403. },
  404. ["_16"] = {
  405. node_box = {
  406. type = "fixed",
  407. fixed = {-0.5, -0.5, 0, 0.5, 0.5, 0.5},
  408. },
  409. light=16/32,
  410. }
  411. }
  412. function stairs.register_panel(subname, recipeitem, groups, images, description, sounds)
  413. local stair_images = {}
  414. for i, image in ipairs(images) do
  415. if type(image) == "string" then
  416. stair_images[i] = {
  417. name = image,
  418. backface_culling = true,
  419. }
  420. elseif image.backface_culling == nil then -- override using any other value
  421. stair_images[i] = table.copy(image)
  422. stair_images[i].backface_culling = true
  423. end
  424. end
  425. local defs = table.copy(panels_defs)
  426. -- Do not modify function argument.
  427. local groups = table.copy(groups)
  428. groups.not_in_craft_guide = 1
  429. groups.stairs_panel = 1
  430. groups.stairs_node = 1
  431. local ndef = minetest.registered_items[recipeitem]
  432. assert(ndef)
  433. for alternate, def in pairs(defs) do
  434. def.drawtype = "nodebox"
  435. def.paramtype = "light"
  436. def.paramtype2 = "facedir"
  437. def.on_place = function(...) return stairs.rotate_and_place(...) end
  438. def.groups = groups
  439. def.sounds = sounds
  440. def.description = description
  441. def.tiles = stair_images
  442. def.light_source = math.ceil(ndef.light_source*def.light)
  443. def.light = nil
  444. stairs.setup_nodedef_callbacks(subname, def)
  445. minetest.register_node(":stairs:panel_" ..subname..alternate, def)
  446. end
  447. minetest.register_alias("stairs:panel_" ..subname.. "_bottom", "stairs:panel_" ..subname)
  448. if recipeitem then
  449. circular_saw.known_nodes[recipeitem] = {"stairs", subname}
  450. end
  451. end
  452. local microblocks_defs = {
  453. [""] = {
  454. node_box = {
  455. type = "fixed",
  456. fixed = {-0.5, -0.5, 0, 0, 0, 0.5},
  457. },
  458. light=8/64,
  459. },
  460. ["_1"] = {
  461. node_box = {
  462. type = "fixed",
  463. fixed = {-0.5, -0.5, 0, 0, -0.4375, 0.5},
  464. },
  465. light=1/64,
  466. },
  467. ["_2"] = {
  468. node_box = {
  469. type = "fixed",
  470. fixed = {-0.5, -0.5, 0, 0, -0.375, 0.5},
  471. },
  472. light=2/64,
  473. },
  474. ["_4"] = {
  475. node_box = {
  476. type = "fixed",
  477. fixed = {-0.5, -0.5, 0, 0, -0.25, 0.5},
  478. },
  479. light=4/64,
  480. },
  481. ["_12"] = {
  482. node_box = {
  483. type = "fixed",
  484. fixed = {-0.5, -0.5, 0, 0, 0.25, 0.5},
  485. },
  486. light=12/64,
  487. },
  488. ["_14"] = {
  489. node_box = {
  490. type = "fixed",
  491. fixed = {-0.5, -0.5, 0, 0, 0.375, 0.5},
  492. },
  493. light=14/64,
  494. },
  495. ["_15"] = {
  496. node_box = {
  497. type = "fixed",
  498. fixed = {-0.5, -0.5, 0, 0, 0.4375, 0.5},
  499. },
  500. light=15/64,
  501. },
  502. ["_16"] = {
  503. node_box = {
  504. type = "fixed",
  505. fixed = {-0.5, -0.5, 0, 0, 0.5, 0.5},
  506. },
  507. light=16/64,
  508. }
  509. }
  510. function stairs.register_micro(subname, recipeitem, groups, images, description, sounds)
  511. local stair_images = {}
  512. for i, image in ipairs(images) do
  513. if type(image) == "string" then
  514. stair_images[i] = {
  515. name = image,
  516. backface_culling = true,
  517. }
  518. elseif image.backface_culling == nil then -- override using any other value
  519. stair_images[i] = table.copy(image)
  520. stair_images[i].backface_culling = true
  521. end
  522. end
  523. local defs = table.copy(microblocks_defs)
  524. -- Do not modify function argument.
  525. local groups = table.copy(groups)
  526. groups.not_in_craft_guide = 1
  527. groups.stairs_microblock = 1
  528. groups.stairs_node = 1
  529. local ndef = minetest.registered_items[recipeitem]
  530. assert(ndef)
  531. for alternate, def in pairs(defs) do
  532. def.drawtype = "nodebox"
  533. def.paramtype = "light"
  534. def.paramtype2 = "facedir"
  535. def.on_place = function(...) return stairs.rotate_and_place(...) end
  536. def.groups = groups
  537. def.sounds = sounds
  538. def.description = description
  539. def.tiles = stair_images
  540. def.light_source = math.ceil(ndef.light_source*def.light)
  541. def.light = nil
  542. stairs.setup_nodedef_callbacks(subname, def)
  543. minetest.register_node(":stairs:micro_" .. subname .. alternate, def)
  544. end
  545. minetest.register_alias("stairs:micro_" ..subname.. "_bottom", "stairs:micro_" ..subname)
  546. if recipeitem then
  547. circular_saw.known_nodes[recipeitem] = {"stairs", subname}
  548. end
  549. end
  550. -- Register aliases for new pine node names
  551. minetest.register_alias("stairs:stair_pinewood", "stairs:stair_pine_wood")
  552. minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood")
  553. -- Register stairs.
  554. -- Node will be called stairs:stair_<subname>
  555. function stairs.register_stair(subname, recipeitem, groups, images, description, sounds)
  556. local stair_images = {}
  557. for i, image in ipairs(images) do
  558. if type(image) == "string" then
  559. stair_images[i] = {
  560. name = image,
  561. backface_culling = true,
  562. }
  563. elseif image.backface_culling == nil then -- override using any other value
  564. stair_images[i] = table.copy(image)
  565. stair_images[i].backface_culling = true
  566. end
  567. end
  568. -- Do not modify function argument.
  569. groups = table.copy(groups)
  570. groups.stair = 1
  571. groups.stairs_stair = 1
  572. groups.not_in_craft_guide = 1
  573. groups.stairs_node = 1
  574. local ndef = minetest.registered_items[recipeitem]
  575. assert(ndef)
  576. local stair_def = {
  577. description = description,
  578. drawtype = "mesh",
  579. mesh = "stairs_stair.obj",
  580. tiles = stair_images,
  581. paramtype = "light",
  582. paramtype2 = "facedir",
  583. is_ground_content = false,
  584. groups = groups,
  585. sounds = sounds,
  586. light_source = math.ceil(ndef.light_source*0.75),
  587. selection_box = {
  588. type = "fixed",
  589. fixed = {
  590. {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
  591. {-0.5, 0, 0, 0.5, 0.5, 0.5},
  592. },
  593. },
  594. collision_box = {
  595. type = "fixed",
  596. fixed = {
  597. {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
  598. {-0.5, 0, 0, 0.5, 0.5, 0.5},
  599. },
  600. },
  601. on_place = function(itemstack, placer, pointed_thing)
  602. if pointed_thing.type ~= "node" then
  603. return itemstack
  604. end
  605. local p0 = pointed_thing.under
  606. local p1 = pointed_thing.above
  607. local param2 = 0
  608. local placer_pos = placer:getpos()
  609. if placer_pos then
  610. local dir = {
  611. x = p1.x - placer_pos.x,
  612. y = p1.y - placer_pos.y,
  613. z = p1.z - placer_pos.z
  614. }
  615. param2 = minetest.dir_to_facedir(dir)
  616. end
  617. if p0.y - 1 == p1.y then
  618. param2 = param2 + 20
  619. if param2 == 21 then
  620. param2 = 23
  621. elseif param2 == 23 then
  622. param2 = 21
  623. end
  624. end
  625. return minetest.item_place(itemstack, placer, pointed_thing, param2)
  626. end,
  627. }
  628. stairs.setup_nodedef_callbacks(subname, stair_def)
  629. minetest.register_node(":stairs:stair_" .. subname, stair_def)
  630. if recipeitem then
  631. assert(type(recipeitem) == "string")
  632. circular_saw.known_nodes[recipeitem] = {"stairs", subname}
  633. -- Use stairs to craft full blocks again (1:1)
  634. minetest.register_craft({
  635. output = recipeitem .. ' 3',
  636. recipe = {
  637. {'stairs:stair_' .. subname, 'stairs:stair_' .. subname},
  638. {'stairs:stair_' .. subname, 'stairs:stair_' .. subname},
  639. },
  640. })
  641. -- Recipe matches appearence in inventory
  642. minetest.register_craft({
  643. output = 'stairs:stair_' .. subname .. ' 8',
  644. recipe = {
  645. {"", "", recipeitem},
  646. {"", recipeitem, recipeitem},
  647. {recipeitem, recipeitem, recipeitem},
  648. },
  649. })
  650. end
  651. end
  652. -- Slab facedir to placement 6d matching table
  653. local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4}
  654. -- Slab facedir when placing initial slab against other surface
  655. local slab_trans_dir_place = {[0] = 0, 20, 12, 16, 4, 8}
  656. -- Register slabs.
  657. -- Node will be called stairs:slab_<subname>
  658. function stairs.register_slab(subname, recipeitem, groups, images, description, sounds)
  659. -- Do not modify function argument.
  660. groups = table.copy(groups)
  661. groups.slab = 1
  662. groups.stairs_slab = 1
  663. groups.not_in_craft_guide = 1
  664. groups.stairs_node = 1
  665. local ndef = minetest.registered_items[recipeitem]
  666. assert(ndef)
  667. local slab_def = {
  668. description = description,
  669. drawtype = "nodebox",
  670. tiles = images,
  671. paramtype = "light",
  672. paramtype2 = "facedir",
  673. is_ground_content = false,
  674. groups = groups,
  675. sounds = sounds,
  676. movement_speed_depends = recipeitem,
  677. light_source = math.ceil(ndef.light_source*0.5),
  678. node_box = {
  679. type = "fixed",
  680. fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
  681. },
  682. on_place = function(itemstack, placer, pointed_thing)
  683. local under = minetest.get_node(pointed_thing.under)
  684. local wield_item = itemstack:get_name()
  685. if under and wield_item == under.name then
  686. -- place slab using under node orientation
  687. local dir = minetest.dir_to_facedir(vector.subtract(
  688. pointed_thing.above, pointed_thing.under), true)
  689. local p2 = under.param2
  690. -- combine two slabs if possible
  691. if slab_trans_dir[math.floor(p2 / 4)] == dir then
  692. if not recipeitem then
  693. return itemstack
  694. end
  695. local player_name = placer:get_player_name()
  696. if minetest.is_protected(pointed_thing.under, player_name) and not
  697. minetest.check_player_privs(placer, "protection_bypass") then
  698. minetest.record_protection_violation(pointed_thing.under,
  699. player_name)
  700. return
  701. end
  702. minetest.add_node(pointed_thing.under, {name = recipeitem, param2 = p2})
  703. if not minetest.setting_getbool("creative_mode") then
  704. itemstack:take_item()
  705. end
  706. return itemstack
  707. end
  708. -- Placing a slab on an upside down slab should make it right-side up.
  709. if p2 >= 20 and dir == 8 then
  710. p2 = p2 - 20
  711. -- same for the opposite case: slab below normal slab
  712. elseif p2 <= 3 and dir == 4 then
  713. p2 = p2 + 20
  714. end
  715. -- else attempt to place node with proper param2
  716. minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2)
  717. if not minetest.setting_getbool("creative_mode") then
  718. itemstack:take_item()
  719. end
  720. return itemstack
  721. else
  722. -- place slab using look direction of player
  723. local dir = minetest.dir_to_wallmounted(vector.subtract(
  724. pointed_thing.above, pointed_thing.under), true)
  725. local rot = slab_trans_dir_place[dir]
  726. if rot == 0 or rot == 20 then
  727. rot = rot + minetest.dir_to_facedir(placer:get_look_dir())
  728. end
  729. return minetest.item_place(itemstack, placer, pointed_thing, rot)
  730. end
  731. end,
  732. }
  733. stairs.setup_nodedef_callbacks(subname, slab_def)
  734. minetest.register_node(":stairs:slab_" .. subname, slab_def)
  735. if recipeitem then
  736. -- Use 2 slabs to craft a full block again (1:1)
  737. minetest.register_craft({
  738. output = recipeitem,
  739. recipe = {
  740. {'stairs:slab_' .. subname},
  741. {'stairs:slab_' .. subname},
  742. },
  743. })
  744. minetest.register_craft({
  745. output = 'stairs:slab_' .. subname .. ' 6',
  746. recipe = {
  747. {recipeitem, recipeitem, recipeitem},
  748. },
  749. })
  750. end
  751. end
  752. -- Stair/slab registration function.
  753. -- Now includes all extra blocks.
  754. function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc, sounds)
  755. stairs.register_micro(subname, recipeitem, groups, images, desc .. " Microblock", sounds)
  756. stairs.register_panel(subname, recipeitem, groups, images, desc .. " Panel", sounds)
  757. stairs.register_stair(subname, recipeitem, groups, images, desc .. " Stair", sounds)
  758. stairs.register_extra_stairs(subname, recipeitem, groups, images, desc .. " Stair", sounds)
  759. stairs.register_slab(subname, recipeitem, groups, images, desc .. " Slab", sounds)
  760. stairs.register_extra_slabs(subname, recipeitem, groups, images, desc .. " Slab", sounds)
  761. stairs.register_slopes(subname, recipeitem, groups, images, desc .. " Slope", sounds)
  762. end