parent
04cb3b10a4
commit
8da48c6f3f
|
@ -154,7 +154,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
* [bright_night][] ([Unlicense][lic.unlicense]) -- version: [69b750a Git][ver.bright_night] *2018-06-03*
|
||||
* [desert_life][] ([CC BY-SA][lic.ccbysa4.0]) -- version: [188f984 Git][ver.desert_life] *2020-01-24*
|
||||
* [ethereal][] ([MIT][lic.ethereal]) -- version: [2021-07-18][ver.ethereal] ([patched][patch.ethereal])
|
||||
* [nether][] ([ISC / CC BY / CC BY-SA / CC0][lic.nether]) -- version: [3][ver.nether] *2021-01-22* ([patched][patch.nether])
|
||||
* [nether][] ([ISC / CC BY / CC BY-SA / CC0][lic.nether]) -- version: [3.1][ver.nether] *2021-07-31* ([patched][patch.nether])
|
||||
* [snowdrift][] ([MIT / CC BY / CC BY-SA][lic.snowdrift]) -- version: [3342939 Git][ver.snowdrift] *2020-04-24* ([patched][patch.snowdrift])
|
||||
|
||||
|
||||
|
@ -396,7 +396,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[myroofs]: https://forum.minetest.net/viewtopic.php?t=11416
|
||||
[mysheetmetal]: https://forum.minetest.net/viewtopic.php?t=11702
|
||||
[mywoodslopes]: https://forum.minetest.net/viewtopic.php?t=11433
|
||||
[nether]: https://forum.minetest.net/viewtopic.php?t=5790
|
||||
[nether]: https://content.minetest.net/packages/PilzAdam/nether/
|
||||
[no_fall_damage]: https://forum.minetest.net/viewtopic.php?t=25876
|
||||
[painting]: https://github.com/minetest-mods/painting
|
||||
[pbmarks]: https://github.com/AntumMT/mod-pbmarks
|
||||
|
@ -662,7 +662,7 @@ The game includes the mods from the default [minetest_game](https://github.com/m
|
|||
[ver.myroofs]: https://github.com/minetest-mods/myroofs/tree/fe98461
|
||||
[ver.mysheetmetal]: https://github.com/minetest-mods/mysheetmetal/tree/7c5ab71
|
||||
[ver.mywoodslopes]: https://github.com/minetest-mods/mywoodslopes/tree/3a1b531
|
||||
[ver.nether]: https://github.com/minetest-mods/nether/tree/v3
|
||||
[ver.nether]: https://github.com/minetest-mods/nether/tree/v3.1
|
||||
[ver.no_fall_damage]: https://repo.or.cz/minetest_no_fall_damage.git/shortlog/refs/tags/1.0.0
|
||||
[ver.painting]: https://github.com/minetest-mods/painting/tree/da8f4ba
|
||||
[ver.pbmarks]: https://github.com/AntumMT/mod-pbmarks/releases/tag/v1.0
|
||||
|
|
|
@ -74,4 +74,7 @@ SOFTWARE.
|
|||
* `nether_rack`* (files starting with "nether_rack"): Zeg9
|
||||
* `nether_tool_`* (files starting with "nether_tool_"): color adjusted versions from "[default](https://github.com/minetest/minetest_game/tree/master/mods/default)" mod, originals by BlockMen
|
||||
|
||||
All other media: Copyright © 2013 PilzAdam, licensed under CC BY-SA 3.0 by PilzAdam.
|
||||
### [Unlicensed but permission for inclusion by kovaszos_uborka](https://www.planetminecraft.com/member/kovaszos_uborka/)
|
||||
* `nether_brick_deep.png` (edited by TenPlus1)
|
||||
|
||||
All other media: Copyright © 2013 PilzAdam, licensed under CC BY-SA 3.0 by PilzAdam.
|
||||
|
|
|
@ -44,6 +44,14 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "nether:brick_deep 4",
|
||||
recipe = {
|
||||
{"nether:rack_deep", "nether:rack_deep"},
|
||||
{"nether:rack_deep", "nether:rack_deep"}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "nether:basalt_hewn",
|
||||
type = "shapeless",
|
||||
|
@ -61,4 +69,4 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
-- See tools.lua for tools related crafting
|
||||
-- See tools.lua for tools related crafting
|
||||
|
|
|
@ -6,3 +6,4 @@ fire?
|
|||
loot?
|
||||
mesecons?
|
||||
moreblocks?
|
||||
climate_api?
|
||||
|
|
|
@ -42,12 +42,18 @@ end
|
|||
|
||||
-- Global Nether namespace
|
||||
nether = {}
|
||||
nether.mapgen = {} -- Shared Nether mapgen namespace, for mapgen files to expose functions and constants
|
||||
nether.modname = minetest.get_current_modname()
|
||||
nether.path = minetest.get_modpath(nether.modname)
|
||||
nether.get_translator = S
|
||||
-- nether.useBiomes allows other mods to know whether they can register ores etc. in the Nether.
|
||||
-- See mapgen.lua for an explanation of why minetest.read_schematic is being checked
|
||||
nether.useBiomes = minetest.get_mapgen_setting("mg_name") ~= "v6" and minetest.read_schematic ~= nil
|
||||
nether.fogColor = { -- only used if climate_api is installed
|
||||
netherCaverns = "#1D0504", -- Distance-fog colour for classic nether
|
||||
mantle = "#070916", -- Distance-fog colour for the Mantle region
|
||||
geodes = "#300530" -- Distance-fog colour for secondary region
|
||||
}
|
||||
|
||||
|
||||
-- Settings
|
||||
|
@ -70,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.
|
||||
|
@ -149,7 +168,7 @@ This opens to a truly hellish place, though for small mercies the air there is s
|
|||
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),
|
||||
|
||||
is_within_realm = function(pos) -- return true if pos is inside the Nether
|
||||
return pos.y < nether.DEPTH_CEILING
|
||||
return pos.y < nether.DEPTH_CEILING and pos.y > nether.DEPTH_FLOOR
|
||||
end,
|
||||
|
||||
find_realm_anchorPos = function(surface_anchorPos, player_name)
|
||||
|
@ -157,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 =
|
||||
|
@ -182,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 =
|
||||
|
@ -227,7 +246,91 @@ The expedition parties have found no diamonds or gold, and after an experienced
|
|||
end
|
||||
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- Set appropriate nether distance-fog if climate_api is available
|
||||
--
|
||||
-- Delegating to a mod like climate_api means nether won't unexpectedly stomp on the sky of
|
||||
-- any other mod.
|
||||
-- Skylayer is another mod which can perform this role, and skylayer support could be added
|
||||
-- here as well. However skylayer doesn't provide a position-based method of specifying sky
|
||||
-- colours out-of-the-box, so the nether mod will have to monitor when players enter and
|
||||
-- leave the nether.
|
||||
if minetest.get_modpath("climate_api") and minetest.global_exists("climate_api") and climate_api.register_weather ~= nil then
|
||||
|
||||
climate_api.register_influence(
|
||||
"nether_biome",
|
||||
function(pos)
|
||||
local result = "surface"
|
||||
|
||||
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 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.get_region(pos)
|
||||
if region == regions.CENTER or region == regions.CENTERSHELL then
|
||||
result = "mantle"
|
||||
elseif region == regions.NEGATIVE or region == regions.NEGATIVESHELL then
|
||||
result = "geode"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
)
|
||||
|
||||
-- using sky type "plain" unfortunately means we don't get smooth fading transitions when
|
||||
-- the color of the sky changes, but it seems to be the only way to obtain a sky colour
|
||||
-- which doesn't brighten during the daytime.
|
||||
local undergroundSky = {
|
||||
sky_data = {
|
||||
base_color = nil,
|
||||
type = "plain",
|
||||
textures = nil,
|
||||
clouds = false,
|
||||
},
|
||||
sun_data = {
|
||||
visible = false,
|
||||
sunrise_visible = false
|
||||
},
|
||||
moon_data = {
|
||||
visible = false
|
||||
},
|
||||
star_data = {
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
|
||||
local netherSky, mantleSky, geodeSky = table.copy(undergroundSky), table.copy(undergroundSky), table.copy(undergroundSky)
|
||||
netherSky.sky_data.base_color = nether.fogColor.netherCaverns
|
||||
mantleSky.sky_data.base_color = nether.fogColor.mantle
|
||||
geodeSky.sky_data.base_color = nether.fogColor.geodes
|
||||
|
||||
climate_api.register_weather(
|
||||
"nether:nether",
|
||||
{ nether_biome = "nether" },
|
||||
{ ["climate_api:skybox"] = netherSky }
|
||||
)
|
||||
|
||||
climate_api.register_weather(
|
||||
"nether:mantle",
|
||||
{ nether_biome = "mantle" },
|
||||
{ ["climate_api:skybox"] = mantleSky }
|
||||
)
|
||||
|
||||
climate_api.register_weather(
|
||||
"nether:geode",
|
||||
{ nether_biome = "geode" },
|
||||
{ ["climate_api:skybox"] = geodeSky }
|
||||
)
|
||||
end
|
||||
|
||||
end -- end of "if nether.NETHER_REALM_ENABLED..."
|
||||
|
||||
|
||||
-- Play bubbling lava sounds if player killed by lava
|
||||
|
|
|
@ -13,9 +13,25 @@ Construction requires 14 blocks of obsidian, which we found deep underground whe
|
|||
|
||||
Nether Portal=Portail du Nether
|
||||
|
||||
### mapgen_mantle.lua ###
|
||||
|
||||
, @1m above lava-sea level=
|
||||
, @1m below lava-sea level=
|
||||
, approaching y boundary of Nether=
|
||||
@1@2@3@4=
|
||||
Center/Mantle, but outside the caverns=
|
||||
Center/Mantle, inside cavern=
|
||||
Describes which region of the nether the player is in=
|
||||
Negative nether=
|
||||
Positive nether=
|
||||
Shell between negative nether and center region=
|
||||
Shell between positive nether and center region=
|
||||
The Overworld=
|
||||
Unknown player position=
|
||||
[Perlin @1] =
|
||||
|
||||
### nodes.lua ###
|
||||
|
||||
=
|
||||
A finely finished block of solid Nether Basalt.=
|
||||
A rough cut solid block of Nether Basalt.=
|
||||
A thin crust of cooled lava with liquid lava beneath=
|
||||
|
|
|
@ -12,9 +12,25 @@ Construction requires 14 blocks of obsidian, which we found deep underground whe
|
|||
|
||||
Nether Portal=
|
||||
|
||||
### mapgen_mantle.lua ###
|
||||
|
||||
, @1m above lava-sea level=
|
||||
, @1m below lava-sea level=
|
||||
, approaching y boundary of Nether=
|
||||
@1@2@3@4=
|
||||
Center/Mantle, but outside the caverns=
|
||||
Center/Mantle, inside cavern=
|
||||
Describes which region of the nether the player is in=
|
||||
Negative nether=
|
||||
Positive nether=
|
||||
Shell between negative nether and center region=
|
||||
Shell between positive nether and center region=
|
||||
The Overworld=
|
||||
Unknown player position=
|
||||
[Perlin @1] =
|
||||
|
||||
### nodes.lua ###
|
||||
|
||||
=
|
||||
A finely finished block of solid Nether Basalt.=
|
||||
A rough cut solid block of Nether Basalt.=
|
||||
A thin crust of cooled lava with liquid lava beneath=
|
||||
|
|
|
@ -45,7 +45,6 @@ local BASALT_COLUMN_LOWER_LIMIT = CENTER_CAVERN_LIMIT * 0.25 -- This value
|
|||
|
||||
-- Shared Nether mapgen namespace
|
||||
-- For mapgen files to share functions and constants
|
||||
nether.mapgen = {}
|
||||
local mapgen = nether.mapgen
|
||||
|
||||
mapgen.TCAVE = TCAVE -- const needed in mapgen_mantle.lua
|
||||
|
@ -69,7 +68,8 @@ if minetest.read_schematic == nil then
|
|||
error("This " .. nether.modname .. " mapgen requires Minetest v5.1 or greater, use mapgen_nobiomes.lua instead.", 0)
|
||||
end
|
||||
|
||||
-- Load helper functions for generating the mantle / center region
|
||||
-- Load specialty helper functions
|
||||
dofile(nether.path .. "/mapgen_dungeons.lua")
|
||||
dofile(nether.path .. "/mapgen_mantle.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
|
||||
|
@ -108,7 +109,7 @@ local function override_underground_biomes()
|
|||
end
|
||||
for old_ore_key, old_ore_def in pairs(minetest.registered_ores) do
|
||||
registered_ores_copy[old_ore_key] = old_ore_def
|
||||
end
|
||||
end
|
||||
|
||||
-- clear biomes, decorations, and ores
|
||||
minetest.clear_registered_decorations()
|
||||
|
@ -117,23 +118,36 @@ local function override_underground_biomes()
|
|||
|
||||
-- Restore biomes, adjusted to not overlap the Nether
|
||||
for biome_key, new_biome_def in pairs(registered_biomes_copy) do
|
||||
local biome_y_max, biome_y_min = tonumber(new_biome_def.y_max), tonumber(new_biome_def.y_min)
|
||||
-- follow similar min_pos/max_pos processing logic as read_biome_def() in l_mapgen.cpp
|
||||
local biome_y_max, biome_y_min = 31000, -31000
|
||||
if type(new_biome_def.min_pos) == 'table' and type(new_biome_def.min_pos.y) == 'number' then biome_y_min = new_biome_def.min_pos.y end
|
||||
if type(new_biome_def.max_pos) == 'table' and type(new_biome_def.max_pos.y) == 'number' then biome_y_max = new_biome_def.max_pos.y end
|
||||
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 spaceOccupiedAbove = biome_y_max - NETHER_CEILING
|
||||
local spaceOccupiedBelow = NETHER_FLOOR - biome_y_min
|
||||
local new_y_min, new_y_max
|
||||
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_biome_def.y_min = NETHER_CEILING + 1
|
||||
new_biome_def.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_biome_def.y_max = NETHER_FLOOR - 1
|
||||
new_biome_def.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)
|
||||
|
||||
if type(new_biome_def.min_pos) == 'table' and type(new_biome_def.min_pos.y) == 'number' then new_biome_def.min_pos.y = new_y_min end
|
||||
if type(new_biome_def.max_pos) == 'table' and type(new_biome_def.max_pos.y) == 'number' then new_biome_def.max_pos.y = new_y_max end
|
||||
new_biome_def.y_min = new_y_min -- Ensure the new heights are saved, even if original biome never specified one
|
||||
new_biome_def.y_max = new_y_max
|
||||
end
|
||||
minetest.register_biome(new_biome_def)
|
||||
end
|
||||
|
@ -149,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.
|
||||
|
@ -244,6 +258,19 @@ mapgen.np_cave = {
|
|||
--flags = ""
|
||||
}
|
||||
|
||||
local cavePointPerlin = nil
|
||||
|
||||
mapgen.get_cave_point_perlin = function()
|
||||
cavePointPerlin = cavePointPerlin or minetest.get_perlin(mapgen.np_cave)
|
||||
return cavePointPerlin
|
||||
end
|
||||
|
||||
mapgen.get_cave_perlin_at = function(pos)
|
||||
cavePointPerlin = cavePointPerlin or minetest.get_perlin(mapgen.np_cave)
|
||||
return cavePointPerlin:get_3d(pos)
|
||||
end
|
||||
|
||||
|
||||
-- Buffers and objects we shouldn't recreate every on_generate
|
||||
|
||||
local nobj_cave = nil
|
||||
|
@ -256,206 +283,11 @@ local dbuf = {}
|
|||
local c_air = minetest.get_content_id("air")
|
||||
local c_netherrack = minetest.get_content_id("nether:rack")
|
||||
local c_netherrack_deep = minetest.get_content_id("nether:rack_deep")
|
||||
local c_dungeonbrick = minetest.get_content_id("nether:brick")
|
||||
local c_dungeonbrick_alt = minetest.get_content_id("nether:brick_cracked")
|
||||
local c_netherbrick_slab = minetest.get_content_id("stairs:slab_nether_brick")
|
||||
local c_netherfence = minetest.get_content_id("nether:fence_nether_brick")
|
||||
local c_glowstone = minetest.get_content_id("nether:glowstone")
|
||||
local c_lava_source = minetest.get_content_id("default:lava_source")
|
||||
local c_lavasea_source = minetest.get_content_id("nether:lava_source") -- same as lava but with staggered animation to look better as an ocean
|
||||
local c_lava_crust = minetest.get_content_id("nether:lava_crust")
|
||||
local c_native_mapgen = minetest.get_content_id("nether:native_mapgen")
|
||||
|
||||
|
||||
-- Dungeon excavation functions
|
||||
|
||||
function is_dungeon_brick(node_id)
|
||||
return node_id == c_dungeonbrick or node_id == c_dungeonbrick_alt
|
||||
end
|
||||
|
||||
function build_dungeon_room_list(data, area)
|
||||
|
||||
local result = {}
|
||||
|
||||
-- Unfortunately gennotify only returns dungeon rooms, not corridors.
|
||||
-- We don't need to check for temples because only dungeons are generated in biomes
|
||||
-- that define their own dungeon nodes.
|
||||
local gennotify = minetest.get_mapgen_object("gennotify")
|
||||
local roomLocations = gennotify["dungeon"] or {}
|
||||
|
||||
-- Excavation should still know to stop if a cave or corridor has removed the dungeon wall.
|
||||
-- See MapgenBasic::generateDungeons in mapgen.cpp for max room sizes.
|
||||
local maxRoomSize = 18
|
||||
local maxRoomRadius = math.ceil(maxRoomSize / 2)
|
||||
|
||||
local xStride, yStride, zStride = 1, area.ystride, area.zstride
|
||||
local minEdge, maxEdge = area.MinEdge, area.MaxEdge
|
||||
|
||||
for _, roomPos in ipairs(roomLocations) do
|
||||
|
||||
if area:containsp(roomPos) then -- this safety check does not appear to be necessary, but lets make it explicit
|
||||
|
||||
local room_vi = area:indexp(roomPos)
|
||||
--data[room_vi] = minetest.get_content_id("default:torch") -- debug
|
||||
|
||||
local startPos = vector.new(roomPos)
|
||||
if roomPos.y + 1 <= maxEdge.y and data[room_vi + yStride] == c_air then
|
||||
-- The roomPos coords given by gennotify are at floor level, but whenever possible we
|
||||
-- want to be performing searches a node higher than floor level to avoids dungeon chests.
|
||||
startPos.y = startPos.y + 1
|
||||
room_vi = area:indexp(startPos)
|
||||
end
|
||||
|
||||
local bound_min_x = math_max(minEdge.x, roomPos.x - maxRoomRadius)
|
||||
local bound_min_y = math_max(minEdge.y, roomPos.y - 1) -- room coords given by gennotify are on the floor
|
||||
local bound_min_z = math_max(minEdge.z, roomPos.z - maxRoomRadius)
|
||||
|
||||
local bound_max_x = math_min(maxEdge.x, roomPos.x + maxRoomRadius)
|
||||
local bound_max_y = math_min(maxEdge.y, roomPos.y + maxRoomSize) -- room coords given by gennotify are on the floor
|
||||
local bound_max_z = math_min(maxEdge.z, roomPos.z + maxRoomRadius)
|
||||
|
||||
local room_min = vector.new(startPos)
|
||||
local room_max = vector.new(startPos)
|
||||
|
||||
local vi = room_vi
|
||||
while room_max.y < bound_max_y and data[vi + yStride] == c_air do
|
||||
room_max.y = room_max.y + 1
|
||||
vi = vi + yStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_min.y > bound_min_y and data[vi - yStride] == c_air do
|
||||
room_min.y = room_min.y - 1
|
||||
vi = vi - yStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_max.z < bound_max_z and data[vi + zStride] == c_air do
|
||||
room_max.z = room_max.z + 1
|
||||
vi = vi + zStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_min.z > bound_min_z and data[vi - zStride] == c_air do
|
||||
room_min.z = room_min.z - 1
|
||||
vi = vi - zStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_max.x < bound_max_x and data[vi + xStride] == c_air do
|
||||
room_max.x = room_max.x + 1
|
||||
vi = vi + xStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_min.x > bound_min_x and data[vi - xStride] == c_air do
|
||||
room_min.x = room_min.x - 1
|
||||
vi = vi - xStride
|
||||
end
|
||||
|
||||
local roomInfo = vector.new(roomPos)
|
||||
roomInfo.minp = room_min
|
||||
roomInfo.maxp = room_max
|
||||
result[#result + 1] = roomInfo
|
||||
end
|
||||
end
|
||||
|
||||
return result;
|
||||
end
|
||||
|
||||
-- Only partially excavates dungeons, the rest is left as an exercise for the player ;)
|
||||
-- (Corridors and the parts of rooms which extend beyond the emerge boundary will remain filled)
|
||||
function excavate_dungeons(data, area, rooms)
|
||||
|
||||
local vi, node_id
|
||||
|
||||
-- any air from the native mapgen has been replaced by netherrack, but
|
||||
-- we don't want this inside dungeons, so fill dungeon rooms with air
|
||||
for _, roomInfo in ipairs(rooms) do
|
||||
|
||||
local room_min = roomInfo.minp
|
||||
local room_max = roomInfo.maxp
|
||||
|
||||
for z = room_min.z, room_max.z do
|
||||
for y = room_min.y, room_max.y do
|
||||
vi = area:index(room_min.x, y, z)
|
||||
for x = room_min.x, room_max.x do
|
||||
node_id = data[vi]
|
||||
if node_id == c_netherrack or node_id == c_netherrack_deep then data[vi] = c_air end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Since we already know where all the rooms and their walls are, and have all the nodes stored
|
||||
-- in a voxelmanip already, we may as well add a little Nether flair to the dungeons found here.
|
||||
function decorate_dungeons(data, area, rooms)
|
||||
|
||||
local xStride, yStride, zStride = 1, area.ystride, area.zstride
|
||||
local minEdge, maxEdge = area.MinEdge, area.MaxEdge
|
||||
|
||||
for _, roomInfo in ipairs(rooms) do
|
||||
|
||||
local room_min, room_max = roomInfo.minp, roomInfo.maxp
|
||||
local room_size = vector.distance(room_min, room_max)
|
||||
|
||||
if room_size > 10 then
|
||||
local room_seed = roomInfo.x + 3 * roomInfo.z + 13 * roomInfo.y
|
||||
local window_y = roomInfo.y + math_min(2, room_max.y - roomInfo.y - 1)
|
||||
|
||||
if room_seed % 3 == 0 and room_max.y < maxEdge.y then
|
||||
-- Glowstone chandelier (feel free to replace with a fancy schematic)
|
||||
local vi = area:index(roomInfo.x, room_max.y + 1, roomInfo.z)
|
||||
if is_dungeon_brick(data[vi]) then data[vi] = c_glowstone end
|
||||
|
||||
elseif room_seed % 4 == 0 and room_min.y > minEdge.y
|
||||
and room_min.x > minEdge.x and room_max.x < maxEdge.x
|
||||
and room_min.z > minEdge.z and room_max.z < maxEdge.z then
|
||||
-- lava well (feel free to replace with a fancy schematic)
|
||||
local vi = area:index(roomInfo.x, room_min.y, roomInfo.z)
|
||||
if is_dungeon_brick(data[vi - yStride]) then
|
||||
data[vi - yStride] = c_lava_source
|
||||
if data[vi - zStride] == c_air then data[vi - zStride] = c_netherbrick_slab end
|
||||
if data[vi + zStride] == c_air then data[vi + zStride] = c_netherbrick_slab end
|
||||
if data[vi - xStride] == c_air then data[vi - xStride] = c_netherbrick_slab end
|
||||
if data[vi + xStride] == c_air then data[vi + xStride] = c_netherbrick_slab end
|
||||
end
|
||||
end
|
||||
|
||||
-- Barred windows
|
||||
if room_seed % 7 < 5 and room_max.x - room_min.x >= 4 and room_max.z - room_min.z >= 4
|
||||
and window_y >= minEdge.y and window_y + 1 <= maxEdge.y
|
||||
and room_min.x > minEdge.x and room_max.x < maxEdge.x
|
||||
and room_min.z > minEdge.z and room_max.z < maxEdge.z then
|
||||
--data[area:indexp(roomInfo)] = minetest.get_content_id("default:mese_post_light") -- debug
|
||||
|
||||
-- Until whisper glass is added, every window will be made of netherbrick fence (rather
|
||||
-- than material depending on room_seed)
|
||||
local window_node = c_netherfence
|
||||
|
||||
local vi_min = area:index(room_min.x - 1, window_y, roomInfo.z)
|
||||
local vi_max = area:index(room_max.x + 1, window_y, roomInfo.z)
|
||||
local locations = {-zStride, zStride, -zStride + yStride, zStride + yStride}
|
||||
for _, offset in ipairs(locations) do
|
||||
if is_dungeon_brick(data[vi_min + offset]) then data[vi_min + offset] = window_node end
|
||||
if is_dungeon_brick(data[vi_max + offset]) then data[vi_max + offset] = window_node end
|
||||
end
|
||||
vi_min = area:index(roomInfo.x, window_y, room_min.z - 1)
|
||||
vi_max = area:index(roomInfo.x, window_y, room_max.z + 1)
|
||||
locations = {-xStride, xStride, -xStride + yStride, xStride + yStride}
|
||||
for _, offset in ipairs(locations) do
|
||||
if is_dungeon_brick(data[vi_min + offset]) then data[vi_min + offset] = window_node end
|
||||
if is_dungeon_brick(data[vi_max + offset]) then data[vi_max + offset] = window_node end
|
||||
end
|
||||
end
|
||||
|
||||
-- Weeds on the floor once Nether weeds are added
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local yblmin = NETHER_FLOOR + BLEND * 2
|
||||
local yblmax = NETHER_CEILING - BLEND * 2
|
||||
|
@ -514,27 +346,29 @@ local function on_generated(minp, maxp, seed)
|
|||
nobj_cave = nobj_cave or minetest.get_perlin_map(mapgen.np_cave, chulens)
|
||||
local nvals_cave = nobj_cave:get_3d_map_flat(minp, nbuf_cave)
|
||||
|
||||
local dungeonRooms = build_dungeon_room_list(data, area)
|
||||
local dungeonRooms = mapgen.build_dungeon_room_list(data, area) -- function from mapgen_dungeons.lua
|
||||
local abs_cave_noise, abs_cave_noise_adjusted
|
||||
|
||||
local contains_nether = false
|
||||
local contains_shell = false
|
||||
local contains_mantle = false
|
||||
local contains_ocean = false
|
||||
local contains_ocean = false
|
||||
|
||||
|
||||
for y = y0, y1 do -- Y loop first to minimise tcave & lava-sea calculations
|
||||
|
||||
local sea_level, cavern_limit_distance = mapgen.find_nearest_lava_sealevel(y) -- function provided by mapgen_mantle.lua
|
||||
local sea_level, cavern_limit_distance = mapgen.find_nearest_lava_sealevel(y) -- function from mapgen_mantle.lua
|
||||
local above_lavasea = y > sea_level
|
||||
local below_lavasea = y < sea_level
|
||||
|
||||
local tcave_adj, centerRegionLimit_adj = mapgen.get_mapgenblend_adjustments(y)
|
||||
local tcave = TCAVE + tcave_adj
|
||||
local tmantle = CENTER_REGION_LIMIT + centerRegionLimit_adj -- cavern_noise_adj already contains central_region_limit_adj, so tmantle is only for comparisons when cavern_noise_adj hasn't been added to the noise value
|
||||
|
||||
-- cavern_noise_adj gets added to noise value instead of added to the limit np_noise
|
||||
-- is compared against, so subtract centerRegionLimit_adj instead of adding
|
||||
local cavern_noise_adj =
|
||||
CENTER_REGION_LIMIT * (cavern_limit_distance * cavern_limit_distance * cavern_limit_distance) -
|
||||
centerRegionLimit_adj -- cavern_noise_adj gets added to noise value instead of added to the limit np_noise is compared against, so subtract centerRegionLimit_adj instead of adding
|
||||
centerRegionLimit_adj
|
||||
|
||||
for z = z0, z1 do
|
||||
local vi = area:index(x0, y, z) -- Initial voxelmanip index
|
||||
|
@ -581,7 +415,6 @@ local function on_generated(minp, maxp, seed)
|
|||
else
|
||||
-- the shell seperating the mantle from the rest of the nether...
|
||||
data[vi] = c_netherrack -- excavate_dungeons() will mostly reverse this inside dungeons
|
||||
contains_shell = true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -605,12 +438,12 @@ local function on_generated(minp, maxp, seed)
|
|||
end
|
||||
|
||||
if contains_mantle or contains_ocean then
|
||||
mapgen.add_basalt_columns(data, area, minp, maxp) -- function provided by mapgen_mantle.lua
|
||||
mapgen.add_basalt_columns(data, area, minp, maxp) -- function from mapgen_mantle.lua
|
||||
end
|
||||
|
||||
if contains_nether and contains_mantle then
|
||||
tunnelCandidate_count = tunnelCandidate_count + 1
|
||||
local success = mapgen.excavate_tunnel_to_center_of_the_nether(data, area, nvals_cave, minp, maxp) -- function provided by mapgen_mantle.lua
|
||||
local success = mapgen.excavate_tunnel_to_center_of_the_nether(data, area, nvals_cave, minp, maxp) -- function from mapgen_mantle.lua
|
||||
if success then tunnel_count = tunnel_count + 1 end
|
||||
end
|
||||
total_chunk_count = total_chunk_count + 1
|
||||
|
@ -627,8 +460,8 @@ local function on_generated(minp, maxp, seed)
|
|||
|
||||
-- any air from the native mapgen has been replaced by netherrack, but we
|
||||
-- don't want netherrack inside dungeons, so fill known dungeon rooms with air.
|
||||
excavate_dungeons(data, area, dungeonRooms)
|
||||
decorate_dungeons(data, area, dungeonRooms)
|
||||
mapgen.excavate_dungeons(data, area, dungeonRooms) -- function from mapgen_dungeons.lua
|
||||
mapgen.decorate_dungeons(data, area, dungeonRooms) -- function from mapgen_dungeons.lua
|
||||
|
||||
vm:set_data(data)
|
||||
|
||||
|
@ -645,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 = minetest.get_perlin(mapgen.np_cave)
|
||||
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")
|
||||
|
@ -653,7 +486,7 @@ function nether.find_nether_ground_y(target_x, target_z, start_y, player_name)
|
|||
local maxp = {x = maxp_schem.x, y = 0, z = maxp_schem.z}
|
||||
|
||||
for y = start_y, math_max(NETHER_FLOOR + BLEND, start_y - 4096), -1 do
|
||||
local nval_cave = nobj_cave_point:get3d({x = target_x, y = y, z = target_z})
|
||||
local nval_cave = nobj_cave_point:get_3d({x = target_x, y = y, z = target_z})
|
||||
|
||||
if nval_cave > TCAVE then -- Cavern
|
||||
air = air + 1
|
||||
|
@ -677,8 +510,4 @@ function nether.find_nether_ground_y(target_x, target_z, start_y, player_name)
|
|||
return math_max(start_y, NETHER_FLOOR + BLEND) -- Fallback
|
||||
end
|
||||
|
||||
-- We don't need to be gen-notified of temples because only dungeons will be generated
|
||||
-- if a biome defines the dungeon nodes
|
||||
minetest.set_gen_notify({dungeon = true})
|
||||
|
||||
minetest.register_on_generated(on_generated)
|
||||
minetest.register_on_generated(on_generated)
|
||||
|
|
|
@ -0,0 +1,333 @@
|
|||
--[[
|
||||
|
||||
Nether mod for minetest
|
||||
|
||||
All the Dungeon related functions used by the biomes-based mapgen are here.
|
||||
|
||||
|
||||
Copyright (C) 2021 Treer
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for
|
||||
any purpose with or without fee is hereby granted, provided that the
|
||||
above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
-- We don't need to be gen-notified of temples because only dungeons will be generated
|
||||
-- if a biome defines the dungeon nodes
|
||||
minetest.set_gen_notify({dungeon = true})
|
||||
|
||||
|
||||
-- Content ids
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_netherrack = minetest.get_content_id("nether:rack")
|
||||
local c_netherrack_deep = minetest.get_content_id("nether:rack_deep")
|
||||
local c_dungeonbrick = minetest.get_content_id("nether:brick")
|
||||
local c_dungeonbrick_alt = minetest.get_content_id("nether:brick_cracked")
|
||||
local c_netherbrick_slab = minetest.get_content_id("stairs:slab_nether_brick")
|
||||
local c_netherfence = minetest.get_content_id("nether:fence_nether_brick")
|
||||
local c_glowstone = minetest.get_content_id("nether:glowstone")
|
||||
local c_glowstone_deep = minetest.get_content_id("nether:glowstone_deep")
|
||||
local c_lava_source = minetest.get_content_id("default:lava_source")
|
||||
|
||||
|
||||
-- Misc math functions
|
||||
|
||||
-- avoid needing table lookups each time a common math function is invoked
|
||||
local math_max, math_min = math.max, math.min
|
||||
|
||||
|
||||
-- Dungeon excavation functions
|
||||
|
||||
function is_dungeon_brick(node_id)
|
||||
return node_id == c_dungeonbrick or node_id == c_dungeonbrick_alt
|
||||
end
|
||||
|
||||
|
||||
|
||||
nether.mapgen.build_dungeon_room_list = function(data, area)
|
||||
|
||||
local result = {}
|
||||
|
||||
-- Unfortunately gennotify only returns dungeon rooms, not corridors.
|
||||
-- We don't need to check for temples because only dungeons are generated in biomes
|
||||
-- that define their own dungeon nodes.
|
||||
local gennotify = minetest.get_mapgen_object("gennotify")
|
||||
local roomLocations = gennotify["dungeon"] or {}
|
||||
|
||||
-- Excavation should still know to stop if a cave or corridor has removed the dungeon wall.
|
||||
-- See MapgenBasic::generateDungeons in mapgen.cpp for max room sizes.
|
||||
local maxRoomSize = 18
|
||||
local maxRoomRadius = math.ceil(maxRoomSize / 2)
|
||||
|
||||
local xStride, yStride, zStride = 1, area.ystride, area.zstride
|
||||
local minEdge, maxEdge = area.MinEdge, area.MaxEdge
|
||||
|
||||
for _, roomPos in ipairs(roomLocations) do
|
||||
|
||||
if area:containsp(roomPos) then -- this safety check does not appear to be necessary, but lets make it explicit
|
||||
|
||||
local room_vi = area:indexp(roomPos)
|
||||
--data[room_vi] = minetest.get_content_id("default:torch") -- debug
|
||||
|
||||
local startPos = vector.new(roomPos)
|
||||
if roomPos.y + 1 <= maxEdge.y and data[room_vi + yStride] == c_air then
|
||||
-- The roomPos coords given by gennotify are at floor level, but whenever possible we
|
||||
-- want to be performing searches a node higher than floor level to avoids dungeon chests.
|
||||
startPos.y = startPos.y + 1
|
||||
room_vi = area:indexp(startPos)
|
||||
end
|
||||
|
||||
local bound_min_x = math_max(minEdge.x, roomPos.x - maxRoomRadius)
|
||||
local bound_min_y = math_max(minEdge.y, roomPos.y - 1) -- room coords given by gennotify are on the floor
|
||||
local bound_min_z = math_max(minEdge.z, roomPos.z - maxRoomRadius)
|
||||
|
||||
local bound_max_x = math_min(maxEdge.x, roomPos.x + maxRoomRadius)
|
||||
local bound_max_y = math_min(maxEdge.y, roomPos.y + maxRoomSize) -- room coords given by gennotify are on the floor
|
||||
local bound_max_z = math_min(maxEdge.z, roomPos.z + maxRoomRadius)
|
||||
|
||||
local room_min = vector.new(startPos)
|
||||
local room_max = vector.new(startPos)
|
||||
|
||||
local vi = room_vi
|
||||
while room_max.y < bound_max_y and data[vi + yStride] == c_air do
|
||||
room_max.y = room_max.y + 1
|
||||
vi = vi + yStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_min.y > bound_min_y and data[vi - yStride] == c_air do
|
||||
room_min.y = room_min.y - 1
|
||||
vi = vi - yStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_max.z < bound_max_z and data[vi + zStride] == c_air do
|
||||
room_max.z = room_max.z + 1
|
||||
vi = vi + zStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_min.z > bound_min_z and data[vi - zStride] == c_air do
|
||||
room_min.z = room_min.z - 1
|
||||
vi = vi - zStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_max.x < bound_max_x and data[vi + xStride] == c_air do
|
||||
room_max.x = room_max.x + 1
|
||||
vi = vi + xStride
|
||||
end
|
||||
|
||||
vi = room_vi
|
||||
while room_min.x > bound_min_x and data[vi - xStride] == c_air do
|
||||
room_min.x = room_min.x - 1
|
||||
vi = vi - xStride
|
||||
end
|
||||
|
||||
local roomInfo = vector.new(roomPos)
|
||||
roomInfo.minp = room_min
|
||||
roomInfo.maxp = room_max
|
||||
result[#result + 1] = roomInfo
|
||||
end
|
||||
end
|
||||
|
||||
return result;
|
||||
end
|
||||
|
||||
-- Only partially excavates dungeons, the rest is left as an exercise for the player ;)
|
||||
-- (Corridors and the parts of rooms which extend beyond the emerge boundary will remain filled)
|
||||
nether.mapgen.excavate_dungeons = function(data, area, rooms)
|
||||
|
||||
local vi, node_id
|
||||
|
||||
-- any air from the native mapgen has been replaced by netherrack, but
|
||||
-- we don't want this inside dungeons, so fill dungeon rooms with air
|
||||
for _, roomInfo in ipairs(rooms) do
|
||||
|
||||
local room_min = roomInfo.minp
|
||||
local room_max = roomInfo.maxp
|
||||
|
||||
for z = room_min.z, room_max.z do
|
||||
for y = room_min.y, room_max.y do
|
||||
vi = area:index(room_min.x, y, z)
|
||||
for x = room_min.x, room_max.x do
|
||||
node_id = data[vi]
|
||||
if node_id == c_netherrack or node_id == c_netherrack_deep then data[vi] = c_air end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- clear netherrack from dungeon stairways
|
||||
if #rooms > 0 then
|
||||
local stairPositions = minetest.find_nodes_in_area(area.MinEdge, area.MaxEdge, minetest.registered_biomes["nether_caverns"].node_dungeon_stair)
|
||||
for _, stairPos in ipairs(stairPositions) do
|
||||
vi = area:indexp(stairPos)
|
||||
for i = 1, 4 do
|
||||
if stairPos.y + i > area.MaxEdge.y then break end
|
||||
vi = vi + area.ystride
|
||||
node_id = data[vi]
|
||||
-- searching forward of the stairs could also be done
|
||||
if node_id == c_netherrack or node_id == c_netherrack_deep then data[vi] = c_air end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Since we already know where all the rooms and their walls are, and have all the nodes stored
|
||||
-- in a voxelmanip already, we may as well add a little Nether flair to the dungeons found here.
|
||||
nether.mapgen.decorate_dungeons = function(data, area, rooms)
|
||||
|
||||
local xStride, yStride, zStride = 1, area.ystride, area.zstride
|
||||
local minEdge, maxEdge = area.MinEdge, area.MaxEdge
|
||||
|
||||
for _, roomInfo in ipairs(rooms) do
|
||||
|
||||
local room_min, room_max = roomInfo.minp, roomInfo.maxp
|
||||
local room_size = vector.distance(room_min, room_max)
|
||||
|
||||
if room_size > 10 then
|
||||
local room_seed = roomInfo.x + 3 * roomInfo.z + 13 * roomInfo.y
|
||||
local window_y = roomInfo.y + math_min(2, room_max.y - roomInfo.y - 1)
|
||||
local roomWidth = room_max.x - room_min.x + 1
|
||||
local roomLength = room_max.z - room_min.z + 1
|
||||
|
||||
if room_seed % 3 == 0 and room_max.y < maxEdge.y then
|
||||
-- Glowstone chandelier (feel free to replace with a fancy schematic)
|
||||
local vi = area:index(roomInfo.x, room_max.y + 1, roomInfo.z)
|
||||
if is_dungeon_brick(data[vi]) then data[vi] = c_glowstone end
|
||||
|
||||
elseif room_seed % 4 == 0 and room_min.y > minEdge.y
|
||||
and room_min.x > minEdge.x and room_max.x < maxEdge.x
|
||||
and room_min.z > minEdge.z and room_max.z < maxEdge.z then
|
||||
-- lava well (feel free to replace with a fancy schematic)
|
||||
local vi = area:index(roomInfo.x, room_min.y, roomInfo.z)
|
||||
if is_dungeon_brick(data[vi - yStride]) then
|
||||
data[vi - yStride] = c_lava_source
|
||||
if data[vi - zStride] == c_air then data[vi - zStride] = c_netherbrick_slab end
|
||||
if data[vi + zStride] == c_air then data[vi + zStride] = c_netherbrick_slab end
|
||||
if data[vi - xStride] == c_air then data[vi - xStride] = c_netherbrick_slab end
|
||||
if data[vi + xStride] == c_air then data[vi + xStride] = c_netherbrick_slab end
|
||||
end
|
||||
end
|
||||
|
||||
-- Barred windows
|
||||
if room_seed % 7 < 5 and roomWidth >= 5 and roomLength >= 5
|
||||
and window_y >= minEdge.y and window_y + 1 <= maxEdge.y
|
||||
and room_min.x > minEdge.x and room_max.x < maxEdge.x
|
||||
and room_min.z > minEdge.z and room_max.z < maxEdge.z then
|
||||
--data[area:indexp(roomInfo)] = minetest.get_content_id("default:mese_post_light") -- debug
|
||||
|
||||
-- Can't use glass panes because they need the param data set.
|
||||
-- Until whisper glass is added, every window will be made of netherbrick fence (rather
|
||||
-- than material depending on room_seed)
|
||||
local window_node = c_netherfence
|
||||
--if c_netherglass ~= nil and room_seed % 20 >= 12 then window_node = c_crystallight end
|
||||
|
||||
local function placeWindow(vi, viOutsideOffset, windowNo)
|
||||
if is_dungeon_brick(data[vi]) and is_dungeon_brick(data[vi + yStride]) then
|
||||
data[vi] = window_node
|
||||
|
||||
if room_seed % 19 == windowNo then
|
||||
-- place a glowstone light behind the window
|
||||
local node_id = data[vi + viOutsideOffset]
|
||||
if node_id == c_netherrack then
|
||||
data[vi + viOutsideOffset] = c_glowstone
|
||||
elseif node_id == c_netherrack_deep then
|
||||
data[vi + viOutsideOffset] = c_glowstone_deep
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local vi_min = area:index(room_min.x - 1, window_y, roomInfo.z)
|
||||
local vi_max = area:index(room_max.x + 1, window_y, roomInfo.z)
|
||||
local locations = {-zStride, zStride, -zStride + yStride, zStride + yStride}
|
||||
for i, offset in ipairs(locations) do
|
||||
placeWindow(vi_min + offset, -1, i)
|
||||
placeWindow(vi_max + offset, 1, i + #locations)
|
||||
end
|
||||
vi_min = area:index(roomInfo.x, window_y, room_min.z - 1)
|
||||
vi_max = area:index(roomInfo.x, window_y, room_max.z + 1)
|
||||
locations = {-xStride, xStride, -xStride + yStride, xStride + yStride}
|
||||
for i, offset in ipairs(locations) do
|
||||
placeWindow(vi_min + offset, -zStride, i + #locations * 2)
|
||||
placeWindow(vi_max + offset, zStride, i + #locations * 3)
|
||||
end
|
||||
end
|
||||
|
||||
-- pillars or mezzanine floor
|
||||
if room_seed % 43 > 10 and roomWidth >= 6 and roomLength >= 6 then
|
||||
|
||||
local pillar_vi = {}
|
||||
local pillarHeight = 0
|
||||
local wallDist = 1 + math.floor((roomWidth + roomLength) / 14)
|
||||
|
||||
local roomHeight = room_max.y - room_min.y
|
||||
if roomHeight >= 7 then
|
||||
-- mezzanine floor
|
||||
local mezzMax = {
|
||||
x = room_min.x + math.floor(roomWidth / 7 * 4),
|
||||
y = room_min.y + math.floor(roomHeight / 5 * 3),
|
||||
z = room_max.z
|
||||
}
|
||||
|
||||
pillarHeight = mezzMax.y - room_min.y - 1
|
||||
pillar_vi = {
|
||||
area:index(mezzMax.x, room_min.y, room_min.z + wallDist),
|
||||
area:index(mezzMax.x, room_min.y, room_max.z - wallDist),
|
||||
}
|
||||
|
||||
if is_dungeon_brick(data[pillar_vi[1] - yStride]) and is_dungeon_brick(data[pillar_vi[2] - yStride]) then
|
||||
-- The floor of the dungeon looks like it exists (i.e. not erased by nether
|
||||
-- cavern), so add the mezzanine floor
|
||||
for z = 0, roomLength - 1 do
|
||||
local vi = area:index(room_min.x, mezzMax.y, room_min.z + z)
|
||||
for x = room_min.x, mezzMax.x do
|
||||
if data[vi] == c_air then data[vi] = c_dungeonbrick end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif roomHeight >= 4 then
|
||||
-- 4 pillars
|
||||
pillarHeight = roomHeight
|
||||
pillar_vi = {
|
||||
area:index(room_min.x + wallDist, room_min.y, room_min.z + wallDist),
|
||||
area:index(room_min.x + wallDist, room_min.y, room_max.z - wallDist),
|
||||
area:index(room_max.x - wallDist, room_min.y, room_min.z + wallDist),
|
||||
area:index(room_max.x - wallDist, room_min.y, room_max.z - wallDist)
|
||||
}
|
||||
end
|
||||
|
||||
for i = #pillar_vi, 1, -1 do
|
||||
if not is_dungeon_brick(data[pillar_vi[i] - yStride]) then
|
||||
-- there's no dungeon floor under this pillar so skip it, it's probably been cut away by nether cavern.
|
||||
table.remove(pillar_vi, i)
|
||||
end
|
||||
end
|
||||
for y = 0, pillarHeight do
|
||||
for _, vi in ipairs(pillar_vi) do
|
||||
if data[vi + y * yStride] == c_air then data[vi + y * yStride] = c_dungeonbrick end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Weeds on the floor once Nether weeds are added
|
||||
end
|
||||
end
|
||||
end
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
local debugf = nether.debug
|
||||
local mapgen = nether.mapgen
|
||||
local S = nether.get_translator
|
||||
|
||||
local BASALT_COLUMN_UPPER_LIMIT = mapgen.BASALT_COLUMN_UPPER_LIMIT
|
||||
local BASALT_COLUMN_LOWER_LIMIT = mapgen.BASALT_COLUMN_LOWER_LIMIT
|
||||
|
@ -49,7 +50,6 @@ local np_basalt = {
|
|||
|
||||
local nobj_basalt = nil
|
||||
local nbuf_basalt = {}
|
||||
local cavePerlin = nil
|
||||
|
||||
-- Content ids
|
||||
|
||||
|
@ -119,7 +119,7 @@ mapgen.add_basalt_columns = function(data, area, minp, maxp)
|
|||
local yStride = area.ystride
|
||||
local yCaveStride = x1 - x0 + 1
|
||||
|
||||
cavePerlin = cavePerlin or minetest.get_perlin(mapgen.np_cave)
|
||||
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)
|
||||
|
||||
|
@ -136,7 +136,7 @@ mapgen.add_basalt_columns = function(data, area, minp, maxp)
|
|||
if basaltNoise > 0 then
|
||||
-- a basalt column is here
|
||||
|
||||
local abs_sealevel_cave_noise = math_abs(cavePerlin:get3d({x = x, y = nearest_sea_level, z = z}))
|
||||
local abs_sealevel_cave_noise = math_abs(cavePerlin:get_3d({x = x, y = nearest_sea_level, z = z}))
|
||||
|
||||
-- Add Some quick deterministic noise to the column heights
|
||||
-- This is probably not good noise, but it doesn't have to be.
|
||||
|
@ -399,11 +399,14 @@ mapgen.excavate_tunnel_to_center_of_the_nether = function(data, area, nvals_cave
|
|||
if lowest < mapgen.CENTER_CAVERN_LIMIT and highest > mapgen.TCAVE + 0.03 then
|
||||
|
||||
local mantle_y = area:position(lowest_vi).y
|
||||
local sealevel, cavern_limit_distance = mapgen.find_nearest_lava_sealevel(mantle_y)
|
||||
local _, cavern_limit_distance = mapgen.find_nearest_lava_sealevel(mantle_y)
|
||||
local _, centerRegionLimit_adj = mapgen.get_mapgenblend_adjustments(mantle_y)
|
||||
|
||||
-- cavern_noise_adj gets added to noise value instead of added to the limit np_noise
|
||||
-- is compared against, so subtract centerRegionLimit_adj instead of adding
|
||||
local cavern_noise_adj =
|
||||
mapgen.CENTER_REGION_LIMIT * (cavern_limit_distance * cavern_limit_distance * cavern_limit_distance) -
|
||||
centerRegionLimit_adj -- cavern_noise_adj gets added to noise value instead of added to the limit np_noise is compared against, so subtract centerRegionLimit_adj instead of adding
|
||||
centerRegionLimit_adj
|
||||
|
||||
if lowest + cavern_noise_adj < mapgen.CENTER_CAVERN_LIMIT then
|
||||
excavate_pathway(data, area, area:position(highest_vi), area:position(lowest_vi), minp, maxp)
|
||||
|
@ -414,63 +417,96 @@ mapgen.excavate_tunnel_to_center_of_the_nether = function(data, area, nvals_cave
|
|||
end
|
||||
|
||||
|
||||
-- an enumerated list of the different regions in the nether
|
||||
mapgen.RegionEnum = {
|
||||
OVERWORLD = {name = "overworld", desc = S("The Overworld") }, -- Outside the Nether / none of the regions in the Nether
|
||||
POSITIVE = {name = "positive", desc = S("Positive nether") }, -- The classic nether caverns are here - where cavePerlin > 0.6
|
||||
POSITIVESHELL = {name = "positive shell", desc = S("Shell between positive nether and center region") }, -- the nether side of the wall/buffer area separating classic nether from the mantle
|
||||
CENTER = {name = "center", desc = S("Center/Mantle, inside cavern") },
|
||||
CENTERSHELL = {name = "center shell", desc = S("Center/Mantle, but outside the caverns") }, -- the mantle side of the wall/buffer area separating the positive and negative regions from the center region
|
||||
NEGATIVE = {name = "negative", desc = S("Negative nether") }, -- Secondary/spare region - where cavePerlin < -0.6
|
||||
NEGATIVESHELL = {name = "negative shell", desc = S("Shell between negative nether and center region") } -- the spare region side of the wall/buffer area separating the negative region from the mantle
|
||||
}
|
||||
|
||||
|
||||
-- Returns (region, noise) where region is a value from mapgen.RegionEnum
|
||||
-- and noise is the unadjusted cave perlin value
|
||||
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.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
|
||||
local tmantle = mapgen.CENTER_REGION_LIMIT + centerRegionLimit_adj
|
||||
|
||||
-- cavern_noise_adj gets added to noise value instead of added to the limit np_noise
|
||||
-- is compared against, so subtract centerRegionLimit_adj instead of adding
|
||||
local cavern_noise_adj =
|
||||
mapgen.CENTER_REGION_LIMIT * (cavern_limit_distance * cavern_limit_distance * cavern_limit_distance) -
|
||||
centerRegionLimit_adj
|
||||
|
||||
local region
|
||||
if caveNoise > tcave then
|
||||
region = mapgen.RegionEnum.POSITIVE
|
||||
elseif -caveNoise > tcave then
|
||||
region = mapgen.RegionEnum.NEGATIVE
|
||||
elseif math_abs(caveNoise) < tmantle then
|
||||
|
||||
if math_abs(caveNoise) + cavern_noise_adj < mapgen.CENTER_CAVERN_LIMIT then
|
||||
region = mapgen.RegionEnum.CENTER
|
||||
else
|
||||
region = mapgen.RegionEnum.CENTERSHELL
|
||||
end
|
||||
|
||||
elseif caveNoise > 0 then
|
||||
region = mapgen.RegionEnum.POSITIVESHELL
|
||||
else
|
||||
region = mapgen.RegionEnum.NEGATIVESHELL
|
||||
end
|
||||
|
||||
return region, caveNoise
|
||||
end
|
||||
|
||||
|
||||
minetest.register_chatcommand("nether_whereami",
|
||||
{
|
||||
description = "Describes which region of the nether the player is in",
|
||||
{
|
||||
description = S("Describes which region of the nether the player is in"),
|
||||
privs = {debug = true},
|
||||
func = function(name, param)
|
||||
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player == nil then return false, "Unknown player position" end
|
||||
if player == nil then return false, S("Unknown player position") end
|
||||
local playerPos = vector.round(player:get_pos())
|
||||
|
||||
local pos = vector.round(player:get_pos())
|
||||
if pos.y > nether.DEPTH_CEILING or pos.y < nether.DEPTH_FLOOR then
|
||||
return true, "The Overworld"
|
||||
end
|
||||
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)
|
||||
|
||||
cavePerlin = cavePerlin or minetest.get_perlin(mapgen.np_cave)
|
||||
local densityNoise = cavePerlin:get_3d(pos)
|
||||
local sea_level, 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
|
||||
local tmantle = mapgen.CENTER_REGION_LIMIT + centerRegionLimit_adj
|
||||
local cavern_noise_adj =
|
||||
mapgen.CENTER_REGION_LIMIT * (cavern_limit_distance * cavern_limit_distance * cavern_limit_distance) -
|
||||
centerRegionLimit_adj -- cavern_noise_adj gets added to noise value instead of added to the limit np_noise is compared against, so subtract centerRegionLimit_adj so subtract centerRegionLimit_adj instead of adding
|
||||
local seaDesc = ""
|
||||
local boundaryDesc = ""
|
||||
local perlinDesc = ""
|
||||
|
||||
local desc
|
||||
if region ~= mapgen.RegionEnum.OVERWORLD then
|
||||
|
||||
if densityNoise > tcave then
|
||||
desc = "Positive nether"
|
||||
elseif -densityNoise > tcave then
|
||||
desc = "Negative nether"
|
||||
elseif math_abs(densityNoise) < tmantle then
|
||||
desc = "Mantle"
|
||||
|
||||
if math_abs(densityNoise) + cavern_noise_adj < mapgen.CENTER_CAVERN_LIMIT then
|
||||
desc = desc .. " inside cavern"
|
||||
local seaPos = playerPos.y - seaLevel
|
||||
if seaPos > 0 then
|
||||
seaDesc = S(", @1m above lava-sea level", seaPos)
|
||||
else
|
||||
desc = desc .. " but outside cavern"
|
||||
seaDesc = S(", @1m below lava-sea level", seaPos)
|
||||
end
|
||||
|
||||
elseif densityNoise > 0 then
|
||||
desc = "Shell between positive nether and center region"
|
||||
else
|
||||
desc = "Shell between negative nether and center region"
|
||||
if tcave_adj > 0 then
|
||||
boundaryDesc = S(", approaching y boundary of Nether")
|
||||
end
|
||||
|
||||
perlinDesc = S("[Perlin @1] ", (math_floor(caveNoise * 1000) / 1000))
|
||||
end
|
||||
|
||||
local sea_pos = pos.y - sea_level
|
||||
if sea_pos > 0 then
|
||||
desc = desc .. ", " .. sea_pos .. "m above lava-sea level"
|
||||
else
|
||||
desc = desc .. ", " .. sea_pos .. "m below lava-sea level"
|
||||
end
|
||||
|
||||
if tcave_adj > 0 then
|
||||
desc = desc .. ", approaching y boundary of Nether"
|
||||
end
|
||||
|
||||
return true, "[Perlin " .. (math_floor(densityNoise * 1000) / 1000) .. "] " .. desc
|
||||
return true, S("@1@2@3@4", perlinDesc, region.desc, seaDesc, boundaryDesc)
|
||||
end
|
||||
}
|
||||
)
|
||||
|
|
|
@ -216,7 +216,7 @@ function nether.find_nether_ground_y(target_x, target_z, start_y, player_name)
|
|||
local maxp = {x = maxp_schem.x, y = 0, z = maxp_schem.z}
|
||||
|
||||
for y = start_y, math.max(NETHER_FLOOR + BLEND, start_y - 4096), -1 do
|
||||
local nval_cave = nobj_cave_point:get3d({x = target_x, y = y, z = target_z})
|
||||
local nval_cave = nobj_cave_point:get_3d({x = target_x, y = y, z = target_z})
|
||||
|
||||
if nval_cave > TCAVE then -- Cavern
|
||||
air = air + 1
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
name = nether
|
||||
description = Adds a deep underground realm with different mapgen that you can reach with obsidian portals.
|
||||
depends = stairs, default
|
||||
optional_depends = moreblocks, mesecons, loot, dungeon_loot, doc_basics, fire
|
||||
optional_depends = moreblocks, mesecons, loot, dungeon_loot, doc_basics, fire, climate_api, ethereal
|
||||
release = 8686
|
||||
author = PilzAdam
|
||||
title = Nether
|
||||
|
|
|
@ -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.
|
|
@ -161,6 +161,13 @@ minetest.register_node("nether:fence_nether_brick", {
|
|||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("nether:brick_deep", {
|
||||
description = S("Deep Nether Brick"),
|
||||
tiles = {"nether_brick_deep.png"},
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, level = 2},
|
||||
sounds = default.node_sound_stone_defaults()
|
||||
})
|
||||
|
||||
-- Register stair and slab
|
||||
|
||||
|
@ -308,6 +315,8 @@ lavasea_source.tiles = {
|
|||
},
|
||||
},
|
||||
}
|
||||
lavasea_source.groups = { not_in_creative_inventory = 1 } -- Avoid having two lava source blocks in the inv.
|
||||
for key, value in pairs(lava_source.groups) do lavasea_source.groups[key] = value end
|
||||
lavasea_source.liquid_alternative_source = "nether:lava_source"
|
||||
lavasea_source.inventory_image = minetest.inventorycube(
|
||||
"nether_lava_source_animated.png^[sheet:2x16:0,0",
|
||||
|
@ -327,8 +336,8 @@ 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_node_group(node_above.name, "water") > 0 and
|
||||
pos.y < nether.DEPTH_CEILING and pos.y > nether.DEPTH_FLOOR then
|
||||
if minetest.get_item_group(node_above.name, "water") > 0 and
|
||||
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"})
|
||||
|
@ -374,7 +383,7 @@ minetest.register_on_mods_loaded(function()
|
|||
|
||||
-- register a bucket of Lava-sea source - but make it just the same bucket as default lava.
|
||||
-- (by doing this in register_on_mods_loaded we don't need to declare a soft dependency)
|
||||
if minetest.get_modpath("bucket") and minetest.global_exists("bucket") then
|
||||
if minetest.get_modpath("bucket") and minetest.global_exists("bucket") and type(bucket.liquids) == "table" then
|
||||
local lava_bucket = bucket.liquids["default:lava_source"]
|
||||
if lava_bucket ~= nil then
|
||||
local lavasea_bucket = {}
|
||||
|
@ -527,7 +536,7 @@ minetest.register_node("nether:lava_crust", {
|
|||
paramtype = "light",
|
||||
light_source = default.LIGHT_MAX - 3,
|
||||
buildable_to = false,
|
||||
walkable_to = true,
|
||||
walkable = true,
|
||||
is_ground_content = true,
|
||||
drop = {
|
||||
items = {{
|
||||
|
@ -595,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
|
||||
|
|
|
@ -2007,7 +2007,8 @@ local wormhole_nodedef_default = {
|
|||
a = 160, r = 128, g = 0, b = 80
|
||||
},
|
||||
sunlight_propagates = true,
|
||||
use_texture_alpha = "blend",
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes
|
||||
and "blend" or true,
|
||||
walkable = false,
|
||||
diggable = false,
|
||||
pointable = false,
|
||||
|
@ -2015,7 +2016,6 @@ local wormhole_nodedef_default = {
|
|||
is_ground_content = false,
|
||||
drop = "",
|
||||
light_source = 5,
|
||||
alpha = 192,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
|
@ -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 "<mod name not recorded>"
|
||||
|
||||
-- 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
|
||||
|
@ -2211,7 +2211,7 @@ function nether.volume_is_natural_and_unprotected(minp, maxp, player_name)
|
|||
if id ~= c_air and id ~= c_ignore and id ~= nil then -- checked for common natural or not emerged
|
||||
local name = minetest.get_name_from_content_id(id)
|
||||
local nodedef = minetest.registered_nodes[name]
|
||||
if not nodedef.is_ground_content then
|
||||
if nodedef and not nodedef.is_ground_content then
|
||||
-- trees are natural but not "ground content"
|
||||
local node_groups = nodedef.groups
|
||||
if node_groups == nil or (node_groups.tree == nil and node_groups.leaves == nil and node_groups.leafdecay == nil) then
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 198 B |
Loading…
Reference in New Issue