diff options
author | the lemons <citrons@mondecitronne.com> | 2022-02-14 23:46:06 -0600 |
---|---|---|
committer | the lemons <citrons@mondecitronne.com> | 2022-02-14 23:46:06 -0600 |
commit | d0173cf965d48a292201a2155deca5ce7ecb6ff6 (patch) | |
tree | 6db2a67af7bcfa5de297e7030a5bab0afe0178f0 | |
parent | a666c7fbd69c56b86e8cfa48a36fdfc4b90f21c8 (diff) |
create biome system
-rw-r--r-- | mods/vzxv_worldgen/biome.lua | 159 | ||||
-rw-r--r-- | mods/vzxv_worldgen/init.lua | 63 |
2 files changed, 163 insertions, 59 deletions
diff --git a/mods/vzxv_worldgen/biome.lua b/mods/vzxv_worldgen/biome.lua new file mode 100644 index 0000000..ba7e189 --- /dev/null +++ b/mods/vzxv_worldgen/biome.lua @@ -0,0 +1,159 @@ + +vzxv.biome_generator = {} + +function vzxv.biome_generator.new(minp, maxp) + local self = setmetatable({}, {__index = vzxv.biome_generator}) + self.minp = minp + self.maxp = maxp + self.generated_noisemaps = {} + self.generated_3d_noisemaps = {} + + return self +end + +local noise_params = { + elevation = { + seed = 1, + offset = -50, + scale = 50, + spread = {x=2500,y=2500,z=500}, + octaves = 5, + persistence = 0.8, + lacunarity = 2.0, + flags = "defaults, absvalue", + }, +} + +function vzxv.biome_generator:noisemap(mapname, pos) + local map = self.generated_noisemaps[mapname] + if not map then + local nm = PerlinNoiseMap(noise_params[mapname], { + x = self.maxp.x - self.minp.x + 1, + y = self.maxp.z - self.minp.z + 1, + }) + map = nm:get_2d_map { x = self.minp.x, y = self.minp.z } + self.generated_noisemaps[mapname] = map + end + return map[pos.z - self.minp.z + 1][pos.x - self.minp.x + 1] +end + +function vzxv.biome_generator:noisemap_3d(mapname, pos) + local map = self.generated_3d_noisemaps[mapname] + if not map then + local nm = PerlinNoiseMap(noise_params[mapname], { + x = self.maxp.x - self.minp.x + 1, + y = self.maxp.y - self.minp.y + 1, + z = self.maxp.z - self.minp.z + 1, + }) + map = nm:get_3d_map + { x = self.minp.x, y = self.minp.y, z = self.minp.z } + self.generated_noisemaps[mapname] = map + end + local x = pos.x - self.minp.x + 1 + local y = pos.y - self.minp.y + 1 + local z = pos.z - self.minp.z + 1 + return map[z][y][x] +end + +local water_level = 14 + +function vzxv.biome_generator:get_biome(pos) + -- TODO: underground biomes + if pos.y < -75 then + return "underground" + -- TODO: sky biomes + elseif pos.y > 120 then + return pos.y < 7500 and "sky" or "space" + else + if self:noisemap("elevation", pos) <= water_level + 2 then + return "sea" + else + -- TODO: surface biomes + return "surface" + end + end +end + +local id = minetest.get_content_id + +local biomes = {} + +function biomes.surface(pos, gen) + local height = gen:noisemap("elevation", pos) + if pos.y > height then + return + elseif pos.y == math.floor(height) then + if math.random(256) == 1 then + -- schedule trees to be generated if they haven't been + if not gen.trees_tbg then + gen.trees_tbg = {} + minetest.after(0, function() + for _, pos in ipairs(gen.trees_tbg) do + vzxv.generate_tree(pos) + end + gen.trees_tbg = {} + end) + end + table.insert(gen.trees_tbg, pos) + end + return id "vzxv:moistgrass" + elseif pos.y > height - 5 then + return id "vzxv:moistdirt" + else + return id "vzxv:stone" + end +end + +function biomes.sea(pos, gen) + local height = gen:noisemap("elevation", pos) + if pos.y > height then + if pos.y < water_level then + return id "vzxv:water" + else + return + end + elseif pos.y > height - 4 then + return id "vzxv:sand" + else + return id "vzxv:stone" + end +end + +function biomes.underground(pos) + return id "vzxv:stone" +end + +local function generate_block(gen, pos, data, va) + local biome = gen:get_biome(pos) + return biomes[biome] and biomes[biome](pos, gen, data, va) +end + +local data = {} +function vzxv.biome_generator:generate_chunk() + -- sky is empty. when sky biomes are added, add a maximum position here + if self.minp.y > 120 then + return + end + + local voxmn, vmin, vmax = minetest.get_mapgen_object "voxelmanip" + local va = VoxelArea:new { MinEdge = vmin, MaxEdge = vmax } + + voxmn:get_data(data) + for x=self.minp.x, self.maxp.x do + for z=self.minp.z, self.maxp.z do + for y=self.minp.y, self.maxp.y do + local pos = { x = x, y = y, z = z } + local block = generate_block(self, pos, data, va) + local i = va:index(x, y, z) + if block then + data[i] = block + end + end + end + end + + voxmn:set_data(data) + voxmn:update_liquids() + voxmn:write_to_map(true) + voxmn:calc_lighting() +end diff --git a/mods/vzxv_worldgen/init.lua b/mods/vzxv_worldgen/init.lua index a8d398f..17ea168 100644 --- a/mods/vzxv_worldgen/init.lua +++ b/mods/vzxv_worldgen/init.lua @@ -1,69 +1,14 @@ + minetest.set_mapgen_setting('mg_name','singlenode',true) minetest.set_mapgen_setting('flags','nolight',true) -local stone = minetest.get_content_id("vzxv:stone") -local dirt = minetest.get_content_id("vzxv:moistdirt") -local grass = minetest.get_content_id("vzxv:moistgrass") -local water = minetest.get_content_id("vzxv:water") -local sand = minetest.get_content_id("vzxv:sand") -local tree = minetest.get_content_id("vzxv_trees:seed") +vzxv.include "biome.lua" -local data = {} -local surface_height = 6 -local water_level = 14 -local trees_tbg = {} --- chunks minetest.register_on_generated(function(minp,maxp,seed) - local voxmn, vmin, vmax = minetest.get_mapgen_object("voxelmanip") - local va = VoxelArea:new{MinEdge=vmin,MaxEdge=vmax} - - local noisemap = PerlinNoiseMap({ - seed = 1, - offset = -50, - scale = 50, - spread = {x=2500,y=2500,z=500}, - octaves = 5, - persistence = 0.8, - lacunarity = 2.0, - flags = "defaults, absvalue", - }, {x=maxp.x-minp.x+1,y=maxp.z-minp.z+1}) - local heightmap = noisemap:get_2d_map{x=minp.x,y=minp.z} - - voxmn:get_data(data) - for x=minp.x, maxp.x do - for z=minp.z, maxp.z do - local height = heightmap[z-minp.z+1][x-minp.x+1] - for y=minp.y, maxp.y do - local i = va:index(x,y,z) - local underwater = y < water_level - if y < height then - local shore = height <= water_level - local surface = shore and sand or dirt - data[i] = y > height - surface_height and surface or stone - if y == math.floor(height) and not underwater then - if math.random(0,255) == 0 then - table.insert(trees_tbg,{x=x,y=y,z=z}) - end - data[i] = grass - end - elseif underwater then - data[i] = water - end - end - end - end - - voxmn:set_data(data) - voxmn:update_liquids() - voxmn:write_to_map(true) - voxmn:calc_lighting() - + local gen = vzxv.biome_generator.new(minp, maxp) + gen:generate_chunk() minetest.after(0,function() minetest.fix_light(minp,maxp) - for i, v in ipairs(trees_tbg) do - vzxv.generate_tree(v) - end - trees_tbg = {} end) end) |