forked from MineClone5/MineClone5
[mcl_portals, mcl_structures] Add End gateways W-I-P by Elias Fleckenstein with minor portals improvements and fixes
This commit is contained in:
parent
430f958fae
commit
069e089ae4
|
@ -24,12 +24,21 @@ local gateway_positions = {
|
||||||
{x = 91, y = -26925, z = -29},
|
{x = 91, y = -26925, z = -29},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local function spawn_gateway_portal(pos, dest_str)
|
||||||
|
local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts"
|
||||||
|
return mcl_structures.place_schematic(vector.add(pos, vector.new(-1, -2, -1)), path, "0", nil, true, nil, dest_str and function(p1, p2, size, orientation, pr, param)
|
||||||
|
-- minetest.get_voxel_manip():read_from_map(pos, pos)
|
||||||
|
minetest.get_meta(vector.add(p1, {x=1,y=2,z=1})):set_string("mcl_portals:gateway_destination", param.dest_str)
|
||||||
|
print(param.dest_str)
|
||||||
|
end, nil, {dest_str=dest_str})
|
||||||
|
end
|
||||||
|
|
||||||
function mcl_portals.spawn_gateway_portal()
|
function mcl_portals.spawn_gateway_portal()
|
||||||
local id = storage:get_int("gateway_last_id") + 1
|
local id = storage:get_int("gateway_last_id") + 1
|
||||||
local pos = gateway_positions[id]
|
local pos = gateway_positions[id]
|
||||||
if not pos then return end
|
if not pos then return end
|
||||||
storage:set_int("gateway_last_id", id)
|
storage:set_int("gateway_last_id", id)
|
||||||
mcl_structures.call_struct(vector.add(pos, vector.new(-1, -2, -1)), "end_gateway_portal")
|
spawn_gateway_portal(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
local gateway_def = table.copy(minetest.registered_nodes["mcl_portals:portal_end"])
|
local gateway_def = table.copy(minetest.registered_nodes["mcl_portals:portal_end"])
|
||||||
|
@ -43,3 +52,70 @@ gateway_def.node_box = nil
|
||||||
gateway_def.walkable = true
|
gateway_def.walkable = true
|
||||||
gateway_def.tiles[3] = nil
|
gateway_def.tiles[3] = nil
|
||||||
minetest.register_node("mcl_portals:portal_gateway", gateway_def)
|
minetest.register_node("mcl_portals:portal_gateway", gateway_def)
|
||||||
|
|
||||||
|
local function find_destination_pos(minp, maxp)
|
||||||
|
for y = maxp.y, minp.y, -1 do
|
||||||
|
for x = maxp.x, minp.x, -1 do
|
||||||
|
for z = maxp.z, minp.z, -1 do
|
||||||
|
local pos = vector.new(x, y, z)
|
||||||
|
local nn = minetest.get_node(pos).name
|
||||||
|
if nn ~= "ignore" and nn ~= "mcl_portals:portal_gateway" and nn ~= "mcl_core:bedrock" then
|
||||||
|
local def = minetest.registered_nodes[nn]
|
||||||
|
if def and def.walkable then
|
||||||
|
return vector.add(pos, vector.new(0, 1.5, 0))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local preparing = {}
|
||||||
|
|
||||||
|
local function teleport(pos, obj)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local dest_portal
|
||||||
|
local dest_str = meta:get_string("mcl_portals:gateway_destination")
|
||||||
|
local pos_str = minetest.pos_to_string(pos)
|
||||||
|
if dest_str == "" then
|
||||||
|
dest_portal = vector.multiply(vector.direction(vector.new(0, pos.y, 0), pos), math.random(768, 1024))
|
||||||
|
dest_portal.y = -26970
|
||||||
|
spawn_gateway_portal(dest_portal, pos_str)
|
||||||
|
meta:set_string("mcl_portals:gateway_destination", minetest.pos_to_string(dest_portal))
|
||||||
|
else
|
||||||
|
dest_portal = minetest.string_to_pos(dest_str)
|
||||||
|
end
|
||||||
|
local minp = vector.subtract(dest_portal, vector.new(5, 40, 5))
|
||||||
|
local maxp = vector.add(dest_portal, vector.new(5, 10, 5))
|
||||||
|
preparing[pos_str] = true
|
||||||
|
minetest.emerge_area(
|
||||||
|
minp,
|
||||||
|
maxp,
|
||||||
|
function(blockpos, action, calls_remaining, param)
|
||||||
|
if calls_remaining < 1 then
|
||||||
|
local minp, maxp, dest_portal, obj, pos_str = param.minp, param.maxp, param.dest_portal, param.obj, param.pos_str
|
||||||
|
if obj and obj:is_player() or obj:get_luaentity() then
|
||||||
|
obj:set_pos(find_destination_pos(minp, maxp) or vector.add(dest_portal, vector.new(0, 3.5, 0)))
|
||||||
|
end
|
||||||
|
preparing[pos_str] = false
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{minp=vector.new(minp), maxp=vector.new(maxp), dest_portal=vector.new(dest_portal), obj=obj, pos_str=pos_str}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
label = "End gateway portal teleportation",
|
||||||
|
nodenames = {"mcl_portals:portal_gateway"},
|
||||||
|
interval = 0.1,
|
||||||
|
chance = 1,
|
||||||
|
action = function(pos)
|
||||||
|
if preparing[minetest.pos_to_string(pos)] then return end
|
||||||
|
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||||
|
if obj:get_hp() > 0 then
|
||||||
|
teleport(pos, obj)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
local S = minetest.get_translator("mcl_portals")
|
local S = minetest.get_translator("mcl_portals")
|
||||||
|
|
||||||
|
local SCAN_2_MAP_CHUNKS = true -- slower but helps to find more suitable places
|
||||||
|
|
||||||
-- Localize functions for better performance
|
-- Localize functions for better performance
|
||||||
local abs = math.abs
|
local abs = math.abs
|
||||||
local ceil = math.ceil
|
local ceil = math.ceil
|
||||||
|
@ -26,7 +28,7 @@ local DISTANCE_MAX = 128
|
||||||
local PORTAL = "mcl_portals:portal"
|
local PORTAL = "mcl_portals:portal"
|
||||||
local OBSIDIAN = "mcl_core:obsidian"
|
local OBSIDIAN = "mcl_core:obsidian"
|
||||||
local O_Y_MIN, O_Y_MAX = max(mcl_vars.mg_overworld_min, -31), min(mcl_vars.mg_overworld_max_official, 2048)
|
local O_Y_MIN, O_Y_MAX = max(mcl_vars.mg_overworld_min, -31), min(mcl_vars.mg_overworld_max_official, 2048)
|
||||||
local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_top_max
|
local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_top_max - H_MIN
|
||||||
local O_DY, N_DY = O_Y_MAX - O_Y_MIN + 1, N_Y_MAX - N_Y_MIN + 1
|
local O_DY, N_DY = O_Y_MAX - O_Y_MIN + 1, N_Y_MAX - N_Y_MIN + 1
|
||||||
|
|
||||||
-- Alpha and particles
|
-- Alpha and particles
|
||||||
|
@ -486,6 +488,14 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param)
|
||||||
create_portal_2(pos0, name, obj)
|
create_portal_2(pos0, name, obj)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if param.next_chunk_1 and param.next_chunk_2 and param.next_pos then
|
||||||
|
local pos1, pos2, pos = param.next_chunk_1, param.next_chunk_2, param.next_pos
|
||||||
|
log("action", "[mcl_portals] Making additional search in chunk below, because current one doesn't contain any air space for portal, target pos "..pos_to_string(pos))
|
||||||
|
minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = pos, pos1 = pos1, pos2 = pos2, name=name, obj=obj})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
log("action", "[mcl_portals] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal")
|
log("action", "[mcl_portals] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal")
|
||||||
if pos.y < lava then
|
if pos.y < lava then
|
||||||
pos.y = lava + 1
|
pos.y = lava + 1
|
||||||
|
@ -507,18 +517,35 @@ local function create_portal(pos, limit1, limit2, name, obj)
|
||||||
|
|
||||||
-- we need to emerge the area here, but currently (mt5.4/mcl20.71) map generation is slow
|
-- we need to emerge the area here, but currently (mt5.4/mcl20.71) map generation is slow
|
||||||
-- so we'll emerge single chunk only: 5x5x5 blocks, 80x80x80 nodes maximum
|
-- so we'll emerge single chunk only: 5x5x5 blocks, 80x80x80 nodes maximum
|
||||||
|
-- and maybe one more chunk from below if (SCAN_2_MAP_CHUNKS = true)
|
||||||
|
|
||||||
local pos1 = add(mul(mcl_vars.pos_to_chunk(pos), mcl_vars.chunk_size_in_nodes), mcl_vars.central_chunk_offset_in_nodes)
|
local pos1 = add(mul(mcl_vars.pos_to_chunk(pos), mcl_vars.chunk_size_in_nodes), mcl_vars.central_chunk_offset_in_nodes)
|
||||||
local pos2 = add(pos1, mcl_vars.chunk_size_in_nodes - 1)
|
local pos2 = add(pos1, mcl_vars.chunk_size_in_nodes - 1)
|
||||||
|
|
||||||
|
if not SCAN_2_MAP_CHUNKS then
|
||||||
|
if limit1 and limit1.x and limit1.y and limit1.z then
|
||||||
|
pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)}
|
||||||
|
end
|
||||||
|
if limit2 and limit2.x and limit2.y and limit2.z then
|
||||||
|
pos2 = {x = min(max(limit2.x, pos.x), pos2.x), y = min(max(limit2.y, pos.y), pos2.y), z = min(max(limit2.z, pos.z), pos2.z)}
|
||||||
|
end
|
||||||
|
minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = vector.new(pos), pos1 = pos1, pos2 = pos2, name=name, obj=obj})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Basically the copy of code above, with minor additions to continue the search in single additional chunk below:
|
||||||
|
local next_chunk_1 = {x = pos1.x, y = pos1.y - mcl_vars.chunk_size_in_nodes, z = pos1.z}
|
||||||
|
local next_chunk_2 = add(next_chunk_1, mcl_vars.chunk_size_in_nodes - 1)
|
||||||
|
local next_pos = {x = pos.x, y=next_chunk_2.y, z = pos.z}
|
||||||
if limit1 and limit1.x and limit1.y and limit1.z then
|
if limit1 and limit1.x and limit1.y and limit1.z then
|
||||||
pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)}
|
pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)}
|
||||||
|
next_chunk_1 = {x = max(min(limit1.x, next_pos.x), next_chunk_1.x), y = max(min(limit1.y, next_pos.y), next_chunk_1.y), z = max(min(limit1.z, next_pos.z), next_chunk_1.z)}
|
||||||
end
|
end
|
||||||
if limit2 and limit2.x and limit2.y and limit2.z then
|
if limit2 and limit2.x and limit2.y and limit2.z then
|
||||||
pos2 = {x = min(max(limit2.x, pos.x), pos2.x), y = min(max(limit2.y, pos.y), pos2.y), z = min(max(limit2.z, pos.z), pos2.z)}
|
pos2 = {x = min(max(limit2.x, pos.x), pos2.x), y = min(max(limit2.y, pos.y), pos2.y), z = min(max(limit2.z, pos.z), pos2.z)}
|
||||||
|
next_chunk_2 = {x = min(max(limit2.x, next_pos.x), next_chunk_2.x), y = min(max(limit2.y, next_pos.y), next_chunk_2.y), z = min(max(limit2.z, next_pos.z), next_chunk_2.z)}
|
||||||
end
|
end
|
||||||
|
minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = vector.new(pos), pos1 = pos1, pos2 = pos2, name=name, obj=obj, next_chunk_1 = next_chunk_1, next_chunk_2 = next_chunk_2, next_pos = next_pos})
|
||||||
minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = vector.new(pos), pos1 = pos1, pos2 = pos2, name=name, obj=obj})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function available_for_nether_portal(p)
|
local function available_for_nether_portal(p)
|
||||||
|
|
|
@ -1484,6 +1484,7 @@ local function register_dimension_biomes()
|
||||||
node_stone = "mcl_nether:netherrack",
|
node_stone = "mcl_nether:netherrack",
|
||||||
node_water = "air",
|
node_water = "air",
|
||||||
node_river_water = "air",
|
node_river_water = "air",
|
||||||
|
node_cave_liquid = "air",
|
||||||
y_min = mcl_vars.mg_nether_min,
|
y_min = mcl_vars.mg_nether_min,
|
||||||
-- FIXME: For some reason the Nether stops generating early if this constant is not added.
|
-- FIXME: For some reason the Nether stops generating early if this constant is not added.
|
||||||
-- Figure out why.
|
-- Figure out why.
|
||||||
|
@ -1501,6 +1502,7 @@ local function register_dimension_biomes()
|
||||||
node_filler = "air",
|
node_filler = "air",
|
||||||
node_water = "air",
|
node_water = "air",
|
||||||
node_river_water = "air",
|
node_river_water = "air",
|
||||||
|
node_cave_liquid = "air",
|
||||||
-- FIXME: For some reason the End stops generating early if this constant is not added.
|
-- FIXME: For some reason the End stops generating early if this constant is not added.
|
||||||
-- Figure out why.
|
-- Figure out why.
|
||||||
y_min = mcl_vars.mg_end_min,
|
y_min = mcl_vars.mg_end_min,
|
||||||
|
|
|
@ -11,10 +11,10 @@ local function ecb_place(blockpos, action, calls_remaining, param)
|
||||||
if calls_remaining >= 1 then return end
|
if calls_remaining >= 1 then return end
|
||||||
minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags)
|
minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags)
|
||||||
if param.after_placement_callback and param.p1 and param.p2 then
|
if param.after_placement_callback and param.p1 and param.p2 then
|
||||||
param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr)
|
param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
mcl_structures.place_schematic = function(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr)
|
mcl_structures.place_schematic = function(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param)
|
||||||
local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return(schematic)")()
|
local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return(schematic)")()
|
||||||
if s and s.size then
|
if s and s.size then
|
||||||
local x, z = s.size.x, s.size.z
|
local x, z = s.size.x, s.size.z
|
||||||
|
@ -32,7 +32,7 @@ mcl_structures.place_schematic = function(pos, schematic, rotation, replacements
|
||||||
local p1 = {x=pos.x , y=pos.y , z=pos.z }
|
local p1 = {x=pos.x , y=pos.y , z=pos.z }
|
||||||
local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1}
|
local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1}
|
||||||
minetest.log("verbose","[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
|
minetest.log("verbose","[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
|
||||||
local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr}
|
local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param}
|
||||||
minetest.emerge_area(p1, p2, ecb_place, param)
|
minetest.emerge_area(p1, p2, ecb_place, param)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -548,7 +548,7 @@ end
|
||||||
|
|
||||||
-- Debug command
|
-- Debug command
|
||||||
minetest.register_chatcommand("spawnstruct", {
|
minetest.register_chatcommand("spawnstruct", {
|
||||||
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_opens | end_portal_shrine | nether_portal | dungeon",
|
params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_opens | end_portal_shrine | nether_portal | gateway_portal | dungeon",
|
||||||
description = S("Generate a pre-defined structure near your position."),
|
description = S("Generate a pre-defined structure near your position."),
|
||||||
privs = {debug = true},
|
privs = {debug = true},
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
|
@ -590,6 +590,8 @@ minetest.register_chatcommand("spawnstruct", {
|
||||||
mcl_dungeons.spawn_dungeon(pos, rot, pr)
|
mcl_dungeons.spawn_dungeon(pos, rot, pr)
|
||||||
elseif param == "nether_portal" and mcl_portals and mcl_portals.spawn_nether_portal then
|
elseif param == "nether_portal" and mcl_portals and mcl_portals.spawn_nether_portal then
|
||||||
mcl_portals.spawn_nether_portal(pos, rot, pr, name)
|
mcl_portals.spawn_nether_portal(pos, rot, pr, name)
|
||||||
|
elseif param == "gateway_portal" and mcl_portals.spawn_gateway_portal then
|
||||||
|
mcl_portals.spawn_gateway_portal(pos, rot, pr, name)
|
||||||
elseif param == "" then
|
elseif param == "" then
|
||||||
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
|
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
|
||||||
errord = true
|
errord = true
|
||||||
|
|
Loading…
Reference in New Issue