114 lines
2.3 KiB
Lua
114 lines
2.3 KiB
Lua
|
--[[
|
||
|
|
||
|
Due to engine limitations with non-trivial technical hurdles, minetest
|
||
|
collision boxes can only occupy a 3x3x3 node space at most. To work
|
||
|
around this limitation, magic invisible undiggable nodes are added to
|
||
|
fill in the shape of a mesh. The nodes are tracked in meta and removed
|
||
|
on destruction.
|
||
|
|
||
|
]]
|
||
|
|
||
|
|
||
|
|
||
|
bitumen.magic = {}
|
||
|
|
||
|
|
||
|
|
||
|
local function add(a, b)
|
||
|
return {
|
||
|
x = a.x + b[1],
|
||
|
y = a.y + b[2], -- wtf?
|
||
|
z = a.z + b[3]
|
||
|
}
|
||
|
end
|
||
|
|
||
|
bitumen.magic.set_nodes = function(pos, nodename, def)
|
||
|
local set = {}
|
||
|
|
||
|
for _,delta in ipairs(def) do
|
||
|
|
||
|
local p = add(pos, delta)
|
||
|
local n = minetest.get_node(p)
|
||
|
if true or n.name == "air" then
|
||
|
print("magic node at ".. minetest.pos_to_string(p))
|
||
|
minetest.set_node(p, {name= nodename})
|
||
|
-- minetest.set_node(p, {name= "default:glass"})
|
||
|
|
||
|
-- save the parent node
|
||
|
local meta = minetest.get_meta(p)
|
||
|
meta:set_string("magic_parent", minetest.serialize(pos))
|
||
|
|
||
|
table.insert(set, p)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- save positions for all the magic nodes
|
||
|
local meta = minetest.get_meta(pos)
|
||
|
local oldset = meta:get_string("magic_children") or ""
|
||
|
if oldset == "" then
|
||
|
oldset = {}
|
||
|
else
|
||
|
oldset = minetest.deserialize(oldset)
|
||
|
end
|
||
|
|
||
|
for _,p in ipairs(set) do
|
||
|
table.insert(oldset, p)
|
||
|
end
|
||
|
|
||
|
meta:set_string("magic_children", minetest.serialize(oldset))
|
||
|
end
|
||
|
|
||
|
bitumen.magic.set_collision_nodes = function(pos, def)
|
||
|
bitumen.magic.set_nodes(pos, "bitumen:collision_node", def)
|
||
|
end
|
||
|
|
||
|
bitumen.magic.gensphere = function(center, radius)
|
||
|
local out = {}
|
||
|
|
||
|
for x = -radius, radius do
|
||
|
for y = -radius, radius do
|
||
|
for z = -radius, radius do
|
||
|
if math.sqrt(x * x + y * y + z * z) <= radius then
|
||
|
|
||
|
table.insert(out, {center[1]+x, center[2]+y, center[3]+z})
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return out
|
||
|
end
|
||
|
|
||
|
bitumen.magic.gencube = function(low, high)
|
||
|
local out = {}
|
||
|
|
||
|
for x = low[1], high[1] do
|
||
|
for y = low[2], high[2] do
|
||
|
for z = low[3], high[3] do
|
||
|
table.insert(out, {x, y, z})
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return out
|
||
|
end
|
||
|
|
||
|
|
||
|
bitumen.magic.on_destruct = function(pos)
|
||
|
local meta = minetest.get_meta(pos)
|
||
|
local magic = meta:get_string("magic_children")
|
||
|
if magic == nil then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
magic = minetest.deserialize(magic)
|
||
|
if magic == nil then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
-- clean up all the magic
|
||
|
for _,p in ipairs(magic) do
|
||
|
minetest.set_node(p, {name = "air"})
|
||
|
end
|
||
|
end
|