init.lua 23 KB

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