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:
Paramat 2016-05-30 20:55:04 +01:00 committed by Auke Kok
parent c35f6a2d03
commit 47d39871d2

259
init.lua
View File

@ -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)