mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-12-22 16:09:33 +01:00
More MC-like end portal block (WIP)
This commit is contained in:
parent
526217a21b
commit
7c15d5f9ac
3 changed files with 115 additions and 171 deletions
|
@ -72,6 +72,8 @@ end
|
|||
mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border
|
||||
mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit
|
||||
mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000
|
||||
mcl_vars.mg_end_platform_pos = { x = 100, y = mcl_vars.mg_end_min + 80, z = 0 }
|
||||
|
||||
-- Realm barrier used to safely separate the End from the void below the Overworld
|
||||
mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max
|
||||
mcl_vars.mg_realm_barrier_overworld_end_min = mcl_vars.mg_end_max - 11
|
||||
|
|
|
@ -18,13 +18,6 @@ local np_cave = {
|
|||
octaves = 5,
|
||||
persist = 0.7
|
||||
}
|
||||
-- Portal frame material
|
||||
local fake_portal_frame = "mcl_nether:quartz_block"
|
||||
|
||||
-- Table of objects (including players) which recently teleported by a
|
||||
-- End portal. Those objects have a brief cooloff period before they
|
||||
-- can teleport again. This prevents annoying back-and-forth teleportation.
|
||||
local portal_cooloff = {}
|
||||
|
||||
-- Destroy portal if pos (portal frame or portal node) got destroyed
|
||||
local destroy_portal = function(pos)
|
||||
|
@ -56,7 +49,7 @@ local destroy_portal = function(pos)
|
|||
end
|
||||
end
|
||||
local nn = minetest.get_node(p).name
|
||||
if nn == fake_portal_frame or nn == "mcl_portals:portal_end" then
|
||||
if nn == "mcl_portals:portal_end" then
|
||||
-- Remove portal nodes, but not myself
|
||||
if nn == "mcl_portals:portal_end" and not vector.equals(p, pos) then
|
||||
minetest.remove_node(p)
|
||||
|
@ -72,26 +65,13 @@ local destroy_portal = function(pos)
|
|||
end
|
||||
end
|
||||
|
||||
-- Fake end portal
|
||||
-- End portal
|
||||
-- TODO: Create real end portal
|
||||
minetest.register_node("mcl_portals:portal_end", {
|
||||
description = "End Portal",
|
||||
_doc_items_longdesc = "An End portal teleports creatures and objects to the mysterious End dimension (and back!).",
|
||||
_doc_items_usagehelp = "Stand in the portal for a moment to activate the teleportation. Entering such a portal for the first time will create a new portal in your destination. End portal which were built in the End will lead back to the Overworld. An End portal is destroyed if any of its surrounding frame blocks is destroyed.",
|
||||
tiles = {
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
{
|
||||
name = "mcl_portals_end_portal.png",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 16,
|
||||
aspect_h = 16,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "mcl_portals_end_portal.png",
|
||||
animation = {
|
||||
|
@ -101,10 +81,14 @@ minetest.register_node("mcl_portals:portal_end", {
|
|||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
"blank.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
use_texture_alpha = true,
|
||||
walkable = false,
|
||||
|
@ -120,7 +104,7 @@ minetest.register_node("mcl_portals:portal_end", {
|
|||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.1, 0.5, 0.5, 0.1},
|
||||
{-0.5, -0.5, -0.5, 0.5, 4/16, 0.5},
|
||||
},
|
||||
},
|
||||
groups = {not_in_creative_inventory = 1},
|
||||
|
@ -130,84 +114,25 @@ minetest.register_node("mcl_portals:portal_end", {
|
|||
_mcl_blast_resistance = 18000000,
|
||||
})
|
||||
|
||||
local function build_end_portal(pos, target3)
|
||||
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 = fake_portal_frame})
|
||||
p.y = p.y + 1
|
||||
end
|
||||
for i = 1, 3 do
|
||||
minetest.set_node(p, {name = fake_portal_frame})
|
||||
p.x = p.x + 1
|
||||
end
|
||||
for i = 1, 4 do
|
||||
minetest.set_node(p, {name = fake_portal_frame})
|
||||
p.y = p.y - 1
|
||||
end
|
||||
for i = 1, 3 do
|
||||
minetest.set_node(p, {name = fake_portal_frame})
|
||||
p.x = p.x - 1
|
||||
end
|
||||
local function build_end_portal_destination(pos)
|
||||
local p1 = {x = pos.x - 2, y = pos.y, z = pos.z-2}
|
||||
local p2 = {x = pos.x + 2, y = pos.y+2, z = pos.z+2}
|
||||
|
||||
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 = "mcl_portals:portal_end", param2 = 0})
|
||||
end
|
||||
local meta = minetest.get_meta(p)
|
||||
meta:set_string("portal_frame1", minetest.pos_to_string(p1))
|
||||
meta:set_string("portal_frame2", minetest.pos_to_string(p2))
|
||||
meta:set_string("portal_target", minetest.pos_to_string(target3))
|
||||
|
||||
for z = -2, 2 do
|
||||
if z ~= 0 then
|
||||
local newp = {x=p.x, y=p.y, z=p.z+z}
|
||||
if y ~= p1.y then
|
||||
if minetest.registered_nodes[
|
||||
minetest.get_node(newp).name].is_ground_content then
|
||||
minetest.remove_node(newp)
|
||||
end
|
||||
else
|
||||
-- Build obsidian platform if floating
|
||||
local newp_below = table.copy(newp)
|
||||
newp_below.y = newp.y - 1
|
||||
if minetest.get_node(newp).name == "air" and minetest.get_node(newp_below).name == "air" then
|
||||
minetest.set_node(newp, {name="mcl_core:obsidian"})
|
||||
end
|
||||
|
||||
end
|
||||
for z = p1.z, p2.z do
|
||||
local newp = {x=x,y=y,z=z}
|
||||
-- Build obsidian platform
|
||||
if minetest.registered_nodes[minetest.get_node(newp).name].is_ground_content then
|
||||
if y == p1.y then
|
||||
minetest.set_node(newp, {name="mcl_core:obsidian"})
|
||||
else
|
||||
minetest.remove_node(newp)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function find_end_target3_y2(target3_x, target3_z)
|
||||
local start_y = math.random(SPAWN_MIN, SPAWN_MAX) -- Search start
|
||||
if not nobj_cave then
|
||||
nobj_cave = minetest.get_perlin(np_cave)
|
||||
end
|
||||
local air = 0 -- Consecutive air nodes found
|
||||
|
||||
for y = start_y, SPAWN_MIN, -1 do
|
||||
local nval_cave = nobj_cave:get3d({x = target3_x, y = y, z = target3_z})
|
||||
|
||||
if nval_cave > TCAVE then -- Cavern
|
||||
air = air + 1
|
||||
else -- Not cavern, check if 4 nodes of space above
|
||||
if air >= 4 then
|
||||
return y + 2
|
||||
else -- Not enough space, reset air to zero
|
||||
air = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return start_y -- Fallback
|
||||
end
|
||||
|
||||
local function move_check2(p1, max, dir)
|
||||
|
@ -304,18 +229,6 @@ local function make_end_portal(pos)
|
|||
param2 = 1
|
||||
end
|
||||
|
||||
local target3 = {x = p1.x, y = p1.y, z = p1.z}
|
||||
target3.x = target3.x + 1
|
||||
if target3.y < mcl_vars.mg_end_max and target3.y > mcl_vars.mg_end_min then
|
||||
if mg_name == "flat" then
|
||||
target3.y = mcl_vars.mg_bedrock_overworld_max + 5
|
||||
else
|
||||
target3.y = math.random(mcl_vars.mg_overworld_min + 40, mcl_vars.mg_overworld_min + 96)
|
||||
end
|
||||
else
|
||||
target3.y = find_end_target3_y2(target3.x, target3.z)
|
||||
end
|
||||
|
||||
for d = 0, 3 do
|
||||
for y = p1.y, p2.y do
|
||||
local p = {}
|
||||
|
@ -345,67 +258,86 @@ minetest.register_abm({
|
|||
label = "End portal teleportation",
|
||||
nodenames = {"mcl_portals:portal_end"},
|
||||
interval = 1,
|
||||
chance = 2,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
for _,obj in ipairs(minetest.get_objects_inside_radius(pos,1)) do --maikerumine added for objects to travel
|
||||
local lua_entity = obj:get_luaentity() --maikerumine added for objects to travel
|
||||
-- Destroy legacy end portals created with quartz block frame
|
||||
-- by turning them into cobwebs.
|
||||
-- We can tell if a end portal is legacy if it has portal_target as metadata.
|
||||
-- FIXME: Remove this after some time.
|
||||
local meta = minetest.get_meta(pos)
|
||||
local legacy_portal_target = minetest.string_to_pos(meta:get_string("portal_target"))
|
||||
if legacy_portal_target and legacy_portal_target ~= "" then
|
||||
minetest.set_node(pos, {name="mcl_core:cobweb"})
|
||||
return
|
||||
end
|
||||
|
||||
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
local lua_entity = obj:get_luaentity() --maikerumine added for objects to travel
|
||||
if obj:is_player() or lua_entity then
|
||||
-- No rapid back-and-forth teleportatio
|
||||
if portal_cooloff[obj] then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local target3 = minetest.string_to_pos(meta:get_string("portal_target"))
|
||||
if target3 then
|
||||
-- force emerge of target3 area
|
||||
minetest.get_voxel_manip():read_from_map(target3, target3)
|
||||
if not minetest.get_node_or_nil(target3) then
|
||||
minetest.emerge_area(
|
||||
vector.subtract(target3, 4), vector.add(target3, 4))
|
||||
local _, dim = mcl_util.y_to_layer(pos.y)
|
||||
|
||||
local target
|
||||
if dim == "end" then
|
||||
-- End portal in the End:
|
||||
-- Teleport back to the player's spawn in the Overworld.
|
||||
-- TODO: Implement better spawn point detection
|
||||
|
||||
target = minetest.string_to_pos(obj:get_attribute("mcl_beds:spawn"))
|
||||
if not target then
|
||||
target = minetest.setting_get_pos("static_spawnpoint")
|
||||
end
|
||||
if not target then
|
||||
target = { x=0, y=0, z=0 }
|
||||
end
|
||||
else
|
||||
-- End portal in any other dimension:
|
||||
-- Teleport to the End at a fixed position and generate a
|
||||
-- 5×5 obsidian platform below.
|
||||
|
||||
local platform_pos = mcl_vars.mg_end_platform_pos
|
||||
|
||||
-- force emerge of target1 area
|
||||
minetest.get_voxel_manip():read_from_map(platform_pos, platform_pos)
|
||||
if not minetest.get_node_or_nil(platform_pos) then
|
||||
minetest.emerge_area(vector.subtract(platform_pos, 3), vector.add(platform_pos, 3))
|
||||
end
|
||||
|
||||
-- teleport the object
|
||||
minetest.after(3, function(obj, pos, target3)
|
||||
-- No rapid back-and-forth teleportatio
|
||||
if portal_cooloff[obj] then
|
||||
return
|
||||
end
|
||||
local objpos = obj:getpos()
|
||||
if objpos == nil then
|
||||
return
|
||||
end
|
||||
-- If player stands, player is at ca. something+0.5
|
||||
-- which might cause precision problems, so we used ceil.
|
||||
objpos.y = math.ceil(objpos.y)
|
||||
if minetest.get_node(objpos).name ~= "mcl_portals:portal_end" then
|
||||
return
|
||||
end
|
||||
local objpos = obj:getpos()
|
||||
if objpos == nil then
|
||||
return
|
||||
end
|
||||
-- If player stands, player is at ca. something+0.5
|
||||
-- which might cause precision problems, so we used ceil.
|
||||
objpos.y = math.ceil(objpos.y)
|
||||
if minetest.get_node(objpos).name ~= "mcl_portals:portal_end" then
|
||||
return
|
||||
end
|
||||
|
||||
-- Build destination
|
||||
local function check_and_build_end_portal(pos, target3)
|
||||
local n = minetest.get_node_or_nil(target3)
|
||||
if n and n.name ~= "mcl_portals:portal_end" then
|
||||
build_end_portal(target3, pos)
|
||||
minetest.after(2, check_and_build_end_portal, pos, target3)
|
||||
elseif not n then
|
||||
minetest.after(1, check_and_build_end_portal, pos, target3)
|
||||
end
|
||||
end
|
||||
-- Build destination
|
||||
local function check_and_build_end_portal_destination(pos)
|
||||
local n = minetest.get_node_or_nil(pos)
|
||||
if n and n.name ~= "mcl_core:obsidian" then
|
||||
build_end_portal_destination(pos)
|
||||
minetest.after(2, check_and_build_end_portal_destination, pos)
|
||||
elseif not n then
|
||||
minetest.after(1, check_and_build_end_portal_destination, pos)
|
||||
end
|
||||
end
|
||||
|
||||
check_and_build_end_portal(pos, target3)
|
||||
local platform
|
||||
check_and_build_end_portal_destination(platform_pos)
|
||||
|
||||
-- Teleport
|
||||
obj:setpos(target3)
|
||||
minetest.sound_play("mcl_portals_teleport", {pos=target3, gain=0.5, max_hear_distance = 16})
|
||||
|
||||
-- Enable teleportation cooloff to prevent frequent back-and-forth teleportation
|
||||
portal_cooloff[obj] = true
|
||||
minetest.after(3, function(o)
|
||||
portal_cooloff[o] = false
|
||||
end, obj)
|
||||
|
||||
end, obj, pos, target3)
|
||||
target = table.copy(platform_pos)
|
||||
target.y = target.y + 1
|
||||
end
|
||||
|
||||
-- Teleport
|
||||
obj:set_pos(target)
|
||||
-- Look towards the End island
|
||||
if obj:is_player() and dim ~= "end" then
|
||||
obj:set_look_horizontal(math.pi/2)
|
||||
end
|
||||
minetest.sound_play("mcl_portals_teleport", {pos=target, gain=0.5, max_hear_distance = 16})
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
@ -414,20 +346,9 @@ minetest.register_abm({
|
|||
|
||||
--[[ ITEM OVERRIDES ]]
|
||||
|
||||
local portal_open_help = "To open an End portal, place an upright frame of quartz blocks with a length of 4 blocks and a height of 5 blocks, leaving only air in the center. After placing this frame, use an eye of ender on the frame. The eye of ender is destroyed in the process."
|
||||
|
||||
-- Fake frame material
|
||||
minetest.override_item(fake_portal_frame, {
|
||||
_doc_items_longdesc = "A block of quartz can be used to create End portals.",
|
||||
_doc_items_usagehelp = portal_open_help,
|
||||
on_destruct = destroy_portal,
|
||||
})
|
||||
|
||||
|
||||
-- End Portal Frame (TODO)
|
||||
minetest.register_node("mcl_portals:end_portal_frame", {
|
||||
description = "End Portal Frame",
|
||||
_doc_items_longdesc = "This block is currently only used for decoration. You can place an eye of ender into it for fun, but nothing will happen.",
|
||||
groups = { creative_breakable = 1, deco_block = 1 },
|
||||
tiles = { "mcl_portals_endframe_top.png", "mcl_portals_endframe_bottom.png", "mcl_portals_endframe_side.png" },
|
||||
paramtype2 = "facedir",
|
||||
|
@ -477,7 +398,7 @@ end
|
|||
-- Portal opener
|
||||
minetest.override_item("mcl_end:ender_eye", {
|
||||
_doc_items_longdesc = "An eye of ender can be used to open End portals.",
|
||||
_doc_items_usagehelp = portal_open_help,
|
||||
-- TODO: _doc_items_usagehelp = ,
|
||||
on_place = function(itemstack, user, pointed_thing)
|
||||
-- Use pointed node's on_rightclick function first, if present
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
|
|
|
@ -45,6 +45,7 @@ local WITCH_HUT_HEIGHT = 3 -- Exact Y level to spawn witch huts at. This height
|
|||
|
||||
-- Content IDs
|
||||
local c_bedrock = minetest.get_content_id("mcl_core:bedrock")
|
||||
local c_obsidian = minetest.get_content_id("mcl_core:obsidian")
|
||||
local c_stone = minetest.get_content_id("mcl_core:stone")
|
||||
local c_dirt = minetest.get_content_id("mcl_core:dirt")
|
||||
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
|
||||
|
@ -1829,6 +1830,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
|||
-- End block fixes:
|
||||
-- * Replace water with end stone or air (depending on height).
|
||||
-- * Remove stone, sand, dirt in v6 so our End map generator works in v6.
|
||||
-- * Generate spawn platform (End portal destination)
|
||||
elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then
|
||||
local nodes
|
||||
if mg_name == "v6" then
|
||||
|
@ -1854,6 +1856,25 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
-- Obsidian spawn platform
|
||||
if minp.y <= mcl_vars.mg_end_platform_pos.y and maxp.y >= mcl_vars.mg_end_platform_pos.y and
|
||||
minp.x <= mcl_vars.mg_end_platform_pos.x and maxp.x >= mcl_vars.mg_end_platform_pos.z and
|
||||
minp.z <= mcl_vars.mg_end_platform_pos.z and maxp.z >= mcl_vars.mg_end_platform_pos.z then
|
||||
for x=math.max(minp.x, mcl_vars.mg_end_platform_pos.x-2), math.min(maxp.x, mcl_vars.mg_end_platform_pos.x+2) do
|
||||
for z=math.max(minp.z, mcl_vars.mg_end_platform_pos.z-2), math.min(maxp.z, mcl_vars.mg_end_platform_pos.z+2) do
|
||||
for y=math.max(minp.y, mcl_vars.mg_end_platform_pos.y), math.min(maxp.y, mcl_vars.mg_end_platform_pos.y+2) do
|
||||
local p_pos = area:index(x, y, z)
|
||||
if y == mcl_vars.mg_end_platform_pos.y then
|
||||
data[p_pos] = c_obsidian
|
||||
else
|
||||
data[p_pos] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
lvm_used = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue