forked from minetest-mods/nether
Caverns. Fix node defs/crafting. Smaller emerge. Find cavern floor (#17)
Large caverns using squashed 3D noise Less lava, more glowstone, no air pockets Preserve nether dungeons Allow light to spread from glowstone and make brighter Fix 'is ground content' settings, portals should not be excavated by overgenerated caves Rack drops itself as normal Make brick, fence, stair, slab groups consistent Use 'node sound gravel defaults' for sand Make brick crafting consistent with default Make fence recipe output number consistent with default Make 'emerge area' volume mimimum required size Add 'find nether target y' function to search for a cavern floor with space above for nether portal spawn
This commit is contained in:
parent
c35f6a2d03
commit
47d39871d2
259
init.lua
259
init.lua
@ -1,6 +1,25 @@
|
|||||||
-- Parameters
|
-- Parameters
|
||||||
|
|
||||||
local NETHER_DEPTH = -5000
|
local NETHER_DEPTH = -5000
|
||||||
|
local TCAVE = 0.6
|
||||||
|
local BLEND = 128
|
||||||
|
|
||||||
|
|
||||||
|
-- 3D noise
|
||||||
|
|
||||||
|
local np_cave = {
|
||||||
|
offset = 0,
|
||||||
|
scale = 1,
|
||||||
|
spread = {x = 384, y = 128, z = 384}, -- squashed 3:1
|
||||||
|
seed = 59033,
|
||||||
|
octaves = 5,
|
||||||
|
persist = 0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-- Stuff
|
||||||
|
|
||||||
|
local yblmax = NETHER_DEPTH - BLEND * 2
|
||||||
|
|
||||||
|
|
||||||
-- Functions
|
-- Functions
|
||||||
@ -42,7 +61,8 @@ local function build_portal(pos, target)
|
|||||||
for z = -2, 2 do
|
for z = -2, 2 do
|
||||||
if z ~= 0 then
|
if z ~= 0 then
|
||||||
p.z = p.z + z
|
p.z = p.z + z
|
||||||
if minetest.registered_nodes[minetest.get_node(p).name].is_ground_content then
|
if minetest.registered_nodes[
|
||||||
|
minetest.get_node(p).name].is_ground_content then
|
||||||
minetest.remove_node(p)
|
minetest.remove_node(p)
|
||||||
end
|
end
|
||||||
p.z = p.z - z
|
p.z = p.z - z
|
||||||
@ -53,6 +73,28 @@ local function build_portal(pos, target)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function find_nether_target_y(target_x, target_z)
|
||||||
|
local start_y = NETHER_DEPTH - math.random(500, 1500) -- Search start
|
||||||
|
local nobj_cave_point = minetest.get_perlin(np_cave)
|
||||||
|
local air = 0 -- Consecutive air nodes found
|
||||||
|
|
||||||
|
for y = start_y, start_y - 4096, -1 do
|
||||||
|
local nval_cave = nobj_cave_point:get3d({x = target_x, y = y, z = target_z})
|
||||||
|
|
||||||
|
if nval_cave > TCAVE then -- Cavern
|
||||||
|
air = air + 1
|
||||||
|
else -- Not cavern, check if 4 nodes of space above
|
||||||
|
if air >= 4 then
|
||||||
|
return y + 2
|
||||||
|
else -- Not enough space, reset air to zero
|
||||||
|
air = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return y -- Fallback
|
||||||
|
end
|
||||||
|
|
||||||
local function move_check(p1, max, dir)
|
local function move_check(p1, max, dir)
|
||||||
local p = {x = p1.x, y = p1.y, z = p1.z}
|
local p = {x = p1.x, y = p1.y, z = p1.z}
|
||||||
local d = math.abs(max - p1[dir]) / (max - p1[dir])
|
local d = math.abs(max - p1[dir]) / (max - p1[dir])
|
||||||
@ -142,9 +184,9 @@ local function make_portal(pos)
|
|||||||
local target = {x = p1.x, y = p1.y, z = p1.z}
|
local target = {x = p1.x, y = p1.y, z = p1.z}
|
||||||
target.x = target.x + 1
|
target.x = target.x + 1
|
||||||
if target.y < NETHER_DEPTH then
|
if target.y < NETHER_DEPTH then
|
||||||
target.y = math.random(-50, 20)
|
target.y = math.random(-32, 1)
|
||||||
else
|
else
|
||||||
target.y = NETHER_DEPTH - math.random(500, 1500)
|
target.y = find_nether_target_y(target.x, target.z)
|
||||||
end
|
end
|
||||||
|
|
||||||
for d = 0, 3 do
|
for d = 0, 3 do
|
||||||
@ -201,7 +243,7 @@ minetest.register_abm({
|
|||||||
minetest.get_voxel_manip():read_from_map(target, target)
|
minetest.get_voxel_manip():read_from_map(target, target)
|
||||||
if not minetest.get_node_or_nil(target) then
|
if not minetest.get_node_or_nil(target) then
|
||||||
minetest.emerge_area(
|
minetest.emerge_area(
|
||||||
vector.subtract(target, 80), vector.add(target, 80))
|
vector.subtract(target, 4), vector.add(target, 4))
|
||||||
end
|
end
|
||||||
-- teleport the player
|
-- teleport the player
|
||||||
minetest.after(3, function(obj, pos, target)
|
minetest.after(3, function(obj, pos, target)
|
||||||
@ -271,6 +313,7 @@ minetest.register_node("nether:portal", {
|
|||||||
diggable = false,
|
diggable = false,
|
||||||
pointable = false,
|
pointable = false,
|
||||||
buildable_to = false,
|
buildable_to = false,
|
||||||
|
is_ground_content = false,
|
||||||
drop = "",
|
drop = "",
|
||||||
light_source = 5,
|
light_source = 5,
|
||||||
post_effect_color = {a = 180, r = 128, g = 0, b = 128},
|
post_effect_color = {a = 180, r = 128, g = 0, b = 128},
|
||||||
@ -287,7 +330,7 @@ minetest.register_node("nether:portal", {
|
|||||||
minetest.register_node(":default:obsidian", {
|
minetest.register_node(":default:obsidian", {
|
||||||
description = "Obsidian",
|
description = "Obsidian",
|
||||||
tiles = {"default_obsidian.png"},
|
tiles = {"default_obsidian.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = false,
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
groups = {cracky = 1, level = 2},
|
groups = {cracky = 1, level = 2},
|
||||||
|
|
||||||
@ -350,12 +393,6 @@ minetest.register_node("nether:rack", {
|
|||||||
description = "Netherrack",
|
description = "Netherrack",
|
||||||
tiles = {"nether_rack.png"},
|
tiles = {"nether_rack.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
drop = {
|
|
||||||
max_items = 1,
|
|
||||||
items = {
|
|
||||||
{rarity = 3, items = {"nether:rack"}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
groups = {cracky = 3, level = 2},
|
groups = {cracky = 3, level = 2},
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
})
|
})
|
||||||
@ -365,7 +402,7 @@ minetest.register_node("nether:sand", {
|
|||||||
tiles = {"nether_sand.png"},
|
tiles = {"nether_sand.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
groups = {crumbly = 3, level = 2, falling_node = 1},
|
groups = {crumbly = 3, level = 2, falling_node = 1},
|
||||||
sounds = default.node_sound_dirt_defaults({
|
sounds = default.node_sound_gravel_defaults({
|
||||||
footstep = {name = "default_gravel_footstep", gain = 0.45},
|
footstep = {name = "default_gravel_footstep", gain = 0.45},
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
@ -374,7 +411,8 @@ minetest.register_node("nether:glowstone", {
|
|||||||
description = "Glowstone",
|
description = "Glowstone",
|
||||||
tiles = {"nether_glowstone.png"},
|
tiles = {"nether_glowstone.png"},
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
light_source = 13,
|
light_source = 14,
|
||||||
|
paramtype = "light",
|
||||||
groups = {cracky = 3, oddly_breakable_by_hand = 3},
|
groups = {cracky = 3, oddly_breakable_by_hand = 3},
|
||||||
sounds = default.node_sound_glass_defaults(),
|
sounds = default.node_sound_glass_defaults(),
|
||||||
})
|
})
|
||||||
@ -382,6 +420,7 @@ minetest.register_node("nether:glowstone", {
|
|||||||
minetest.register_node("nether:brick", {
|
minetest.register_node("nether:brick", {
|
||||||
description = "Nether Brick",
|
description = "Nether Brick",
|
||||||
tiles = {"nether_brick.png"},
|
tiles = {"nether_brick.png"},
|
||||||
|
is_ground_content = false,
|
||||||
groups = {cracky = 2, level = 2},
|
groups = {cracky = 2, level = 2},
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
})
|
})
|
||||||
@ -402,7 +441,7 @@ minetest.register_node("nether:fence_nether_brick", {
|
|||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7},
|
fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7},
|
||||||
},
|
},
|
||||||
groups = {cracky = 3, level = 2},
|
groups = {cracky = 2, level = 2},
|
||||||
sounds = default.node_sound_stone_defaults(),
|
sounds = default.node_sound_stone_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -412,7 +451,7 @@ minetest.register_node("nether:fence_nether_brick", {
|
|||||||
stairs.register_stair_and_slab(
|
stairs.register_stair_and_slab(
|
||||||
"nether_brick",
|
"nether_brick",
|
||||||
"nether:brick",
|
"nether:brick",
|
||||||
{cracky = 3, oddly_breakable_by_hand = 1},
|
{cracky = 2, level = 2},
|
||||||
{"nether_brick.png"},
|
{"nether_brick.png"},
|
||||||
"nether stair",
|
"nether stair",
|
||||||
"nether slab",
|
"nether slab",
|
||||||
@ -441,18 +480,15 @@ minetest.register_craftitem(":default:mese_crystal_fragment", {
|
|||||||
-- Crafting
|
-- Crafting
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "nether:brick",
|
output = "nether:brick 4",
|
||||||
type = "shapeless",
|
|
||||||
recipe = {
|
recipe = {
|
||||||
"nether:rack",
|
{"nether:rack", "nether:rack"},
|
||||||
"nether:rack",
|
{"nether:rack", "nether:rack"},
|
||||||
"nether:rack",
|
}
|
||||||
"nether:rack",
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "nether:fence_nether_brick 16",
|
output = "nether:fence_nether_brick 6",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"nether:brick", "nether:brick", "nether:brick"},
|
{"nether:brick", "nether:brick", "nether:brick"},
|
||||||
{"nether:brick", "nether:brick", "nether:brick"},
|
{"nether:brick", "nether:brick", "nether:brick"},
|
||||||
@ -462,61 +498,141 @@ minetest.register_craft({
|
|||||||
|
|
||||||
-- Mapgen
|
-- Mapgen
|
||||||
|
|
||||||
local air = minetest.get_content_id("air")
|
-- Initialize noise object and localise noise buffer
|
||||||
local stone_with_coal = minetest.get_content_id("default:stone_with_coal")
|
|
||||||
local stone_with_iron = minetest.get_content_id("default:stone_with_iron")
|
|
||||||
local stone_with_mese = minetest.get_content_id("default:stone_with_mese")
|
|
||||||
local stone_with_diamond = minetest.get_content_id("default:stone_with_diamond")
|
|
||||||
local stone_with_gold = minetest.get_content_id("default:stone_with_gold")
|
|
||||||
local stone_with_copper = minetest.get_content_id("default:stone_with_copper")
|
|
||||||
local gravel = minetest.get_content_id("default:gravel")
|
|
||||||
local dirt = minetest.get_content_id("default:dirt")
|
|
||||||
local sand = minetest.get_content_id("default:sand")
|
|
||||||
local cobble = minetest.get_content_id("default:cobble")
|
|
||||||
local mossycobble = minetest.get_content_id("default:mossycobble")
|
|
||||||
local stair_cobble = minetest.get_content_id("stairs:stair_cobble")
|
|
||||||
local lava_source = minetest.get_content_id("default:lava_source")
|
|
||||||
local lava_flowing = minetest.get_content_id("default:lava_flowing")
|
|
||||||
|
|
||||||
local glowstone = minetest.get_content_id("nether:glowstone")
|
local nobj_cave = nil
|
||||||
local nethersand = minetest.get_content_id("nether:sand")
|
local nbuf_cave
|
||||||
local netherbrick = minetest.get_content_id("nether:brick")
|
|
||||||
local netherrack = minetest.get_content_id("nether:rack")
|
|
||||||
|
-- Content ids
|
||||||
|
|
||||||
|
local c_air = minetest.get_content_id("air")
|
||||||
|
|
||||||
|
local c_stone_with_coal = minetest.get_content_id("default:stone_with_coal")
|
||||||
|
local c_stone_with_iron = minetest.get_content_id("default:stone_with_iron")
|
||||||
|
local c_stone_with_mese = minetest.get_content_id("default:stone_with_mese")
|
||||||
|
local c_stone_with_diamond = minetest.get_content_id("default:stone_with_diamond")
|
||||||
|
local c_stone_with_gold = minetest.get_content_id("default:stone_with_gold")
|
||||||
|
local c_stone_with_copper = minetest.get_content_id("default:stone_with_copper")
|
||||||
|
local c_mese = minetest.get_content_id("default:mese")
|
||||||
|
|
||||||
|
local c_gravel = minetest.get_content_id("default:gravel")
|
||||||
|
local c_dirt = minetest.get_content_id("default:dirt")
|
||||||
|
local c_sand = minetest.get_content_id("default:sand")
|
||||||
|
|
||||||
|
local c_cobble = minetest.get_content_id("default:cobble")
|
||||||
|
local c_mossycobble = minetest.get_content_id("default:mossycobble")
|
||||||
|
local c_stair_cobble = minetest.get_content_id("stairs:stair_cobble")
|
||||||
|
|
||||||
|
local c_lava_source = minetest.get_content_id("default:lava_source")
|
||||||
|
local c_lava_flowing = minetest.get_content_id("default:lava_flowing")
|
||||||
|
local c_water_source = minetest.get_content_id("default:water_source")
|
||||||
|
local c_water_flowing = minetest.get_content_id("default:water_flowing")
|
||||||
|
|
||||||
|
local c_glowstone = minetest.get_content_id("nether:glowstone")
|
||||||
|
local c_nethersand = minetest.get_content_id("nether:sand")
|
||||||
|
local c_netherbrick = minetest.get_content_id("nether:brick")
|
||||||
|
local c_netherrack = minetest.get_content_id("nether:rack")
|
||||||
|
|
||||||
|
|
||||||
|
-- On-generated function
|
||||||
|
|
||||||
minetest.register_on_generated(function(minp, maxp, seed)
|
minetest.register_on_generated(function(minp, maxp, seed)
|
||||||
if maxp.y > NETHER_DEPTH then
|
if minp.y > NETHER_DEPTH then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
local t1 = os.clock()
|
||||||
local data = vm:get_data()
|
|
||||||
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
|
|
||||||
|
|
||||||
for vi in area:iterp(minp, maxp) do
|
local x1 = maxp.x
|
||||||
local id = data[vi]
|
local y1 = maxp.y
|
||||||
if id == air or
|
local z1 = maxp.z
|
||||||
id == stone_with_coal or
|
local x0 = minp.x
|
||||||
id == stone_with_iron then
|
local y0 = minp.y
|
||||||
data[vi] = air
|
local z0 = minp.z
|
||||||
elseif id == stone_with_mese or
|
|
||||||
id == stone_with_diamond or
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||||
id == lava_source then
|
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
|
||||||
data[vi] = lava_source
|
local data = vm:get_data()
|
||||||
elseif id == lava_flowing then
|
|
||||||
-- nothing
|
local x11 = emax.x -- Limits of mapchunk plus mapblock shell
|
||||||
elseif id == stone_with_gold then
|
local y11 = emax.y
|
||||||
data[vi] = glowstone
|
local z11 = emax.z
|
||||||
elseif id == stone_with_copper or
|
local x00 = emin.x
|
||||||
id == gravel or
|
local y00 = emin.y
|
||||||
id == dirt or
|
local z00 = emin.z
|
||||||
id == sand then
|
|
||||||
data[vi] = nethersand
|
local ystride = x1 - x0 + 1
|
||||||
elseif id == cobble or
|
local zstride = ystride * ystride
|
||||||
id == mossycobble or
|
local chulens = {x = ystride, y = ystride, z = ystride}
|
||||||
id == stair_cobble then
|
local minposxyz = {x = x0, y = y0, z = z0}
|
||||||
data[vi] = netherbrick
|
|
||||||
|
nobj_cave = nobj_cave or minetest.get_perlin_map(np_cave, chulens)
|
||||||
|
local nvals_cave = nobj_cave:get3dMap_flat(minposxyz, nbuf_cave)
|
||||||
|
|
||||||
|
for y = y00, y11 do -- Y loop first to minimise tcave calculations
|
||||||
|
local tcave
|
||||||
|
local in_chunk_y = false
|
||||||
|
if y >= y0 and y <= y1 then
|
||||||
|
if y > yblmax then
|
||||||
|
tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
|
||||||
else
|
else
|
||||||
data[vi] = netherrack
|
tcave = TCAVE
|
||||||
|
end
|
||||||
|
in_chunk_y = true
|
||||||
|
end
|
||||||
|
|
||||||
|
for z = z00, z11 do
|
||||||
|
local vi = area:index(x00, y, z) -- Initial voxelmanip index
|
||||||
|
local ni
|
||||||
|
local in_chunk_yz = in_chunk_y and z >= z0 and z <= z1
|
||||||
|
|
||||||
|
for x = x00, x11 do
|
||||||
|
if in_chunk_yz and x == x0 then
|
||||||
|
-- Initial noisemap index
|
||||||
|
ni = (z - z0) * zstride + (y - y0) * ystride + 1
|
||||||
|
end
|
||||||
|
local in_chunk_yzx = in_chunk_yz and x >= x0 and x <= x1 -- In mapchunk
|
||||||
|
|
||||||
|
local id = data[vi] -- Existing node
|
||||||
|
-- Cave air, cave liquids and dungeons are overgenerated,
|
||||||
|
-- convert these throughout mapchunk plus shell
|
||||||
|
if id == c_air or -- Air and liquids to air
|
||||||
|
id == c_lava_source or
|
||||||
|
id == c_lava_flowing or
|
||||||
|
id == c_water_source or
|
||||||
|
id == c_water_flowing then
|
||||||
|
data[vi] = c_air
|
||||||
|
-- Dungeons are preserved so we don't need
|
||||||
|
-- to check for cavern in the shell
|
||||||
|
elseif id == c_cobble or -- Dungeons (preserved) to netherbrick
|
||||||
|
id == c_mossycobble or
|
||||||
|
id == c_stair_cobble then
|
||||||
|
data[vi] = c_netherbrick
|
||||||
|
end
|
||||||
|
|
||||||
|
if in_chunk_yzx then -- In mapchunk
|
||||||
|
if nvals_cave[ni] > tcave then -- Only excavate cavern in mapchunk
|
||||||
|
data[vi] = c_air
|
||||||
|
elseif id == c_mese then -- Mese block to lava
|
||||||
|
data[vi] = c_lava_source
|
||||||
|
elseif id == c_stone_with_gold or -- Precious ores to glowstone
|
||||||
|
id == c_stone_with_mese or
|
||||||
|
id == c_stone_with_diamond then
|
||||||
|
data[vi] = c_glowstone
|
||||||
|
elseif id == c_gravel or -- Blob ore to nethersand
|
||||||
|
id == c_dirt or
|
||||||
|
id == c_sand then
|
||||||
|
data[vi] = c_nethersand
|
||||||
|
else -- All else to netherstone
|
||||||
|
data[vi] = c_netherrack
|
||||||
|
end
|
||||||
|
|
||||||
|
ni = ni + 1 -- Only increment noise index in mapchunk
|
||||||
|
end
|
||||||
|
|
||||||
|
vi = vi + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -525,4 +641,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
|
|||||||
vm:calc_lighting()
|
vm:calc_lighting()
|
||||||
vm:update_liquids()
|
vm:update_liquids()
|
||||||
vm:write_to_map()
|
vm:write_to_map()
|
||||||
|
|
||||||
|
local chugent = math.ceil((os.clock() - t1) * 1000)
|
||||||
|
print ("[nether] generate chunk " .. chugent .. " ms")
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user