mirror of
https://github.com/minetest-mods/nether.git
synced 2024-12-27 19:30:28 +01:00
Portals connect to nearby targets
Records portal positions. More testing required
This commit is contained in:
parent
43b37e96b2
commit
1a6d15def3
32
init.lua
32
init.lua
@ -75,28 +75,42 @@ The expedition parties have found no diamonds or gold, and after an experienced
|
||||
return pos.y < nether.DEPTH
|
||||
end,
|
||||
|
||||
find_realm_anchorPos = function(surface_pos)
|
||||
find_realm_anchorPos = function(surface_anchorPos)
|
||||
-- divide x and z by a factor of 8 to implement Nether fast-travel
|
||||
local destination_pos = vector.divide(surface_pos, nether.FASTTRAVEL_FACTOR)
|
||||
local destination_pos = vector.divide(surface_anchorPos, nether.FASTTRAVEL_FACTOR)
|
||||
destination_pos.x = math.floor(0.5 + destination_pos.x) -- round to int
|
||||
destination_pos.z = math.floor(0.5 + destination_pos.z) -- round to int
|
||||
destination_pos.y = nether.DEPTH - 1000 -- temp value so find_nearest_working_portal() returns nether portals
|
||||
|
||||
local start_y = nether.DEPTH - math.random(500, 1500) -- Search start
|
||||
destination_pos.y = nether.find_nether_ground_y(destination_pos.x, destination_pos.z, start_y)
|
||||
return destination_pos
|
||||
-- a y_factor of 0 makes the search ignore the altitude of the portals (as long as they are in the Nether)
|
||||
local existing_portal_location, existing_portal_orientation = nether.find_nearest_working_portal("nether_portal", destination_pos, 8, 0)
|
||||
if existing_portal_location ~= nil then
|
||||
return existing_portal_location, existing_portal_orientation
|
||||
else
|
||||
local start_y = nether.DEPTH - math.random(500, 1500) -- Search starting altitude
|
||||
destination_pos.y = nether.find_nether_ground_y(destination_pos.x, destination_pos.z, start_y)
|
||||
return destination_pos
|
||||
end
|
||||
end,
|
||||
|
||||
find_surface_anchorPos = function(realm_pos)
|
||||
find_surface_anchorPos = function(realm_anchorPos)
|
||||
-- A portal definition doesn't normally need to provide a find_surface_anchorPos() function,
|
||||
-- since find_surface_target_y() will be used by default, but Nether portals also scale position
|
||||
-- to create fast-travel:
|
||||
|
||||
-- Multiply x and z by a factor of 8 to implement Nether fast-travel
|
||||
local destination_pos = vector.multiply(realm_pos, nether.FASTTRAVEL_FACTOR)
|
||||
local destination_pos = vector.multiply(realm_anchorPos, nether.FASTTRAVEL_FACTOR)
|
||||
destination_pos.x = math.min(30900, math.max(-30900, destination_pos.x)) -- clip to world boundary
|
||||
destination_pos.z = math.min(30900, math.max(-30900, destination_pos.z)) -- clip to world boundary
|
||||
destination_pos.y = 0 -- temp value so find_nearest_working_portal() doesn't return nether portals
|
||||
|
||||
destination_pos.y = nether.find_surface_target_y(destination_pos.x, destination_pos.z, "nether_portal")
|
||||
return destination_pos
|
||||
-- a y_factor of 0 makes the search ignore the altitude of the portals (as long as they are outside the Nether)
|
||||
local existing_portal_location, existing_portal_orientation = nether.find_nearest_working_portal("nether_portal", destination_pos, 8 * nether.FASTTRAVEL_FACTOR, 0)
|
||||
if existing_portal_location ~= nil then
|
||||
return existing_portal_location, existing_portal_orientation
|
||||
else
|
||||
destination_pos.y = nether.find_surface_target_y(destination_pos.x, destination_pos.z, "nether_portal")
|
||||
return destination_pos
|
||||
end
|
||||
end
|
||||
})
|
||||
|
206
portal_api.lua
206
portal_api.lua
@ -1,5 +1,5 @@
|
||||
-- see portal_api.txt for documentation
|
||||
local DEBUG = false
|
||||
local DEBUG = true
|
||||
|
||||
|
||||
nether.registered_portals = {}
|
||||
@ -214,8 +214,9 @@ nether.PortalShape_Traditional = {
|
||||
|
||||
-- list of node names that are used as frame nodes by registered portals
|
||||
local is_frame_node = {}
|
||||
local S = nether.get_translator
|
||||
local ignition_item_name
|
||||
local S = nether.get_translator
|
||||
local mod_storage = minetest.get_mod_storage()
|
||||
|
||||
-- this is a function that will be assigned to further down, allowing functions to use it
|
||||
-- that are defined before it is.
|
||||
@ -231,8 +232,8 @@ local function get_timerPos_from_p1_and_p2(p1, p2)
|
||||
-- makes a cubic portal shape, orientation can be determined from p1 and p2 in the node's
|
||||
-- metadata (frame nodes don't have orientation set in param2 like wormhole nodes do).
|
||||
--
|
||||
-- We shouldn't pick p1 (or p2) as it's possible for two orthogonal portals to share
|
||||
-- the same p1, etc. Or at least it was - there's code to try to stop that now.
|
||||
-- We shouldn't pick p1 or p2 as it's possible for two orthogonal portals to share
|
||||
-- the same p1, etc. - or at least it was - there's code to try to stop that now.
|
||||
--
|
||||
-- I'll pick the bottom center node of the portal, since that works for rectangular portals
|
||||
-- and if someone want to make a circular portal then that positon will still likely be part
|
||||
@ -245,7 +246,7 @@ local function get_timerPos_from_p1_and_p2(p1, p2)
|
||||
end
|
||||
|
||||
-- orientation is the rotation degrees passed to place_schematic: 0, 90, 180, or 270
|
||||
-- color is a value from 0 to 7 corresponding to the pixels in portals_palette.png
|
||||
-- color is a value from 0 to 7 corresponding to the color of pixels in nether_portals_palette.png
|
||||
local function get_param2_from_color_and_orientation(color, orientation)
|
||||
assert(orientation, "no orientation passed")
|
||||
|
||||
@ -301,8 +302,66 @@ local function list_portal_definitions_for_frame_node(frame_node_name)
|
||||
end
|
||||
|
||||
|
||||
local function set_portal_metadata(portal_definition, anchorPos, orientation, destination_wormholePos, ignite)
|
||||
-- Add portal information to mod storage, so new portals may find existing portals near the target location.
|
||||
-- Do this whenever a portal is created or changes its ignition state
|
||||
local function store_portal_location_info(portal_name, anchorPos, orientation, ignited)
|
||||
mod_storage:set_string(
|
||||
minetest.pos_to_string(anchorPos) .. " is " .. portal_name,
|
||||
minetest.serialize({orientation = orientation, active = ignited})
|
||||
)
|
||||
end
|
||||
|
||||
-- Remove portal information from mod storage.
|
||||
-- Do this if a portal frame is destroyed such that it cannot be ignited anymore.
|
||||
local function remove_portal_location_info(portal_name, anchorPos)
|
||||
mod_storage:set_string(minetest.pos_to_string(anchorPos) .. " is " .. portal_name, "")
|
||||
end
|
||||
|
||||
-- Returns a table of the nearest portals to anchorPos indexed by distance, based on mod_storage
|
||||
-- data.
|
||||
-- Only portals in the same realm as the anchorPos will be returned, even if y_factor is 0.
|
||||
-- WARNING: Portals are not checked, and inactive portals especially may have been damaged without
|
||||
-- being removed from the mod_storage data. Check these portals still exist before using them, and
|
||||
-- invoke remove_portal_location_info() on any found to no longer exist.
|
||||
--
|
||||
-- A y_factor of 0 means y does not affect the distance_limit, a y_factor of 1 means y is included,
|
||||
-- and a y_factor of 2 would squash the search-sphere by a factor of 2 on the y-axis, etc.
|
||||
-- Pass a nil or negative distance_limit to indicate no distance limit
|
||||
local function list_closest_portals(portal_definition, anchorPos, distance_limit, y_factor)
|
||||
|
||||
local result = {}
|
||||
|
||||
local isRealm = portal_definition.within_realm(anchorPos)
|
||||
if distance_limit == nil then distance_limit = -1 end
|
||||
if y_factor == nil then y_factor = 1 end
|
||||
|
||||
for key, value in pairs(mod_storage:to_table().fields) do
|
||||
local closingBrace = key:find(")", 6, true)
|
||||
if closingBrace ~= nil then
|
||||
local found_anchorPos = minetest.string_to_pos(key:sub(0, closingBrace))
|
||||
if found_anchorPos ~= nil and portal_definition.within_realm(found_anchorPos) == isRealm then
|
||||
local found_name = key:sub(closingBrace + 5)
|
||||
if found_name == portal_definition.name then
|
||||
local x = anchorPos.x - found_anchorPos.x
|
||||
local y = anchorPos.y - found_anchorPos.y
|
||||
local z = anchorPos.z - found_anchorPos.z
|
||||
local distance = math.hypot(y * y_factor, math.hypot(x, z))
|
||||
if distance <= distance_limit or distance_limit < 0 then
|
||||
local info = minetest.deserialize(value) or {}
|
||||
if DEBUG then minetest.chat_send_all("found at distance " .. distance .. " from dest " .. minetest.pos_to_string(anchorPos) .. ", found: " .. minetest.pos_to_string(found_anchorPos) .. " orientation " .. info.orientation) end
|
||||
info.anchorPos = found_anchorPos
|
||||
info.distance = distance
|
||||
result[distance] = info
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
local function set_portal_metadata(portal_definition, anchorPos, orientation, destination_wormholePos, ignite)
|
||||
|
||||
-- Portal position is stored in metadata as p1 and p2 to keep maps compatible with earlier versions of this mod.
|
||||
-- p1 is the bottom/west/south corner of the portal, and p2 is the opposite corner, together
|
||||
@ -363,24 +422,40 @@ local function set_portal_metadata(portal_definition, anchorPos, orientation, de
|
||||
|
||||
local timerPos = get_timerPos_from_p1_and_p2(p1, p2)
|
||||
minetest.get_node_timer(timerPos):start(1)
|
||||
|
||||
store_portal_location_info(portal_definition.name, anchorPos, orientation, true)
|
||||
end
|
||||
|
||||
local function set_portal_metadata_and_ignite(portal_definition, anchorPos, orientation, destination_wormholePos)
|
||||
set_portal_metadata(portal_definition, anchorPos, orientation, destination_wormholePos, true)
|
||||
end
|
||||
|
||||
-- Checks pos, and if it's part of a portal or portal frame then three values are returned: anchorPos, orientation, is_ignited
|
||||
-- where orientation is 0 or 90 (0 meaning a portal that faces north/south - i.e. obsidian running east/west)
|
||||
local function is_portal_frame(portal_definition, pos)
|
||||
|
||||
-- this function returns two bools: portal found, portal is lit
|
||||
local function is_portal_at_anchorPos(portal_definition, anchorPos, orientation, force_chunk_load)
|
||||
|
||||
local nodes_are_valid -- using closures to allow the check functions to return extra information - by setting this variable
|
||||
local portal_is_ignited -- using closures to allow the check functions to return extra information - by setting this variable
|
||||
|
||||
local frame_node_name = portal_definition.frame_node_name
|
||||
local check_frame_Func = function(check_pos)
|
||||
if minetest.get_node(check_pos).name ~= frame_node_name then
|
||||
nodes_are_valid = false
|
||||
return true -- short-circuit the search
|
||||
local foundName = minetest.get_node(check_pos).name
|
||||
if foundName ~= frame_node_name then
|
||||
|
||||
if force_chunk_load and foundName == "ignore" then
|
||||
-- area isn't loaded, force loading/emerge of check area
|
||||
minetest.get_voxel_manip():read_from_map(check_pos, check_pos)
|
||||
foundName = minetest.get_node(check_pos).name
|
||||
if DEBUG then minetest.chat_send_all("Forced loading of 'ignore' node at " .. minetest.pos_to_string(check_pos) .. ", got " .. foundName) end
|
||||
|
||||
if foundName ~= frame_node_name then
|
||||
nodes_are_valid = false
|
||||
return true -- short-circuit the search
|
||||
end
|
||||
else
|
||||
nodes_are_valid = false
|
||||
return true -- short-circuit the search
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -396,21 +471,22 @@ local function is_portal_frame(portal_definition, pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- this function returns two bools: portal found, portal is lit
|
||||
local is_portal_at_anchorPos = function(anchorPos, orientation)
|
||||
nodes_are_valid = true
|
||||
portal_is_ignited = true
|
||||
portal_definition.shape.apply_func_to_frame_nodes(anchorPos, orientation, check_frame_Func) -- check_frame_Func affects nodes_are_valid, portal_is_ignited
|
||||
|
||||
nodes_are_valid = true
|
||||
portal_is_ignited = true
|
||||
portal_definition.shape.apply_func_to_frame_nodes(anchorPos, orientation, check_frame_Func) -- check_frame_Func affects nodes_are_valid, portal_is_ignited
|
||||
|
||||
if nodes_are_valid then
|
||||
-- a valid frame exists at anchorPos, check the wormhole is either ignited or unobstructed
|
||||
portal_definition.shape.apply_func_to_wormhole_nodes(anchorPos, orientation, check_wormhole_Func) -- check_wormhole_Func affects nodes_are_valid, portal_is_ignited
|
||||
end
|
||||
|
||||
return nodes_are_valid, portal_is_ignited and nodes_are_valid -- returns two bools: portal was found, portal is lit
|
||||
if nodes_are_valid then
|
||||
-- a valid frame exists at anchorPos, check the wormhole is either ignited or unobstructed
|
||||
portal_definition.shape.apply_func_to_wormhole_nodes(anchorPos, orientation, check_wormhole_Func) -- check_wormhole_Func affects nodes_are_valid, portal_is_ignited
|
||||
end
|
||||
|
||||
return nodes_are_valid, portal_is_ignited and nodes_are_valid -- returns two bools: portal was found, portal is lit
|
||||
end
|
||||
|
||||
-- Checks pos, and if it's part of a portal or portal frame then three values are returned: anchorPos, orientation, is_ignited
|
||||
-- where orientation is 0 or 90 (0 meaning a portal that faces north/south - i.e. obsidian running east/west)
|
||||
local function is_portal_frame(portal_definition, pos)
|
||||
|
||||
local width_minus_1 = portal_definition.shape.size.x - 1
|
||||
local height_minus_1 = portal_definition.shape.size.y - 1
|
||||
local depth_minus_1 = portal_definition.shape.size.z - 1
|
||||
@ -420,14 +496,14 @@ local function is_portal_frame(portal_definition, pos)
|
||||
for y = -height_minus_1, height_minus_1 do
|
||||
|
||||
local testAnchorPos_x = {x = pos.x + w, y = pos.y + y, z = pos.z + d}
|
||||
local portal_found, portal_lit = is_portal_at_anchorPos(testAnchorPos_x, 0)
|
||||
local portal_found, portal_lit = is_portal_at_anchorPos(portal_definition, testAnchorPos_x, 0, true)
|
||||
|
||||
if portal_found then
|
||||
return testAnchorPos_x, 0, portal_lit
|
||||
else
|
||||
-- try orthogonal orientation
|
||||
local testForAnchorPos_z = {x = pos.x + d, y = pos.y + y, z = pos.z + w}
|
||||
portal_found, portal_lit = is_portal_at_anchorPos(testForAnchorPos_z, 90)
|
||||
portal_found, portal_lit = is_portal_at_anchorPos(portal_definition, testForAnchorPos_z, 90, true)
|
||||
|
||||
if portal_found then return testForAnchorPos_z, 90, portal_lit end
|
||||
end
|
||||
@ -568,8 +644,20 @@ function nether.find_surface_target_y(target_x, target_z, portal_name)
|
||||
|
||||
-- try to spawn on surface first
|
||||
if minetest.get_spawn_level ~= nil then -- older versions of Minetest don't have this
|
||||
local surface_level = minetest.get_spawn_level(target_x, target_z)
|
||||
local surface_level = minetest.get_spawn_level(target_x, target_z)
|
||||
if surface_level ~= nil then
|
||||
-- get_spawn_level() seems to err on the side of caution and sometimes spawn the player a
|
||||
-- block higher than the ground level.
|
||||
local shouldBeGroundPos = {x = target_x, y = surface_level - 1, z = target_z}
|
||||
local groundNode = minetest.get_node(shouldBeGroundPos)
|
||||
if groundNode.Name = 'ignore' then
|
||||
-- force the area to be loaded - it's going to be loaded anyway by volume_is_natural()
|
||||
minetest.get_voxel_manip():read_from_map(shouldBeGroundPos, shouldBeGroundPos)
|
||||
local groundNode = minetest.get_node(shouldBeGroundPos)
|
||||
end
|
||||
if not groundNode.is_ground_content then
|
||||
surface_level = surface_level - 1
|
||||
end
|
||||
-- Check volume for non-natural nodes
|
||||
local minp = {x = target_x - 1, y = surface_level - 1, z = target_z - 2}
|
||||
local maxp = {x = target_x + 2, y = surface_level + 3, z = target_z + 2}
|
||||
@ -629,14 +717,16 @@ local function ignite_portal(ignition_pos, ignition_node_name)
|
||||
if continue == false then
|
||||
if DEBUG then minetest.chat_send_all("Found portal frame. Looked at " .. minetest.pos_to_string(ignition_pos) .. ", found at " .. minetest.pos_to_string(anchorPos) .. " orientation " .. orientation) end
|
||||
|
||||
local destination_anchorPos
|
||||
local destination_anchorPos, destination_orientation
|
||||
if portal_definition.within_realm(ignition_pos) then
|
||||
destination_anchorPos = portal_definition.find_surface_anchorPos(anchorPos)
|
||||
destination_anchorPos, destination_orientation = portal_definition.find_surface_anchorPos(anchorPos)
|
||||
else
|
||||
destination_anchorPos = portal_definition.find_realm_anchorPos(anchorPos)
|
||||
destination_anchorPos, destination_orientation = portal_definition.find_realm_anchorPos(anchorPos)
|
||||
end
|
||||
|
||||
local destination_wormholePos = portal_definition.shape.get_wormholePos_from_anchorPos(destination_anchorPos, orientation)
|
||||
if DEBUG and destination_orientation == nil then minetest.chat_send_all("No destination_orientation given") end
|
||||
if destination_orientation == nil then destination_orientation = orientation end
|
||||
|
||||
local destination_wormholePos = portal_definition.shape.get_wormholePos_from_anchorPos(destination_anchorPos, destination_orientation)
|
||||
if DEBUG then minetest.chat_send_all("Destinaton set to " .. minetest.pos_to_string(destination_anchorPos)) end
|
||||
|
||||
-- ignition/BURN_BABY_BURN
|
||||
@ -649,7 +739,7 @@ end
|
||||
|
||||
|
||||
-- WARNING - this is invoked by on_destruct, so you can't assume there's an accesible node at pos
|
||||
extinguish_portal = function(pos, node_name) -- assigned rather than declared because extinguish_portal is already declared, for use by earlier functions in the file.
|
||||
extinguish_portal = function(pos, node_name, frame_was_destroyed) -- assigned rather than declared because extinguish_portal is already declared, for use by earlier functions in the file.
|
||||
|
||||
-- mesecons seems to invoke action_off() 6 times every time you place a block?
|
||||
if DEBUG then minetest.chat_send_all("extinguish_portal" .. minetest.pos_to_string(pos) .. " " .. node_name) end
|
||||
@ -667,6 +757,15 @@ extinguish_portal = function(pos, node_name) -- assigned rather than declared be
|
||||
minetest.log("error", "extinguish_portal() invoked on " .. node_name .. " but no registered portal is constructed from " .. node_name)
|
||||
return -- no portal frames are made from this type of node
|
||||
end
|
||||
|
||||
-- update the ignition state in the portal location info
|
||||
local anchorPos, orientation = portal_definition.shape.get_anchorPos_and_orientation_from_p1_and_p2(p1, p2)
|
||||
if frame_was_destroyed then
|
||||
remove_portal_location_info(portal_definition.name, anchorPos)
|
||||
else
|
||||
store_portal_location_info(portal_definition.name, anchorPos, orientation, false)
|
||||
end
|
||||
|
||||
local frame_node_name = portal_definition.frame_node_name
|
||||
local wormhole_node_name = portal_definition.wormhole_node_name
|
||||
|
||||
@ -698,6 +797,8 @@ end
|
||||
-- Make portals immortal for ~20 seconds after creation
|
||||
local function remote_portal_checkup(elapsed, portal_definition, anchorPos, orientation, destination_wormholePos)
|
||||
|
||||
if DEBUG then minetest.chat_send_all("portal checkup at " .. elapsed .. " seconds") end
|
||||
|
||||
local wormholePos = portal_definition.shape.get_wormholePos_from_anchorPos(anchorPos, orientation)
|
||||
local wormhole_node = minetest.get_node_or_nil(wormholePos)
|
||||
|
||||
@ -711,7 +812,7 @@ local function remote_portal_checkup(elapsed, portal_definition, anchorPos, orie
|
||||
build_portal(portal_definition, anchorPos, orientation, destination_wormholePos)
|
||||
end
|
||||
|
||||
if elapsed < 20 then -- stop checking after 20 seconds
|
||||
if elapsed < 10 then -- stop checking after ~20 seconds
|
||||
local delay = elapsed * 2
|
||||
minetest.after(delay, remote_portal_checkup, elapsed + delay, portal_definition, anchorPos, orientation, destination_wormholePos)
|
||||
end
|
||||
@ -970,7 +1071,7 @@ function register_frame_node(frame_node_name)
|
||||
}}
|
||||
extended_node_def.replaced_by_portalapi.on_destruct = extended_node_def.on_destruct
|
||||
extended_node_def.on_destruct = function(pos)
|
||||
extinguish_portal(pos, frame_node_name)
|
||||
extinguish_portal(pos, frame_node_name, true)
|
||||
end
|
||||
extended_node_def.replaced_by_portalapi.on_timer = extended_node_def.on_timer
|
||||
extended_node_def.on_timer = function(pos, elapsed)
|
||||
@ -1186,4 +1287,37 @@ function nether.register_portal_ignition_item(item_name)
|
||||
})
|
||||
|
||||
ignition_item_name = item_name
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the anchorPos, orientation of the nearest portal, or nil.
|
||||
-- A y_factor of 0 means y does not affect the distance_limit, a y_factor of 1 means y is included,
|
||||
-- and a y_factor of 2 would squash the search-sphere by a factor of 2 on the y-axis, etc.
|
||||
-- Pass a negative distance_limit to indicate no distance limit
|
||||
function nether.find_nearest_working_portal(portal_name, anchorPos, distance_limit, y_factor)
|
||||
|
||||
local portal_definition = nether.registered_portals[portal_name]
|
||||
assert(portal_definition ~= nil, "find_nearest_working_portal() called with portal_name '" .. portal_name .. "', but no portal is registered with that name.")
|
||||
|
||||
local contenders = list_closest_portals(portal_definition, anchorPos, distance_limit, y_factor)
|
||||
|
||||
-- sort by distance
|
||||
local dist_list = {}
|
||||
for dist, _ in pairs(contenders) do table.insert(dist_list, dist) end
|
||||
table.sort(dist_list)
|
||||
|
||||
for _, dist in ipairs(dist_list) do
|
||||
local portal_info = contenders[dist]
|
||||
if DEBUG then minetest.chat_send_all("checking portal from mod_storage at " .. minetest.pos_to_string(portal_info.anchorPos) .. " orientation " .. portal_info.orientation) end
|
||||
|
||||
local portalFound, portalActive = is_portal_at_anchorPos(portal_definition, portal_info.anchorPos, portal_info.orientation, true)
|
||||
|
||||
if portalFound then
|
||||
return portal_info.anchorPos, portal_info.orientation
|
||||
else
|
||||
if DEBUG then minetest.chat_send_all("removing portal from mod_storage at " .. minetest.pos_to_string(portal_info.anchorPos) .. " orientation " .. portal_info.orientation) end
|
||||
-- The portal at that location must have been destroyed
|
||||
remove_portal_location_info(portal_name, portal_info.anchorPos)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
@ -9,16 +9,23 @@ to other realms.
|
||||
Helper functions
|
||||
----------------
|
||||
|
||||
* `nether.volume_is_natural(minp, maxp)`
|
||||
* `nether.volume_is_natural(minp, maxp)`: returns a boolean
|
||||
* use this when determining where to spawn a portal, to avoid overwriting
|
||||
player builds. It checks the area for any nodes that aren't ground or
|
||||
trees.
|
||||
|
||||
* `nether.find_surface_target_y(target_x, target_z, portal_name)`
|
||||
* `nether.find_surface_target_y(target_x, target_z, portal_name)`: returns a suitable anchorPos
|
||||
* Can be used to implement custom find_surface_anchorPos() functions
|
||||
* Providing the portal_name allows existing portals on the surface to be reused.
|
||||
|
||||
* portal_name is optional, and providing it allows existing portals on the
|
||||
surface to be reused.
|
||||
|
||||
* `nether.find_nearest_working_portal(portal_name, anchorPos, distance_limit, y_factor)`: returns
|
||||
an anchorPos, or nil if no portal was found within the the distance_limit.
|
||||
* A y_factor of 0 means y does not affect the distance_limit, a y_factor
|
||||
of 1 means y is included, and a y_factor of 2 would squash the
|
||||
search-sphere by a factor of 2 on the y-axis, etc.
|
||||
* Only portals in the same realm as the anchorPos will be returned, even if y_factor is 0.
|
||||
* Pass a nil or negative distance_limit to indicate no distance limit
|
||||
|
||||
|
||||
API functions
|
||||
@ -53,28 +60,33 @@ Used by `nether.register_portal`.
|
||||
-- or texture.
|
||||
|
||||
wormhole_node_color = 0,
|
||||
-- A value from 0 to 7 corresponding to the color of pixels in
|
||||
-- nether_portals_palette.png
|
||||
|
||||
particle_color = "#808",
|
||||
-- Optional. Will default to the same colour as wormhole_node_color if
|
||||
-- not specified.
|
||||
|
||||
frame_node_name = "default:obsidian",
|
||||
-- required
|
||||
-- Required. For best results, have your portal constructed of a
|
||||
-- material nobody else is using.
|
||||
|
||||
|
||||
sound_ambient = "portal_hum",
|
||||
sound_ambient = "nether_portal_hum",
|
||||
sound_ignite = "",
|
||||
sound_extinguish = "",
|
||||
sound_teleport = "",
|
||||
|
||||
within_realm = function(pos)
|
||||
end,
|
||||
within_realm = function(pos),
|
||||
-- Required. Return true if a portal at pos is in the realm, rather
|
||||
than the surface world.
|
||||
|
||||
find_realm_anchorPos = function(pos)
|
||||
end,
|
||||
find_realm_anchorPos = function(surface_anchorPos)
|
||||
-- Required. Return a position in the realm that a portal created at
|
||||
-- surface_anchorPos will link to.
|
||||
|
||||
find_surface_anchorPos = function(pos)
|
||||
end,
|
||||
find_surface_anchorPos = function(realm_anchorPos),
|
||||
-- Optional. If you don't use this then a position near the surface
|
||||
-- will be picked.
|
||||
|
||||
on_run_wormhole,
|
||||
on_ignite,
|
||||
|
Loading…
Reference in New Issue
Block a user