From 66fded90d55eaab1aa9ec561a8ba72310b843d3d Mon Sep 17 00:00:00 2001 From: kay27 Date: Mon, 17 Jan 2022 03:25:47 +0400 Subject: [PATCH] Fix vines --- mods/CORE/mcl_mapgen/API.md | 10 +- mods/CORE/mcl_mapgen/init.lua | 10 +- mods/ITEMS/mcl_core/functions.lua | 11 +- mods/ITEMS/mcl_core/mod.conf | 2 +- mods/MAPGEN/mcl_mapgen_core/init.lua | 237 +---------------- mods/MAPGEN/mcl_mapgen_core/structures.lua | 7 - .../mcl_mapgen_core/tree_decoration.lua | 251 ++++++++++++++++++ 7 files changed, 273 insertions(+), 255 deletions(-) create mode 100644 mods/MAPGEN/mcl_mapgen_core/tree_decoration.lua diff --git a/mods/CORE/mcl_mapgen/API.md b/mods/CORE/mcl_mapgen/API.md index fed1fd1d8..23365b357 100644 --- a/mods/CORE/mcl_mapgen/API.md +++ b/mods/CORE/mcl_mapgen/API.md @@ -15,19 +15,19 @@ See https://git.minetest.land/MineClone2/MineClone2/issues/1395 `vm_context` will pass into next lvm callback function from the queue! `vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function: `vm`: curent voxel manipulator object itself; - `blockseed`: seed of this mapchunk; + `chunkseed`: seed of this mapchunk; `minp` & `maxp`: minimum and maximum chunk position; `emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT; `area`: voxel area, can be helpful to access data; `data`: LVM buffer data array, data loads into it before the callbacks; `write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it; - `data2`: LVM buffer data array of `param2`, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: - `vm_context.data2 = vm_context.data2 or vm_context.vm.get_param2_data(vm_context.lvm_param2_buffer)` - `write_param2`: set it to true in your lvm callback function, if you used `data2` and want to write it; + `param2_data`: LVM buffer data array of `param2`, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: + `vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)` + `write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it; `light`: LVM buffer data array of light, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: `vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)` `write_light`: set it to true in your lvm callback function, if you used `light` and want to write it; - `lvm_param2_buffer`: static `param2` buffer pointer, used to load `data2` array; + `lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array; `shadow`: set it to false to disable shadow propagation; `heightmap`: mapgen object contanting y coordinates of ground level, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index a64bc1e6f..7210d85c6 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -125,7 +125,7 @@ minetest.register_on_shutdown(function() end) local vm_context -- here will be many references and flags, like: param2, light_data, heightmap, biomemap, heatmap, humiditymap, gennotify, write_lvm, write_param2, shadow -local data, data2, light, area +local data, param2_data, light, area local current_blocks = {} local current_chunks = {} local lvm_buffer, lvm_param2_buffer, lvm_light_buffer = {}, {}, {} -- Static buffer pointers @@ -139,7 +139,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) area = VoxelArea:new({MinEdge=emin, MaxEdge=emax}) vm_context = { data = data, - data2 = data2, + param2_data = param2_data, light = light, area = area, lvm_buffer = lvm_buffer, @@ -270,7 +270,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) vm:set_data(data) end if vm_context.write_param2 then - vm:set_param2_data(data2) + vm:set_param2_data(vm_context.param2_data) end if vm_context.write_light then vm:set_light_data(light) @@ -291,7 +291,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) area = VoxelArea:new({MinEdge=minp, MaxEdge=maxp}) vm_context = { data = data, - data2 = data2, + param2_data = param2_data, light = light, area = area, lvm_buffer = lvm_buffer, @@ -314,7 +314,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) vm:set_data(data) end if vm_context.write_param2 then - vm:set_param2_data(data2) + vm:set_param2_data(param2_data) end if vm_context.write_light then vm:set_light_data(light) diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index 7107a2373..20978e26f 100644 --- a/mods/ITEMS/mcl_core/functions.lua +++ b/mods/ITEMS/mcl_core/functions.lua @@ -4,7 +4,8 @@ local modpath = minetest.get_modpath(minetest.get_current_modname()) -local mg_name = minetest.get_mapgen_setting("mg_name") +local mg_name = mcl_mapgen.name +local v6 = mcl_mapgen.v6 local math = math local vector = vector @@ -381,7 +382,7 @@ function mcl_core.generate_tree(pos, tree_type, options) local balloon = options and options.balloon if tree_type == nil or tree_type == OAK_TREE_ID then - if mg_name == "v6" then + if v6 then mcl_core.generate_v6_oak_tree(pos) else if balloon then @@ -396,7 +397,7 @@ function mcl_core.generate_tree(pos, tree_type, options) if two_by_two then mcl_core.generate_huge_spruce_tree(pos) else - if mg_name == "v6" then + if v6 then mcl_core.generate_v6_spruce_tree(pos) else mcl_core.generate_spruce_tree(pos) @@ -408,7 +409,7 @@ function mcl_core.generate_tree(pos, tree_type, options) if two_by_two then mcl_core.generate_huge_jungle_tree(pos) else - if mg_name == "v6" then + if v6 then mcl_core.generate_v6_jungle_tree(pos) else mcl_core.generate_jungle_tree(pos) @@ -786,7 +787,7 @@ function mcl_core.generate_huge_jungle_tree(pos) end -local grass_spread_randomizer = PseudoRandom(minetest.get_mapgen_setting("seed")) +local grass_spread_randomizer = PseudoRandom(mcl_mapgen.seed) function mcl_core.get_grass_palette_index(pos) local biome_data = minetest.get_biome_data(pos) diff --git a/mods/ITEMS/mcl_core/mod.conf b/mods/ITEMS/mcl_core/mod.conf index 45018df75..3d7f59245 100644 --- a/mods/ITEMS/mcl_core/mod.conf +++ b/mods/ITEMS/mcl_core/mod.conf @@ -1,4 +1,4 @@ name = mcl_core description = Core items of MineClone 2: Basic biome blocks (dirt, sand, stones, etc.), derived items, glass, sugar cane, cactus, barrier, mining tools, hand, craftitems, and misc. items which don't really fit anywhere else. -depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors +depends = mcl_autogroup, mcl_init, mcl_sounds, mcl_particles, mcl_util, mcl_worlds, doc_items, mcl_enchanting, mcl_colors, mcl_mapgen optional_depends = doc diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index f36bf8b9a..5a9d3582e 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -84,21 +84,9 @@ local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier") local c_top_snow = minetest.get_content_id("mcl_core:snow") local c_snow_block = minetest.get_content_id("mcl_core:snowblock") local c_clay = minetest.get_content_id("mcl_core:clay") -local c_leaves = minetest.get_content_id("mcl_core:leaves") -local c_jungleleaves = minetest.get_content_id("mcl_core:jungleleaves") --local c_jungletree = minetest.get_content_id("mcl_core:jungletree") -local c_vine = minetest.get_content_id("mcl_core:vine") local c_air = minetest.CONTENT_AIR -local c_cocoas = nil -if minetest.get_modpath("mcl_cocoas") then - c_cocoas = { - minetest.get_content_id("mcl_cocoas:cocoa_1"), - minetest.get_content_id("mcl_cocoas:cocoa_2"), - minetest.get_content_id("mcl_cocoas:cocoa_3") - } -end - -- -- Ore generation -- @@ -1167,9 +1155,6 @@ minetest.set_mapgen_setting("mg_flags", mg_flags_str, true) return x, z end]] --- Perlin noise objects -local perlin_vines, perlin_vines_fine, perlin_vines_upwards, perlin_vines_length, perlin_vines_density - local dragon_spawn_pos = false local dragon_spawned, portal_generated = false, false @@ -1209,214 +1194,6 @@ function mcl_mapgen_core.generate_end_exit_portal(pos) portal_generated = true end - --- Buffers for LuaVoxelManip --- local lvm_buffer = {} --- local lvm_buffer_param2 = {} - --- Generate tree decorations in the bounding box. This adds: --- * Cocoa at jungle trees --- * Jungle tree vines --- * Oak vines in swamplands -local function generate_tree_decorations(minp, maxp, seed, data, param2_data, area, biomemap, lvm_used, pr) - if maxp.y < 0 then - return lvm_used - end - - local oaktree, oakleaves, jungletree, jungleleaves = {}, {}, {}, {} - local swampland = minetest.get_biome_id("Swampland") - local swampland_shore = minetest.get_biome_id("Swampland_shore") - local jungle = minetest.get_biome_id("Jungle") - local jungle_shore = minetest.get_biome_id("Jungle_shore") - local jungle_m = minetest.get_biome_id("JungleM") - local jungle_m_shore = minetest.get_biome_id("JungleM_shore") - local jungle_edge = minetest.get_biome_id("JungleEdge") - local jungle_edge_shore = minetest.get_biome_id("JungleEdge_shore") - local jungle_edge_m = minetest.get_biome_id("JungleEdgeM") - local jungle_edge_m_shore = minetest.get_biome_id("JungleEdgeM_shore") - - -- Modifier for Jungle M biome: More vines and cocoas - local dense_vegetation = false - - if biomemap then - -- Biome map available: Check if the required biome (jungle or swampland) - -- is in this mapchunk. We are only interested in trees in the correct biome. - -- The nodes are added if the correct biome is *anywhere* in the mapchunk. - -- TODO: Strictly generate vines in the correct biomes only. - local swamp_biome_found, jungle_biome_found = false, false - for b=1, #biomemap do - local id = biomemap[b] - - if not swamp_biome_found and (id == swampland or id == swampland_shore) then - oaktree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:tree"}) - oakleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:leaves"}) - swamp_biome_found = true - end - if not jungle_biome_found and (id == jungle or id == jungle_shore or id == jungle_m or id == jungle_m_shore or id == jungle_edge or id == jungle_edge_shore or id == jungle_edge_m or id == jungle_edge_m_shore) then - jungletree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"}) - jungleleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"}) - jungle_biome_found = true - end - if not dense_vegetation and (id == jungle_m or id == jungle_m_shore) then - dense_vegetation = true - end - if swamp_biome_found and jungle_biome_found and dense_vegetation then - break - end - end - else - -- If there is no biome map, we just count all jungle things we can find. - -- Oak vines will not be generated. - jungletree = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"}) - jungleleaves = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"}) - end - - local pos, treepos, dir - - if c_cocoas ~= nil then - local cocoachance = 40 - if dense_vegetation then - cocoachance = 32 - end - - -- Pass 1: Generate cocoas at jungle trees - for n = 1, #jungletree do - - pos = table.copy(jungletree[n]) - treepos = table.copy(pos) - - if minetest.find_node_near(pos, 1, {"mcl_core:jungleleaves"}) then - - dir = pr:next(1, cocoachance) - - if dir == 1 then - pos.z = pos.z + 1 - elseif dir == 2 then - pos.z = pos.z - 1 - elseif dir == 3 then - pos.x = pos.x + 1 - elseif dir == 4 then - pos.x = pos.x -1 - end - - local p_pos = area:index(pos.x, pos.y, pos.z) - local l = minetest.get_node_light(pos) - - if dir < 5 - and data[p_pos] == c_air - and l and l > 12 then - local c = pr:next(1, 3) - data[p_pos] = c_cocoas[c] - param2_data[p_pos] = minetest.dir_to_facedir(vector.subtract(treepos, pos)) - lvm_used = true - end - end - end - end - - -- Pass 2: Generate vines at jungle wood, jungle leaves in jungle and oak wood, oak leaves in swampland - perlin_vines = perlin_vines or minetest.get_perlin(555, 4, 0.6, 500) - perlin_vines_fine = perlin_vines_fine or minetest.get_perlin(43000, 3, 0.6, 1) - perlin_vines_length = perlin_vines_length or minetest.get_perlin(435, 4, 0.6, 75) - perlin_vines_upwards = perlin_vines_upwards or minetest.get_perlin(436, 3, 0.6, 10) - perlin_vines_density = perlin_vines_density or minetest.get_perlin(436, 3, 0.6, 500) - - -- Extra long vines in Jungle M - local maxvinelength = 7 - if dense_vegetation then - maxvinelength = 14 - end - local treething - for i=1, 4 do - if i==1 then - treething = jungletree - elseif i == 2 then - treething = jungleleaves - elseif i == 3 then - treething = oaktree - elseif i == 4 then - treething = oakleaves - end - - for n = 1, #treething do - pos = treething[n] - - treepos = table.copy(pos) - - local dirs = { - {x=1,y=0,z=0}, - {x=-1,y=0,z=0}, - {x=0,y=0,z=1}, - {x=0,y=0,z=-1}, - } - - for d = 1, #dirs do - local pos = vector.add(pos, dirs[d]) - local p_pos = area:index(pos.x, pos.y, pos.z) - - local vine_threshold = math.max(0.33333, perlin_vines_density:get_2d(pos)) - if dense_vegetation then - vine_threshold = vine_threshold * (2/3) - end - - if perlin_vines:get_2d(pos) > -1.0 and perlin_vines_fine:get_3d(pos) > vine_threshold and data[p_pos] == c_air then - - local rdir = {} - rdir.x = -dirs[d].x - rdir.y = dirs[d].y - rdir.z = -dirs[d].z - local param2 = minetest.dir_to_wallmounted(rdir) - - -- Determine growth direction - local grow_upwards = false - -- Only possible on the wood, not on the leaves - if i == 1 then - grow_upwards = perlin_vines_upwards:get_3d(pos) > 0.8 - end - if grow_upwards then - -- Grow vines up 1-4 nodes, even through jungleleaves. - -- This may give climbing access all the way to the top of the tree :-) - -- But this will be fairly rare. - local length = math.ceil(math.abs(perlin_vines_length:get_3d(pos)) * 4) - for l=0, length-1 do - local t_pos = area:index(treepos.x, treepos.y, treepos.z) - - if (data[p_pos] == c_air or data[p_pos] == c_jungleleaves or data[p_pos] == c_leaves) and mcl_core.supports_vines(minetest.get_name_from_content_id(data[t_pos])) then - data[p_pos] = c_vine - param2_data[p_pos] = param2 - lvm_used = true - - else - break - end - pos.y = pos.y + 1 - p_pos = area:index(pos.x, pos.y, pos.z) - treepos.y = treepos.y + 1 - end - else - -- Grow vines down, length between 1 and maxvinelength - local length = math.ceil(math.abs(perlin_vines_length:get_3d(pos)) * maxvinelength) - for l=0, length-1 do - if data[p_pos] == c_air then - data[p_pos] = c_vine - param2_data[p_pos] = param2 - lvm_used = true - - else - break - end - pos.y = pos.y - 1 - p_pos = area:index(pos.x, pos.y, pos.z) - end - end - end - end - - end - end - return lvm_used -end - -- Generate mushrooms in caves manually. -- Minetest's API does not support decorations in caves yet. :-( local function generate_underground_mushrooms(minp, maxp, seed) @@ -1604,8 +1381,8 @@ end -- Below the bedrock, generate air/void local function basic_safe(vm_context) local vm, data, emin, emax, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.emin, vm_context.emax, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed - vm_context.data2 = vm_context.data2 or vm:get_param2_data(vm_context.lvm_param2_buffer) - local data2 = vm_context.data2 + vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) + local param2_data = vm_context.param2_data local lvm_used = false local pr = PseudoRandom(blockseed) @@ -1649,14 +1426,9 @@ local function basic_safe(vm_context) end end - -- Clay, vines, cocoas - -- lvm_used = generate_clay(minp, maxp, chunkseed, data, area, lvm_used) - vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") local biomemap = vm_context.biomemap - lvm_used = generate_tree_decorations(minp, maxp, blockseed, data, data2, area, biomemap, lvm_used, pr) - ----- Interactive block fixing section ----- ----- The section to perform basic block overrides of the core mapgen generated world. ----- @@ -1714,8 +1486,8 @@ local function basic_safe(vm_context) if bn then local biome = minetest.registered_biomes[bn] if biome and biome._mcl_biome_type then - data2[p_pos] = biome._mcl_palette_index - lvm_used = true + param2_data[p_pos] = biome._mcl_palette_index + vm_context.write_param2 = true end end if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then @@ -1829,6 +1601,7 @@ mcl_mapgen.register_mapgen_block_lvm(basic_safe, 1) local modpath = minetest.get_modpath(minetest.get_current_modname()) dofile(modpath .. "/clay.lua") +dofile(modpath .. "/tree_decoration.lua") if minetest.get_modpath("mcl_structures") then dofile(modpath .. "/structures.lua") end diff --git a/mods/MAPGEN/mcl_mapgen_core/structures.lua b/mods/MAPGEN/mcl_mapgen_core/structures.lua index 3a25d1cfd..5c0632c98 100644 --- a/mods/MAPGEN/mcl_mapgen_core/structures.lua +++ b/mods/MAPGEN/mcl_mapgen_core/structures.lua @@ -163,16 +163,9 @@ local function spawn_witch_hut(p, nn, pr, vm_context) vm_context.biomemap = minetest_get_mapgen_object('biomemap') biomemap = vm_context.biomemap end - -- minetest.chat_send_all(minetest.serialize(biomemap)) local swampland = minetest.get_biome_id("Swampland") local swampland_shore = minetest.get_biome_id("Swampland_shore") local bi = xz_to_biomemap_index(p.x, p.z, vm_context.minp, vm_context.maxp) - if (biomemap[bi] == swampland) then - minetest.chat_send_all('swampland') - end - if (biomemap[bi] == swampland_shore) then - minetest.chat_send_all('swampland_shore') - end -- if biomemap[bi] ~= swampland and biomemap[bi] ~= swampland_shore then return end end diff --git a/mods/MAPGEN/mcl_mapgen_core/tree_decoration.lua b/mods/MAPGEN/mcl_mapgen_core/tree_decoration.lua new file mode 100644 index 000000000..5cdcd023e --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/tree_decoration.lua @@ -0,0 +1,251 @@ +-- Generate tree decorations in the bounding box. This adds: +-- * Cocoa at jungle trees +-- * Jungle tree vines +-- * Oak vines in swamplands + +local minetest_find_nodes_in_area = minetest.find_nodes_in_area +local minetest_find_node_near = minetest.find_node_near +local minetest_get_node_light = minetest.get_node_light +local minetest_dir_to_facedir = minetest.dir_to_facedir +local minetest_dir_to_wallmounted = minetest.dir_to_wallmounted +local table_copy = table.copy +local vector_subtract = vector.subtract +local vector_add = vector.add +local math_max = math.max +local math_ceil = math.ceil +local math_abs = math.abs + +local c_air = minetest.CONTENT_AIR +local c_cocoas +local c_jungleleaves = minetest.get_content_id("mcl_core:jungleleaves") +local c_leaves = minetest.get_content_id("mcl_core:leaves") +local c_vine = minetest.get_content_id("mcl_core:vine") + +if minetest.get_modpath("mcl_cocoas") then + c_cocoas = { + minetest.get_content_id("mcl_cocoas:cocoa_1"), + minetest.get_content_id("mcl_cocoas:cocoa_2"), + minetest.get_content_id("mcl_cocoas:cocoa_3"), + } +end + +local swampland +local swampland_shore +local jungle +local jungle_shore +local jungle_m +local jungle_m_shore +local jungle_edge +local jungle_edge_shore +local jungle_edge_m +local jungle_edge_m_shore + +local perlin_vines, perlin_vines_fine, perlin_vines_upwards, perlin_vines_length, perlin_vines_density + +local dirs = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1}, +} + +local function generate_tree_decorations(vm_context) + local maxp = vm_context.maxp + if maxp.y < 0 then return end + local minp = vm_context.minp + + local data = vm_context.data + vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer) + local param2_data = vm_context.param2_data + local area = vm_context.area + + local biomemap = vm_context.biomemap + + local pr = PseudoRandom(vm_context.chunkseed) + + local oaktree, oakleaves, jungletree, jungleleaves = {}, {}, {}, {} + + -- Modifier for Jungle M biome: More vines and cocoas + local dense_vegetation = false + + if biomemap then + swampland = swampland or minetest.get_biome_id("Swampland") + swampland_shore = swampland_shore or minetest.get_biome_id("Swampland_shore") + jungle = jungle or minetest.get_biome_id("Jungle") + jungle_shore = jungle_shore or minetest.get_biome_id("Jungle_shore") + jungle_m = jungle_m or minetest.get_biome_id("JungleM") + jungle_m_shore = jungle_m_shore or minetest.get_biome_id("JungleM_shore") + jungle_edge = jungle_edge or minetest.get_biome_id("JungleEdge") + jungle_edge_shore = jungle_edge_shore or minetest.get_biome_id("JungleEdge_shore") + jungle_edge_m = jungle_edge_m or minetest.get_biome_id("JungleEdgeM") + jungle_edge_m_shore = jungle_edge_m_shore or minetest.get_biome_id("JungleEdgeM_shore") + + -- Biome map available: Check if the required biome (jungle or swampland) + -- is in this mapchunk. We are only interested in trees in the correct biome. + -- The nodes are added if the correct biome is *anywhere* in the mapchunk. + -- TODO: Strictly generate vines in the correct biomes only. + local swamp_biome_found, jungle_biome_found = false, false + for b=1, #biomemap do + local id = biomemap[b] + + if not swamp_biome_found and (id == swampland or id == swampland_shore) then + oaktree = minetest_find_nodes_in_area(minp, maxp, {"mcl_core:tree"}) + oakleaves = minetest_find_nodes_in_area(minp, maxp, {"mcl_core:leaves"}) + swamp_biome_found = true + end + if not jungle_biome_found and (id == jungle or id == jungle_shore or id == jungle_m or id == jungle_m_shore or id == jungle_edge or id == jungle_edge_shore or id == jungle_edge_m or id == jungle_edge_m_shore) then + jungletree = minetest_find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"}) + jungleleaves = minetest_find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"}) + jungle_biome_found = true + end + if not dense_vegetation and (id == jungle_m or id == jungle_m_shore) then + dense_vegetation = true + end + if swamp_biome_found and jungle_biome_found and dense_vegetation then + break + end + end + else + -- If there is no biome map, we just count all jungle things we can find. + -- Oak vines will not be generated. + jungletree = minetest_find_nodes_in_area(minp, maxp, {"mcl_core:jungletree"}) + jungleleaves = minetest_find_nodes_in_area(minp, maxp, {"mcl_core:jungleleaves"}) + end + + local pos, treepos, dir + + if c_cocoas then + local cocoachance = 40 + if dense_vegetation then + cocoachance = 32 + end + + -- Pass 1: Generate cocoas at jungle trees + for n = 1, #jungletree do + + pos = table_copy(jungletree[n]) + treepos = table_copy(pos) + + if minetest_find_node_near(pos, 1, {"mcl_core:jungleleaves"}) then + + dir = pr:next(1, cocoachance) + + if dir == 1 then + pos.z = pos.z + 1 + elseif dir == 2 then + pos.z = pos.z - 1 + elseif dir == 3 then + pos.x = pos.x + 1 + elseif dir == 4 then + pos.x = pos.x -1 + end + + local p_pos = area:index(pos.x, pos.y, pos.z) + local l = minetest_get_node_light(pos) + + if dir < 5 + and data[p_pos] == c_air + and l and l > 12 then + local c = pr:next(1, 3) + data[p_pos] = c_cocoas[c] + vm_context.write = true + param2_data[p_pos] = minetest_dir_to_facedir(vector_subtract(treepos, pos)) + vm_context.write_param2 = true + end + end + end + end + + -- Pass 2: Generate vines at jungle wood, jungle leaves in jungle and oak wood, oak leaves in swampland + perlin_vines = perlin_vines or minetest.get_perlin(555, 4, 0.6, 500) + perlin_vines_fine = perlin_vines_fine or minetest.get_perlin(43000, 3, 0.6, 1) + perlin_vines_length = perlin_vines_length or minetest.get_perlin(435, 4, 0.6, 75) + perlin_vines_upwards = perlin_vines_upwards or minetest.get_perlin(436, 3, 0.6, 10) + perlin_vines_density = perlin_vines_density or minetest.get_perlin(436, 3, 0.6, 500) + + -- Extra long vines in Jungle M + local maxvinelength = 7 + if dense_vegetation then + maxvinelength = 14 + end + local treething + for i=1, 4 do + if i==1 then + treething = jungletree + elseif i == 2 then + treething = jungleleaves + elseif i == 3 then + treething = oaktree + elseif i == 4 then + treething = oakleaves + end + + for n = 1, #treething do + pos = treething[n] + + treepos = table_copy(pos) + + for d = 1, #dirs do + local pos = vector_add(pos, dirs[d]) + local p_pos = area:index(pos.x, pos.y, pos.z) + + local vine_threshold = math_max(0.33333, perlin_vines_density:get_2d(pos)) + if dense_vegetation then + vine_threshold = vine_threshold * (2/3) + end + + if perlin_vines:get_2d(pos) > -1.0 and perlin_vines_fine:get_3d(pos) > vine_threshold and data[p_pos] == c_air then + + local rdir = {} + rdir.x = -dirs[d].x + rdir.y = dirs[d].y + rdir.z = -dirs[d].z + local param2 = minetest_dir_to_wallmounted(rdir) + + -- Determine growth direction + local grow_upwards = false + -- Only possible on the wood, not on the leaves + if i == 1 then + grow_upwards = perlin_vines_upwards:get_3d(pos) > 0.8 + end + if grow_upwards then + -- Grow vines up 1-4 nodes, even through jungleleaves. + -- This may give climbing access all the way to the top of the tree :-) + -- But this will be fairly rare. + local length = math_ceil(math_abs(perlin_vines_length:get_3d(pos)) * 4) + for l=0, length-1 do + local t_pos = area:index(treepos.x, treepos.y, treepos.z) + + if (data[p_pos] == c_air or data[p_pos] == c_jungleleaves or data[p_pos] == c_leaves) and mcl_core.supports_vines(minetest.get_name_from_content_id(data[t_pos])) then + data[p_pos] = c_vine + param2_data[p_pos] = param2 + vm_context.write = true + else + break + end + pos.y = pos.y + 1 + p_pos = area:index(pos.x, pos.y, pos.z) + treepos.y = treepos.y + 1 + end + else + -- Grow vines down, length between 1 and maxvinelength + local length = math_ceil(math_abs(perlin_vines_length:get_3d(pos)) * maxvinelength) + for l=0, length-1 do + if data[p_pos] == c_air then + data[p_pos] = c_vine + param2_data[p_pos] = param2 + vm_context.write = true + else + break + end + pos.y = pos.y - 1 + p_pos = area:index(pos.x, pos.y, pos.z) + end + end + end + end + end + end +end + +mcl_mapgen.register_on_generated(generate_tree_decorations, 0)