diff --git a/init.lua b/init.lua index 89cc87e..04d56b1 100644 --- a/init.lua +++ b/init.lua @@ -704,12 +704,13 @@ function internal.generate_caves(data, minp, maxp) ) local air = minetest.get_content_id("air") + local schems = {} -- Place blocks where necessary internal.iter_3d_area(bminp, bmaxp, function (i, pos) + local vi = vmanip:pos_to_index(pos) local function place(name) - local vi = vmanip:pos_to_index(pos) if vmanip:get_index(vi) == air then elseif type(name) == "string" then @@ -726,14 +727,6 @@ function internal.generate_caves(data, minp, maxp) elseif nt == internal.node_types.stick_edge then elseif nt == internal.node_types.air then place("air") - elseif nt == internal.node_types.floor_deco then - for _, deco in ipairs(noordstar_caves.registered_decorations) do - if deco.place_on ~= "floor" then - elseif math.random() > deco.fill_ratio then - else - -- TODO: Check for biome - end - end else -- Find appropriate biome local heat = heat_points:get_index(i) @@ -747,6 +740,32 @@ function internal.generate_caves(data, minp, maxp) place(def.node_wall) elseif nt == internal.node_types.ceiling then place(def.node_roof) + elseif nt == internal.node_types.floor_deco then + local schem_placed = false + + if not schem_placed then + -- Prevent decorations from spawning in the air + if vmanip:get_index(vi) == air then + schem_placed = true + end + end + + if not schem_placed then + for _, deco in ipairs(noordstar_caves.registered_decorations) do + if deco.place_on ~= "floor" then + elseif math.random() > deco.fill_ratio then + elseif not internal.is_deco_biome(deco, def.name) then + else + table.insert(schems, { pos = pos, deco = deco }) + schem_placed = true + break + end + end + end + + if not schem_placed then + place(def.node_dust or "air") + end else error( table.concat( @@ -763,7 +782,7 @@ function internal.generate_caves(data, minp, maxp) end end) - return vmanip.arr + return vmanip.arr, schems end -- Get the noise params for the cave biome temperature. @@ -799,6 +818,23 @@ function internal.is_cave_node(noise, vastness) return noise > 1 - vastness end +-- Return whether a given decoration definition can spawn in a given biome name +function internal.is_deco_biome(def, biome_name) + if type(def.biomes) == "nil" then + return true + elseif type(def.biomes) == "string" then + return def.biomes == biome_name + elseif type(def.biomes) == "table" then + for _, name in pairs(def.biomes) do + if name == biome_name then + return true + end + end + end + + return false +end + -- Return a bool whether a position is within a given volume function internal.is_valid_pos(pos, minp, maxp) if minp.x <= pos.x and pos.x <= maxp.x then @@ -869,6 +905,80 @@ end -- minetest.chat_send_all(os.time() .. " - " .. text) -- end +-- Place a table full of schematics into the world +function internal.place_schematics(schems) + for _, schem in ipairs(schems) do + local pos = schem.pos + local deco = schem.deco + + if deco.deco_type == "simple" then + local h_min = deco.height + local h_max = math.max(deco.height_max, deco.height) + local dy = deco.place_offset_y - 1 + + if deco.place_on == "floor" then + for y = 1, math.random(h_min, h_max), 1 do + + minetest.set_node( + { x = pos.x, y = pos.y + y + dy, z = pos.z }, + { name = deco.decoration } + ) + end + elseif deco.place_on == "ceiling" then + for y = 1, math.random(h_min, h_max), 1 do + + minetest.set_node( + { x = pos.x, y = pos.y - y - dy, z = pos.z }, + { name = deco.decoration } + ) + end + else + error("Unknown place_on parameter `" .. deco.place_on .. "` for simple decoration!") + end + elseif deco.deco_type == "schematic" then + local name = deco.schematic + local force_placement = true + if string.find("force_placement", deco.flags) then + force_placement = true + end + + if deco.place_on == "floor" then + local n = minetest.place_schematic( + pos, name, deco.rotation, deco.replacements, + force_placement, deco.flags + ) + + if type(n) == "nil" then + minetest.chat_send_all("Squeak could not load!") + else + minetest.chat_send_all("Placed a Squeak!") + if not tpd_yet then + minetest.get_player_by_name("singleplayer"):move_to(pos) + tpd_yet = true + minetest.chat_send_all(internal.pos_to_str(pos)) + end + end + elseif deco.place_on == "ceiling" then + -- Aim to place schematic against the ceiling, not through it + local h = minetest.read_schematic(name).size.y + local c_pos = { x = pos.x, y = pos.y - h, z = pos.z } + if string.find("place_center_y", deco.flags) then + c_pos = pos + end + + minetest.place_schematic( + pos, name, deco.rotation, deco.replacements, + force_placement, deco.flags + ) + else + error("Unknown place_on parameter `" .. deco.place_on .. "` for simple decoration!") + end + else + error("Unknown decoration type `" .. deco.deco_type .. "`") + end + end +end + -- Helper function to convert a set of coordinates to a readable string function internal.pos_to_str(pos) return "(" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. " )" @@ -1090,13 +1200,17 @@ end ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- minetest.register_on_generated(function(minp, maxp, blockseed) + math.randomseed(blockseed) + local vm = minetest.get_mapgen_object("voxelmanip") local data = vm:get_data() - data = internal.generate_caves(data, minp, maxp) + data, schems = internal.generate_caves(data, minp, maxp) vm:set_data(data) vm:write_to_map() + + internal.place_schematics(schems) end) ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- @@ -1202,6 +1316,7 @@ noordstar_caves.register_biome({ node_floor = "mcl_core:crying_obsidian", node_wall = "mcl_core:sand", node_roof = "mcl_ocean:sea_lantern", + node_dust = "mcl_core:snow", heat_point = 0, humidity_point = 0, }) @@ -1213,3 +1328,21 @@ noordstar_caves.register_biome({ heat_point = 100, humidity_point = 100, }) + +noordstar_caves.register_decoration({ + deco_type = "simple", + place_on = "floor", + fill_ratio = 0.01, + decoration = "mcl_core:cactus", + height = 3, + height_max = 8, + biomes = { "test" }, +}) +noordstar_caves.register_decoration({ + deco_type = "schematic", + place_on = "floor", + fill_ratio = 0.005, + schematic = "test.mts", + rotation = "random", + place_offset_y = 5, +})