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
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
@ -42,7 +61,8 @@ local function build_portal(pos, target)
for z = -2, 2 do
if z ~= 0 then
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)
end
p.z = p.z - z
@ -53,6 +73,28 @@ local function build_portal(pos, target)
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 p = {x = p1.x, y = p1.y, z = p1.z}
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}
target.x = target.x + 1
if target.y < NETHER_DEPTH then
target.y = math.random(-50, 20)
target.y = math.random(-32, 1)
else
target.y = NETHER_DEPTH - math.random(500, 1500)
target.y = find_nether_target_y(target.x, target.z)
end
for d = 0, 3 do
@ -201,7 +243,7 @@ minetest.register_abm({
minetest.get_voxel_manip():read_from_map(target, target)
if not minetest.get_node_or_nil(target) then
minetest.emerge_area(
vector.subtract(target, 80), vector.add(target, 80))
vector.subtract(target, 4), vector.add(target, 4))
end
-- teleport the player
minetest.after(3, function(obj, pos, target)
@ -271,6 +313,7 @@ minetest.register_node("nether:portal", {
diggable = false,
pointable = false,
buildable_to = false,
is_ground_content = false,
drop = "",
light_source = 5,
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", {
description = "Obsidian",
tiles = {"default_obsidian.png"},
is_ground_content = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
groups = {cracky = 1, level = 2},
@ -350,12 +393,6 @@ minetest.register_node("nether:rack", {
description = "Netherrack",
tiles = {"nether_rack.png"},
is_ground_content = true,
drop = {
max_items = 1,
items = {
{rarity = 3, items = {"nether:rack"}},
}
},
groups = {cracky = 3, level = 2},
sounds = default.node_sound_stone_defaults(),
})
@ -365,7 +402,7 @@ minetest.register_node("nether:sand", {
tiles = {"nether_sand.png"},
is_ground_content = true,
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},
}),
})
@ -374,7 +411,8 @@ minetest.register_node("nether:glowstone", {
description = "Glowstone",
tiles = {"nether_glowstone.png"},
is_ground_content = true,
light_source = 13,
light_source = 14,
paramtype = "light",
groups = {cracky = 3, oddly_breakable_by_hand = 3},
sounds = default.node_sound_glass_defaults(),
})
@ -382,6 +420,7 @@ minetest.register_node("nether:glowstone", {
minetest.register_node("nether:brick", {
description = "Nether Brick",
tiles = {"nether_brick.png"},
is_ground_content = false,
groups = {cracky = 2, level = 2},
sounds = default.node_sound_stone_defaults(),
})
@ -402,7 +441,7 @@ minetest.register_node("nether:fence_nether_brick", {
type = "fixed",
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(),
})
@ -412,7 +451,7 @@ minetest.register_node("nether:fence_nether_brick", {
stairs.register_stair_and_slab(
"nether_brick",
"nether:brick",
{cracky = 3, oddly_breakable_by_hand = 1},
{cracky = 2, level = 2},
{"nether_brick.png"},
"nether stair",
"nether slab",
@ -441,18 +480,15 @@ minetest.register_craftitem(":default:mese_crystal_fragment", {
-- Crafting
minetest.register_craft({
output = "nether:brick",
type = "shapeless",
output = "nether:brick 4",
recipe = {
"nether:rack",
"nether:rack",
"nether:rack",
"nether:rack",
},
{"nether:rack", "nether:rack"},
{"nether:rack", "nether:rack"},
}
})
minetest.register_craft({
output = "nether:fence_nether_brick 16",
output = "nether:fence_nether_brick 6",
recipe = {
{"nether:brick", "nether:brick", "nether:brick"},
{"nether:brick", "nether:brick", "nether:brick"},
@ -462,61 +498,141 @@ minetest.register_craft({
-- Mapgen
local air = minetest.get_content_id("air")
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")
-- Initialize noise object and localise noise buffer
local glowstone = minetest.get_content_id("nether:glowstone")
local nethersand = minetest.get_content_id("nether:sand")
local netherbrick = minetest.get_content_id("nether:brick")
local netherrack = minetest.get_content_id("nether:rack")
local nobj_cave = nil
local nbuf_cave
-- 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)
if maxp.y > NETHER_DEPTH then
if minp.y > NETHER_DEPTH then
return
end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
local t1 = os.clock()
for vi in area:iterp(minp, maxp) do
local id = data[vi]
if id == air or
id == stone_with_coal or
id == stone_with_iron then
data[vi] = air
elseif id == stone_with_mese or
id == stone_with_diamond or
id == lava_source then
data[vi] = lava_source
elseif id == lava_flowing then
-- nothing
elseif id == stone_with_gold then
data[vi] = glowstone
elseif id == stone_with_copper or
id == gravel or
id == dirt or
id == sand then
data[vi] = nethersand
elseif id == cobble or
id == mossycobble or
id == stair_cobble then
data[vi] = netherbrick
local x1 = maxp.x
local y1 = maxp.y
local z1 = maxp.z
local x0 = minp.x
local y0 = minp.y
local z0 = minp.z
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
local data = vm:get_data()
local x11 = emax.x -- Limits of mapchunk plus mapblock shell
local y11 = emax.y
local z11 = emax.z
local x00 = emin.x
local y00 = emin.y
local z00 = emin.z
local ystride = x1 - x0 + 1
local zstride = ystride * ystride
local chulens = {x = ystride, y = ystride, z = ystride}
local minposxyz = {x = x0, y = y0, z = z0}
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
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
@ -525,4 +641,7 @@ minetest.register_on_generated(function(minp, maxp, seed)
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
local chugent = math.ceil((os.clock() - t1) * 1000)
print ("[nether] generate chunk " .. chugent .. " ms")
end)