forked from minetest-mods/nether
Place portal as schematic. Avoid portal griefing
This commit is contained in:
parent
47d39871d2
commit
e230813af8
107
init.lua
107
init.lua
@ -25,56 +25,55 @@ local yblmax = NETHER_DEPTH - BLEND * 2
|
|||||||
-- Functions
|
-- Functions
|
||||||
|
|
||||||
local function build_portal(pos, target)
|
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 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}
|
local p2 = {x = p1.x + 3, y = p1.y + 4, z = p1.z}
|
||||||
|
|
||||||
for i = 1, 4 do
|
local path = minetest.get_modpath("nether") .. "/schematics/nether_portal.mts"
|
||||||
minetest.set_node(p, {name = "default:obsidian"})
|
minetest.place_schematic({x = p1.x, y = p1.y, z = p1.z - 2}, path, 0, nil, true)
|
||||||
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
|
|
||||||
|
|
||||||
for x = p1.x, p2.x do
|
|
||||||
for y = p1.y, p2.y do
|
for y = p1.y, p2.y do
|
||||||
p = {x = x, y = y, z = p1.z}
|
for x = p1.x, p2.x do
|
||||||
if not (x == p1.x or x == p2.x or y == p1.y or y == p2.y) then
|
local meta = minetest.get_meta({x = x, y = y, z = p1.z})
|
||||||
minetest.set_node(p, {name = "nether:portal", param2 = 0})
|
|
||||||
end
|
|
||||||
local meta = minetest.get_meta(p)
|
|
||||||
meta:set_string("p1", minetest.pos_to_string(p1))
|
meta:set_string("p1", minetest.pos_to_string(p1))
|
||||||
meta:set_string("p2", minetest.pos_to_string(p2))
|
meta:set_string("p2", minetest.pos_to_string(p2))
|
||||||
meta:set_string("target", minetest.pos_to_string(target))
|
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
|
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 nobj_cave_point = minetest.get_perlin(np_cave)
|
||||||
local air = 0 -- Consecutive air nodes found
|
local air = 0 -- Consecutive air nodes found
|
||||||
|
|
||||||
@ -85,16 +84,38 @@ local function find_nether_target_y(target_x, target_z)
|
|||||||
air = air + 1
|
air = air + 1
|
||||||
else -- Not cavern, check if 4 nodes of space above
|
else -- Not cavern, check if 4 nodes of space above
|
||||||
if air >= 4 then
|
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
|
else -- Not enough space, reset air to zero
|
||||||
air = 0
|
air = 0
|
||||||
end
|
end
|
||||||
end
|
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
|
return y -- Fallback
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function move_check(p1, max, dir)
|
local function move_check(p1, max, dir)
|
||||||
local p = {x = p1.x, y = p1.y, z = p1.z}
|
local p = {x = p1.x, y = p1.y, z = p1.z}
|
||||||
local d = math.abs(max - p1[dir]) / (max - p1[dir])
|
local d = math.abs(max - p1[dir]) / (max - p1[dir])
|
||||||
@ -109,6 +130,7 @@ local function move_check(p1, max, dir)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function check_portal(p1, p2)
|
local function check_portal(p1, p2)
|
||||||
if p1.x ~= p2.x then
|
if p1.x ~= p2.x then
|
||||||
if not move_check(p1, p2.x, "x") then
|
if not move_check(p1, p2.x, "x") then
|
||||||
@ -138,6 +160,7 @@ local function check_portal(p1, p2)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function is_portal(pos)
|
local function is_portal(pos)
|
||||||
for d = -3, 3 do
|
for d = -3, 3 do
|
||||||
for y = -4, 4 do
|
for y = -4, 4 do
|
||||||
@ -154,6 +177,7 @@ local function is_portal(pos)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function make_portal(pos)
|
local function make_portal(pos)
|
||||||
local p1, p2 = is_portal(pos)
|
local p1, p2 = is_portal(pos)
|
||||||
if not p1 or not p2 then
|
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}
|
local target = {x = p1.x, y = p1.y, z = p1.z}
|
||||||
target.x = target.x + 1
|
target.x = target.x + 1
|
||||||
if target.y < NETHER_DEPTH then
|
if target.y < NETHER_DEPTH then
|
||||||
target.y = math.random(-32, 1)
|
target.y = find_surface_target_y(target.x, target.z, -16)
|
||||||
else
|
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
|
end
|
||||||
|
|
||||||
for d = 0, 3 do
|
for d = 0, 3 do
|
||||||
|
BIN
schematics/nether_portal.mts
Normal file
BIN
schematics/nether_portal.mts
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user