Code: Select all
local load_time_start = os.clock()
-- the function to get the hull
local function get_tab(pos, func, max)
local tab = {pos}
local tab_avoid = {[pos.x.." "..pos.y.." "..pos.z] = true}
local tab_done,num = {pos},2
while tab[1] do
for n,p in pairs(tab) do
--[[
for i = -1,1,2 do
for _,p2 in pairs({
{x=p.x+i, y=p.y, z=p.z},
{x=p.x, y=p.y+i, z=p.z},
{x=p.x, y=p.y, z=p.z+i},
}) do]]
for i = -1,1 do
for j = -1,1 do
for k = -1,1 do
local p2 = {x=p.x+i, y=p.y+j, z=p.z+k}
local pstr = p2.x.." "..p2.y.." "..p2.z
if not tab_avoid[pstr]
and func(p2) then
tab_avoid[pstr] = true
tab_done[num] = p2
num = num+1
table.insert(tab, p2)
if max
and num > max then
return false
end
end
end
end
end
tab[n] = nil
end
end
return tab_done
end
-- everything not air belongs to the hull
local function is_solid(pos)
return minetest.get_node(pos).name ~= "air"
end
-- gets the ship with e.g. floating stuff inside
local function get_ship(pos)
local hull = get_tab(pos, is_solid, 3000)
if not hull then
return
end
local min = vector.new(pos)
local max = vector.new(pos)
local ps = {}
for _,pos in pairs(hull) do
local pstr = pos.x.." "..pos.z
local mm = ps[pstr]
if not mm then
ps[pstr] = {pos.y, pos.y}
else
ps[pstr][1] = math.min(mm[1], pos.y)
ps[pstr][2] = math.max(mm[2], pos.y)
end
for _,i in pairs({"x", "y", "z"}) do
min[i] = math.min(min[i], pos[i])
max[i] = math.max(max[i], pos[i])
end
end
return ps, min, max
end
local log = minetest.chat_send_all --minetest.log
-- moves it
local c_air = minetest.get_content_id("air")
local function move_ship(dif, ps, min, max)
local manip = minetest.get_voxel_manip()
local emerged_pos1, emerged_pos2 = manip:read_from_map(min, max)
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
local nodes = manip:get_data()
local param2s = manip:get_param2_data()
local nmin = vector.add(min, dif)
local nmax = vector.add(max, dif)
local manip2 = minetest.get_voxel_manip()
local emerged_pos1, emerged_pos2 = manip2:read_from_map(nmin, nmax)
local area2 = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
local nodes2 = manip2:get_data()
local param2s2 = manip:get_param2_data()
for xz,y in pairs(ps) do
local x,z = unpack(string.split(xz, " "))
for y = y[1], y[2] do
local index = area:index(x,y,z)
local index2 = area2:index(x+dif.x,y+dif.y,z+dif.z)
if nodes2[index2] ~= c_air then
log("[as_transport] error: "..minetest.get_name_from_content_id(nodes2[index2]).." was blocking.")
return
end
nodes2[index2] = nodes[index]
param2s2[index2] = param2s[index]
nodes[index] = c_air
end
end
manip:set_data(nodes)
manip:write_to_map()
manip:update_map()
manip2:set_data(nodes2)
manip:set_param2_data(param2s2)
manip2:write_to_map()
manip2:update_map()
return true
end
-- moves a ship
local function transport_ship(pos, dif)
local ps, min, max = get_ship(pos)
if not ps then
log("[as_transport] error: hull couldn't become detected, maybe the as is too big or connected to sth")
return
end
local worked = move_ship(dif, ps, min, max)
if not worked then
log("[as_transport] error: as couldn't become teleported, maybe you tried to move it into not air nodes")
return
end
log("[as_transport] as succesfully teleported")
return true
end
minetest.register_node("as_transport:teleport", {
description = "asirs telwer",
tiles = {"as_transport.png"},
groups = {snappy=2},
on_place = function(_, puncher, pos)
local t1 = os.clock()
if not pos
or not puncher then
return
end
local pos = pos.under
transport_ship(pos, {x=0, y=20, z=0})
log(string.format("[as_transport] ended after ca. %.2fs", os.clock() - t1))
end
})
minetest.log("info", string.format("[as_transport] loaded after ca. %.2fs", os.clock() - load_time_start))