summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthe lemons <citrons@mondecitronne.com>2022-02-14 23:46:06 -0600
committerthe lemons <citrons@mondecitronne.com>2022-02-14 23:46:06 -0600
commitd0173cf965d48a292201a2155deca5ce7ecb6ff6 (patch)
tree6db2a67af7bcfa5de297e7030a5bab0afe0178f0
parenta666c7fbd69c56b86e8cfa48a36fdfc4b90f21c8 (diff)
create biome system
-rw-r--r--mods/vzxv_worldgen/biome.lua159
-rw-r--r--mods/vzxv_worldgen/init.lua63
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)