magic_nodes.lua 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. --[[
  2. Due to engine limitations with non-trivial technical hurdles, minetest
  3. collision boxes can only occupy a 3x3x3 node space at most. To work
  4. around this limitation, magic invisible undiggable nodes are added to
  5. fill in the shape of a mesh. The nodes are tracked in meta and removed
  6. on destruction.
  7. ]]
  8. bitumen.magic = {}
  9. -- used to create a large collision box because minetest doesn't allow ones bigger than 3x3x3
  10. minetest.register_node("bitumen:collision_node", {
  11. paramtype = "light",
  12. drawtype = "airlike",
  13. -- drawtype = "node",
  14. -- tiles = {"default_leaves.png"},
  15. walkable = true,
  16. sunlight_propagates = true,
  17. -- groups = {choppy = 1},
  18. })
  19. local function add(a, b)
  20. return {
  21. x = a.x + b[1],
  22. y = a.y + b[2], -- wtf?
  23. z = a.z + b[3]
  24. }
  25. end
  26. bitumen.magic.set_nodes = function(pos, nodename, def)
  27. local set = {}
  28. for _,delta in ipairs(def) do
  29. local p = add(pos, delta)
  30. local n = minetest.get_node(p)
  31. local g = minetest.registered_nodes[n.name].groups
  32. if g and not g.bitumen_magic_proof then
  33. -- print("magic node at ".. minetest.pos_to_string(p))
  34. minetest.set_node(p, {name= nodename})
  35. -- minetest.set_node(p, {name= "default:glass"})
  36. -- save the parent node
  37. local meta = minetest.get_meta(p)
  38. meta:set_string("magic_parent", minetest.serialize(pos))
  39. table.insert(set, p)
  40. end
  41. end
  42. -- save positions for all the magic nodes
  43. local meta = minetest.get_meta(pos)
  44. local oldset = meta:get_string("magic_children") or ""
  45. if oldset == "" then
  46. oldset = {}
  47. else
  48. oldset = minetest.deserialize(oldset)
  49. end
  50. for _,p in ipairs(set) do
  51. table.insert(oldset, p)
  52. end
  53. meta:set_string("magic_children", minetest.serialize(oldset))
  54. end
  55. bitumen.magic.set_collision_nodes = function(pos, def)
  56. bitumen.magic.set_nodes(pos, "bitumen:collision_node", def)
  57. end
  58. bitumen.magic.gensphere = function(center, radius)
  59. local out = {}
  60. for x = -radius, radius do
  61. for y = -radius, radius do
  62. for z = -radius, radius do
  63. if math.sqrt(x * x + y * y + z * z) <= radius then
  64. table.insert(out, {center[1]+x, center[2]+y, center[3]+z})
  65. end
  66. end
  67. end
  68. end
  69. return out
  70. end
  71. -- center is the base
  72. bitumen.magic.gencylinder = function(center, radius, height)
  73. local out = {}
  74. for x = -radius, radius do
  75. for z = -radius, radius do
  76. if math.sqrt(x * x + z * z) <= radius then
  77. for y = 0, height do
  78. table.insert(out, {center[1]+x, center[2]+y, center[3]+z})
  79. end
  80. end
  81. end
  82. end
  83. return out
  84. end
  85. bitumen.magic.gencube = function(low, high)
  86. local out = {}
  87. for x = low[1], high[1] do
  88. for y = low[2], high[2] do
  89. for z = low[3], high[3] do
  90. table.insert(out, {x, y, z})
  91. end
  92. end
  93. end
  94. return out
  95. end
  96. bitumen.magic.on_destruct = function(pos)
  97. local meta = minetest.get_meta(pos)
  98. local magic = meta:get_string("magic_children")
  99. if magic == nil then
  100. return
  101. end
  102. magic = minetest.deserialize(magic)
  103. if magic == nil then
  104. return
  105. end
  106. -- clean up all the magic
  107. for _,p in ipairs(magic) do
  108. minetest.set_node(p, {name = "air"})
  109. end
  110. end