155 lines
5.6 KiB
Lua
155 lines
5.6 KiB
Lua
---------------------------------------------------------------------------
|
|
-- Voxelis - Voxel survival sandbox for Luanti
|
|
-- Copyright (C) 2024 Mad Star Studio LLC
|
|
--
|
|
-- This program is free software; you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation; either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License along
|
|
-- with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
---------------------------------------------------------------------------
|
|
|
|
vox_mapgen_core = {}
|
|
|
|
-- -------------------------------------------------------------- --
|
|
-- Configuration: Noise Parameters
|
|
-- -------------------------------------------------------------- --
|
|
local noise_heat = {
|
|
offset = 50,
|
|
scale = 50,
|
|
spread = {x = 1000, y = 1000, z = 1000},
|
|
seed = 1234,
|
|
octaves = 3,
|
|
persistence = 0.5,
|
|
lacunarity = 2.0,
|
|
}
|
|
|
|
local noise_humidity = {
|
|
offset = 50,
|
|
scale = 50,
|
|
spread = {x = 1000, y = 1000, z = 1000},
|
|
seed = 5678,
|
|
octaves = 3,
|
|
persistence = 0.5,
|
|
lacunarity = 2.0,
|
|
}
|
|
|
|
local noise_altitude = {
|
|
offset = 50,
|
|
scale = 50,
|
|
spread = {x = 1000, y = 1000, z = 1000},
|
|
seed = 91011,
|
|
octaves = 3,
|
|
persistence = 0.5,
|
|
lacunarity = 2.0,
|
|
}
|
|
|
|
local biome_size_noise = {
|
|
offset = 0,
|
|
scale = 10,
|
|
spread = {x = 2000, y = 2000, z = 2000},
|
|
seed = 78910,
|
|
octaves = 2,
|
|
persistence = 0.4,
|
|
lacunarity = 2.0,
|
|
}
|
|
|
|
-- Apply noise parameters to the map generator
|
|
minetest.register_on_mapgen_init(function(mapgen_params)
|
|
minetest.set_mapgen_setting_noiseparams("heat", noise_heat, true)
|
|
minetest.set_mapgen_setting_noiseparams("humidity", noise_humidity, true)
|
|
minetest.set_mapgen_setting_noiseparams("altitude", noise_altitude, true)
|
|
end)
|
|
|
|
-- -------------------------------------------------------------- --
|
|
-- Biome Assignment Logic
|
|
-- -------------------------------------------------------------- --
|
|
local function get_biome(heat, humidity, altitude)
|
|
if heat > 70 and humidity < 30 then
|
|
return "desert"
|
|
elseif heat > 70 and humidity > 50 then
|
|
if altitude > 100 then
|
|
return "volcanic_fields"
|
|
end
|
|
return "savannah"
|
|
elseif heat > 50 and humidity > 70 then
|
|
return "tropical_rainforest"
|
|
elseif heat < 30 and humidity > 60 then
|
|
return "boreal_forest"
|
|
elseif heat < 10 and humidity > 40 then
|
|
return "frozen_tundra"
|
|
elseif altitude > 256 then
|
|
return "jade_cliffs"
|
|
else
|
|
return "grassland" -- Default biome
|
|
end
|
|
end
|
|
|
|
local function blend_biomes(current_biome, neighbor_biome, distance)
|
|
if distance < 10 and math.random() < 0.5 then
|
|
return neighbor_biome
|
|
end
|
|
return current_biome
|
|
end
|
|
|
|
-- -------------------------------------------------------------- --
|
|
-- Map Generation Logic
|
|
-- -------------------------------------------------------------- --
|
|
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
|
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
|
|
local data = vm:get_data()
|
|
|
|
-- Generate noise maps
|
|
local heat_map = minetest.get_perlin_map(noise_heat, {x = maxp.x - minp.x + 1, y = maxp.z - minp.z + 1})
|
|
local humidity_map = minetest.get_perlin_map(noise_humidity, {x = maxp.x - minp.x + 1, y = maxp.z - minp.z + 1})
|
|
local altitude_map = minetest.get_perlin_map(noise_altitude, {x = maxp.x - minp.x + 1, y = maxp.z - minp.z + 1})
|
|
local biome_size_map = minetest.get_perlin_map(biome_size_noise, {x = maxp.x - minp.x + 1, y = maxp.z - minp.z + 1})
|
|
|
|
local heat = heat_map:get_2d_map_flat({x = minp.x, y = minp.z})
|
|
local humidity = humidity_map:get_2d_map_flat({x = minp.x, y = minp.z})
|
|
local altitude = altitude_map:get_2d_map_flat({x = minp.x, y = minp.z})
|
|
local biome_sizes = biome_size_map:get_2d_map_flat({x = minp.x, y = minp.z})
|
|
|
|
for z = minp.z, maxp.z do
|
|
for x = minp.x, maxp.x do
|
|
local index2d = (z - minp.z) * (maxp.x - minp.x + 1) + (x - minp.x + 1)
|
|
local h = heat[index2d]
|
|
local hum = humidity[index2d]
|
|
local alt = altitude[index2d]
|
|
local biome_size = biome_sizes[index2d]
|
|
|
|
local current_biome = get_biome(h, hum, alt)
|
|
local neighbor_biome = get_biome(h + 5, hum + 5, alt)
|
|
current_biome = blend_biomes(current_biome, neighbor_biome, biome_size)
|
|
|
|
-- Fetch biome properties
|
|
local node_top = core.get_biome_top_node(current_biome) or "vox_worldblocks:grass"
|
|
local node_filler = core.get_biome_filler_node(current_biome) or "vox_worldblocks:dirt"
|
|
local depth_top = core.get_biome_depth_top(current_biome) or 1
|
|
local depth_filler = core.get_biome_depth_filler(current_biome) or 3
|
|
|
|
for y = minp.y, maxp.y do
|
|
local vi = area:index(x, y, z)
|
|
|
|
if y == minp.y then
|
|
data[vi] = minetest.get_content_id("vox_worldblocks:bedrock")
|
|
elseif y < -10001 then
|
|
data[vi] = minetest.get_content_id("air")
|
|
elseif y <= minp.y + depth_top then
|
|
data[vi] = minetest.get_content_id(node_top)
|
|
elseif y <= minp.y + depth_top + depth_filler then
|
|
data[vi] = minetest.get_content_id(node_filler)
|
|
else
|
|
data[vi] = minetest.get_content_id("air")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
end)
|