mirror of
https://github.com/minetest-mods/nether.git
synced 2024-12-28 20:00:30 +01:00
Add settingtypes.txt settings
This commit is contained in:
parent
a971e0359e
commit
43f1f24d53
199
init.lua
199
init.lua
@ -28,19 +28,26 @@ nether.path = minetest.get_modpath(nether.modname)
|
|||||||
nether.get_translator = S
|
nether.get_translator = S
|
||||||
|
|
||||||
-- Settings
|
-- Settings
|
||||||
nether.DEPTH = -5000
|
nether.DEPTH = -5000 -- The y location of the Nether
|
||||||
nether.FASTTRAVEL_FACTOR = 8 -- 10 could be better value for Minetest, since there's no sprint, but ex-Minecraft players will be mathing for 8
|
nether.FASTTRAVEL_FACTOR = 8 -- 10 could be better value for Minetest, since there's no sprint, but ex-Minecraft players will be mathing for 8
|
||||||
nether.PORTAL_BOOK_LOOT_WEIGHTING = 0.9 -- Likelyhood of finding the Book of Portals (guide) in dungeon chests. Set to 0 to disable.
|
nether.PORTAL_BOOK_LOOT_WEIGHTING = 0.9 -- Likelyhood of finding the Book of Portals (guide) in dungeon chests. Set to 0 to disable.
|
||||||
nether.ENABLE_EXAMPLE_PORTALS = false -- Enables extra portal types - examples of how to create your own portal types using the Nether's portal API. Once enabled, their shapes will be shown in the book of portals.
|
nether.NETHER_REALM_ENABLED = true -- Setting to false disables the Nether and Nether portal
|
||||||
|
|
||||||
|
|
||||||
|
-- Override default settings with values from the .conf file, if any are present.
|
||||||
|
nether.FASTTRAVEL_FACTOR = tonumber(minetest.settings:get("nether_fasttravel_factor") or nether.FASTTRAVEL_FACTOR)
|
||||||
|
nether.PORTAL_BOOK_LOOT_WEIGHTING = tonumber(minetest.settings:get("nether_portalBook_loot_weighting") or nether.PORTAL_BOOK_LOOT_WEIGHTING)
|
||||||
|
nether.NETHER_REALM_ENABLED = minetest.settings:get_bool("nether_realm_enabled", nether.NETHER_REALM_ENABLED)
|
||||||
|
|
||||||
|
|
||||||
-- Load files
|
-- Load files
|
||||||
dofile(nether.path .. "/portal_api.lua")
|
dofile(nether.path .. "/portal_api.lua")
|
||||||
dofile(nether.path .. "/nodes.lua")
|
dofile(nether.path .. "/nodes.lua")
|
||||||
dofile(nether.path .. "/mapgen.lua")
|
if nether.NETHER_REALM_ENABLED then
|
||||||
|
dofile(nether.path .. "/mapgen.lua")
|
||||||
if nether.ENABLE_EXAMPLE_PORTALS then
|
|
||||||
dofile(nether.path .. "/portal_examples.lua")
|
|
||||||
end
|
end
|
||||||
|
dofile(nether.path .. "/portal_examples.lua")
|
||||||
|
|
||||||
|
|
||||||
-- Portals are ignited by right-clicking with a mese crystal fragment
|
-- Portals are ignited by right-clicking with a mese crystal fragment
|
||||||
nether.register_portal_ignition_item(
|
nether.register_portal_ignition_item(
|
||||||
@ -49,102 +56,104 @@ nether.register_portal_ignition_item(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
-- Use the Portal API to add a portal type which goes to the Nether
|
if nether.NETHER_REALM_ENABLED then
|
||||||
-- See portal_api.txt for documentation
|
-- Use the Portal API to add a portal type which goes to the Nether
|
||||||
nether.register_portal("nether_portal", {
|
-- See portal_api.txt for documentation
|
||||||
shape = nether.PortalShape_Traditional,
|
nether.register_portal("nether_portal", {
|
||||||
frame_node_name = "default:obsidian",
|
shape = nether.PortalShape_Traditional,
|
||||||
wormhole_node_color = 0, -- 0 is magenta
|
frame_node_name = "default:obsidian",
|
||||||
|
wormhole_node_color = 0, -- 0 is magenta
|
||||||
|
|
||||||
-- Warning: "Four per Em" spaces have been used to align the diagram in this text, rather
|
-- Warning: "Four per Em" spaces have been used to align the diagram in this text, rather
|
||||||
-- than ASCII spaces. If Minetest changes font this may need to be updated.
|
-- than ASCII spaces. If Minetest changes font this may need to be updated.
|
||||||
book_of_portals_pagetext = S([[ ──══♦♦♦◊ The Nether ◊♦♦♦══──
|
book_of_portals_pagetext = S([[ ──══♦♦♦◊ The Nether ◊♦♦♦══──
|
||||||
|
|
||||||
Requiring 14 blocks of obsidian, which we found deep underground where water had solidified molten rock. The frame must be constructed in the following fashion:
|
Requiring 14 blocks of obsidian, which we found deep underground where water had solidified molten rock. The frame must be constructed in the following fashion:
|
||||||
|
|
||||||
┌═╤═╤═╤═╗
|
┌═╤═╤═╤═╗
|
||||||
├─╥─┴─┼─╢
|
├─╥─┴─┼─╢
|
||||||
├─╢ ├─╢
|
├─╢ ├─╢
|
||||||
├─╢ ├─╢ four blocks wide
|
├─╢ ├─╢ four blocks wide
|
||||||
├─╚═╤═╡─╢ five blocks high
|
├─╚═╤═╡─╢ five blocks high
|
||||||
└─┴─┴─┴─┘ Standing vertically, like a doorway
|
└─┴─┴─┴─┘ Standing vertically, like a doorway
|
||||||
|
|
||||||
This opens to a truly hellish place, though for small mercies the air there is still breathable. There is an intriguing dimensional mismatch happening between this realm and ours, as after opening the second portal into it we observed that 10 strides taken in the Nether appear to be an equivalent of @1 in the natural world.
|
This opens to a truly hellish place, though for small mercies the air there is still breathable. There is an intriguing dimensional mismatch happening between this realm and ours, as after opening the second portal into it we observed that 10 strides taken in the Nether appear to be an equivalent of @1 in the natural world.
|
||||||
|
|
||||||
The expedition parties have found no diamonds or gold, and after an experienced search party failed to return from the trail of a missing expedition party, I must conclude this is a dangerous place.
|
The expedition parties have found no diamonds or gold, and after an experienced search party failed to return from the trail of a missing expedition party, I must conclude this is a dangerous place.
|
||||||
]], 10 * nether.FASTTRAVEL_FACTOR),
|
]], 10 * nether.FASTTRAVEL_FACTOR),
|
||||||
|
|
||||||
is_within_realm = function(pos) -- return true if pos is inside the Nether
|
is_within_realm = function(pos) -- return true if pos is inside the Nether
|
||||||
return pos.y < nether.DEPTH
|
return pos.y < nether.DEPTH
|
||||||
end,
|
end,
|
||||||
|
|
||||||
find_realm_anchorPos = function(surface_anchorPos)
|
find_realm_anchorPos = function(surface_anchorPos)
|
||||||
-- divide x and z by a factor of 8 to implement Nether fast-travel
|
-- divide x and z by a factor of 8 to implement Nether fast-travel
|
||||||
local destination_pos = vector.divide(surface_anchorPos, 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.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.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
|
destination_pos.y = nether.DEPTH - 1000 -- temp value so find_nearest_working_portal() returns nether portals
|
||||||
|
|
||||||
|
-- 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_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. Defining a custom function also means we can look for existing nearby portals:
|
||||||
|
|
||||||
|
-- Multiply x and z by a factor of 8 to implement Nether fast-travel
|
||||||
|
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
|
||||||
|
|
||||||
|
-- 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,
|
||||||
|
|
||||||
|
on_ignite = function(portalDef, anchorPos, orientation)
|
||||||
|
|
||||||
|
-- make some sparks fly
|
||||||
|
local p1, p2 = portalDef.shape:get_p1_and_p2_from_anchorPos(anchorPos, orientation)
|
||||||
|
local pos = vector.divide(vector.add(p1, p2), 2)
|
||||||
|
|
||||||
|
local textureName = portalDef.particle_texture
|
||||||
|
if type(textureName) == "table" then textureName = textureName.name end
|
||||||
|
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 110,
|
||||||
|
time = 0.1,
|
||||||
|
minpos = {x = pos.x - 0.5, y = pos.y - 1.2, z = pos.z - 0.5},
|
||||||
|
maxpos = {x = pos.x + 0.5, y = pos.y + 1.2, z = pos.z + 0.5},
|
||||||
|
minvel = {x = -5, y = -1, z = -5},
|
||||||
|
maxvel = {x = 5, y = 1, z = 5},
|
||||||
|
minacc = {x = 0, y = 0, z = 0},
|
||||||
|
maxacc = {x = 0, y = 0, z = 0},
|
||||||
|
minexptime = 0.1,
|
||||||
|
maxexptime = 0.5,
|
||||||
|
minsize = 0.2 * portalDef.particle_texture_scale,
|
||||||
|
maxsize = 0.8 * portalDef.particle_texture_scale,
|
||||||
|
collisiondetection = false,
|
||||||
|
texture = textureName .. "^[colorize:#F4F:alpha",
|
||||||
|
animation = portalDef.particle_texture_animation,
|
||||||
|
glow = 8
|
||||||
|
})
|
||||||
|
|
||||||
-- 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
|
||||||
end,
|
|
||||||
|
|
||||||
find_surface_anchorPos = function(realm_anchorPos)
|
})
|
||||||
-- A portal definition doesn't normally need to provide a find_surface_anchorPos() function,
|
end
|
||||||
-- since find_surface_target_y() will be used by default, but Nether portals also scale position
|
|
||||||
-- to create fast-travel. Defining a custom function also means we can look for existing nearby portals:
|
|
||||||
|
|
||||||
-- Multiply x and z by a factor of 8 to implement Nether fast-travel
|
|
||||||
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
|
|
||||||
|
|
||||||
-- 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,
|
|
||||||
|
|
||||||
on_ignite = function(portalDef, anchorPos, orientation)
|
|
||||||
|
|
||||||
-- make some sparks fly
|
|
||||||
local p1, p2 = portalDef.shape:get_p1_and_p2_from_anchorPos(anchorPos, orientation)
|
|
||||||
local pos = vector.divide(vector.add(p1, p2), 2)
|
|
||||||
|
|
||||||
local textureName = portalDef.particle_texture
|
|
||||||
if type(textureName) == "table" then textureName = textureName.name end
|
|
||||||
|
|
||||||
minetest.add_particlespawner({
|
|
||||||
amount = 110,
|
|
||||||
time = 0.1,
|
|
||||||
minpos = {x = pos.x - 0.5, y = pos.y - 1.2, z = pos.z - 0.5},
|
|
||||||
maxpos = {x = pos.x + 0.5, y = pos.y + 1.2, z = pos.z + 0.5},
|
|
||||||
minvel = {x = -5, y = -1, z = -5},
|
|
||||||
maxvel = {x = 5, y = 1, z = 5},
|
|
||||||
minacc = {x = 0, y = 0, z = 0},
|
|
||||||
maxacc = {x = 0, y = 0, z = 0},
|
|
||||||
minexptime = 0.1,
|
|
||||||
maxexptime = 0.5,
|
|
||||||
minsize = 0.2 * portalDef.particle_texture_scale,
|
|
||||||
maxsize = 0.8 * portalDef.particle_texture_scale,
|
|
||||||
collisiondetection = false,
|
|
||||||
texture = textureName .. "^[colorize:#F4F:alpha",
|
|
||||||
animation = portalDef.particle_texture_animation,
|
|
||||||
glow = 8
|
|
||||||
})
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
})
|
|
@ -1,10 +1,11 @@
|
|||||||
--[[
|
--[[
|
||||||
|
|
||||||
Nether mod portal examples for Minetest
|
Nether mod portal examples for Minetest
|
||||||
|
|
||||||
These portal API examples are independent of the Nether.
|
These portal API examples work independently of the Nether realm and Nether portal.
|
||||||
To use this file, set nether.ENABLE_EXAMPLE_PORTALS to true in init.lua
|
To try these examples, enable them in Mintest -> Settings -> All settings -> Mods -> nether
|
||||||
|
Once enabled, their shapes/plans will be shown in the book of portals.
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
Copyright (C) 2019 Treer
|
Copyright (C) 2019 Treer
|
||||||
|
|
||||||
@ -24,6 +25,10 @@
|
|||||||
]]--
|
]]--
|
||||||
local S = nether.get_translator
|
local S = nether.get_translator
|
||||||
|
|
||||||
|
|
||||||
|
local ENABLE_PORTAL_EXAMPLE_FLOATLANDS = false
|
||||||
|
local ENABLE_PORTAL_EXAMPLE_SURFACETRAVEL = false
|
||||||
|
|
||||||
-- Sets how far a Surface Portal will travel, measured in cells along the Moore curve,
|
-- Sets how far a Surface Portal will travel, measured in cells along the Moore curve,
|
||||||
-- which are about 117 nodes square each. Larger numbers will generally mean further distance
|
-- which are about 117 nodes square each. Larger numbers will generally mean further distance
|
||||||
-- as-the-crow-flies, but for small adjustments this will not always be true due to the how
|
-- as-the-crow-flies, but for small adjustments this will not always be true due to the how
|
||||||
@ -33,175 +38,189 @@ local S = nether.get_translator
|
|||||||
local SURFACE_TRAVEL_DISTANCE = 26
|
local SURFACE_TRAVEL_DISTANCE = 26
|
||||||
|
|
||||||
|
|
||||||
|
--=================================================--
|
||||||
|
-- Portal to the Floatlands, playable code example --
|
||||||
|
--==================================================--
|
||||||
local FLOATLANDS_ENABLED = false
|
local FLOATLANDS_ENABLED = false
|
||||||
local FLOATLAND_LEVEL = 1280
|
local FLOATLAND_LEVEL = 1280
|
||||||
local floatlands_flavortext = ""
|
|
||||||
if minetest.get_mapgen_setting("mg_name") == "v7" then
|
|
||||||
local mgv7_spflags = minetest.get_mapgen_setting("mgv7_spflags")
|
|
||||||
FLOATLANDS_ENABLED = mgv7_spflags ~= nil and mgv7_spflags:find("floatlands") ~= nil and mgv7_spflags:find("nofloatlands") == nil
|
|
||||||
FLOATLAND_LEVEL = minetest.get_mapgen_setting("mgv7_floatland_level") or 1280
|
|
||||||
|
|
||||||
if FLOATLANDS_ENABLED then
|
if minetest.settings:get_bool("nether_enable_portal_example_floatlands", ENABLE_PORTAL_EXAMPLE_FLOATLANDS) then
|
||||||
floatlands_flavortext = "There is a floating land of hills and lakes and forests up there, the edges of which lead to a drop all the way back down to the surface. We have not found how far these strange lands extend. One day I may retire here."
|
|
||||||
|
local floatlands_flavortext = ""
|
||||||
|
if minetest.get_mapgen_setting("mg_name") == "v7" then
|
||||||
|
local mgv7_spflags = minetest.get_mapgen_setting("mgv7_spflags")
|
||||||
|
FLOATLANDS_ENABLED = mgv7_spflags ~= nil and mgv7_spflags:find("floatlands") ~= nil and mgv7_spflags:find("nofloatlands") == nil
|
||||||
|
FLOATLAND_LEVEL = minetest.get_mapgen_setting("mgv7_floatland_level") or 1280
|
||||||
|
|
||||||
|
if FLOATLANDS_ENABLED then
|
||||||
|
floatlands_flavortext = "There is a floating land of hills and lakes and forests up there, the edges of which lead to a drop all the way back down to the surface. We have not found how far these strange lands extend. One day I may retire here."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
nether.register_portal("floatlands_portal", {
|
||||||
|
shape = nether.PortalShape_Platform,
|
||||||
|
frame_node_name = "default:ice",
|
||||||
|
wormhole_node_color = 7, -- 2 is blue
|
||||||
|
wormhole_node_is_horizontal = true, -- indicate the wormhole surface is horizontal
|
||||||
|
particle_texture = {
|
||||||
|
name = "nether_particle_anim1.png",
|
||||||
|
animation = {
|
||||||
|
type = "vertical_frames",
|
||||||
|
aspect_w = 7,
|
||||||
|
aspect_h = 7,
|
||||||
|
length = 1,
|
||||||
|
},
|
||||||
|
scale = 1.5
|
||||||
|
},
|
||||||
|
book_of_portals_pagetext = S([[ ──══♦♦♦◊ The Floatlands ◊♦♦♦══──
|
||||||
|
|
||||||
|
Requiring 21 blocks of ice, and constructed in the shape of a 3 × 3 platform with walls, or like a bowl:
|
||||||
|
|
||||||
|
┌─┬─┬─┐
|
||||||
|
┌─┼─┴─┴─┼─┐ Plan view (looking down from above)
|
||||||
|
├─┤ ├─┤
|
||||||
|
├─┤ ├─┤ five blocks wide
|
||||||
|
└─┼─┬─┬─┼─┘ in both directions
|
||||||
|
└─┴─┴─┘
|
||||||
|
|
||||||
|
┌─┬─┬─┬─┬─┐ Side view (looking from either side)
|
||||||
|
└─┼─┼─┼─┼─┘
|
||||||
|
└─┴─┴─┘ two blocks deep
|
||||||
|
|
||||||
|
This portal is different to the others, rather than acting akin to a doorway it appears to the eye more like a small pool of water which can be stepped into. Upon setting foot in the portal we found ourselves at a great altitude.
|
||||||
|
|
||||||
|
@1
|
||||||
|
]], floatlands_flavortext),
|
||||||
|
|
||||||
|
is_within_realm = function(pos) -- return true if pos is inside the Nether
|
||||||
|
return pos.y > FLOATLAND_LEVEL - 200
|
||||||
|
end,
|
||||||
|
|
||||||
|
find_realm_anchorPos = function(surface_anchorPos)
|
||||||
|
-- TODO: Once paramat finishes adjusting the floatlands, implement a surface algorithm that finds land
|
||||||
|
local destination_pos = {x = surface_anchorPos.x ,y = FLOATLAND_LEVEL + 2, z = surface_anchorPos.z}
|
||||||
|
|
||||||
|
-- a y_factor of 0 makes the search ignore the altitude of the portals (as long as they are in the Floatlands)
|
||||||
|
local existing_portal_location, existing_portal_orientation = nether.find_nearest_working_portal("floatlands_portal", destination_pos, 10, 0)
|
||||||
|
if existing_portal_location ~= nil then
|
||||||
|
return existing_portal_location, existing_portal_orientation
|
||||||
|
else
|
||||||
|
return destination_pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
nether.register_portal("floatlands_portal", {
|
--==============================================--
|
||||||
shape = nether.PortalShape_Platform,
|
-- Surface-travel portal, playable code example --
|
||||||
frame_node_name = "default:ice",
|
--==============================================--
|
||||||
wormhole_node_color = 7, -- 2 is blue
|
|
||||||
wormhole_node_is_horizontal = true, -- indicate the wormhole surface is horizontal
|
|
||||||
particle_texture = {
|
|
||||||
name = "nether_particle_anim1.png",
|
|
||||||
animation = {
|
|
||||||
type = "vertical_frames",
|
|
||||||
aspect_w = 7,
|
|
||||||
aspect_h = 7,
|
|
||||||
length = 1,
|
|
||||||
},
|
|
||||||
scale = 1.5
|
|
||||||
},
|
|
||||||
book_of_portals_pagetext = S([[ ──══♦♦♦◊ The Floatlands ◊♦♦♦══──
|
|
||||||
|
|
||||||
Requiring 21 blocks of ice, and constructed in the shape of a 3 × 3 platform with walls, or like a bowl:
|
|
||||||
|
|
||||||
┌─┬─┬─┐
|
|
||||||
┌─┼─┴─┴─┼─┐ Plan view (looking down from above)
|
|
||||||
├─┤ ├─┤
|
|
||||||
├─┤ ├─┤ five blocks wide
|
|
||||||
└─┼─┬─┬─┼─┘ in both directions
|
|
||||||
└─┴─┴─┘
|
|
||||||
|
|
||||||
┌─┬─┬─┬─┬─┐ Side view (looking from either side)
|
|
||||||
└─┼─┼─┼─┼─┘
|
|
||||||
└─┴─┴─┘ two blocks deep
|
|
||||||
|
|
||||||
This portal is different to the others, rather than acting akin to a doorway it appears to the eye more like a small pool of water which can be stepped into. Upon setting foot in the portal we found ourselves at a great altitude.
|
|
||||||
|
|
||||||
@1
|
|
||||||
]], floatlands_flavortext),
|
|
||||||
|
|
||||||
is_within_realm = function(pos) -- return true if pos is inside the Nether
|
|
||||||
return pos.y > FLOATLAND_LEVEL - 200
|
|
||||||
end,
|
|
||||||
|
|
||||||
find_realm_anchorPos = function(surface_anchorPos)
|
|
||||||
-- TODO: Once paramat finishes adjusting the floatlands, implement a surface algorithm that finds land
|
|
||||||
local destination_pos = {x = surface_anchorPos.x ,y = FLOATLAND_LEVEL + 2, z = surface_anchorPos.z}
|
|
||||||
|
|
||||||
-- a y_factor of 0 makes the search ignore the altitude of the portals (as long as they are in the Floatlands)
|
|
||||||
local existing_portal_location, existing_portal_orientation = nether.find_nearest_working_portal("floatlands_portal", destination_pos, 20, 0)
|
|
||||||
if existing_portal_location ~= nil then
|
|
||||||
return existing_portal_location, existing_portal_orientation
|
|
||||||
else
|
|
||||||
return destination_pos
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
-- These Moore Curve functions requred by surface_portal's find_surface_anchorPos() will
|
-- These Moore Curve functions requred by surface_portal's find_surface_anchorPos() will
|
||||||
-- be assigned later in this file.
|
-- be assigned later in this file.
|
||||||
local get_moore_distance -- will be function get_moore_distance(cell_count, x, y): integer
|
local get_moore_distance -- will be function get_moore_distance(cell_count, x, y): integer
|
||||||
local get_moore_coords -- will be function get_moore_coords(cell_count, distance): pos2d
|
local get_moore_coords -- will be function get_moore_coords(cell_count, distance): pos2d
|
||||||
|
|
||||||
nether.register_portal("surface_portal", {
|
if minetest.settings:get_bool("nether_enable_portal_example_surfacetravel", ENABLE_PORTAL_EXAMPLE_SURFACETRAVEL) then
|
||||||
shape = nether.PortalShape_Circular,
|
|
||||||
frame_node_name = "default:tinblock",
|
|
||||||
wormhole_node_color = 4, -- 4 is cyan
|
|
||||||
book_of_portals_pagetext = S([[ ──══♦♦♦◊ Surface portal ◊♦♦♦══──
|
|
||||||
|
|
||||||
Requiring 16 blocks of tin, the frame must be constructed in the following fashion:
|
nether.register_portal("surface_portal", {
|
||||||
|
shape = nether.PortalShape_Circular,
|
||||||
|
frame_node_name = "default:tinblock",
|
||||||
|
wormhole_node_color = 4, -- 4 is cyan
|
||||||
|
book_of_portals_pagetext = S([[ ──══♦♦♦◊ Surface portal ◊♦♦♦══──
|
||||||
|
|
||||||
┌═╤═╤═╗
|
Requiring 16 blocks of tin, the frame must be constructed in the following fashion:
|
||||||
┌═┼─┴─┴─┼═╗
|
|
||||||
┌═┼─┘ └─┼═╗
|
|
||||||
├─╢ ├─╢
|
|
||||||
├─╢ ├─╢ seven blocks wide
|
|
||||||
└─╚═╗ ┌═╡─┘ seven blocks high
|
|
||||||
└─╚═╤═╤═┼─┘ in a circular shape
|
|
||||||
└─┴─┴─┘ standing vertically, like a doorway
|
|
||||||
|
|
||||||
These travel a distance along the ground, and even when constructed deep underground they link back up to the surface, but we were never able to predict where the matching twin portal would appear. Coudreau believes it works in epicycles, but I am not convinced.
|
┌═╤═╤═╗
|
||||||
]]),
|
┌═┼─┴─┴─┼═╗
|
||||||
|
┌═┼─┘ └─┼═╗
|
||||||
|
├─╢ ├─╢
|
||||||
|
├─╢ ├─╢ seven blocks wide
|
||||||
|
└─╚═╗ ┌═╡─┘ seven blocks high
|
||||||
|
└─╚═╤═╤═┼─┘ in a circular shape
|
||||||
|
└─┴─┴─┘ standing vertically, like a doorway
|
||||||
|
|
||||||
is_within_realm = function(pos)
|
These travel a distance along the ground, and even when constructed deep underground they link back up to the surface, but we were never able to predict where the matching twin portal would appear. Coudreau believes it works in epicycles, but I am not convinced.
|
||||||
-- Always return true, because these portals always just take you around the surface
|
]]),
|
||||||
-- rather than taking you to a realm
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
|
|
||||||
find_realm_anchorPos = function(surface_anchorPos)
|
is_within_realm = function(pos)
|
||||||
-- This function isn't needed, since this type of portal always goes to the surface
|
-- Always return true, because these portals always just take you around the surface
|
||||||
minecraft.log("error" , "find_realm_anchorPos called for surface portal")
|
-- rather than taking you to a realm
|
||||||
return {x=0, y=0, z=0}
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
find_surface_anchorPos = function(realm_anchorPos)
|
find_realm_anchorPos = function(surface_anchorPos)
|
||||||
-- A portal definition doesn't normally need to provide a find_surface_anchorPos() function,
|
-- This function isn't needed, since this type of portal always goes to the surface
|
||||||
-- since find_surface_target_y() will be used by default, but these portals travel around the
|
minecraft.log("error" , "find_realm_anchorPos called for surface portal")
|
||||||
-- surface (following a Moore curve) so will be using a different x and z to realm_anchorPos.
|
return {x=0, y=0, z=0}
|
||||||
|
end,
|
||||||
|
|
||||||
local cellCount = 512
|
find_surface_anchorPos = function(realm_anchorPos)
|
||||||
local maxDistFromOrigin = 30000 -- the world edges are at X=30927, X=−30912, Z=30927 and Z=−30912
|
-- 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 these portals travel around the
|
||||||
|
-- surface (following a Moore curve) so will be calculating a different x and z to realm_anchorPos.
|
||||||
|
|
||||||
-- clip realm_anchorPos to maxDistFromOrigin, and move the origin so that all values are positive
|
local cellCount = 512
|
||||||
local x = math.min(maxDistFromOrigin, math.max(-maxDistFromOrigin, realm_anchorPos.x)) + maxDistFromOrigin
|
local maxDistFromOrigin = 30000 -- the world edges are at X=30927, X=−30912, Z=30927 and Z=−30912
|
||||||
local z = math.min(maxDistFromOrigin, math.max(-maxDistFromOrigin, realm_anchorPos.z)) + maxDistFromOrigin
|
|
||||||
|
|
||||||
local divisor = math.ceil(maxDistFromOrigin * 2 / cellCount)
|
-- clip realm_anchorPos to maxDistFromOrigin, and move the origin so that all values are positive
|
||||||
local distance = get_moore_distance(cellCount, math.floor(x / divisor + 0.5), math.floor(z / divisor + 0.5))
|
local x = math.min(maxDistFromOrigin, math.max(-maxDistFromOrigin, realm_anchorPos.x)) + maxDistFromOrigin
|
||||||
local destination_distance = (distance + SURFACE_TRAVEL_DISTANCE) % (cellCount * cellCount)
|
local z = math.min(maxDistFromOrigin, math.max(-maxDistFromOrigin, realm_anchorPos.z)) + maxDistFromOrigin
|
||||||
local moore_pos = get_moore_coords(cellCount, destination_distance)
|
|
||||||
local target_x = moore_pos.x * divisor - maxDistFromOrigin
|
|
||||||
local target_z = moore_pos.y * divisor - maxDistFromOrigin
|
|
||||||
|
|
||||||
local search_radius = divisor / 2 - 5 -- any portal within this area will do
|
local divisor = math.ceil(maxDistFromOrigin * 2 / cellCount)
|
||||||
|
local distance = get_moore_distance(cellCount, math.floor(x / divisor + 0.5), math.floor(z / divisor + 0.5))
|
||||||
|
local destination_distance = (distance + SURFACE_TRAVEL_DISTANCE) % (cellCount * cellCount)
|
||||||
|
local moore_pos = get_moore_coords(cellCount, destination_distance)
|
||||||
|
local target_x = moore_pos.x * divisor - maxDistFromOrigin
|
||||||
|
local target_z = moore_pos.y * divisor - maxDistFromOrigin
|
||||||
|
|
||||||
-- a y_factor of 0 makes the search ignore the altitude of the portals
|
local search_radius = divisor / 2 - 5 -- any portal within this area will do
|
||||||
local existing_portal_location, existing_portal_orientation =
|
|
||||||
nether.find_nearest_working_portal("surface_portal", {x = target_x, y = 0, z = target_z}, search_radius, 0)
|
|
||||||
|
|
||||||
if existing_portal_location ~= nil then
|
-- a y_factor of 0 makes the search ignore the altitude of the portals
|
||||||
-- use the existing portal that was found near target_x, target_z
|
local existing_portal_location, existing_portal_orientation =
|
||||||
return existing_portal_location, existing_portal_orientation
|
nether.find_nearest_working_portal("surface_portal", {x = target_x, y = 0, z = target_z}, search_radius, 0)
|
||||||
else
|
|
||||||
-- find a good location for the new portal
|
|
||||||
local adj_x, adj_z = 0, 0
|
|
||||||
|
|
||||||
if minetest.get_spawn_level ~= nil then -- older versions of Minetest don't have this
|
if existing_portal_location ~= nil then
|
||||||
-- Deterministically look for a location in the cell where get_spawn_level() can give
|
-- use the existing portal that was found near target_x, target_z
|
||||||
-- us a surface height, since nether.find_surface_target_y() works *much* better when
|
return existing_portal_location, existing_portal_orientation
|
||||||
-- it can use get_spawn_level()
|
else
|
||||||
local prng = PcgRandom( -- seed the prng so that all portals for these Moore Curve coords will use the same random location
|
-- find a good location for the new portal
|
||||||
moore_pos.x * 65732 +
|
local adj_x, adj_z = 0, 0
|
||||||
moore_pos.y * 729 +
|
|
||||||
minetest.get_mapgen_setting("seed") * 3
|
|
||||||
)
|
|
||||||
|
|
||||||
local attemptLimit = 12 -- how many attempts we'll make at finding a good location
|
if minetest.get_spawn_level ~= nil then -- older versions of Minetest don't have this
|
||||||
for attempt = 1, attemptLimit do
|
-- Deterministically look for a location in the cell where get_spawn_level() can give
|
||||||
adj_x = math.floor(prng:rand_normal_dist(-search_radius, search_radius, 2) + 0.5)
|
-- us a surface height, since nether.find_surface_target_y() works *much* better when
|
||||||
adj_z = math.floor(prng:rand_normal_dist(-search_radius, search_radius, 2) + 0.5)
|
-- it can use get_spawn_level()
|
||||||
minetest.chat_send_all(attempt .. ": x " .. target_x + adj_x .. ", z " .. target_z + adj_z)
|
local prng = PcgRandom( -- seed the prng so that all portals for these Moore Curve coords will use the same random location
|
||||||
if minetest.get_spawn_level(target_x + adj_x, target_z + adj_z) ~= nil then
|
moore_pos.x * 65732 +
|
||||||
-- found a location which will be at ground level (unless a player has built there)
|
moore_pos.y * 729 +
|
||||||
minetest.chat_send_all("x " .. target_x + adj_x .. ", z " .. target_z + adj_z .. " is suitable. Within " .. search_radius .. " of " .. target_x .. ", " .. target_z)
|
minetest.get_mapgen_setting("seed") * 3
|
||||||
break
|
)
|
||||||
|
|
||||||
|
local attemptLimit = 12 -- how many attempts we'll make at finding a good location
|
||||||
|
for attempt = 1, attemptLimit do
|
||||||
|
adj_x = math.floor(prng:rand_normal_dist(-search_radius, search_radius, 2) + 0.5)
|
||||||
|
adj_z = math.floor(prng:rand_normal_dist(-search_radius, search_radius, 2) + 0.5)
|
||||||
|
minetest.chat_send_all(attempt .. ": x " .. target_x + adj_x .. ", z " .. target_z + adj_z)
|
||||||
|
if minetest.get_spawn_level(target_x + adj_x, target_z + adj_z) ~= nil then
|
||||||
|
-- found a location which will be at ground level (unless a player has built there)
|
||||||
|
minetest.chat_send_all("x " .. target_x + adj_x .. ", z " .. target_z + adj_z .. " is suitable. Within " .. search_radius .. " of " .. target_x .. ", " .. target_z)
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local destination_pos = {x = target_x + adj_x, y = 0, z = target_z + adj_z}
|
||||||
|
destination_pos.y = nether.find_surface_target_y(destination_pos.x, destination_pos.z, "surface_portal")
|
||||||
|
|
||||||
|
return destination_pos
|
||||||
end
|
end
|
||||||
|
|
||||||
local destination_pos = {x = target_x + adj_x, y = 0, z = target_z + adj_z}
|
|
||||||
destination_pos.y = nether.find_surface_target_y(destination_pos.x, destination_pos.z, "surface_portal")
|
|
||||||
|
|
||||||
return destination_pos
|
|
||||||
end
|
end
|
||||||
end
|
})
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--=========================================--
|
--=========================================--
|
||||||
-- Hilbert curve and Moore curve functions --
|
-- Hilbert curve and Moore curve functions --
|
||||||
@ -211,9 +230,9 @@ These travel a distance along the ground, and even when constructed deep undergr
|
|||||||
-- to place portals. https://en.wikipedia.org/wiki/Moore_curve
|
-- to place portals. https://en.wikipedia.org/wiki/Moore_curve
|
||||||
|
|
||||||
|
|
||||||
-- Flip a quadrant on its diagonal axis
|
-- Flip a quadrant on a diagonal axis
|
||||||
-- cell_count is the number of cells across the square is split into, and must be a power of 2
|
-- cell_count is the number of cells across the square is split into, and must be a power of 2
|
||||||
-- if flip_twice is true then pos does not change (any even numbers of flips would cancel out)
|
-- if flip_twice is true then pos does not change (even numbers of flips cancel out)
|
||||||
-- if flip_direction is true then the position is flipped along the \ diagonal
|
-- if flip_direction is true then the position is flipped along the \ diagonal
|
||||||
-- if flip_direction is false then the position is flipped along the / diagonal
|
-- if flip_direction is false then the position is flipped along the / diagonal
|
||||||
local function hilbert_flip(cell_count, pos, flip_direction, flip_twice)
|
local function hilbert_flip(cell_count, pos, flip_direction, flip_twice)
|
||||||
@ -281,7 +300,7 @@ local function get_hilbert_coords(cell_count, distance)
|
|||||||
|
|
||||||
s = s * 2
|
s = s * 2
|
||||||
end
|
end
|
||||||
return pos
|
return pos
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
19
settingtypes.txt
Normal file
19
settingtypes.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Travelling a short distance in the Nether can correspond to a much further distance on the surface.
|
||||||
|
#
|
||||||
|
# A factor of 10 might be a better value for Minetest, since there's no sprint, but ex-Minecraft players will be mathing for 8.
|
||||||
|
nether_fasttravel_factor (Nether fast-travel factor) int 8
|
||||||
|
|
||||||
|
# The likelyhood of finding a Book containing all the portal plans in a dungeon chest.
|
||||||
|
# Set to 0 to disable, or 10 to have it extremely common.
|
||||||
|
#
|
||||||
|
# (This value is automatically halved when the Nether portal is the only type of portal, since few players will need instruction)
|
||||||
|
nether_portalBook_loot_weighting (Likelyhood of finding Book of Portals in dungeon chests) int 9
|
||||||
|
|
||||||
|
# Turn off to disable the Nether and Nether portal
|
||||||
|
nether_realm_enabled (Enable Nether realm & portal) bool true
|
||||||
|
|
||||||
|
# Enables the Floatlands portal api code example
|
||||||
|
nether_enable_portal_example_floatlands (Enable example portal: Floatlands) bool false
|
||||||
|
|
||||||
|
# Enables the Surface travel portal api code example
|
||||||
|
nether_enable_portal_example_surfacetravel (Enable example portal: Surface travel) bool false
|
Loading…
Reference in New Issue
Block a user