Voxelis/mods/MAPGEN/vox_mapgen_core/init.lua
DesertMermaid a260c4a33a
All checks were successful
Error Check / luacheck_errcheck (push) Successful in 37s
Unit Tests / busted_unit_test (push) Successful in 48s
More work being done. And... bugs.
2024-12-11 14:47:15 -08:00

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)