From d2bf912f94bb1c9d53b6657b44ec1b59c0edb4cc Mon Sep 17 00:00:00 2001 From: cora Date: Sun, 4 Sep 2022 12:43:05 +0200 Subject: [PATCH] Move jungle vines to jungle tree schematics --- .../schematics/mcl_core_jungle_tree.mts | Bin 174 -> 215 bytes .../mcl_core_jungle_tree_huge_1.mts | Bin 500 -> 681 bytes .../mcl_core_jungle_tree_huge_2.mts | Bin 509 -> 710 bytes .../schematics/mcl_core_oak_swamp.mts | Bin 174 -> 239 bytes .../mcl_mapgen_core/world_structure.lua | 381 ++++++++++++++++++ 5 files changed, 381 insertions(+) create mode 100644 mods/MAPGEN/mcl_mapgen_core/world_structure.lua diff --git a/mods/ITEMS/mcl_core/schematics/mcl_core_jungle_tree.mts b/mods/ITEMS/mcl_core/schematics/mcl_core_jungle_tree.mts index c015d242ddbb704569c1278b7eeb60709a17ddab..44ac2b53820e2269eef2459b02d9f9cccbbb9535 100644 GIT binary patch delta 196 zcmZ3-c%4z!Hze4XfrWvUfuDi39u+XKOq7+a=gm#diBHZiO0_D>%u8huhI6w@^U`xt zONvrcE9P9C#K_g4z~g%Tnyu}rzPy=B*R;J9bMpVCyWzew(~L7kYhKSw=U(Asr@qtS zMyU6zSsRM8wk}y8{BdFX)aPH`^vtsE^3+$q;; jxoqByyPK8>-aU0Qb-hHQ?nllQN8%UU{>-+8NoOknG%;5b delta 154 zcmcc4xQY;#vd7`XriEwUmPJD8HQL0r|X!7gayV4EY1?ViToxBN0=l7V%iH-h3`fv+@AU1UE-mFs|Q--G!tFx%P(rgUcG+3 z*?RUEy z&?FF8cIJ6WR8RP%$-zrxXSXRBEt<>Uw4y!C@=LgYi|2}UZE|Yog;f_7e|;Hp=kwX# z$DI)+$2_`^yn6U*|K;g_YvwHW>)aQ8`ZVL~x}E0^{C;$8o>zry*k`Z{ap9slFZe6ua)&bii*FvQLj73 z;C)&3{-P6?Ri_=g{`K?cy5sM@2G?A;%1h(jDtgK6yDy^XLEjPhuCvo!A|DFya-D z9nLNBX9cTTZ^yiB+S4L&ZNjrU-jxCi{%rnwhwts?jX&pI zJ9Rlf_WZ#cuTywVtX?NI)w@=)W&Ods@^5TbspssB4>vbjqUR{UGI1WG-qWj z^-ERt4ON^}rbT4G-!j=IitVBI=Glp}wyl5j@!z+O|KhjapNPuNuC1R@a6I-}w_AJ7 g9LdS&=FK>+fng9R* delta 483 zcmV<90UZ9R1@r?bO;l4&00aOI02%-eKR-V|KRLcr932pwHO}v zFr6tz$K>WVMF;>YVpGA5(XZCy3J4KY2dr@r4}u6NyQ=DJzd zrBn3Y+%wAE^&xiFyHhoJUWsw|8gOHJLi;7}d4A{$?mvfs7DzdUj@H6HOZXa4*z-9R zt+(ef=jNX^;Of3Vr*lqWWnFNacp zp4fr%A`rfP7;5?I_tsKtLhGH&TPLWcRAEp5m9BB~wf0lhy3(C?ciP65QrBw5cdLr$ zvZ?!d+xlH^YNsYjGg_0oKwVY-?V;8>TkGaoE76JgW!w?+`wZctUt<8z~}Mc&R`t6(|RU1%*^xl0p%G^ ZYt~crGTVOfDKMv!#xCbe!+I4~BVsXME&dt8&vhz6GXgYcIcEWw5lRm?^Op=w?5E z=&`RTDSTw^OIvNaO2u`aN%_2Ow)xURTd20fx*ZX{BJTU`|82V~Of{c;uFXj$&iQj~ zo#l@H&RZ%Kb)N1Xi`&mK{8y4jDcZ{N(NidWmpO~2NpdhMRBYIh>KR=dGPwS)D4C>B@O9C)a1pk6FguN;4&fmZ|0~ z!!uDaQ-n*Af46*(q|Zl;WTW_NB;RY!b42?!)i$~wk@T7ABV`OEMjy_1krq{dmUq+p ziCGFc@f|W>294(4NNvQoi_VI9er5#yGR?t_NE+Qi?2Ct{tn_%~I_A!GEg&Zwd2l6- zRIb~erI82;nUrNMsI`#x#gW|_m#AnT?YNxNv_h;@RTLbx8z_URqPx2fK;|V!FT-H~ z0FaayyCwbDp27$65|RBmka3(_UlMAhta+!RVwTG>@I2oESdUAu(It%i8m>p`^SP;` zK;G}=uLycwUqU8N1pNx4D2*}@nzHU?th3vJ)Hc{9Sw2gng85rsdR+tnh{NCA9RLoT K3jG7c%u57dGerXc delta 474 zcmV<00VV#%1^ojtO;l4&00aOI03HAie>F8Ve}8{}e}6SKHGhA9e{O$&e}6SKHGfHe ze}4c200UuZa*;qUf0jX#gCGz^(M49-dR~ss7&Q?T&`D4lc#lezfMsYtziFia8m1c? z0DMcgY5q3=Ak5Z9u4nKVq^8F6;&ajJjJU_tfx`gybgGY>mNL%K{=Ba~=%@Jp^=T&f2%8gtNE^pFV9?PejfK% zDtN5qIaxkx1?iEOUuE5oq`D4d5cW}AIW+aN-!pvFGTl;>`n5yV^ZZu3;iA&vK1#)} zcMcvZ8`Mh$UI9o2Ua11DbFToR=ml#a<7&Wz){aOhc9#40MQcZ-jbdse7<|yi*_I3T z=(F#W2F3(5f7-dKX^hjmU{i*{{=RFJ^BTEw8FNQZpMJBvp0;~~F{?i0q+4SO;l4&00aOB00;mFe}8{}e}8{}00aO7VQF#z4Q*p=Ut@1_Wjc0g zZe@`hB7eP-(Gmj@3`MV|{VzY`)w4IBuB_H3l&PgXJChNT+=K-dP-S%!-*4dcYdxvG z(#fZp)U+Onn%q;(*;_H?lhC7!^Qq3hWM#f9{OA27{BAc?^~o5YFcWF!i1!)jXf&Xm zb$YDiIoShTw625zA;*W8=a0P5=Gka%tx$;$^(3~=$C{YGPuypMmpGMZ5Oq?1E@~DX R9-aN~^fu9J0#9|wL*pR5W*Yzi delta 149 zcmV;G0BZm50j>cXO;l4&00aOB00;mFe?NbJe}8{}00RI6VQF%aDk5=XV4w 0 then + mg_flags_str = string.sub(mg_flags_str, 1, string.len(mg_flags_str)-1) +end +minetest.set_mapgen_setting("mg_flags", mg_flags_str, true) + +-- Takes an index of a biomemap table (from minetest.get_mapgen_object), +-- minp and maxp (from an on_generated callback) and returns the real world coordinates +-- as X, Z. +-- Inverse function of xz_to_biomemap +--[[local function biomemap_to_xz(index, minp, maxp) + local xwidth = maxp.x - minp.x + 1 + local zwidth = maxp.z - minp.z + 1 + local x = ((index-1) % xwidth) + minp.x + local z = ((index-1) / zwidth) + minp.z + return x, z +end]] + +-- Takes x and z coordinates and minp and maxp of a generated chunk +-- (in on_generated callback) and returns a biomemap index) +-- Inverse function of biomemap_to_xz +local function xz_to_biomemap_index(x, z, minp, maxp) + local xwidth = maxp.x - minp.x + 1 + local zwidth = maxp.z - minp.z + 1 + local minix = x % xwidth + local miniz = z % zwidth + + return (minix + miniz * zwidth) + 1 +end + +-- Perlin noise objects +local perlin_structures +local perlin_vines, perlin_vines_fine, perlin_vines_upwards, perlin_vines_length, perlin_vines_density +local perlin_clay + +local function generate_clay(minp, maxp, blockseed, voxelmanip_data, voxelmanip_area, lvm_used) + -- TODO: Make clay generation reproducible for same seed. + if maxp.y < -5 or minp.y > 0 then + return lvm_used + end + + local pr = PseudoRandom(blockseed) + + perlin_clay = perlin_clay or minetest.get_perlin({ + offset = 0.5, + scale = 0.2, + spread = {x = 5, y = 5, z = 5}, + seed = -316, + octaves = 1, + persist = 0.0 + }) + + for y=math.max(minp.y, 0), math.min(maxp.y, -8), -1 do + -- Assume X and Z lengths are equal + local divlen = 4 + local divs = (maxp.x-minp.x)/divlen+1; + for divx=0+1,divs-2 do + for divz=0+1,divs-2 do + -- Get position and shift it a bit randomly so the clay do not obviously appear in a grid + local cx = minp.x + math.floor((divx+0.5)*divlen) + pr:next(-1,1) + local cz = minp.z + math.floor((divz+0.5)*divlen) + pr:next(-1,1) + + local water_pos = voxelmanip_area:index(cx, y+1, cz) + local waternode = voxelmanip_data[water_pos] + local surface_pos = voxelmanip_area:index(cx, y, cz) + local surfacenode = voxelmanip_data[surface_pos] + + local genrnd = pr:next(1, 20) + if genrnd == 1 and perlin_clay:get_3d({x=cx,y=y,z=cz}) > 0 and waternode == c_water and + (surfacenode == c_dirt or minetest.get_item_group(minetest.get_name_from_content_id(surfacenode), "sand") == 1) then + local diamondsize = pr:next(1, 3) + for x1 = -diamondsize, diamondsize do + for z1 = -(diamondsize - math.abs(x1)), diamondsize - math.abs(x1) do + local ccpos = voxelmanip_area:index(cx+x1, y, cz+z1) + local claycandidate = voxelmanip_data[ccpos] + if voxelmanip_data[ccpos] == c_dirt or minetest.get_item_group(minetest.get_name_from_content_id(claycandidate), "sand") == 1 then + voxelmanip_data[ccpos] = c_clay + lvm_used = true + end + end + end + end + end + end + end + return lvm_used +end + +local function generate_end_exit_portal(pos) + local obj = minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon") + if obj then + local dragon_entity = obj:get_luaentity() + dragon_entity._initial = true + dragon_entity._portal_pos = pos + else + minetest.log("error", "[mcl_mapgen_core] ERROR! Ender dragon doesn't want to spawn") + end + mcl_structures.call_struct(pos, "end_exit_portal") +end + +-- Helper function to set all nodes in the layers between min and max. +-- content_id: Node to set +-- check: optional. +-- If content_id, node will be set only if it is equal to check. +-- If function(pos_to_check, content_id_at_this_pos), will set node only if returns true. +-- min, max: Minimum and maximum Y levels of the layers to set +-- minp, maxp: minp, maxp of the on_generated +-- lvm_used: Set to true if any node in this on_generated has been set before. +-- +-- returns true if any node was set and lvm_used otherwise +local function set_layers(data, area, content_id, check, min, max, minp, maxp, lvm_used, pr) + if (maxp.y >= min and minp.y <= max) then + for y = math.max(min, minp.y), math.min(max, maxp.y) do + for x = minp.x, maxp.x do + for z = minp.z, maxp.z do + local p_pos = area:index(x, y, z) + if check then + if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then + data[p_pos] = content_id + lvm_used = true + elseif check == data[p_pos] then + data[p_pos] = content_id + lvm_used = true + end + else + data[p_pos] = content_id + lvm_used = true + end + end + end + end + end + return lvm_used +end + +-- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc. +-- Also perform some basic node replacements. + +local bedrock_check +if mcl_vars.mg_bedrock_is_rough then + function bedrock_check(pos, _, pr) + local y = pos.y + -- Bedrock layers with increasing levels of roughness, until a perfecly flat bedrock later at the bottom layer + -- This code assumes a bedrock height of 5 layers. + + local diff = mcl_vars.mg_bedrock_overworld_max - y -- Overworld bedrock + local ndiff1 = mcl_vars.mg_bedrock_nether_bottom_max - y -- Nether bedrock, bottom + local ndiff2 = mcl_vars.mg_bedrock_nether_top_max - y -- Nether bedrock, ceiling + + local top + if diff == 0 or ndiff1 == 0 or ndiff2 == 4 then + -- 50% bedrock chance + top = 2 + elseif diff == 1 or ndiff1 == 1 or ndiff2 == 3 then + -- 66.666...% + top = 3 + elseif diff == 2 or ndiff1 == 2 or ndiff2 == 2 then + -- 75% + top = 4 + elseif diff == 3 or ndiff1 == 3 or ndiff2 == 1 then + -- 90% + top = 10 + elseif diff == 4 or ndiff1 == 4 or ndiff2 == 0 then + -- 100% + return true + else + -- Not in bedrock layer + return false + end + + return pr:next(1, top) <= top-1 + end +end + +-- Below the bedrock, generate air/void +local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) + local biomemap --ymin, ymax + local lvm_used = false + local pr = PseudoRandom(blockseed) + + -- The Void below the Nether: + lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mapgen_edge_min , mcl_vars.mg_nether_min -1, minp, maxp, lvm_used, pr) + + -- [[ THE NETHER: mcl_vars.mg_nether_min mcl_vars.mg_nether_max ]] + + -- The Air on the Nether roof, https://git.minetest.land/MineClone2/MineClone2/issues/1186 + lvm_used = set_layers(data, area, c_air , nil, mcl_vars.mg_nether_max +1, mcl_vars.mg_nether_max + 128 , minp, maxp, lvm_used, pr) + -- The Void above the Nether below the End: + lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_nether_max + 128 +1, mcl_vars.mg_end_min -1, minp, maxp, lvm_used, pr) + + -- [[ THE END: mcl_vars.mg_end_min mcl_vars.mg_end_max ]] + + -- The Void above the End below the Realm barrier: + lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_end_max +1, mcl_vars.mg_realm_barrier_overworld_end_min-1, minp, maxp, lvm_used, pr) + -- Realm barrier between the Overworld void and the End + lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_vars.mg_realm_barrier_overworld_end_min , mcl_vars.mg_realm_barrier_overworld_end_max , minp, maxp, lvm_used, pr) + -- The Void above Realm barrier below the Overworld: + lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_realm_barrier_overworld_end_max+1, mcl_vars.mg_overworld_min -1, minp, maxp, lvm_used, pr) + + + if mg_name ~= "singlenode" then + -- Bedrock + lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_overworld_min, mcl_vars.mg_bedrock_overworld_max, minp, maxp, lvm_used, pr) + lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_bottom_max, minp, maxp, lvm_used, pr) + lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_top_min, mcl_vars.mg_bedrock_nether_top_max, minp, maxp, lvm_used, pr) + + -- Flat Nether + if mg_name == "flat" then + lvm_used = set_layers(data, area, c_air, nil, mcl_vars.mg_flat_nether_floor, mcl_vars.mg_flat_nether_ceiling, minp, maxp, lvm_used, pr) + end + + -- Big lava seas by replacing air below a certain height + if mcl_vars.mg_lava then + lvm_used = set_layers(data, area, c_lava, c_air, mcl_vars.mg_overworld_min, mcl_vars.mg_lava_overworld_max, minp, maxp, lvm_used, pr) + lvm_used = set_layers(data, area, c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used, pr) + end + + -- Clay, vines, cocoas + lvm_used = generate_clay(minp, maxp, blockseed, data, area, lvm_used) + biomemap = minetest.get_mapgen_object("biomemap") + + + ----- Interactive block fixing section ----- + ----- The section to perform basic block overrides of the core mapgen generated world. ----- + + -- Snow and sand fixes. This code implements snow consistency + -- and fixes floating sand and cut plants. + -- A snowy grass block must be below a top snow or snow block at all times. + if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then + -- v6 mapgen: + if mg_name ~= "v6" then + -- Non-v6 mapgens: + -- Set param2 (=color) of grass blocks. + -- Clear snowy grass blocks without snow above to ensure consistency. + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) + + -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: + local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + local p_pos_above = area:index(n.x, n.y+1, n.z) + --local p_pos_below = area:index(n.x, n.y-1, n.z) + local b_pos = aream:index(n.x, 0, n.z) + local bn = minetest.get_biome_name(biomemap[b_pos]) + 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 + 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 + data[p_pos] = c_dirt_with_grass + lvm_used = true + end + end + + -- Set param2 (=color) of sugar cane + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:reeds"}) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + local b_pos = aream:index(n.x, 0, n.z) + local bn = minetest.get_biome_name(biomemap[b_pos]) + 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 + end + end + end + end + + -- Nether block fixes: + -- * Replace water with Nether lava. + -- * Replace stone, sand dirt in v6 so the Nether works in v6. + elseif emin.y <= mcl_vars.mg_nether_max and emax.y >= mcl_vars.mg_nether_min then + if mg_name ~= "v6" then + local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether_lava + end + end + + -- End block fixes: + -- * Replace water with end stone or air (depending on height). + -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. + -- * Generate spawn platform (End portal destination) + elseif minp.y <= mcl_vars.mg_end_max and maxp.y >= mcl_vars.mg_end_min then + local nodes + if mg_name ~= "v6" then + nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"}) + if #nodes > 0 then + lvm_used = true + for _,n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_air + end + end + end + -- Obsidian spawn platform + if minp.y <= mcl_vars.mg_end_platform_pos.y and maxp.y >= mcl_vars.mg_end_platform_pos.y and + minp.x <= mcl_vars.mg_end_platform_pos.x and maxp.x >= mcl_vars.mg_end_platform_pos.z and + minp.z <= mcl_vars.mg_end_platform_pos.z and maxp.z >= mcl_vars.mg_end_platform_pos.z then + + --local pos1 = {x = math.max(minp.x, mcl_vars.mg_end_platform_pos.x-2), y = math.max(minp.y, mcl_vars.mg_end_platform_pos.y), z = math.max(minp.z, mcl_vars.mg_end_platform_pos.z-2)} + --local pos2 = {x = math.min(maxp.x, mcl_vars.mg_end_platform_pos.x+2), y = math.min(maxp.y, mcl_vars.mg_end_platform_pos.y+2), z = math.min(maxp.z, mcl_vars.mg_end_platform_pos.z+2)} + + for x=math.max(minp.x, mcl_vars.mg_end_platform_pos.x-2), math.min(maxp.x, mcl_vars.mg_end_platform_pos.x+2) do + for z=math.max(minp.z, mcl_vars.mg_end_platform_pos.z-2), math.min(maxp.z, mcl_vars.mg_end_platform_pos.z+2) do + for y=math.max(minp.y, mcl_vars.mg_end_platform_pos.y), math.min(maxp.y, mcl_vars.mg_end_platform_pos.y+2) do + local p_pos = area:index(x, y, z) + if y == mcl_vars.mg_end_platform_pos.y then + data[p_pos] = c_obsidian + else + data[p_pos] = c_air + end + end + end + end + lvm_used = true + end + end + end + -- Final hackery: Set sun light level in the End. + -- -26912 is at a mapchunk border. + local shadow = true + if minp.y >= -26912 and maxp.y <= mcl_vars.mg_end_max then + vm:set_lighting({day=15, night=15}) + lvm_used = true + end + if minp.y >= mcl_vars.mg_end_min and maxp.y <= -26911 then + shadow = false + lvm_used = true + end + + return lvm_used, shadow +end + +mcl_mapgen_core.register_generator("main", basic, basic_node, 1, true) + +mcl_mapgen_core.register_generator("end_exit_portal",nil, function(minp, maxp, blockseed) + if minp.y <= END_EXIT_PORTAL_POS.y and maxp.y >= END_EXIT_PORTAL_POS.y and + minp.x <= END_EXIT_PORTAL_POS.x and maxp.x >= END_EXIT_PORTAL_POS.x and + minp.z <= END_EXIT_PORTAL_POS.z and maxp.z >= END_EXIT_PORTAL_POS.z then + for y=maxp.y, minp.y, -1 do + local p = {x=END_EXIT_PORTAL_POS.x, y=y, z=END_EXIT_PORTAL_POS.z} + if minetest.get_node(p).name == "mcl_end:end_stone" then + generate_end_exit_portal(p) + return + end + end + generate_end_exit_portal(END_EXIT_PORTAL_POS) + end +end,101,true)