mirror of
https://github.com/FaceDeer/dfcaverns.git
synced 2024-12-25 02:10:37 +01:00
first pass of bubble caves
This commit is contained in:
parent
dd0468b376
commit
476f8a7b89
144
bubble_caves/init.lua
Normal file
144
bubble_caves/init.lua
Normal file
@ -0,0 +1,144 @@
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
local mapgen_test_path = minetest.get_modpath("mapgen_test")
|
||||
--local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
local c_glow
|
||||
if minetest.get_modpath("df_underworld_items") then
|
||||
c_glow = minetest.get_content_id("df_underworld_items:glowstone")
|
||||
end
|
||||
|
||||
local perlin_params = {
|
||||
offset = 0,
|
||||
scale = 1,
|
||||
spread = {x=1000, y=500, z=1000},
|
||||
seed = 501221,
|
||||
octaves = 3,
|
||||
persist = 0.67
|
||||
}
|
||||
local data = {}
|
||||
local light_data = {}
|
||||
local light = 15 + (15 * 16)
|
||||
|
||||
local max_depth = -5000
|
||||
local min_depth = -6000
|
||||
|
||||
local noise_obj
|
||||
|
||||
local block_size = 80
|
||||
local cube_inside = 1/math.sqrt(3) -- https://www.quora.com/What-is-the-largest-volume-of-a-cube-that-can-be-enclosed-in-a-sphere-of-diameter-2
|
||||
|
||||
local get_bubbles = function(pos)
|
||||
noise_obj = noise_obj or minetest.get_perlin(perlin_params)
|
||||
local bubbles = {}
|
||||
local next_seed = math.random(1000000)
|
||||
for block_x = -1, 1 do
|
||||
for block_y = -1, 1 do
|
||||
for block_z = -1, 1 do
|
||||
local this_pos = vector.add(pos, {x=block_x*block_size, y=block_y*block_size, z=block_z*block_size})
|
||||
math.randomseed(this_pos.x + this_pos.y*8 + this_pos.z*16)
|
||||
this_pos.x = this_pos.x + math.floor(math.random()*block_size - block_size/2)
|
||||
this_pos.y = this_pos.y + math.floor(math.random()*block_size - block_size/2)
|
||||
this_pos.z = this_pos.z + math.floor(math.random()*block_size - block_size/2)
|
||||
local noise_val = math.min(noise_obj:get_3d(this_pos), 1.0)
|
||||
if noise_val > 0 then
|
||||
local radius = noise_val*block_size*math.random()+5
|
||||
local y = this_pos.y
|
||||
if y + radius < max_depth and y - radius > min_depth then -- make sure bubbles remain within the layer
|
||||
if mapgen_test_path then
|
||||
if noise_val < 0.1 then
|
||||
mapgen_test.record_first_location("bubble cave sparse", this_pos, "a bubble cave in a sparsely populated region")
|
||||
elseif noise_val < 0.55 and noise_val > 0.45 then
|
||||
mapgen_test.record_first_location("bubble cave middle", this_pos, "a bubble cave in a middlingly populated region")
|
||||
elseif noise_val > 0.9 then
|
||||
mapgen_test.record_first_location("bubble cave dense", this_pos, "a bubble cave in a densely populated region")
|
||||
end
|
||||
end
|
||||
table.insert(bubbles, {loc=this_pos, radius=radius})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
math.randomseed(next_seed)
|
||||
return bubbles
|
||||
end
|
||||
|
||||
|
||||
if mapgen_test_path then
|
||||
mapgen_test.log_time_settings("bubble_caves")
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
if minp.y > max_depth or maxp.y < min_depth then
|
||||
return
|
||||
end
|
||||
|
||||
local nearby_bubbles = get_bubbles({x=minp.x+block_size/2, y=minp.y+block_size/2, z=minp.z+block_size/2})
|
||||
if not next(nearby_bubbles) then
|
||||
return
|
||||
end
|
||||
|
||||
if mapgen_test_path then
|
||||
mapgen_test.log_time_start("bubble_caves")
|
||||
end
|
||||
|
||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
||||
vm:get_data(data)
|
||||
vm:set_lighting({day = 0, night = 0})
|
||||
vm:get_light_data(light_data)
|
||||
|
||||
for vi, x, y, z in area:iterp_xyz(emin, emax) do
|
||||
for _, bubble in pairs(nearby_bubbles) do
|
||||
if data[vi] ~= c_air then
|
||||
local loc = bubble.loc
|
||||
local loc_x = loc.x
|
||||
local loc_y = loc.y
|
||||
local loc_z = loc.z
|
||||
local radius = bubble.radius
|
||||
-- check outer bounding box first, faster than true distance
|
||||
if x <= loc_x + radius and x >= loc_x - radius and y <= loc_y + radius and y >= loc_y - radius and z <= loc_z + radius and z >= loc_z - radius then
|
||||
local inner_box = radius * cube_inside
|
||||
if (x <= loc_x + inner_box and x >= loc_x - inner_box and y <= loc_y + inner_box and y >= loc_y - inner_box and z <= loc_z + inner_box and z >= loc_z - inner_box)
|
||||
or vector.distance({x=x, y=y, z=z}, loc) < radius+math.random()/2 then
|
||||
data[vi] = c_air
|
||||
light_data[vi] = light
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if c_glow then
|
||||
for _, bubble in pairs(nearby_bubbles) do
|
||||
local loc = bubble.loc
|
||||
if area:containsp(loc) then
|
||||
local vol = math.floor(bubble.radius / 20)
|
||||
if vol > 0 then
|
||||
for vi in area:iter(loc.x-vol, loc.y-vol, loc.z-vol, loc.x+vol, loc.y+vol, loc.z+vol) do
|
||||
if area:containsi(vi) then
|
||||
data[vi] = c_glow
|
||||
end
|
||||
end
|
||||
else
|
||||
data[area:indexp(loc)] = c_glow
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--send data back to voxelmanip
|
||||
vm:set_data(data)
|
||||
--calc lighting
|
||||
vm:set_light_data(light_data)
|
||||
vm:calc_lighting()
|
||||
vm:update_liquids()
|
||||
--write it to world
|
||||
vm:write_to_map()
|
||||
|
||||
if mapgen_test_path then
|
||||
mapgen_test.log_time_stop("bubble_caves")
|
||||
end
|
||||
|
||||
end)
|
4
bubble_caves/mod.conf
Normal file
4
bubble_caves/mod.conf
Normal file
@ -0,0 +1,4 @@
|
||||
name = bubble_caves
|
||||
description = Inserts foamy spherical bubble caves in a layer underground
|
||||
depends = mapgen_helper
|
||||
optional_depends = mapgen_test, df_underworld_items
|
Loading…
Reference in New Issue
Block a user