Place portal as schematic. Avoid portal griefing

This commit is contained in:
paramat 2016-05-31 19:13:56 +01:00 committed by Auke Kok
parent 47d39871d2
commit e230813af8
2 changed files with 66 additions and 41 deletions

107
init.lua
View File

@ -25,56 +25,55 @@ local yblmax = NETHER_DEPTH - BLEND * 2
-- Functions
local function build_portal(pos, target)
local p = {x = pos.x - 1, y = pos.y - 1, z = pos.z}
local p1 = {x = pos.x - 1, y = pos.y - 1, z = pos.z}
local p2 = {x = p1.x + 3, y = p1.y + 4, z = p1.z}
for i = 1, 4 do
minetest.set_node(p, {name = "default:obsidian"})
p.y = p.y + 1
end
for i = 1, 3 do
minetest.set_node(p, {name = "default:obsidian"})
p.x = p.x + 1
end
for i = 1, 4 do
minetest.set_node(p, {name = "default:obsidian"})
p.y = p.y - 1
end
for i = 1, 3 do
minetest.set_node(p, {name = "default:obsidian"})
p.x = p.x - 1
end
local path = minetest.get_modpath("nether") .. "/schematics/nether_portal.mts"
minetest.place_schematic({x = p1.x, y = p1.y, z = p1.z - 2}, path, 0, nil, true)
for x = p1.x, p2.x do
for y = p1.y, p2.y do
p = {x = x, y = y, z = p1.z}
if not (x == p1.x or x == p2.x or y == p1.y or y == p2.y) then
minetest.set_node(p, {name = "nether:portal", param2 = 0})
end
local meta = minetest.get_meta(p)
for x = p1.x, p2.x do
local meta = minetest.get_meta({x = x, y = y, z = p1.z})
meta:set_string("p1", minetest.pos_to_string(p1))
meta:set_string("p2", minetest.pos_to_string(p2))
meta:set_string("target", minetest.pos_to_string(target))
if y ~= p1.y then
for z = -2, 2 do
if z ~= 0 then
p.z = p.z + z
if minetest.registered_nodes[
minetest.get_node(p).name].is_ground_content then
minetest.remove_node(p)
end
p.z = p.z - z
end
end
end
end
end
end
local function find_nether_target_y(target_x, target_z)
local start_y = NETHER_DEPTH - math.random(500, 1500) -- Search start
local function volume_is_natural(minp, maxp)
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local vm = minetest.get_voxel_manip()
local pos1 = {x = minp.x, y = minp.y, z = minp.z}
local pos2 = {x = maxp.x, y = maxp.y, z = maxp.z}
local emin, emax = vm:read_from_map(pos1, pos2)
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
for z = pos1.z, pos2.z do
for y = pos1.y, pos2.y do
local vi = area:index(pos1.x, y, z)
for x = pos1.x, pos2.x do
local id = data[vi] -- Existing node
if id ~= c_air and id ~= c_ignore then -- These are natural
local name = minetest.get_name_from_content_id(id)
if not minetest.registered_nodes[name].is_ground_content then
return false
end
end
vi = vi + 1
end
end
end
return true
end
local function find_nether_target_y(target_x, target_z, start_y)
local nobj_cave_point = minetest.get_perlin(np_cave)
local air = 0 -- Consecutive air nodes found
@ -85,16 +84,38 @@ local function find_nether_target_y(target_x, target_z)
air = air + 1
else -- Not cavern, check if 4 nodes of space above
if air >= 4 then
return y + 2
-- Check volume for non-natural nodes
local minp = {x = target_x - 1, y = y - 1, z = target_z - 2}
local maxp = {x = target_x + 2, y = y + 3, z = target_z + 2}
if volume_is_natural(minp, maxp) then
return y + 2
else -- Restart search a little lower
find_nether_target_y(target_x, target_z, y - 16)
end
else -- Not enough space, reset air to zero
air = 0
end
end
end
return start_y -- Fallback
end
local function find_surface_target_y(target_x, target_z, start_y)
for y = start_y, start_y - 256, -16 do
-- Check volume for non-natural nodes
local minp = {x = target_x - 1, y = y - 1, z = target_z - 2}
local maxp = {x = target_x + 2, y = y + 3, z = target_z + 2}
if volume_is_natural(minp, maxp) then
return y
end
end
return y -- Fallback
end
local function move_check(p1, max, dir)
local p = {x = p1.x, y = p1.y, z = p1.z}
local d = math.abs(max - p1[dir]) / (max - p1[dir])
@ -109,6 +130,7 @@ local function move_check(p1, max, dir)
return true
end
local function check_portal(p1, p2)
if p1.x ~= p2.x then
if not move_check(p1, p2.x, "x") then
@ -138,6 +160,7 @@ local function check_portal(p1, p2)
return true
end
local function is_portal(pos)
for d = -3, 3 do
for y = -4, 4 do
@ -154,6 +177,7 @@ local function is_portal(pos)
end
end
local function make_portal(pos)
local p1, p2 = is_portal(pos)
if not p1 or not p2 then
@ -184,9 +208,10 @@ local function make_portal(pos)
local target = {x = p1.x, y = p1.y, z = p1.z}
target.x = target.x + 1
if target.y < NETHER_DEPTH then
target.y = math.random(-32, 1)
target.y = find_surface_target_y(target.x, target.z, -16)
else
target.y = find_nether_target_y(target.x, target.z)
local start_y = NETHER_DEPTH - math.random(500, 1500) -- Search start
target.y = find_nether_target_y(target.x, target.z, start_y)
end
for d = 0, 3 do

Binary file not shown.