diff --git a/init.lua b/init.lua index 5a05c7f..13fcaa6 100644 --- a/init.lua +++ b/init.lua @@ -76,6 +76,19 @@ if nether.DEPTH_FLOOR + 1000 > nether.DEPTH_CEILING then end nether.DEPTH = nether.DEPTH_CEILING -- Deprecated, use nether.DEPTH_CEILING instead. +-- DEPTH_FLOOR_LAYERS gives the bottom Y of all locations that wish to be +-- considered part of the Nether. +-- DEPTH_FLOOR_LAYERS Allows mods to insert extra layers below the +-- Nether, by knowing where their layer ceiling should start, and letting +-- the layers be included in effects which only happen in the Nether. +-- If a mod wishes to add a layer below the Nether it should read +-- nether.DEPTH_FLOOR_LAYERS to find the bottom Y of the Nether and any +-- other layers already under the Nether. The mod should leave a small gap +-- between DEPTH_FLOOR_LAYERS and its ceiling (e.g. use DEPTH_FLOOR_LAYERS - 6 +-- for its ceiling Y, so there is room to shift edge-case biomes), then set +-- nether.DEPTH_FLOOR_LAYERS to reflect the mod's floor Y value, and call +-- shift_existing_biomes() with DEPTH_FLOOR_LAYERS as the floor_y argument. +nether.DEPTH_FLOOR_LAYERS = nether.DEPTH_FLOOR -- A debug-print function that understands vectors etc. and does not -- evaluate when debugging is turned off. @@ -163,7 +176,7 @@ The expedition parties have found no diamonds or gold, and after an experienced 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_CEILING - 1000 -- temp value so find_nearest_working_portal() returns nether portals + destination_pos.y = nether.DEPTH_CEILING - 1 -- 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 = @@ -188,7 +201,7 @@ The expedition parties have found no diamonds or gold, and after an experienced 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.DEPTH_CEILING + 1 -- 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 = @@ -253,12 +266,12 @@ The expedition parties have found no diamonds or gold, and after an experienced if pos.y <= nether.DEPTH_CEILING and pos.y >= nether.DEPTH_FLOOR then result = "nether" - -- since mapgen_nobiomes.lua has no regions it doesn't implement getRegion(), - -- so only use getRegion() if it exists - if nether.mapgen.getRegion ~= nil then + -- since mapgen_nobiomes.lua has no regions it doesn't implement get_region(), + -- so only use get_region() if it exists + if nether.mapgen.get_region ~= nil then -- the biomes-based mapgen supports 2 extra regions local regions = nether.mapgen.RegionEnum - local region = nether.mapgen.getRegion(pos) + local region = nether.mapgen.get_region(pos) if region == regions.CENTER or region == regions.CENTERSHELL then result = "mantle" elseif region == regions.NEGATIVE or region == regions.NEGATIVESHELL then diff --git a/mapgen.lua b/mapgen.lua index b8b1ed0..df82e58 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -81,7 +81,8 @@ local math_max, math_min, math_abs, math_floor = math.max, math.min, math.abs, m -- Inject nether_caverns biome -local function override_underground_biomes() +-- Move any existing biomes out of the y-range specified by 'floor_y' and 'ceiling_y' +mapgen.shift_existing_biomes = function(floor_y, ceiling_y) -- https://forum.minetest.net/viewtopic.php?p=257522#p257522 -- Q: Is there a way to override an already-registered biome so I can get it out of the -- way of my own underground biomes without disturbing the other biomes registered by @@ -124,21 +125,21 @@ local function override_underground_biomes() if type(new_biome_def.y_min) == 'number' then biome_y_min = new_biome_def.y_min end if type(new_biome_def.y_max) == 'number' then biome_y_max = new_biome_def.y_max end - if biome_y_max > NETHER_FLOOR and biome_y_min < NETHER_CEILING then + if biome_y_max > floor_y and biome_y_min < ceiling_y then -- This biome occupies some or all of the depth of the Nether, shift/crop it. local new_y_min, new_y_max - local spaceOccupiedAbove = biome_y_max - NETHER_CEILING - local spaceOccupiedBelow = NETHER_FLOOR - biome_y_min + local spaceOccupiedAbove = biome_y_max - ceiling_y + local spaceOccupiedBelow = floor_y - biome_y_min if spaceOccupiedAbove >= spaceOccupiedBelow or biome_y_min <= -30000 then -- place the biome above the Nether -- We also shift biomes which extend to the bottom of the map above the Nether, since they -- likely only extend that deep as a catch-all, and probably have a role nearer the surface. - new_y_min = NETHER_CEILING + 1 - new_y_max = math_max(biome_y_max, NETHER_CEILING + 2) + new_y_min = ceiling_y + 1 + new_y_max = math_max(biome_y_max, ceiling_y + 2) else -- shift the biome to below the Nether - new_y_max = NETHER_FLOOR - 1 - new_y_min = math_min(biome_y_min, NETHER_CEILING - 2) + new_y_max = floor_y - 1 + new_y_min = math_min(biome_y_min, floor_y - 2) end debugf("Moving biome \"%s\" from %s..%s to %s..%s", new_biome_def.name, new_biome_def.y_min, new_biome_def.y_max, new_y_min, new_y_max) @@ -162,7 +163,7 @@ local function override_underground_biomes() end -- Shift any overlapping biomes out of the way before we create the Nether biomes -override_underground_biomes() +mapgen.shift_existing_biomes(NETHER_FLOOR, NETHER_CEILING) -- nether:native_mapgen is used to prevent ores and decorations being generated according -- to landforms created by the native mapgen. @@ -259,12 +260,12 @@ mapgen.np_cave = { local cavePointPerlin = nil -mapgen.getCavePointPerlin = function() +mapgen.get_cave_point_perlin = function() cavePointPerlin = cavePointPerlin or minetest.get_perlin(mapgen.np_cave) return cavePointPerlin end -mapgen.getCavePerlinAt = function(pos) +mapgen.get_cave_perlin_at = function(pos) cavePointPerlin = cavePointPerlin or minetest.get_perlin(mapgen.np_cave) return cavePointPerlin:get_3d(pos) end @@ -477,7 +478,7 @@ end -- use knowledge of the nether mapgen algorithm to return a suitable ground level for placing a portal. -- player_name is optional, allowing a player to spawn a remote portal in their own protected areas. function nether.find_nether_ground_y(target_x, target_z, start_y, player_name) - local nobj_cave_point = mapgen.getCavePointPerlin() + local nobj_cave_point = mapgen.get_cave_point_perlin() local air = 0 -- Consecutive air nodes found local minp_schem, maxp_schem = nether.get_schematic_volume({x = target_x, y = 0, z = target_z}, nil, "nether_portal") diff --git a/mapgen_mantle.lua b/mapgen_mantle.lua index 46e6e93..7883fb0 100644 --- a/mapgen_mantle.lua +++ b/mapgen_mantle.lua @@ -119,7 +119,7 @@ mapgen.add_basalt_columns = function(data, area, minp, maxp) local yStride = area.ystride local yCaveStride = x1 - x0 + 1 - local cavePerlin = mapgen.getCavePointPerlin() + local cavePerlin = mapgen.get_cave_point_perlin() nobj_basalt = nobj_basalt or minetest.get_perlin_map(np_basalt, {x = yCaveStride, y = yCaveStride}) local nvals_basalt = nobj_basalt:get_2d_map_flat({x=minp.x, y=minp.z}, {x=yCaveStride, y=yCaveStride}, nbuf_basalt) @@ -431,13 +431,13 @@ mapgen.RegionEnum = { -- Returns (region, noise) where region is a value from mapgen.RegionEnum -- and noise is the unadjusted cave perlin value -mapgen.getRegion = function(pos) +mapgen.get_region = function(pos) if pos.y > nether.DEPTH_CEILING or pos.y < nether.DEPTH_FLOOR then return mapgen.RegionEnum.OVERWORLD, nil end - local caveNoise = mapgen.getCavePerlinAt(pos) + local caveNoise = mapgen.get_cave_perlin_at(pos) local sealevel, cavern_limit_distance = mapgen.find_nearest_lava_sealevel(pos.y) local tcave_adj, centerRegionLimit_adj = mapgen.get_mapgenblend_adjustments(pos.y) local tcave = mapgen.TCAVE + tcave_adj @@ -482,7 +482,7 @@ minetest.register_chatcommand("nether_whereami", if player == nil then return false, S("Unknown player position") end local playerPos = vector.round(player:get_pos()) - local region, caveNoise = mapgen.getRegion(playerPos) + local region, caveNoise = mapgen.get_region(playerPos) local seaLevel, cavernLimitDistance = mapgen.find_nearest_lava_sealevel(playerPos.y) local tcave_adj, centerRegionLimit_adj = mapgen.get_mapgenblend_adjustments(playerPos.y) diff --git a/nether_api.txt b/nether_api.txt new file mode 100644 index 0000000..40f86a5 --- /dev/null +++ b/nether_api.txt @@ -0,0 +1,78 @@ +Modding/interop guide to Nether +=============================== + +For portals API see portal_api.txt + +The Nether mod exposes some of its functions and data via the lua global +`nether` and `nether.mapgen` + + +* `nether.DEPTH_CEILING`: [read-only] Y value of the top of the Nether. + +* `nether.DEPTH_FLOOR`: [read-only] Y value of the bottom of the Nether. + +* `nether.DEPTH_FLOOR_LAYERS`: [writable] Gives the bottom Y of all + locations that wish to be considered part of the Nether. + DEPTH_FLOOR_LAYERS Allows mods to insert extra layers below the + Nether, by knowing where their layer ceiling should start, and letting + the layers be included in effects which only happen in the Nether. + If a mod wishes to add a layer below the Nether it should read + `nether.DEPTH_FLOOR_LAYERS` to find the bottom Y of the Nether and any + other layers already under the Nether. The mod should leave a small gap + between DEPTH_FLOOR_LAYERS and its ceiling (e.g. use DEPTH_FLOOR_LAYERS - 6 + for its ceiling Y, so there is room to shift edge-case biomes), then set + `nether.DEPTH_FLOOR_LAYERS` to reflect the mod's floor Y value, and call + `shift_existing_biomes()` with DEPTH_FLOOR_LAYERS as the `floor_y` argument. + +* `nether.NETHER_REALM_ENABLED`: [read-only] Gets the value of the "Enable + Nether realm & portal" setting the nether mod exposes in Minetest's + "All Settings" -> "Mods" -> "nether" options. + When false, the entire nether mapgen is disabled (not run), and the portal + to it is not registered. Reasons someone might disable the Nether realm + include if a nether-layer mod was to be used as the Nether instead, or if + the portal mechanic was desired in a game without the Nether, etc. + +* `nether.useBiomes`: [read-only] When this is false, the Nether interop + functions below are not available (nil). + Indicates that the biomes-enabled mapgen is in use. The Nether mod falls back + to older mapgen code for v6 maps and old versions of Minetest, the older + mapgen code doesn't use biomes and doesn't provide API/interop functions. + + +Mapgen functions available when nether.useBiomes is true +-------------------------------------------------------- + +The following functions are nil if `nether.useBiomes` is false, +and also nil if `nether.NETHER_REALM_ENABLED` is false. + +* `nether.mapgen.shift_existing_biomes(floor_y, ceiling_y)` Move any existing + biomes out of the y-range specified by `floor_y` and `ceiling_y`. + +* `nether.mapgen.get_region(pos)`: Returns two values, (region, noise) where + `region` is a value from `nether.mapgen.RegionEnum` and `noise` is the + unadjusted cave perlin value. + * `nether.mapgen.RegionEnum` values are tables which contain an invariant + `name` and a localized `desc`. Current region names include overworld, + positive, positive shell, center, center shell, negative, and negative + shell. + "positive" corresponds to conventional Nether caverns, and "center" + corresponds to the Mantle region. + +* `nether.mapgen.get_cave_point_perlin()`: Returns the PerlinNoise object for + the Nether's cavern noise. + +* `nether.mapgen.get_cave_perlin_at(pos)`: Returns the Nether cavern noise + value at a given 3D position. + + +Other mapgen functions +------------------------------------------- + +If the Nether realm is enabled, then this function will be available +regardless of whether `nether.useBiomes` is true: + +* `nether.find_nether_ground_y(target_x, target_z, start_y, player_name)` + Uses knowledge of the nether mapgen algorithm to return a suitable ground + level for placing a portal. + * `player_name` is optional, allowing a player to spawn a remote portal + in their own protected areas. \ No newline at end of file diff --git a/nodes.lua b/nodes.lua index 104b5ff..073f6b0 100644 --- a/nodes.lua +++ b/nodes.lua @@ -337,7 +337,7 @@ nether.cool_lava = function(pos, node) -- Evaporate water sitting above lava, if it's in the Nether. -- (we don't want Nether mod to affect overworld lava mechanics) if minetest.get_item_group(node_above.name, "water") > 0 and - pos.y < nether.DEPTH_CEILING and pos.y > nether.DEPTH_FLOOR then + pos.y < nether.DEPTH_CEILING and pos.y > nether.DEPTH_FLOOR_LAYERS then -- cools_lava might be a better group to check for, but perhaps there's -- something in that group that isn't a liquid and shouldn't be evaporated? minetest.swap_node(pos_above, {name="air"}) @@ -604,7 +604,7 @@ local function fumarole_onTimer(pos, elapsed) -- Fumaroles in the Nether can catch fire. -- (if taken to the surface and used as cottage chimneys, they don't catch fire) - local inNether = pos.y <= nether.DEPTH and pos.y >= nether.DEPTH_FLOOR + local inNether = pos.y <= nether.DEPTH and pos.y >= nether.DEPTH_FLOOR_LAYERS local canCatchFire = inNether and minetest.registered_nodes["fire:permanent_flame"] ~= nil local smoke_offset = 0 local timeout_factor = 1 diff --git a/portal_api.lua b/portal_api.lua index e1c84f8..c67b27d 100644 --- a/portal_api.lua +++ b/portal_api.lua @@ -2073,7 +2073,7 @@ function nether.register_portal(name, portaldef) end portaldef.name = name - portaldef.mod_name = minetest.get_current_modname() + portaldef.mod_name = minetest.get_current_modname() or "" -- use portaldef_default for any values missing from portaldef or portaldef.sounds if portaldef.sounds ~= nil then setmetatable(portaldef.sounds, {__index = portaldef_default.sounds}) end diff --git a/portal_api.txt b/portal_api.txt index ecac500..15c82d8 100644 --- a/portal_api.txt +++ b/portal_api.txt @@ -250,16 +250,16 @@ Used by `nether.register_portal`. -- player_name may be "", e.g. if the portal was ignited by a mesecon, -- and is provided for use with volume_is_natural_and_unprotected() etc. - on_run_wormhole = function(portalDef, anochorPos, orientation), + on_run_wormhole = function(portalDef, anchorPos, orientation), -- invoked once per second per portal - on_extinguish = function(portalDef, anochorPos, orientation), + on_extinguish = function(portalDef, anchorPos, orientation), -- invoked when a portal is extinguished, including when the portal -- it connected to was extinguished. on_player_teleported = function(portalDef, player, oldPos, newPos), -- invoked immediately after a player is teleported - on_ignite = function(portalDef, anochorPos, orientation) + on_ignite = function(portalDef, anchorPos, orientation) -- invoked when a player or mesecon ignites a portal - on_created = function(portalDef, anochorPos, orientation) + on_created = function(portalDef, anchorPos, orientation) -- invoked when a portal creates a remote twin, this is usually when -- a player travels through a portal for the first time. } diff --git a/portal_examples.lua b/portal_examples.lua index ac71848..663ee63 100644 --- a/portal_examples.lua +++ b/portal_examples.lua @@ -106,7 +106,7 @@ end -- Surface-travel portal, playable code example -- --==============================================-- --- These Moore Curve functions requred by surface_portal's find_surface_anchorPos() will +-- These Moore Curve functions required by surface_portal's find_surface_anchorPos() will -- be assigned later in this file. 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