diff --git a/deco.lua b/deco.lua index 62a7a23..dbcb2f5 100644 --- a/deco.lua +++ b/deco.lua @@ -34,12 +34,9 @@ minetest.register_craft({ minetest.add_group("default:cactus", {oddly_breakable_by_hand=1}) dofile(fun_caves.path.."/deco_caves.lua") ---dofile(fun_caves.path.."/deco_coral.lua") --dofile(fun_caves.path.."/deco_dirt.lua") ---dofile(fun_caves.path.."/deco_trees.lua") ---dofile(fun_caves.path.."/deco_plants.lua") +dofile(fun_caves.path.."/deco_plants.lua") --dofile(fun_caves.path.."/deco_rocks.lua") ---dofile(fun_caves.path.."/deco_fungal_tree.lua") --dofile(fun_caves.path.."/deco_ferns.lua") --dofile(fun_caves.path.."/deco_ferns_tree.lua") ---dofile(fun_caves.path.."/deco_water.lua") +dofile(fun_caves.path.."/deco_water.lua") diff --git a/deco_caves.lua b/deco_caves.lua index 4fc8d95..be8c57c 100644 --- a/deco_caves.lua +++ b/deco_caves.lua @@ -2,6 +2,10 @@ local node = fun_caves.node local min_surface = -80 function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) + if not (data[ivm] == node("air") or data[ivm] == node("default:stone")) then + return + end + local ivm_below = ivm - area.ystride local ivm_above = ivm + area.ystride local biome_val = biome_val_in @@ -9,7 +13,6 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) ------------------- local stone_type = node("default:stone") local stone_depth = 1 - local air_count = 0 if y > -500 then biome_val = biome_val / math.max(1, math.log(500 + y)) @@ -34,9 +37,6 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) elseif biome_val < 0.35 then stone_type = node("fun_caves:stone_with_salt") stone_depth = 2 - if data[ivm] == node("default:stone") then - return stone_type - end elseif biome_val < 0.5 then stone_type = node("default:sand") stone_depth = 2 @@ -54,45 +54,44 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) end local node_above = data[ivm + area.ystride] - local air_above = false - for i = 1, stone_depth do - if data[ivm + area.ystride * i] == node("air") then - air_above = true + if data[ivm] == node("default:stone") then + local air_above = false + for i = 1, stone_depth do + if data[ivm + area.ystride * i] == node("air") then + air_above = true + end end - end - if data[ivm] == node("default:stone") and (stone_type == node("fun_caves:stone_with_algae") or stone_type == node("fun_caves:stone_with_lichen")) and node_above == node("air") and math.random(3) == 1 then - return node("dirt") - end - - if data[ivm] == node("default:stone") and air_above then - if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then - return node("fun_caves:radioactive_ore") - else - return stone_type + if node_above == node("air") and (stone_type == node("fun_caves:stone_with_algae") or stone_type == node("fun_caves:stone_with_lichen")) and math.random(4) == 1 then + return node("dirt") end - end - local air_below = false - for i = 1, stone_depth do - if data[ivm - area.ystride * i] == node("air") then - air_below = true + if air_above then + if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then + return node("fun_caves:radioactive_ore") + elseif node_above == node("air") and stone_type == node("fun_caves:stone_with_moss") and math.random(50) == 1 then + return node("fun_caves:glowing_fungal_stone") + else + return stone_type + end end - end - if data[ivm] == node("default:stone") and air_below then - if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then - return node("fun_caves:radioactive_ore") - else - return stone_type + local air_below = false + for i = 1, stone_depth do + if data[ivm - area.ystride * i] == node("air") then + air_below = true + end end - end - if node_below == node("air") and (data[ivm] == node("fun_caves:stone_with_lichen") or data[ivm] == node("fun_caves:stone_with_moss")) and math.random(50) == 1 then - return node("fun_caves:glowing_fungal_stone") - end - if node_above == node("air") and data[ivm] == node("fun_caves:stone_with_moss") and math.random(50) == 1 then - return node("fun_caves:glowing_fungal_stone") + if data[ivm] == node("default:stone") and air_below then + if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then + return node("fun_caves:radioactive_ore") + elseif node_below == node("air") and (stone_type == node("fun_caves:stone_with_lichen") or stone_type == node("fun_caves:stone_with_moss")) and math.random(50) == 1 then + return node("fun_caves:glowing_fungal_stone") + else + return stone_type + end + end end if data[ivm] == node("air") then @@ -114,11 +113,11 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) end -- fluids - --if y < min_surface and (node_below == node("default:stone") or node_below == node("fun_caves:hot_cobble")) and sr < 3 then if y > minp.y and (node_below == node("default:stone") or node_below == node("fun_caves:hot_cobble")) and sr < 3 then return node("default:lava_source") elseif node_below == node("fun_caves:stone_with_moss") and sr < 3 then return node("default:water_source") + -- standing up elseif node_below == node("default:ice") and sr < 80 then return node("fun_caves:icicle_up") @@ -138,6 +137,7 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) end elseif node_below == node("default:coalblock") and sr < 20 then return node("fun_caves:constant_flame") + -- vegetation elseif node_below == node("default:dirt") and (stone_type == node("fun_caves:stone_with_lichen") or stone_type == node("fun_caves:stone_with_algae")) and biome_val >= -0.5 then if sr < 110 then @@ -147,6 +147,7 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) elseif node_above == node("air") and sr < 330 then return node("fun_caves:giant_mushroom_stem") elseif sr < 360 then + local air_count = 0 for i = 1, 12 do local j = ivm + area.ystride * i if j <= #data and data[j] == node("air") then @@ -155,7 +156,6 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) end if air_count > 5 then fun_caves.make_fungal_tree(data, area, ivm, math.random(2,math.min(air_count, 12)), node(fun_caves.fungal_tree_leaves[math.random(1,#fun_caves.fungal_tree_leaves)]), node("fun_caves:fungal_tree_fruit")) - --node_below = node("dirt") end end elseif node_below == node("fun_caves:giant_mushroom_stem") and data[ivm - area.ystride * 2] == node("fun_caves:giant_mushroom_stem") then @@ -167,151 +167,5 @@ function fun_caves.decorate_cave(data, area, minp, y, ivm, biome_val_in) return node("fun_caves:huge_mushroom_cap") end end - - if data[ivm] == node("air") then - air_count = air_count + 1 - end end end - ---function original_fun_caves_decorate_cave(data, area) --- local ivm_below = ivm - area.ystride --- local ivm_above = ivm + area.ystride --- local dy = y - minp.y --- --- ------------------- --- local stone_type = node("default:stone") --- local stone_depth = 1 --- local biome_val = biome_n[index3d] --- if y > -500 then --- biome_val = biome_val / math.max(1, math.log(500 + y)) --- end --- ------------------- --- --biome_val = 0.7 --- ------------------- --- if biome_val < -0.6 then --- if true then --- stone_type = node("default:ice") --- stone_depth = 2 --- else --- stone_type = node("fun_caves:thinice") --- stone_depth = 2 --- end --- elseif biome_val < -0.5 then --- stone_type = node("fun_caves:stone_with_lichen") --- elseif biome_val < -0.3 then --- stone_type = node("fun_caves:stone_with_moss") --- elseif biome_val < -0.0 then --- stone_type = node("fun_caves:stone_with_lichen") --- elseif biome_val < 0.2 then --- stone_type = node("fun_caves:stone_with_algae") --- elseif biome_val < 0.35 then --- stone_type = node("fun_caves:stone_with_salt") --- stone_depth = 2 --- if data[ivm] == node("default:stone") then --- data[ivm] = stone_type --- end --- elseif biome_val < 0.5 then --- stone_type = node("default:sand") --- stone_depth = 2 --- elseif biome_val < 0.6 then --- stone_type = node("default:coalblock") --- stone_depth = 2 --- else --- stone_type = node("fun_caves:hot_cobble") --- end --- -- "glow" --- --- if data[ivm] == node("air") then --- -- Change stone per biome. --- if data[ivm_below] == node("default:stone") or (stone_type == node("fun_caves:stone_with_salt") and data[ivm_below] ~= node("fun_caves:stone_with_salt") and data[ivm_below] ~= node("air")) then --- data[ivm_below] = stone_type --- if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then --- data[ivm_below - area.ystride] = node("fun_caves:radioactive_ore") --- elseif stone_depth == 2 then --- data[ivm_below - area.ystride] = stone_type --- end --- end --- if data[ivm_above] == node("default:stone") or (stone_type == node("fun_caves:stone_with_salt") and data[ivm_above] ~= node("fun_caves:stone_with_salt") and data[ivm_above] ~= node("air")) then --- data[ivm_above] = stone_type --- if stone_type == node("fun_caves:stone_with_salt") and math.random(500) == 1 then --- data[ivm_above - area.ystride] = node("fun_caves:radioactive_ore") --- elseif stone_depth == 2 then --- data[ivm_above + area.ystride] = stone_type --- end --- end --- --- if (data[ivm_above] == node("fun_caves:stone_with_lichen") or data[ivm_above] == node("fun_caves:stone_with_moss")) and math.random(1,50) == 1 then --- data[ivm_above] = node("fun_caves:glowing_fungal_stone") --- end --- --- if data[ivm] == node("air") then --- local sr = math.random(1,1000) --- --- -- fluids --- if (data[ivm_below] == node("default:stone") or data[ivm_below] == node("fun_caves:hot_cobble")) and sr < 3 then --- data[ivm] = node("default:lava_source") --- elseif data[ivm_below] == node("fun_caves:stone_with_moss") and sr < 3 then --- data[ivm] = node("default:water_source") --- -- hanging down --- elseif data[ivm_above] == node("default:ice") and sr < 80 then --- data[ivm] = node("fun_caves:icicle_down") --- elseif (data[ivm_above] == node("fun_caves:stone_with_lichen") or data[ivm_above] == node("fun_caves:stone_with_moss") or data[ivm_above] == node("fun_caves:stone_with_algae") or data[ivm_above] == node("default:stone")) and sr < 80 then --- if data[ivm_above] == node("fun_caves:stone_with_algae") then --- data[ivm] = node("fun_caves:stalactite_slimy") --- elseif data[ivm_above] == node("fun_caves:stone_with_moss") then --- data[ivm] = node("fun_caves:stalactite_mossy") --- else --- data[ivm] = node("fun_caves:stalactite") --- end --- -- standing up --- elseif data[ivm_below] == node("fun_caves:hot_cobble") and sr < 20 then --- if sr < 10 then --- data[ivm] = node("fun_caves:hot_spike") --- else --- data[ivm] = node("fun_caves:hot_spike_"..(math.ceil(sr / 3) - 2)) --- end --- elseif data[ivm_below] == node("default:coalblock") and sr < 20 then --- data[ivm] = node("fun_caves:constant_flame") --- elseif data[ivm_below] == node("default:ice") and sr < 80 then --- data[ivm] = node("fun_caves:icicle_up") --- elseif (data[ivm_below] == node("fun_caves:stone_with_lichen") or data[ivm_below] == node("fun_caves:stone_with_algae") or data[ivm_below] == node("default:stone") or data[ivm_below] == node("fun_caves:stone_with_moss")) and sr < 80 then --- if data[ivm_below] == node("fun_caves:stone_with_algae") then --- data[ivm] = node("fun_caves:stalagmite_slimy") --- elseif data[ivm_below] == node("fun_caves:stone_with_moss") then --- data[ivm] = node("fun_caves:stalagmite_mossy") --- elseif data[ivm_below] == node("fun_caves:stone_with_lichen") or data[ivm_above] == node("default:stone") then --- data[ivm] = node("fun_caves:stalagmite") --- end --- elseif data[ivm_below] == node("fun_caves:stone_with_moss") and sr < 90 then --- data[ivm_below] = node("fun_caves:glowing_fungal_stone") --- -- vegetation --- elseif (data[ivm_below] == node("fun_caves:stone_with_lichen") or data[ivm_below] == node("fun_caves:stone_with_algae")) and biome_val >= -0.5 then --- if sr < 110 then --- data[ivm] = node("flowers:mushroom_red") --- elseif sr < 140 then --- data[ivm] = node("flowers:mushroom_brown") --- elseif air_count > 1 and sr < 160 then --- data[ivm_above] = node("fun_caves:huge_mushroom_cap") --- data[ivm] = node("fun_caves:giant_mushroom_stem") --- elseif air_count > 2 and sr < 170 then --- data[ivm + 2 * area.ystride] = node("fun_caves:giant_mushroom_cap") --- data[ivm_above] = node("fun_caves:giant_mushroom_stem") --- data[ivm] = node("fun_caves:giant_mushroom_stem") --- elseif air_count > 5 and sr < 180 then --- fun_caves.make_fungal_tree(data, area, ivm, math.random(2,math.min(air_count, 12)), node(fun_caves.fungal_tree_leaves[math.random(1,#fun_caves.fungal_tree_leaves)]), node("fun_caves:fungal_tree_fruit")) --- data[ivm_below] = node("dirt") --- elseif sr < 300 then --- data[ivm_below] = node("dirt") --- end --- if data[ivm] ~= node("air") then --- data[ivm_below] = node("dirt") --- end --- end --- end --- --- if data[ivm] == node("air") then --- air_count = air_count + 1 --- end --- end ---end diff --git a/deco_coral.lua b/deco_coral.lua deleted file mode 100644 index 7968ce3..0000000 --- a/deco_coral.lua +++ /dev/null @@ -1,97 +0,0 @@ - -minetest.register_node("fun_caves:pillar_coral", { - description = "Pillar Coral", - tiles = {"fun_caves_pillar_coral.png"}, - paramtype = "light", - light_source = 2, - groups = {cracky = 3, stone=1}, - sounds = default.node_sound_stone_defaults(), -}) - - -minetest.register_node("fun_caves:brain_coral", { - description = "Brain Coral", - tiles = {"fun_caves_brain_coral.png"}, - light_source = 4, - groups = {cracky = 3, stone=1,}, - sounds = default.node_sound_stone_defaults(), -}) - - -minetest.register_node("fun_caves:dragon_eye", { - description = "Dragon Eye", - tiles = {"fun_caves_dragon_eye.png"}, - light_source = 4, - groups = {cracky = 3, stone=1,}, - sounds = default.node_sound_stone_defaults(), -}) - - -minetest.register_node("fun_caves:staghorn_coral", { - description = "Staghorn Coral", - drawtype = "plantlike", - tiles = {"fun_caves_staghorn_coral.png"}, - waving = false, - sunlight_propagates = true, - paramtype = "light", - light_source = 2, - walkable = false, - groups = {cracky = 3, stone=1, attached_node=1, sea=1}, - sounds = default.node_sound_stone_defaults(), - selection_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}, - }, -}) - -function fun_caves.sea_plants() - if y >= light_depth and (data[index_3d] == node["sand"] or data[index_3d] == node["dirt"]) and (data[index_3d_above] == node["water_source"] or data[index_3d_above] == node["river_water_source"]) then - -- Check the biomes and plant water plants, if called for. - biome = valc.biome_ids[biomemap[index_2d]] - if y < water_level and data[index_3d_above + ystride] == node["water_source"] and table.contains(coral_biomes, biome) and n21[index_2d] < -0.1 and math_random(1,3) ~= 1 then - sr = math_random(1,100) - if sr < 4 then - data[index_3d_above] = node["brain_coral"] - elseif sr < 6 then - data[index_3d_above] = node["dragon_eye"] - elseif sr < 35 then - data[index_3d_above] = node["staghorn_coral"] - elseif sr < 100 then - data[index_3d_above] = node["pillar_coral"] - end - elseif surround then - for _, desc in pairs(valc.water_plants) do - placeable = false - - if not node_match_cache[desc] then - node_match_cache[desc] = {} - end - - if node_match_cache[desc][data[index_3d]] then - placeable = node_match_cache[desc][data[index_3d]] - else - -- This is a great way to match all node type strings - -- against a given node (or nodes). However, it's slow. - -- To speed it up, we cache the results for each plant - -- on each node, and avoid calling find_nodes every time. - pos, count = minetest.find_nodes_in_area({x=x,y=y,z=z}, {x=x,y=y,z=z}, desc.place_on) - if #pos > 0 then - placeable = true - end - node_match_cache[desc][data[index_3d]] = placeable - end - - if placeable and desc.fill_ratio and desc.content_id then - biome = valc.biome_ids[biomemap[index_2d]] - - if not desc.biomes or (biome and desc.biomes and table.contains(desc.biomes, biome)) then - if math_random() <= desc.fill_ratio then - data[index_3d] = desc.content_id - write = true - end - end - end - end - end - end -end diff --git a/deco_plants.lua b/deco_plants.lua new file mode 100644 index 0000000..e01270d --- /dev/null +++ b/deco_plants.lua @@ -0,0 +1,209 @@ +fun_caves.water_plants = {} +function fun_caves.register_water_plant(desc) + fun_caves.water_plants[#fun_caves.water_plants+1] = desc +end + + +minetest.register_node("fun_caves:pillar_coral", { + description = "Pillar Coral", + tiles = {"fun_caves_pillar_coral.png"}, + paramtype = "light", + light_source = 2, + groups = {cracky = 3, stone=1}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("fun_caves:brain_coral", { + description = "Brain Coral", + tiles = {"fun_caves_brain_coral.png"}, + light_source = 4, + groups = {cracky = 3, stone=1,}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("fun_caves:dragon_eye", { + description = "Dragon Eye", + tiles = {"fun_caves_dragon_eye.png"}, + light_source = 4, + groups = {cracky = 3, stone=1,}, + sounds = default.node_sound_stone_defaults(), +}) + + +fun_caves.plantlist = { + {name="staghorn_coral", + desc="Staghorn Coral", + water=true, + light_source=1, + coral=true, + sounds = default.node_sound_stone_defaults(), + }, + + {name="water_plant_1", + desc="Water Plant", + water=true, + }, + + {name="bird_of_paradise", + desc="Bird of Paradise", + light=true, + groups={flower=1}, + }, + + {name="gerbera", + desc="Gerbera", + light=true, + groups={flower=1, color_pink=1}, + }, + + {name="hibiscus", + desc="Hibiscus", + wave=true, + groups={flower=1, color_white=1}, + }, + + {name="orchid", + desc="Orchid", + wave=true, + light=true, + groups={flower=1, color_white=1}, + }, +} + + +for _, plant in ipairs(fun_caves.plantlist) do + if plant.coral then + groups = {cracky=3, stone=1, attached_node=1} + else + groups = {snappy=3,flammable=2,flora=1,attached_node=1} + end + if plant.groups then + for k,v in pairs(plant.groups) do + groups[k] = v + end + end + + minetest.register_node("fun_caves:"..plant.name, { + description = plant.desc, + drawtype = "plantlike", + tiles = {"fun_caves_"..plant.name..".png"}, + waving = plant.wave, + sunlight_propagates = plant.light, + paramtype = "light", + walkable = false, + groups = groups, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}, + }, + }) + + if plant.water then + local def = { + description = plant.desc, + drawtype = "nodebox", + node_box = {type='fixed', fixed={{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, {-0.5, 0.5, -0.001, 0.5, 1.5, 0.001}, {-0.001, 0.5, -0.5, 0.001, 1.5, 0.5}}}, + drop = {max_items=2, items={{items={"fun_caves:"..plant.name}, rarity=1}, {items={"default:sand"}, rarity=1}}}, + tiles = { "default_sand.png", "fun_caves_"..plant.name..".png",}, + --tiles = { "default_dirt.png", "fun_caves_"..plant.name..".png",}, + sunlight_propagates = plant.light, + --light_source = 14, + paramtype = "light", + light_source = plant.light_source, + walkable = false, + groups = groups, + selection_box = { + type = "fixed", + fixed = {-0.5, 0.5, -0.5, 0.5, 11/16, 0.5}, + }, + sounds = plant.sounds or default.node_sound_leaves_defaults(), + } + minetest.register_node("fun_caves:"..plant.name.."_water_sand", def) + def2 = table.copy(def) + def2.tiles = { "default_dirt.png", "fun_caves_"..plant.name..".png",} + def2.drop = {max_items=2, items={{items={"fun_caves:"..plant.name}, rarity=1}, {items={"default:dirt"}, rarity=1}}} + minetest.register_node("fun_caves:"..plant.name.."_water_soil", def2) + end +end + + +local function register_flower(name, seed, biomes) + local param = { + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = -0.02, + scale = 0.03, + spread = {x = 200, y = 200, z = 200}, + seed = seed, + octaves = 3, + persist = 0.6 + }, + biomes = biomes, + y_min = 6, + y_max = 31000, + decoration = "fun_caves:"..name, + } + + -- Let rainforest plants show up more often. + local key1 = table.contains(biomes, "rainforest") + --local key2 = table.contains(biomes, "desertstone_grassland") + --if key1 or key2 then + if key1 then + if key1 then + table.remove(param.biomes, key1) + --else + -- table.remove(param.biomes, key2) + end + if #param.biomes > 0 then + minetest.register_decoration(param) + end + + local param2 = table.copy(param) + --param2.biomes = {"rainforest", "desertstone_grassland", } + param2.biomes = {"rainforest", } + param2.noise_params.seed = param2.noise_params.seed + 20 + param2.noise_params.offset = param2.noise_params.offset + 0.01 + minetest.register_decoration(param2) + else + minetest.register_decoration(param) + end +end + +register_flower("bird_of_paradise", 8402, {"rainforest", }) +register_flower("orchid", 3944, {"sandstone_grassland", "tundra", "taiga", "stone_grassland", "coniferous_forest", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp", }) +register_flower("hibiscus", 7831, {"sandstone_grassland", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp", }) +--register_flower("calla_lily", 7985, {"sandstone_grassland", "stone_grassland", "deciduous_forest", "rainforest", }) +register_flower("gerbera", 1976, {"savanna", "rainforest", }) + +do + -- Water Plant + local water_plant_1_def_sand = { + fill_ratio = 0.05, + place_on = {"group:sand"}, + decoration = {"fun_caves:water_plant_1_water_sand"}, + --biomes = {"sandstone_grassland", "stone_grassland", "coniferous_forest", "deciduous_forest", "desert", "savanna", "rainforest", "rainforest_swamp", }, + biomes = {"sandstone_grassland", "stone_grassland", "coniferous_forest", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp","sandstone_grassland_ocean", "stone_grassland_ocean", "coniferous_forest_ocean", "deciduous_forest_ocean", "desert_ocean", "savanna_ocean", }, + y_max = 60, + } + local water_plant_1_def_soil = table.copy(water_plant_1_def_sand) + water_plant_1_def_soil.place_on = {"group:soil"} + water_plant_1_def_soil.decoration = {"fun_caves:water_plant_1_water_soil",} + + fun_caves.register_water_plant(water_plant_1_def_sand) + fun_caves.register_water_plant(water_plant_1_def_soil) +end + + +-- Get the content ids for all registered water plants. +for _, desc in pairs(fun_caves.water_plants) do + if type(desc.decoration) == 'string' then + desc.content_id = minetest.get_content_id(desc.decoration) + elseif type(desc.decoration) == 'table' then + desc.content_id = minetest.get_content_id(desc.decoration[1]) + end +end diff --git a/deco_water.lua b/deco_water.lua new file mode 100644 index 0000000..5a39de9 --- /dev/null +++ b/deco_water.lua @@ -0,0 +1,102 @@ +local node = fun_caves.node +local light_depth = -13 +local water_level = 1 + +local water_lily_biomes = {} +for _, i in pairs({"rainforest_swamp", "rainforest", "savanna_swamp", "savanna", "deciduous_forest_swamp", "deciduous_forest", }) do + water_lily_biomes[i] = true +end +local coral_biomes = {} +for _, i in pairs({"desert_ocean", "savanna_ocean", "rainforest_ocean", }) do + coral_biomes[i] = true +end + +plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = 33, octaves = 3, persist = 0.7, lacunarity = 2.0} + +local function surround(data, area, ivm) + local n + + -- Check to make sure that a plant root is fully surrounded. + -- This is due to the kludgy way you have to make water plants + -- in minetest, to avoid bubbles. + for x1 = -1,1,2 do + n = data[ivm+x1] + if n == node("default:river_water_source") or n == node("default:water_source") or n == node("air") then + return false + end + end + for z1 = -area.zstride,area.zstride,2*area.zstride do + n = data[ivm+z1] + if n == node("default:river_water_source") or n == node("default:water_source") or n == node("air") then + return false + end + end + + return true +end + +function fun_caves.decorate_water(data, area, minp, maxp, pos, ivm, biome_in, pn) + if pos.y < light_depth then + return + end + + local biome = biome_in + + local node_below = data[ivm - area.ystride] + local node_above = data[ivm + area.ystride] + + local inside = false + if pos.x < maxp.x and pos.y < maxp.y and pos.z < maxp.z and pos.x > minp.x and pos.y > minp.y and pos.z > minp.z then + inside = true + end + + if pos.y < water_level and data[ivm] == node("default:sand") and node_above == node("default:water_source") and data[ivm + area.ystride * 2] == node("default:water_source") and coral_biomes[biome] and pn < -0.1 and math.random(5) == 1 and surround(data, area, ivm) then + return node("fun_caves:staghorn_coral_water_sand") + elseif pos.y < water_level and node_below == node("default:sand") and node_above == node("default:water_source") and data[ivm] == node("default:water_source") and coral_biomes[biome] and pn < -0.1 and math.random(5) < 3 then + local sr = math.random(65) + if sr < 4 then + return node("fun_caves:brain_coral") + elseif sr < 6 then + return node("fun_caves:dragon_eye") + elseif sr < 65 then + return node("fun_caves:pillar_coral") + end + elseif inside and (node_above == node("default:water_source") or node_above == node("default:river_water_source")) and (data[ivm] == node("default:sand") or data[ivm] == node("default:dirt")) then + -- Check the biomes and plant water plants, if called for. + if not surround(data, area, ivm) then + return + end + + for _, desc in pairs(fun_caves.water_plants) do + if desc.content_id then + if not fun_caves.node_match_cache[desc.content_id] then + fun_caves.node_match_cache[desc.content_id] = {} + end + + if not fun_caves.node_match_cache[desc.content_id][data[ivm]] then + -- This is a great way to match all node type strings + -- against a given node (or nodes). However, it's slow. + -- To speed it up, we cache the results for each plant + -- on each node, and avoid calling find_nodes every time. + local posm, count = minetest.find_nodes_in_area(pos, pos, desc.place_on) + if #posm > 0 then + fun_caves.node_match_cache[desc.content_id][data[ivm]] = "good" + else + fun_caves.node_match_cache[desc.content_id][data[ivm]] = "bad" + end + end + + if fun_caves.node_match_cache[desc.content_id][data[ivm]] == "good" and desc.fill_ratio and (not desc.biomes or (biome and desc.biomes and table.contains(desc.biomes, biome))) and math.random() <= desc.fill_ratio then + return desc.content_id + end + end + end + elseif pos.y > minp.y and node_below == node("default:river_water_source") and data[ivm] == node("air") then + -- on top of the water + -- I haven't figured out what the decoration manager is + -- doing with the noise functions, but this works ok. + if water_lily_biomes[biome] and pn > 0.5 and math.random(15) == 1 then + return node("flowers:waterlily") + end + end +end diff --git a/init.lua b/init.lua index 71fc024..b57de02 100644 --- a/init.lua +++ b/init.lua @@ -3,6 +3,7 @@ fun_caves.version = "1.0" fun_caves.path = minetest.get_modpath(minetest.get_current_modname()) fun_caves.world = false fun_caves.time_factor = 10 +fun_caves.node_match_cache = {} minetest.register_on_mapgen_init(function(mgparams) diff --git a/mapgen.lua b/mapgen.lua index 2ffe364..f2ca6bd 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -16,6 +16,15 @@ local data = {} local vm, emin, emax, area, noise_area, csize local minp, maxp +-- Create a table of biome ids, so I can use the biomemap. +if not fun_caves.biome_ids then + fun_caves.biome_ids = {} + for name, desc in pairs(minetest.registered_biomes) do + local i = minetest.get_biome_id(desc.name) + fun_caves.biome_ids[i] = desc.name + end +end + local function place_schematic(pos, schem, center) local rot = math.random(4) - 1 local yslice = {} @@ -84,37 +93,44 @@ local function get_decoration(biome) end +local function detect_bull(heightmap, csize) + local j = -31000 + local k = 0 + local cutoff = (csize.x * csize.z) * 0.3 + for i = 1, #heightmap do + if j == heightmap[i] then + k = k + 1 + if k > cutoff then + return true + end + else + k = 0 + end + j = heightmap[i] + end + + return false +end + + function fun_caves.generate(p_minp, p_maxp, seed) minp, maxp = p_minp, p_maxp vm, emin, emax = minetest.get_mapgen_object("voxelmanip") vm:get_data(data) --p2data = vm:get_param2_data() local heightmap = minetest.get_mapgen_object("heightmap") + local biomemap = minetest.get_mapgen_object("biomemap") area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) csize = vector.add(vector.subtract(maxp, minp), 1) noise_area = VoxelArea:new({MinEdge={x=0,y=0,z=0}, MaxEdge=vector.subtract(csize, 1)}) -- There's a bug in the heightmap from valleys_c. Check for it. - local bullshit_heightmap = false - do - local j = -31000 - local k = 0 - for i = 1, #heightmap do - if j == heightmap[i] then - k = k + 1 - if k > (csize.x ^ 2) * 0.5 then - bullshit_heightmap = true - end - else - k = 0 - end - j = heightmap[i] - end - end + local bullshit_heightmap = detect_bull(heightmap, csize) + local write = false -- Deal with memory issues. This, of course, is supposed to be automatic. local mem = math.floor(collectgarbage("count")/1024) - if mem > 300 then + if mem > 200 then print("Fun Caves: Manually collecting garbage...") collectgarbage("collect") end @@ -138,9 +154,11 @@ function fun_caves.generate(p_minp, p_maxp, seed) local ivm = area:index(x, minp.y, z) for y = minp.y, maxp.y do - if (y < min_surface or bullshit_heightmap or y < heightmap[index] - cave_3[index]) and cave_1[index3d] * cave_2[index3d] > 0.05 then + if (y < min_surface or (bullshit_heightmap and y < 0) or y < heightmap[index] - cave_3[index]) and cave_1[index3d] * cave_2[index3d] > 0.05 then data[ivm] = node("air") - if y > min_surface and cave_3[index] < 1 and heightmap[index] == y and y > 0 then + write = true + + if y > 0 and cave_3[index] < 1 and heightmap[index] == y then local ivm2 = ivm for y2 = y + 1, maxp.y + 8 do ivm2 = ivm2 + area.ystride @@ -157,6 +175,7 @@ function fun_caves.generate(p_minp, p_maxp, seed) end end + -- Air needs to be placed prior to decorations. local index = 0 local index3d = 0 for z = minp.z, maxp.z do @@ -172,12 +191,21 @@ function fun_caves.generate(p_minp, p_maxp, seed) local i = fun_caves.decorate_cave(data, area, minp, y, ivm, biome_n[index3d]) if i then data[ivm] = i + write = true end elseif y < heightmap[index] and not bullshit_heightmap then local ivm_below = ivm - area.ystride if data[ivm] == node("air") and data[ivm_below] ~= node('air') then data[ivm_below] = node("dirt") end + else + local pn = minetest.get_perlin(plant_noise):get2d({x=x, y=z}) + local biome = fun_caves.biome_ids[biomemap[index]] + local i = fun_caves.decorate_water(data, area, minp, maxp, {x=x,y=y,z=z}, ivm, biome, pn) + if i then + data[ivm] = i + write = true + end end ivm = ivm + area.ystride @@ -187,15 +215,17 @@ function fun_caves.generate(p_minp, p_maxp, seed) end - vm:set_data(data) - --vm:set_param2_data(p2data) - if DEBUG then - vm:set_lighting({day = 15, night = 15}) - else - vm:calc_lighting() + if write then + vm:set_data(data) + --vm:set_param2_data(p2data) + if DEBUG then + vm:set_lighting({day = 15, night = 15}) + else + vm:calc_lighting() + end + vm:update_liquids() + vm:write_to_map() end - vm:update_liquids() - vm:write_to_map() vm, area, noise_area = nil, nil, nil end diff --git a/textures/fun_caves_bird_of_paradise.png b/textures/fun_caves_bird_of_paradise.png new file mode 100644 index 0000000..e0534c0 Binary files /dev/null and b/textures/fun_caves_bird_of_paradise.png differ diff --git a/textures/fun_caves_gerbera.png b/textures/fun_caves_gerbera.png new file mode 100644 index 0000000..3fae697 Binary files /dev/null and b/textures/fun_caves_gerbera.png differ diff --git a/textures/fun_caves_hibiscus.png b/textures/fun_caves_hibiscus.png new file mode 100644 index 0000000..509ee17 Binary files /dev/null and b/textures/fun_caves_hibiscus.png differ diff --git a/textures/fun_caves_orchid.png b/textures/fun_caves_orchid.png new file mode 100644 index 0000000..5e1b699 Binary files /dev/null and b/textures/fun_caves_orchid.png differ diff --git a/textures/fun_caves_water_plant_1.png b/textures/fun_caves_water_plant_1.png new file mode 100644 index 0000000..225f11f Binary files /dev/null and b/textures/fun_caves_water_plant_1.png differ