From b3e8f2487670f9a855254b781311168227d24f85 Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 19 Jan 2022 19:09:37 +0400 Subject: [PATCH] Add basic part of new mapgen api --- mods/CORE/mcl_init/init.lua | 231 --- mods/CORE/mcl_mapgen/API.md | 100 + mods/CORE/mcl_mapgen/init.lua | 498 +++++ mods/CORE/mcl_mapgen/mod.conf | 4 + .../api/mob_functions/environment.lua | 17 +- mods/ENTITIES/mcl_mobs/mod.conf | 2 +- mods/ENTITIES/mobs_mc_gameconfig/init.lua | 12 +- mods/ITEMS/mcl_core/functions.lua | 30 +- mods/ITEMS/mcl_core/mod.conf | 2 +- mods/ITEMS/mcl_portals/mod.conf | 2 +- mods/ITEMS/mcl_portals/portal_end.lua | 8 +- mods/ITEMS/mcl_portals/portal_nether.lua | 70 +- mods/MAPGEN/mcl_biomes/init.lua | 375 ++-- mods/MAPGEN/mcl_biomes/mod.conf | 2 +- mods/MAPGEN/mcl_dungeons/init.lua | 48 +- mods/MAPGEN/mcl_dungeons/mod.conf | 2 +- mods/MAPGEN/mcl_end_island/init.lua | 18 +- mods/MAPGEN/mcl_mapgen_core/clay.lua | 63 + mods/MAPGEN/mcl_mapgen_core/init.lua | 1654 ++++++----------- mods/MAPGEN/mcl_mapgen_core/mod.conf | 4 +- .../mcl_mapgen_core/tree_decoration.lua | 251 +++ mods/MAPGEN/mcl_ocean_monument/init.lua | 97 + mods/MAPGEN/mcl_ocean_monument/mod.conf | 4 + .../schematics/ocean_monument.mts | Bin 0 -> 8342 bytes mods/MAPGEN/mcl_strongholds/init.lua | 106 -- mods/MAPGEN/mcl_strongholds/mod.conf | 4 - mods/MAPGEN/mcl_structures/desert_temple.lua | 174 ++ mods/MAPGEN/mcl_structures/desert_well.lua | 93 + .../MAPGEN/mcl_structures/end_exit_portal.lua | 52 + mods/MAPGEN/mcl_structures/fossil.lua | 53 + .../MAPGEN/mcl_structures/ice_spike_large.lua | 66 + .../MAPGEN/mcl_structures/ice_spike_small.lua | 65 + mods/MAPGEN/mcl_structures/igloo.lua | 195 ++ mods/MAPGEN/mcl_structures/init.lua | 802 ++++---- mods/MAPGEN/mcl_structures/jungle_temple.lua | 203 ++ mods/MAPGEN/mcl_structures/mod.conf | 6 +- .../mcl_structures/nice_jungle_temple.lua | 209 +++ .../MAPGEN/mcl_structures/noise_indicator.lua | 60 + .../mcl_structures_jungle_temple.mts | Bin 0 -> 2586 bytes .../mcl_structures_nice_jungle_temple.mts | Bin 0 -> 3997 bytes mods/MAPGEN/mcl_structures/stronghold.lua | 184 ++ mods/MAPGEN/mcl_structures/structures.lua | 17 + mods/MAPGEN/mcl_structures/witch_hut.lua | 136 ++ mods/MAPGEN/mcl_villages/README.txt | 2 +- mods/MAPGEN/mcl_villages/buildings.lua | 22 +- mods/MAPGEN/mcl_villages/init.lua | 38 +- mods/MAPGEN/mcl_villages/utils.lua | 40 +- mods/MAPGEN/tsm_railcorridors/init.lua | 11 +- mods/PLAYER/mcl_spawn/init.lua | 8 +- mods/PLAYER/mcl_spawn/mod.conf | 2 +- 50 files changed, 3740 insertions(+), 2302 deletions(-) create mode 100644 mods/CORE/mcl_mapgen/API.md create mode 100644 mods/CORE/mcl_mapgen/init.lua create mode 100644 mods/CORE/mcl_mapgen/mod.conf create mode 100644 mods/MAPGEN/mcl_mapgen_core/clay.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/tree_decoration.lua create mode 100644 mods/MAPGEN/mcl_ocean_monument/init.lua create mode 100644 mods/MAPGEN/mcl_ocean_monument/mod.conf create mode 100644 mods/MAPGEN/mcl_ocean_monument/schematics/ocean_monument.mts delete mode 100644 mods/MAPGEN/mcl_strongholds/init.lua delete mode 100644 mods/MAPGEN/mcl_strongholds/mod.conf create mode 100644 mods/MAPGEN/mcl_structures/desert_temple.lua create mode 100644 mods/MAPGEN/mcl_structures/desert_well.lua create mode 100644 mods/MAPGEN/mcl_structures/end_exit_portal.lua create mode 100644 mods/MAPGEN/mcl_structures/fossil.lua create mode 100644 mods/MAPGEN/mcl_structures/ice_spike_large.lua create mode 100644 mods/MAPGEN/mcl_structures/ice_spike_small.lua create mode 100644 mods/MAPGEN/mcl_structures/igloo.lua create mode 100644 mods/MAPGEN/mcl_structures/jungle_temple.lua create mode 100644 mods/MAPGEN/mcl_structures/nice_jungle_temple.lua create mode 100644 mods/MAPGEN/mcl_structures/noise_indicator.lua create mode 100644 mods/MAPGEN/mcl_structures/schematics/mcl_structures_jungle_temple.mts create mode 100644 mods/MAPGEN/mcl_structures/schematics/mcl_structures_nice_jungle_temple.mts create mode 100644 mods/MAPGEN/mcl_structures/stronghold.lua create mode 100644 mods/MAPGEN/mcl_structures/structures.lua create mode 100644 mods/MAPGEN/mcl_structures/witch_hut.lua diff --git a/mods/CORE/mcl_init/init.lua b/mods/CORE/mcl_init/init.lua index fec9c7ba9..a495935f5 100644 --- a/mods/CORE/mcl_init/init.lua +++ b/mods/CORE/mcl_init/init.lua @@ -24,240 +24,9 @@ mcl_vars.inventory_header = "" -- Tool wield size mcl_vars.tool_wield_scale = { x = 1.8, y = 1.8, z = 1 } --- Mapgen variables -local mg_name = minetest.get_mapgen_setting("mg_name") -local minecraft_height_limit = 256 -local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" -local singlenode = mg_name == "singlenode" - --- Calculate mapgen_edge_min/mapgen_edge_max -mcl_vars.chunksize = math.max(1, tonumber(minetest.get_mapgen_setting("chunksize")) or 5) -mcl_vars.MAP_BLOCKSIZE = math.max(1, minetest.MAP_BLOCKSIZE or 16) -mcl_vars.mapgen_limit = math.max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000) -mcl_vars.MAX_MAP_GENERATION_LIMIT = math.max(1, minetest.MAX_MAP_GENERATION_LIMIT or 31000) -local central_chunk_offset = -math.floor(mcl_vars.chunksize / 2) -mcl_vars.central_chunk_offset_in_nodes = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE -mcl_vars.chunk_size_in_nodes = mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE -local central_chunk_min_pos = central_chunk_offset * mcl_vars.MAP_BLOCKSIZE -local central_chunk_max_pos = central_chunk_min_pos + mcl_vars.chunk_size_in_nodes - 1 -local ccfmin = central_chunk_min_pos - mcl_vars.MAP_BLOCKSIZE -- Fullminp/fullmaxp of central chunk, in nodes -local ccfmax = central_chunk_max_pos + mcl_vars.MAP_BLOCKSIZE -local mapgen_limit_b = math.floor(math.min(mcl_vars.mapgen_limit, mcl_vars.MAX_MAP_GENERATION_LIMIT) / mcl_vars.MAP_BLOCKSIZE) -local mapgen_limit_min = -mapgen_limit_b * mcl_vars.MAP_BLOCKSIZE -local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_vars.MAP_BLOCKSIZE - 1 -local numcmin = math.max(math.floor((ccfmin - mapgen_limit_min) / mcl_vars.chunk_size_in_nodes), 0) -- Number of complete chunks from central chunk -local numcmax = math.max(math.floor((mapgen_limit_max - ccfmax) / mcl_vars.chunk_size_in_nodes), 0) -- fullminp/fullmaxp to effective mapgen limits. -mcl_vars.mapgen_edge_min = central_chunk_min_pos - numcmin * mcl_vars.chunk_size_in_nodes -mcl_vars.mapgen_edge_max = central_chunk_max_pos + numcmax * mcl_vars.chunk_size_in_nodes - -local function coordinate_to_block(x) - return math.floor(x / mcl_vars.MAP_BLOCKSIZE) -end - -local function coordinate_to_chunk(x) - return math.floor((coordinate_to_block(x) - central_chunk_offset) / mcl_vars.chunksize) -end - -function mcl_vars.pos_to_block(pos) - return { - x = coordinate_to_block(pos.x), - y = coordinate_to_block(pos.y), - z = coordinate_to_block(pos.z) - } -end - -function mcl_vars.pos_to_chunk(pos) - return { - x = coordinate_to_chunk(pos.x), - y = coordinate_to_chunk(pos.y), - z = coordinate_to_chunk(pos.z) - } -end - -local k_positive = math.ceil(mcl_vars.MAX_MAP_GENERATION_LIMIT / mcl_vars.chunk_size_in_nodes) -local k_positive_z = k_positive * 2 -local k_positive_y = k_positive_z * k_positive_z - -function mcl_vars.get_chunk_number(pos) -- unsigned int - local c = mcl_vars.pos_to_chunk(pos) - return - (c.y + k_positive) * k_positive_y + - (c.z + k_positive) * k_positive_z + - c.x + k_positive -end - -if not superflat and not singlenode then - -- Normal mode - --[[ Realm stacking (h is for height) - - Overworld (h>=256) - - Void (h>=1000) - - Realm Barrier (h=11), to allow escaping the End - - End (h>=256) - - Void (h>=1000) - - Nether (h=128) - - Void (h>=1000) - ]] - - -- Overworld - mcl_vars.mg_overworld_min = -62 - mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit - mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min - mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min + 4 - mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min + 10 - mcl_vars.mg_lava = true - mcl_vars.mg_bedrock_is_rough = true - -elseif singlenode then - mcl_vars.mg_overworld_min = -66 - mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit - mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min - mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min - mcl_vars.mg_lava = false - mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min - mcl_vars.mg_bedrock_is_rough = false -else - -- Classic superflat - local ground = minetest.get_mapgen_setting("mgflat_ground_level") - ground = tonumber(ground) - if not ground then - ground = 8 - end - mcl_vars.mg_overworld_min = ground - 3 - mcl_vars.mg_overworld_max_official = mcl_vars.mg_overworld_min + minecraft_height_limit - mcl_vars.mg_bedrock_overworld_min = mcl_vars.mg_overworld_min - mcl_vars.mg_bedrock_overworld_max = mcl_vars.mg_bedrock_overworld_min - mcl_vars.mg_lava = false - mcl_vars.mg_lava_overworld_max = mcl_vars.mg_overworld_min - mcl_vars.mg_bedrock_is_rough = false -end - -mcl_vars.mg_overworld_max = mcl_vars.mapgen_edge_max - --- The Nether (around Y = -29000) -mcl_vars.mg_nether_min = -29067 -- Carefully chosen to be at a mapchunk border -mcl_vars.mg_nether_max = mcl_vars.mg_nether_min + 128 -mcl_vars.mg_bedrock_nether_bottom_min = mcl_vars.mg_nether_min -mcl_vars.mg_bedrock_nether_top_max = mcl_vars.mg_nether_max -if not superflat then - mcl_vars.mg_bedrock_nether_bottom_max = mcl_vars.mg_bedrock_nether_bottom_min + 4 - mcl_vars.mg_bedrock_nether_top_min = mcl_vars.mg_bedrock_nether_top_max - 4 - mcl_vars.mg_lava_nether_max = mcl_vars.mg_nether_min + 31 -else - -- Thin bedrock in classic superflat mapgen - mcl_vars.mg_bedrock_nether_bottom_max = mcl_vars.mg_bedrock_nether_bottom_min - mcl_vars.mg_bedrock_nether_top_min = mcl_vars.mg_bedrock_nether_top_max - mcl_vars.mg_lava_nether_max = mcl_vars.mg_nether_min + 2 -end -if mg_name == "flat" then - if superflat then - mcl_vars.mg_flat_nether_floor = mcl_vars.mg_bedrock_nether_bottom_max + 4 - mcl_vars.mg_flat_nether_ceiling = mcl_vars.mg_bedrock_nether_bottom_max + 52 - else - mcl_vars.mg_flat_nether_floor = mcl_vars.mg_lava_nether_max + 4 - mcl_vars.mg_flat_nether_ceiling = mcl_vars.mg_lava_nether_max + 52 - end -end - --- The End (surface at ca. Y = -27000) -mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border -mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit -mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000 -mcl_vars.mg_end_platform_pos = { x = 100, y = mcl_vars.mg_end_min + 74, z = 0 } - --- Realm barrier used to safely separate the End from the void below the Overworld -mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max -mcl_vars.mg_realm_barrier_overworld_end_min = mcl_vars.mg_end_max - 11 - --- Use MineClone 2-style dungeons -mcl_vars.mg_dungeons = true - -- Set default stack sizes minetest.nodedef_default.stack_max = 64 minetest.craftitemdef_default.stack_max = 64 -- Set random seed for all other mods (Remember to make sure no other mod calls this function) math.randomseed(os.time()) - -local chunks = {} -- intervals of chunks generated -function mcl_vars.add_chunk(pos) - local n = mcl_vars.get_chunk_number(pos) -- unsigned int - local prev - for i, d in pairs(chunks) do - if n <= d[2] then -- we've found it - if (n == d[2]) or (n >= d[1]) then return end -- already here - if n == d[1]-1 then -- right before: - if prev and (prev[2] == n-1) then - prev[2] = d[2] - table.remove(chunks, i) - return - end - d[1] = n - return - end - if prev and (prev[2] == n-1) then --join to previous - prev[2] = n - return - end - table.insert(chunks, i, {n, n}) -- insert new interval before i - return - end - prev = d - end - chunks[#chunks+1] = {n, n} -end -function mcl_vars.is_generated(pos) - local n = mcl_vars.get_chunk_number(pos) -- unsigned int - for i, d in pairs(chunks) do - if n <= d[2] then - return (n >= d[1]) - end - end - return false -end - --- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does. --- p: Position, if it's wrong, {name="error"} node will return. --- force: optional (default: false) - Do the maximum to still read the node within us_timeout. --- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job. --- --- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}. -function mcl_vars.get_node(p, force, us_timeout) - -- check initial circumstances - if not p or not p.x or not p.y or not p.z then return {name="error"} end - - -- try common way - local node = minetest.get_node(p) - if node.name ~= "ignore" then - return node - end - - -- copy table to get sure it won't changed by other threads - local pos = {x=p.x,y=p.y,z=p.z} - - -- try LVM - minetest.get_voxel_manip():read_from_map(pos, pos) - node = minetest.get_node(pos) - if node.name ~= "ignore" or not force then - return node - end - - -- all ways failed - need to emerge (or forceload if generated) - local us_timeout = us_timeout or 244 - if mcl_vars.is_generated(pos) then - minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!") - minetest.forceload_block(pos) - else - minetest.emerge_area(pos, pos) - end - - local t = minetest.get_us_time() - - node = minetest.get_node(pos) - - while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do - node = minetest.get_node(pos) - end - - return node - -- it still can return "ignore", LOL, even if force = true, but only after time out -end diff --git a/mods/CORE/mcl_mapgen/API.md b/mods/CORE/mcl_mapgen/API.md new file mode 100644 index 000000000..baae1f584 --- /dev/null +++ b/mods/CORE/mcl_mapgen/API.md @@ -0,0 +1,100 @@ +# mcl_mapgen +============ +Helps to avoid problems caused by 'chunk-in-shell' feature of mapgen.cpp. +It also queues your generators to run them in proper order: + +### mcl_mapgen.register_on_generated(lvm_callback_function, order_number) +========================================================================= +Replacement of engine API function `minetest.register_on_generated(function(vm_context))` +It is still unsafe. Cavegen part can and will overwrite outer 1-block layer of the chunk which is expected to be generated. +Nodes marked as `is_ground_content` could be overwritten. Air and water are usually 'ground content' too. +For Minetest 5.4 it doesn't recommended to place blocks within lvm callback function. +See https://git.minetest.land/MineClone2/MineClone2/issues/1395 + `lvm_callback_function`: chunk callback LVM function definition: + `function(vm_context)`: + `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; + `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; + `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 `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: + `vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')` + `biomemap`: mapgen object contanting biome IDs of nodes, + !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: + `vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')` + `heatmap`: mapgen object contanting temperature values of nodes, + !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: + `vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')` + `humiditymap`: mapgen object contanting humidity values of nodes, + !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: + `vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')` + `gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation, + !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: + `vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')` + `order_number` (optional): the less, the earlier, + e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + +### mcl_mapgen.register_mapgen_block_lvm(lvm_callback_function, order_number) +============================================================================= +Registers lvm callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished. +`vm_context` passes into lvm callback function. + `lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above; + `order_number` (optional): the less, the earlier, + e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + +### mcl_mapgen.register_mapgen_block(node_callback_function, order_number) +========================================================================== +Registers node_callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished. + `node_callback_function`: node callback function definition: + `function(minp, maxp, seed)`: + `minp` & `maxp`: minimum and maximum block position; + `seed`: seed of this mapblock; + `order_number` (optional): the less, the earlier, + e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + +### mcl_mapgen.register_mapgen(callback_function, order_number) +=============================================================== +Registers callback function to be called when current chunk generation is REALLY 100% finished. +For LVM it's the most frustrating function from this mod. +It can't provide you access to mapgen objects. They are probably gone long ago. +Don't use it for accessing mapgen objects please. +To use VM you have to run `vm_context.vm = mcl_mapgen.get_voxel_manip(vm_context.emin, vm_context.emax)`. + `callback_function`: callback function definition: + `function(minp, maxp, seed, vm_context)`: + `minp` & `maxp`: minimum and maximum block position; + `seed`: seed of this mapblock; + `vm_context`: a table - see description above. + `order_number` (optional): the less, the earlier. + +### mcl_mapgen.register_mapgen_lvm(lvm_callback_function, order_number) +======================================================================= +Registers lvm callback function to be called when current chunk generation is REALLY 100% finished. +It's the most frustrating function from this mod. It can't provide you access to mapgen objects. They are probably gone long ago. +Don't use it for accessing mapgen objects please. +`vm_context` passes into lvm callback function. + `lvm_callback_function`: the block callback LVM function definition - same as above; + `order_number` (optional): the less, the earlier. + +### mcl_mapgen.get_far_node(pos) +================================ +Returns node if it is generated, otherwise returns `{name = "ignore"}`. + +## Constants: + +* `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max. +* `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name. +* `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode. +* `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode). diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua new file mode 100644 index 000000000..3340ce9dd --- /dev/null +++ b/mods/CORE/mcl_mapgen/init.lua @@ -0,0 +1,498 @@ +mcl_mapgen = {} + +local order = { -- mcl_mapgen.order... + DEFAULT = 5000, + CHORUS = 100000, + BUILDINGS = 200000, + VILLAGES = 900000, + DUNGEONS = 950000, + STRONGHOLDS = 999999, + OCEAN_MONUMENT = 1000000, + LARGE_BUILDINGS = 2000000, +} + +local math_floor = math.floor +local math_max = math.max +local minetest_get_node = minetest.get_node +local minetest_get_voxel_manip = minetest.get_voxel_manip +local minetest_log = minetest.log +local minetest_pos_to_string = minetest.pos_to_string + +-- Calculate mapgen_edge_min/mapgen_edge_max +mcl_mapgen.CS = math_max(1, tonumber(minetest.get_mapgen_setting("chunksize")) or 5) +mcl_mapgen.BS = math_max(1, core.MAP_BLOCKSIZE or 16) +mcl_mapgen.LIMIT = math_max(1, tonumber(minetest.get_mapgen_setting("mapgen_limit")) or 31000) +mcl_mapgen.MAX_LIMIT = math_max(1, core.MAX_MAP_GENERATION_LIMIT or 31000) -- might be set to 31000 or removed, see https://github.com/minetest/minetest/issues/10428 +mcl_mapgen.OFFSET = - math_floor(mcl_mapgen.CS / 2) +mcl_mapgen.OFFSET_NODES = mcl_mapgen.OFFSET * mcl_mapgen.BS +mcl_mapgen.CS_NODES = mcl_mapgen.CS * mcl_mapgen.BS + +local central_chunk_min_pos = mcl_mapgen.OFFSET * mcl_mapgen.BS +local central_chunk_max_pos = central_chunk_min_pos + mcl_mapgen.CS_NODES - 1 + +local ccfmin = central_chunk_min_pos - mcl_mapgen.BS -- Fullminp/fullmaxp of central chunk, in nodes +local ccfmax = central_chunk_max_pos + mcl_mapgen.BS + +local mapgen_limit_b = math_floor(math.min(mcl_mapgen.LIMIT, mcl_mapgen.MAX_LIMIT) / mcl_mapgen.BS) +local mapgen_limit_min = - mapgen_limit_b * mcl_mapgen.BS +local mapgen_limit_max = (mapgen_limit_b + 1) * mcl_mapgen.BS - 1 + +local numcmin = math_max(math_floor((ccfmin - mapgen_limit_min) / mcl_mapgen.CS_NODES), 0) -- Number of complete chunks from central chunk +local numcmax = math_max(math_floor((mapgen_limit_max - ccfmax) / mcl_mapgen.CS_NODES), 0) -- fullminp/fullmaxp to effective mapgen limits. + +mcl_mapgen.EDGE_MIN = central_chunk_min_pos - numcmin * mcl_mapgen.CS_NODES +mcl_mapgen.EDGE_MAX = central_chunk_max_pos + numcmax * mcl_mapgen.CS_NODES + +minetest_log("action", "[mcl_mapgen] World edges: mcl_mapgen.EDGE_MIN = " .. tostring(mcl_mapgen.EDGE_MIN) .. ", mcl_mapgen.EDGE_MAX = " .. tostring(mcl_mapgen.EDGE_MAX)) +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- Mapgen variables +local overworld, end_, nether = {}, {}, {} +local seed = minetest.get_mapgen_setting("seed") +mcl_mapgen.seed = seed +mcl_mapgen.name = minetest.get_mapgen_setting("mg_name") +mcl_mapgen.v6 = mcl_mapgen.name == "v6" +mcl_mapgen.superflat = mcl_mapgen.name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" +mcl_mapgen.singlenode = mcl_mapgen.name == "singlenode" +mcl_mapgen.normal = not mcl_mapgen.superflat and not mcl_mapgen.singlenode +local superflat, singlenode, normal = mcl_mapgen.superflat, mcl_mapgen.singlenode, mcl_mapgen.normal + +minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or "singlenode"))) +---------------------------------------------------------------------------------------------------------------------------- + +-- Generator queues +local queue_unsafe_engine = {} +local queue_chunks_nodes = {} +local queue_chunks_lvm = {} +local queue_blocks_nodes = {} +local queue_blocks_lvm = {} + +-- Requirements. 0 means 'none', greater than 0 means 'required' +local block = 0 +local queue_blocks_lvm_counter = 0 +local lvm_chunk = 0 +local param2 = 0 +local nodes_block = 0 +local nodes_chunk = 0 +local safe_functions = 0 + +local BS, CS = mcl_mapgen.BS, mcl_mapgen.CS -- Mapblock size (in nodes), Mapchunk size (in blocks) +local LAST_BLOCK, LAST_NODE = CS - 1, BS - 1 -- First mapblock in chunk (node in mapblock) has number 0, last has THIS number. It's for runtime optimization +local offset = mcl_mapgen.OFFSET -- Central mapchunk offset (in blocks) +local CS_NODES = mcl_mapgen.CS_NODES -- 80 + +local CS_3D = CS * CS * CS + +local DEFAULT_ORDER = order.DEFAULT + +function mcl_mapgen.register_on_generated(callback_function, order) + queue_unsafe_engine[#queue_unsafe_engine+1] = {i = order or DEFAULT_ORDER, f = callback_function} + table.sort(queue_unsafe_engine, function(a, b) return (a.i <= b.i) end) +end +function mcl_mapgen.register_mapgen(callback_function, order) + nodes_chunk = nodes_chunk + 1 + safe_functions = safe_functions + 1 + queue_chunks_nodes[nodes_chunk] = {i = order or DEFAULT_ORDER, f = callback_function} + table.sort(queue_chunks_nodes, function(a, b) return (a.i <= b.i) end) +end +function mcl_mapgen.register_mapgen_lvm(callback_function, order) + lvm_chunk = lvm_chunk + 1 + safe_functions = safe_functions + 1 + queue_chunks_lvm[lvm_chunk] = {i = order or DEFAULT_ORDER, f = callback_function} + table.sort(queue_chunks_lvm, function(a, b) return (a.i <= b.i) end) +end +function mcl_mapgen.register_mapgen_block(callback_function, order) + block = block + 1 + nodes_block = nodes_block + 1 + safe_functions = safe_functions + 1 + queue_blocks_nodes[nodes_block] = {i = order or DEFAULT_ORDER, f = callback_function} + table.sort(queue_blocks_nodes, function(a, b) return (a.i <= b.i) end) +end +function mcl_mapgen.register_mapgen_block_lvm(callback_function, order) + block = block + 1 + queue_blocks_lvm_counter = queue_blocks_lvm_counter + 1 + safe_functions = safe_functions + 1 + queue_blocks_lvm[queue_blocks_lvm_counter] = {order = order or DEFAULT_ORDER, callback_function = callback_function} + table.sort(queue_blocks_lvm, function(a, b) return (a.order <= b.order) end) +end + +local storage = minetest.get_mod_storage() +local blocks = minetest.deserialize(storage:get_string("mapgen_blocks") or "return {}") or {} +local chunks = minetest.deserialize(storage:get_string("mapgen_chunks") or "return {}") or {} +minetest.register_on_shutdown(function() + storage:set_string("mapgen_chunks", minetest.serialize(chunks)) + storage:set_string("mapgen_blocks", minetest.serialize(blocks)) +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, param2_data, light, area +local current_blocks = {} +local current_chunks = {} +local lvm_buffer, lvm_param2_buffer, lvm_light_buffer = {}, {}, {} -- Static buffer pointers + +minetest.register_on_generated(function(minp, maxp, chunkseed) + local minp, maxp, chunkseed = minp, maxp, chunkseed + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + minetest_log("warning", "[mcl_mapgen] New_chunk=" .. minetest_pos_to_string(minp) .. "..." .. minetest_pos_to_string(maxp) .. ", shell=" .. minetest_pos_to_string(emin) .. "..." .. minetest_pos_to_string(emax) .. ", chunkseed=" .. tostring(chunkseed)) + + data = vm:get_data(lvm_buffer) + area = VoxelArea:new({MinEdge=emin, MaxEdge=emax}) + vm_context = { + data = data, + param2_data = param2_data, + light = light, + area = area, + lvm_buffer = lvm_buffer, + lvm_param2_buffer = lvm_param2_buffer, + lvm_light_buffer = lvm_light_buffer, + vm = vm, + emin = emin, + emax = emax, + minp = minp, + maxp = maxp, + chunkseed = chunkseed, + } + + if safe_functions > 0 then + local x0, y0, z0 = minp.x, minp.y, minp.z + local bx0, by0, bz0 = math_floor(x0/BS), math_floor(y0/BS), math_floor(z0/BS) + local bx1, by1, bz1 = bx0 + LAST_BLOCK, by0 + LAST_BLOCK, bz0 + LAST_BLOCK -- only for entire chunk check + + -- Keep `chunkseed` in `chunks[cx][cy][cz].seed` for further safe usage: + local cx0, cy0, cz0 = math_floor((bx0-offset)/CS), math_floor((by0-offset)/CS), math_floor((bz0-offset)/CS) + if not chunks[cx0] then chunks[cx0] = {} end + if not chunks[cx0][cy0] then chunks[cx0][cy0] = {} end + if not chunks[cx0][cy0][cz0] then + chunks[cx0][cy0][cz0] = {seed = chunkseed, counter = 0} + else + chunks[cx0][cy0][cz0].seed = chunkseed + end + + local x1, y1, z1, x2, y2, z2 = emin.x, emin.y, emin.z, emax.x, emax.y, emax.z + local x, y, z = x1, y1, z1 -- iterate 7x7x7 mapchunk, {x,y,z} - first node pos. of mapblock + local bx, by, bz -- block coords (in blocs) + local box, boy, boz -- block offsets in chunks (in blocks) + while x < x2 do + bx = math_floor(x/BS) + local block_pos_offset_removed = bx - offset + local cx = math_floor(block_pos_offset_removed / CS) + box = block_pos_offset_removed % CS + if not blocks[bx] then blocks[bx]={} end + + -- We don't know how many calls, including this one, will overwrite this block content! + -- Start calculating it with `total_mapgen_block_writes_through_x` variable. + -- It can be `8 or less`, if we (speaking of `x` axis) are on chunk edge now, + -- or it can be `4 or less` - if we are in the middle of the chunk by `x` axis: + + local total_mapgen_block_writes_through_x = (box > 0 and box < LAST_BLOCK) and 4 or 8 + while y < y2 do + by = math_floor(y/BS) + block_pos_offset_removed = by - offset + local cy = math_floor(block_pos_offset_removed / CS) + boy = block_pos_offset_removed % CS + if not blocks[bx][by] then blocks[bx][by]={} end + + -- Here we just divide `total_mapgen_block_writes_through_x` by 2, + -- if we are (speaking of `y` axis now) in the middle of the chunk now. + -- Or we don't divide it, if not. + -- So, basing on `total_mapgen_block_writes_through_x`, + --- we calculate `total_mapgen_block_writes_through_y` this way: + + local total_mapgen_block_writes_through_y = (boy > 0 and boy < LAST_BLOCK) and math_floor(total_mapgen_block_writes_through_x / 2) or total_mapgen_block_writes_through_x + while z < z2 do + bz = math_floor(z/BS) + block_pos_offset_removed = bz - offset + local cz = math_floor(block_pos_offset_removed / CS) + boz = block_pos_offset_removed % CS + + -- Now we do absolutely the same for `z` axis, basing on our previous result + -- from `total_mapgen_block_writes_through_y` variable. + -- And our final result is in `total_mapgen_block_writes`. + -- It can be still 8, derived from `x` calculation, but it can be less! + -- It can be even 1, if we are in safe 3x3x3 area of mapchunk: + + local total_mapgen_block_writes = (boz > 0 and boz < LAST_BLOCK) and math_floor(total_mapgen_block_writes_through_y / 2) or total_mapgen_block_writes_through_y + + -- Get current number of writes from the table, or just set it to 1, if accessing first time: + + local current_mapgen_block_writes = blocks[bx][by][bz] and (blocks[bx][by][bz] + 1) or 1 + + -- And compare: + + if current_mapgen_block_writes == total_mapgen_block_writes then + -- this block shouldn't be overwritten anymore, no need to keep it in memory + blocks[bx][by][bz] = nil + if not chunks[cx] then chunks[cx] = {} end + if not chunks[cx][cy] then chunks[cx][cy] = {} end + if not chunks[cx][cy][cz] then + if not chunks[cx][cy][cz] then chunks[cx][cy][cz] = {counter = 1} end + else + chunks[cx][cy][cz].counter = chunks[cx][cy][cz].counter + 1 + if chunks[cx][cy][cz].counter >= CS_3D then + current_chunks[#current_chunks+1] = { x = cx, y = cy, z = cz, s = chunks[cx][cy][cz].seed } + -- this chunk shouldn't be overwritten anymore, no need to keep it in memory + chunks[cx][cy][cz] = nil + if next(chunks[cx][cy]) == nil then chunks[cx][cy] = nil end + if next(chunks[cx]) == nil then chunks[cx] = nil end + end + end + local blockseed = seed + bx * 7 + by * 243 + bz * 11931 + if queue_blocks_lvm_counter > 0 then + vm_context.blockseed = blockseed + vm_context.minp, vm_context.maxp = {x=x, y=y, z=z}, {x=x+LAST_NODE, y=y+LAST_NODE, z=z+LAST_NODE} + for _, v in pairs(queue_blocks_lvm) do + v.callback_function(vm_context) + end + end + if nodes_block > 0 then + current_blocks[#current_blocks+1] = { minp = {x=x, y=y, z=z}, maxp = {x=x+LAST_NODE, y=y+LAST_NODE, z=z+LAST_NODE}, seed = blockseed } + end + else + blocks[bx][by][bz] = current_mapgen_block_writes + end + z = z + BS + end + if next(blocks[bx][by]) == nil then blocks[bx][by] = nil end + z = z1 + y = y + BS + end + if next(blocks[bx]) == nil then blocks[bx] = nil end + y = y1 + x = x + BS + end + end + + if #queue_unsafe_engine > 0 then + for _, v in pairs(queue_unsafe_engine) do + v.f(vm_context) + end + if vm_context.write then + vm:set_data(data) + end + if vm_context.write_param2 then + vm:set_param2_data(vm_context.param2_data) + end + if vm_context.write_light then + vm:set_light_data(light) + end + if vm_context.write or vm_context.write_param2 or vm_context.write_light then + vm:calc_lighting(minp, maxp, (vm_context.shadow ~= nil) or true) -- TODO: check boundaries + vm:write_to_map() + vm:update_liquids() + elseif vm_context.calc_lighting then + vm:calc_lighting(minp, maxp, (vm_context.shadow ~= nil) or true) + end + end + + for i, b in pairs(current_chunks) do + local cx, cy, cz, seed = b.x, b.y, b.z, b.s + local bx, by, bz = cx * CS + offset, cy * CS + offset, cz * CS + offset + local x, y, z = bx * BS, by * BS, bz * BS + local minp = {x = x, y = y, z = z} + local maxp = {x = x + CS_NODES - 1, y = y + CS_NODES - 1, z = z + CS_NODES - 1} + area = VoxelArea:new({MinEdge=minp, MaxEdge=maxp}) + vm_context = { + data = data, + param2_data = param2_data, + light = light, + area = area, + lvm_buffer = lvm_buffer, + lvm_param2_buffer = lvm_param2_buffer, + lvm_light_buffer = lvm_light_buffer, + emin = minp, + emax = maxp, + minp = minp, + maxp = maxp, + chunkseed = seed, + } + for _, v in pairs(queue_chunks_lvm) do + vm_context = v.f(vm_context) + end + for _, v in pairs(queue_chunks_nodes) do + v.f(minp, maxp, seed, vm_context) + end + if vm_context.write or vm_context.write_param2 or vm_context.write_light then + if vm_context.write then + vm:set_data(data) + end + if vm_context.write_param2 then + vm:set_param2_data(param2_data) + end + if vm_context.write_light then + vm:set_light_data(light) + end + -- caused error from torches (?) + -- vm:calc_lighting(minp, maxp, vm_context.shadow or true) + vm:write_to_map() + vm:update_liquids() + elseif vm_context.calc_lighting then + vm:calc_lighting(minp, maxp, (vm_context.shadow ~= nil) or true) + end + current_chunks[i] = nil + end + + for i, b in pairs(current_blocks) do + for _, v in pairs(queue_blocks_nodes) do + v.f(b.minp, b.maxp, b.seed) + end + current_blocks[i] = nil + end +end) + +minetest.register_on_generated = mcl_mapgen.register_chunk_generator + +function mcl_mapgen.get_far_node(p) + local p = p + local node = minetest_get_node(p) + if node.name ~= "ignore" then return node end + minetest_get_voxel_manip():read_from_map(p, p) + return minetest_get_node(p) +end + +local function coordinate_to_block(x) + return math_floor(x / BS) +end + +local function coordinate_to_chunk(x) + return math_floor((coordinate_to_block(x) - offset) / CS) +end + +function mcl_mapgen.pos_to_block(pos) + return { + x = coordinate_to_block(pos.x), + y = coordinate_to_block(pos.y), + z = coordinate_to_block(pos.z) + } +end + +function mcl_mapgen.pos_to_chunk(pos) + return { + x = coordinate_to_chunk(pos.x), + y = coordinate_to_chunk(pos.y), + z = coordinate_to_chunk(pos.z) + } +end + +local k_positive = math.ceil(mcl_mapgen.MAX_LIMIT / mcl_mapgen.CS_NODES) +local k_positive_z = k_positive * 2 +local k_positive_y = k_positive_z * k_positive_z + +function mcl_mapgen.get_chunk_number(pos) -- unsigned int + local c = mcl_mapgen.pos_to_chunk(pos) + return + (c.y + k_positive) * k_positive_y + + (c.z + k_positive) * k_positive_z + + c.x + k_positive +end + +mcl_mapgen.minecraft_height_limit = 256 + +mcl_mapgen.bedrock_is_rough = normal + +--[[ Realm stacking (h is for height) +- Overworld (h>=256) +- Void (h>=1000) +- Realm Barrier (h=11), to allow escaping the End +- End (h>=256) +- Void (h>=1000) +- Nether (h=128) +- Void (h>=1000) +]] + +-- Overworld +overworld.min = -62 +if superflat then + mcl_mapgen.ground = tonumber(minetest.get_mapgen_setting("mgflat_ground_level")) or 8 + overworld.min = ground - 3 +end +-- if singlenode then mcl_mapgen.overworld.min = -66 end -- DONT KNOW WHY +overworld.max = mcl_mapgen.EDGE_MAX + +overworld.bedrock_min = overworld.min +overworld.bedrock_max = overworld.bedrock_min + (mcl_mapgen.bedrock_is_rough and 4 or 0) + +mcl_mapgen.lava = normal +overworld.lava_max = overworld.min + (normal and 10 or 0) + + +-- The Nether (around Y = -29000) +nether.min = -29067 -- Carefully chosen to be at a mapchunk border +nether.max = nether.min + 128 +nether.bedrock_bottom_min = nether.min +nether.bedrock_top_max = nether.max +if not superflat then + nether.bedrock_bottom_max = nether.bedrock_bottom_min + 4 + nether.bedrock_top_min = nether.bedrock_top_max - 4 + nether.lava_max = nether.min + 31 +else + -- Thin bedrock in classic superflat mapgen + nether.bedrock_bottom_max = nether.bedrock_bottom_min + nether.bedrock_top_min = nether.bedrock_top_max + nether.lava_max = nether.min + 2 +end +if mcl_mapgen.name == "flat" then + if superflat then + nether.flat_floor = nether.bedrock_bottom_max + 4 + nether.flat_ceiling = nether.bedrock_bottom_max + 52 + else + nether.flat_floor = nether.lava_max + 4 + nether.flat_ceiling = nether.lava_max + 52 + end +end + +-- The End (surface at ca. Y = -27000) +end_.min = -27073 -- Carefully chosen to be at a mapchunk border +end_.max = overworld.min - 2000 +end_.platform_pos = { x = 100, y = end_.min + 74, z = 0 } + +-- Realm barrier used to safely separate the End from the void below the Overworld +mcl_mapgen.realm_barrier_overworld_end_max = end_.max +mcl_mapgen.realm_barrier_overworld_end_min = end_.max - 11 + +-- Use MineClone 2-style dungeons for normal mapgen +mcl_mapgen.dungeons = normal + +mcl_mapgen.overworld = overworld +mcl_mapgen.end_ = end_ +mcl_mapgen["end"] = mcl_mapgen.end_ +mcl_mapgen.nether = nether + +mcl_mapgen.order = order + +function mcl_mapgen.get_voxel_manip(vm_context) + if vm_context.vm then + return vm + end + vm_context.vm = minetest.get_voxel_manip(vm_context.emin, vm_context.emax) + vm_context.emin, vm_context.emax = vm_context.vm:read_from_map(vm_context.emin, vm_context.emax) + vm_context.area = VoxelArea:new({MinEdge=vm_context.emin, MaxEdge=vm_context.emax}) + return vm_context.vm +end + +function mcl_mapgen.clamp_to_chunk(x, size) + if not size then + minetest.log("warning", "[mcl_mapgen] Couldn't clamp " .. tostring(x) .. " - missing size") + return x + end + if size > CS_NODES then + minetest.log("warning", "[mcl_mapgen] Couldn't clamp " .. tostring(x) .. " - given size " .. tostring(size) .. " greater than chunk size " .. tostring(mcl_mapgen.CS_NODES)) + return x + end + local offset_in_chunk = (x + central_chunk_min_pos) % CS_NODES + local x2_in_chunk = offset_in_chunk + size + if x2_in_chunk <= CS_NODES then + return x + end + local overflow = x2_in_chunk - CS_NODES + if overflow > size / 2 then + local next_x = x + (size - overflow) + if next_x < mcl_mapgen.EDGE_MAX then + return next_x + end + end + return x - overflow +end + +function mcl_mapgen.get_chunk_beginning(x) + return x - ((x + central_chunk_min_pos) % CS_NODES) +end diff --git a/mods/CORE/mcl_mapgen/mod.conf b/mods/CORE/mcl_mapgen/mod.conf new file mode 100644 index 000000000..fa734ae2b --- /dev/null +++ b/mods/CORE/mcl_mapgen/mod.conf @@ -0,0 +1,4 @@ +name = mcl_mapgen +author = kay27 +description = MineClone 2/5 MapGen Basic Stuff +depends = mcl_init diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua index 5c431135e..c7fb073b0 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -175,16 +175,16 @@ end -- check if within physical map limits (-30911 to 30927) -- within_limits, wmin, wmax = nil, -30913, 30928 mobs.within_limits = function(pos, radius) - local wmin, wmax - if mcl_vars then - if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then - wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max + local wmin, wmax + if mcl_mapgen then + if mcl_mapgen.EDGE_MIN and mcl_mapgen.EDGE_MAX then + wmin, wmax = mcl_mapgen.EDGE_MIN, mcl_mapgen.EDGE_MAX + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax end end - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax end -- get node but use fallback for nil or unknown @@ -214,6 +214,7 @@ end --a function used for despawning mobs mobs.check_for_player_within_area = function(self, radius) local pos1 = self.object:get_pos() + if not pos1 then return end --get players in radius for _,player in pairs(minetest_get_connected_players()) do if player and player:get_hp() > 0 then diff --git a/mods/ENTITIES/mcl_mobs/mod.conf b/mods/ENTITIES/mcl_mobs/mod.conf index 2a91a7764..6d3a8acc0 100644 --- a/mods/ENTITIES/mcl_mobs/mod.conf +++ b/mods/ENTITIES/mcl_mobs/mod.conf @@ -1,5 +1,5 @@ name = mcl_mobs author = PilzAdam description = Adds a mob API for mods to add animals or monsters, etc. -depends = mcl_particles +depends = mcl_mapgen, mcl_particles optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience diff --git a/mods/ENTITIES/mobs_mc_gameconfig/init.lua b/mods/ENTITIES/mobs_mc_gameconfig/init.lua index 27cb4b4bf..7be16e482 100644 --- a/mods/ENTITIES/mobs_mc_gameconfig/init.lua +++ b/mods/ENTITIES/mobs_mc_gameconfig/init.lua @@ -233,15 +233,15 @@ mobs_mc.override.spawn_height = { water = tonumber(minetest.settings:get("water_level")) or 0, -- Water level in the Overworld -- Overworld boundaries (inclusive) - overworld_min = mcl_vars.mg_overworld_min, - overworld_max = mcl_vars.mg_overworld_max, + overworld_min = mcl_mapgen.overworld.min, + overworld_max = mcl_mapgen.overworld.max, -- Nether boundaries (inclusive) - nether_min = mcl_vars.mg_nether_min, - nether_max = mcl_vars.mg_nether_max, + nether_min = mcl_mapgen.nether.min, + nether_max = mcl_mapgen.nether.max, -- End boundaries (inclusive) - end_min = mcl_vars.mg_end_min, - end_max = mcl_vars.mg_end_max, + end_min = mcl_mapgen.end_.min, + end_max = mcl_mapgen.end_.max, } diff --git a/mods/ITEMS/mcl_core/functions.lua b/mods/ITEMS/mcl_core/functions.lua index d2ff3690a..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 @@ -204,8 +205,23 @@ minetest.register_abm({ action = function(pos, node, active_object_count, active_object_count_wider) for _, object in pairs(minetest.get_objects_inside_radius(pos, 0.9)) do local entity = object:get_luaentity() - if entity and entity.name == "__builtin:item" then - object:remove() + if entity then + local entity_name = entity.name + if entity_name == "__builtin:item" then + object:remove() + elseif entity_name == "mcl_minecarts:minecart" then + local pos = object:get_pos() + local driver = entity._driver + if driver then + mcl_player.player_attached[driver] = nil + local player = minetest.get_player_by_name(driver) + player:set_detach() + player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0}) + mcl_player.player_set_animation(player, "stand" , 30) + end + minetest.add_item(pos, "mcl_minecarts:minecart") + object:remove() + end end end local posses = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } } @@ -366,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 @@ -381,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) @@ -393,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) @@ -771,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/ITEMS/mcl_portals/mod.conf b/mods/ITEMS/mcl_portals/mod.conf index 610b590c6..d4b82cc58 100644 --- a/mods/ITEMS/mcl_portals/mod.conf +++ b/mods/ITEMS/mcl_portals/mod.conf @@ -1,4 +1,4 @@ name = mcl_portals description = Adds buildable portals to the Nether and End dimensions. -depends = mcl_nether, mcl_end, mcl_particles, mcl_spawn, mcl_credits +depends = mcl_mapgen, mcl_nether, mcl_end, mcl_particles, mcl_spawn, mcl_credits, mcl_structures optional_depends = awards, doc diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index e4982c39b..9e1a67a75 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -6,12 +6,6 @@ local math = math local has_doc = minetest.get_modpath("doc") --- Parameters ---local SPAWN_MIN = mcl_vars.mg_end_min+70 ---local SPAWN_MAX = mcl_vars.mg_end_min+98 - ---local mg_name = minetest.get_mapgen_setting("mg_name") - local function destroy_portal(pos) local neighbors = { { x=1, y=0, z=0 }, @@ -184,7 +178,7 @@ function mcl_portals.end_teleport(obj, pos) -- Teleport to the End at a fixed position and generate a -- 5×5 obsidian platform below. - local platform_pos = mcl_vars.mg_end_platform_pos + local platform_pos = mcl_mapgen.end_.platform_pos -- force emerge of target1 area minetest.get_voxel_manip():read_from_map(platform_pos, platform_pos) if not minetest.get_node_or_nil(platform_pos) then diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 46025619c..e6dd255f0 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -19,7 +19,7 @@ local W_MIN, W_MAX = 4, 23 local H_MIN, H_MAX = 5, 23 local N_MIN, N_MAX = 6, (W_MAX-2) * (H_MAX-2) local TRAVEL_X, TRAVEL_Y, TRAVEL_Z = 8, 1, 8 -local LIM_MIN, LIM_MAX = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max +local LIM_MIN, LIM_MAX = mcl_mapgen.EDGE_MIN, mcl_mapgen.EDGE_MAX local PLAYER_COOLOFF, MOB_COOLOFF = 3, 14 -- for this many seconds they won't teleported again local TOUCH_CHATTER_TIME = 1 -- prevent multiple teleportation attempts caused by multiple portal touches, for this number of seconds local CHATTER_US = TOUCH_CHATTER_TIME * 1000000 @@ -27,8 +27,8 @@ local DELAY = 3 -- seconds before teleporting in Nether portal in Survival mo local DISTANCE_MAX = 128 local PORTAL = "mcl_portals:portal" local OBSIDIAN = "mcl_core:obsidian" -local O_Y_MIN, O_Y_MAX = max(mcl_vars.mg_overworld_min, -31), min(mcl_vars.mg_overworld_max, 2048) -local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_top_min - H_MIN +local O_Y_MIN, O_Y_MAX = max(mcl_mapgen.overworld.min, -31), min(mcl_mapgen.overworld.max, 2048) +local N_Y_MIN, N_Y_MAX = mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_top_min - H_MIN -- Alpha and particles local node_particles_allowed = minetest.settings:get("mcl_node_particles") or "none" @@ -66,7 +66,7 @@ minetest.register_on_shutdown(function() storage:set_string("nether_exits_keys", minetest.serialize(keys)) end) -local get_node = mcl_vars.get_node +local get_node = mcl_mapgen.get_far_node local set_node = minetest.set_node local registered_nodes = minetest.registered_nodes local is_protected = minetest.is_protected @@ -137,19 +137,8 @@ local function find_exit(p, dx, dy, dz) if not p or not p.y or not p.z or not p.x then return end local dx, dy, dz = dx or DISTANCE_MAX, dy or DISTANCE_MAX, dz or DISTANCE_MAX if dx < 1 or dy < 1 or dz < 1 then return false end - - --y values aren't used - local x = floor(p.x) - --local y = floor(p.y) - local z = floor(p.z) - - local x1 = x-dx+1 - --local y1 = y-dy+1 - local z1 = z-dz+1 - - local x2 = x+dx-1 - --local y2 = y+dy-1 - local z2 = z+dz-1 + local x, y, z = floor(p.x), floor(p.y), floor(p.z) + local x1, y1, z1, x2, y2, z2 = x-dx+1, y-dy+1, z-dz+1, x+dx-1, y+dy-1, z+dz-1 local k1x, k2x = floor(x1/256), floor(x2/256) local k1z, k2z = floor(z1/256), floor(z2/256) @@ -170,11 +159,27 @@ local function find_exit(p, dx, dy, dz) end end end - if t and abs(t.x-p.x) <= dx and abs(t.y-p.y) <= dy and abs(t.z-p.z) <= dz then + if t and abs(t.x-x) <= dx and abs(t.y-y) <= dy and abs(t.z-z) <= dz then return t end end +-- This functon searches Nether portal nodes whitin distance specified and checks the node +local function find_exit_with_check(p, dx, dy, dz) + while true do + local pos = find_exit(p, dx, dy, dz) + if not pos then + -- not found: + return + end + if (get_node(pos).name == PORTAL) then + return pos + end + -- I don't know the reason why it can happen, but if we're here, let's log it, remove this record and try again: + log("warning", "[mcl_portals] Found faulty exit from Nether portal at " .. pos_to_string(pos) .. " - removed") + remove_exit(pos) + end +end -- Ping-Pong the coordinate for Fast Travelling, https://git.minetest.land/Wuzzy/MineClone2/issues/795#issuecomment-11058 local function ping_pong(x, m, l1, l2) @@ -350,7 +355,7 @@ function build_nether_portal(pos, width, height, orientation, name, clear_before return pos end -function mcl_portals.spawn_nether_portal(pos, rot, pr, name) +function mcl_portals.spawn_nether_portal(pos, rot, pr, placer) if not pos then return end local o = 0 if rot then @@ -360,6 +365,10 @@ function mcl_portals.spawn_nether_portal(pos, rot, pr, name) o = random(0,1) end end + local name + if placer and placer:is_player() then + name = placer:get_player_name() + end build_nether_portal(pos, nil, nil, o, name, true) end @@ -432,7 +441,7 @@ local function create_portal_2(pos1, name, obj) end local exit = build_nether_portal(pos1, W_MIN-2, H_MIN-2, orientation, name) finalize_teleport(obj, exit) - local cn = mcl_vars.get_chunk_number(pos1) + local cn = mcl_mapgen.get_chunk_number(pos1) chunks[cn] = nil if queue[cn] then for next_obj, _ in pairs(queue[cn]) do @@ -446,9 +455,9 @@ end local function get_lava_level(pos, pos1, pos2) if pos.y > -1000 then - return max(min(mcl_vars.mg_lava_overworld_max, pos2.y-1), pos1.y+1) + return max(min(mcl_mapgen.overworld.lava_max, pos2.y-1), pos1.y+1) end - return max(min(mcl_vars.mg_lava_nether_max, pos2.y-1), pos1.y+1) + return max(min(mcl_mapgen.nether.lava_max, pos2.y-1), pos1.y+1) end local function ecb_scan_area_2(blockpos, action, calls_remaining, param) @@ -464,7 +473,7 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param) for _, p in pairs(portals) do add_exit(p) end - local exit = find_exit(pos) + local exit = find_exit_with_check(pos) if exit then finalize_teleport(obj, exit) end @@ -527,7 +536,7 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param) end local function create_portal(pos, limit1, limit2, name, obj) - local cn = mcl_vars.get_chunk_number(pos) + local cn = mcl_mapgen.get_chunk_number(pos) if chunks[cn] then local q = queue[cn] or {} q[obj] = true @@ -540,8 +549,8 @@ local function create_portal(pos, limit1, limit2, name, obj) -- so we'll emerge single chunk only: 5x5x5 blocks, 80x80x80 nodes maximum -- and maybe one more chunk from below if (SCAN_2_MAP_CHUNKS = true) - local pos1 = add(mul(mcl_vars.pos_to_chunk(pos), mcl_vars.chunk_size_in_nodes), mcl_vars.central_chunk_offset_in_nodes) - local pos2 = add(pos1, mcl_vars.chunk_size_in_nodes - 1) + local pos1 = add(mul(mcl_mapgen.pos_to_chunk(pos), mcl_mapgen.CS_NODES), mcl_mapgen.OFFSET_NODES) + local pos2 = add(pos1, mcl_mapgen.CS_NODES - 1) if not SCAN_2_MAP_CHUNKS then if limit1 and limit1.x and limit1.y and limit1.z then @@ -555,8 +564,8 @@ local function create_portal(pos, limit1, limit2, name, obj) end -- Basically the copy of code above, with minor additions to continue the search in single additional chunk below: - local next_chunk_1 = {x = pos1.x, y = pos1.y - mcl_vars.chunk_size_in_nodes, z = pos1.z} - local next_chunk_2 = add(next_chunk_1, mcl_vars.chunk_size_in_nodes - 1) + local next_chunk_1 = {x = pos1.x, y = pos1.y - mcl_mapgen.CS_NODES, z = pos1.z} + local next_chunk_2 = add(next_chunk_1, mcl_mapgen.CS_NODES - 1) local next_pos = {x = pos.x, y=max(next_chunk_2.y, limit1.y), z = pos.z} if limit1 and limit1.x and limit1.y and limit1.z then pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)} @@ -682,11 +691,12 @@ local function teleport_no_delay(obj, pos) name = obj:get_player_name() end - local exit = find_exit(target) + local exit = find_exit_with_check(target) if exit then finalize_teleport(obj, exit) else dim = dimension_to_teleport[dim] + if not dim then return end -- need to create arrival portal create_portal(target, limits[dim].pmin, limits[dim].pmax, name, obj) end @@ -748,6 +758,8 @@ local function teleport(obj, portal_pos) minetest.after(DELAY, teleport_no_delay, obj, portal_pos) end +mcl_structures.register_structure({name = "nether_portal", place_function = mcl_portals.spawn_nether_portal}) + minetest.register_abm({ label = "Nether portal teleportation and particles", nodenames = {PORTAL}, diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua index a04822439..56a3cfe11 100644 --- a/mods/MAPGEN/mcl_biomes/init.lua +++ b/mods/MAPGEN/mcl_biomes/init.lua @@ -1,8 +1,7 @@ -local mg_name = minetest.get_mapgen_setting("mg_name") -local mg_seed = minetest.get_mapgen_setting("seed") +local mg_seed = mcl_mapgen.seed -- Some mapgen settings -local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" +local superflat = mcl_mapgen.superflat local generate_fallen_logs = minetest.settings:get_bool("mcl_generate_fallen_logs", false) @@ -36,8 +35,8 @@ local function register_classic_superflat_biome() node_filler = "mcl_core:dirt", depth_filler = 3, node_stone = "mcl_core:dirt", - y_min = mcl_vars.mg_overworld_min - 512, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min - 512, + y_max = mcl_mapgen.overworld.max, humidity_point = 50, heat_point = 50, _mcl_biome_type = "medium", @@ -140,7 +139,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 24, heat_point = -5, _mcl_biome_type = "snowy", @@ -174,7 +173,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 3, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 58, heat_point = 8, _mcl_biome_type = "snowy", @@ -245,7 +244,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 76, heat_point = 10, _mcl_biome_type = "cold", @@ -277,7 +276,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 100, heat_point = 8, _mcl_biome_type = "cold", @@ -310,7 +309,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 4, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 10, heat_point = 45, _mcl_biome_type = "cold", @@ -360,7 +359,7 @@ local function register_biomes() node_riverbed = "mcl_core:gravel", depth_riverbed = 3, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 0, heat_point = 25, _mcl_biome_type = "cold", @@ -413,7 +412,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 4, y_min = 42, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 24, heat_point = 25, _mcl_biome_type = "cold", @@ -443,7 +442,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 1, y_min = -7, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 0, heat_point = 8, _mcl_biome_type = "cold", @@ -479,7 +478,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 24, heat_point = 8, _mcl_biome_type = "snowy", @@ -511,7 +510,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 3, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 39, heat_point = 58, _mcl_biome_type = "medium", @@ -558,7 +557,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 28, heat_point = 45, _mcl_biome_type = "medium", @@ -590,7 +589,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 58, heat_point = 22, _mcl_biome_type = "cold", @@ -637,7 +636,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 61, heat_point = 45, _mcl_biome_type = "medium", @@ -684,7 +683,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 3, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 44, heat_point = 32, _mcl_biome_type = "medium", @@ -731,7 +730,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 78, heat_point = 31, _mcl_biome_type = "medium", @@ -763,7 +762,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 77, heat_point = 27, _mcl_biome_type = "medium", @@ -796,7 +795,7 @@ local function register_biomes() depth_riverbed = 2, node_stone = "mcl_core:sandstone", y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 26, heat_point = 94, _mcl_biome_type = "hot", @@ -828,7 +827,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 94, heat_point = 27, _mcl_biome_type = "medium", @@ -861,7 +860,7 @@ local function register_biomes() depth_riverbed = 1, node_stone = "mcl_colorblocks:hardened_clay", y_min = 11, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 0, heat_point = 100, _mcl_biome_type = "hot", @@ -911,7 +910,7 @@ local function register_biomes() depth_riverbed = 1, node_stone = "mcl_colorblocks:hardened_clay", y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = -5, heat_point = 100, _mcl_biome_type = "hot", @@ -983,7 +982,7 @@ local function register_biomes() depth_riverbed = 1, node_stone = "mcl_colorblocks:hardened_clay", y_min = 30, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 0, heat_point = 60, _mcl_biome_type = "hot", @@ -1053,7 +1052,7 @@ local function register_biomes() depth_riverbed = 1, node_stone = "mcl_colorblocks:hardened_clay", y_min = 30, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = -5, heat_point = 60, _mcl_biome_type = "hot", @@ -1105,7 +1104,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 36, heat_point = 79, _mcl_biome_type = "hot", @@ -1154,7 +1153,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 48, heat_point = 100, _mcl_biome_type = "hot", @@ -1186,7 +1185,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 88, heat_point = 81, _mcl_biome_type = "medium", @@ -1235,7 +1234,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 92, heat_point = 81, _mcl_biome_type = "medium", @@ -1283,7 +1282,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 88, heat_point = 76, _mcl_biome_type = "medium", @@ -1318,7 +1317,7 @@ local function register_biomes() node_riverbed = "mcl_core:sand", depth_riverbed = 2, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, humidity_point = 90, heat_point = 79, _mcl_biome_type = "medium", @@ -1468,7 +1467,7 @@ local function register_biomes() name = biome .. "_underground", heat_point = minetest.registered_biomes[biome].heat_point, humidity_point = minetest.registered_biomes[biome].humidity_point, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = DEEP_OCEAN_MIN - 1, _mcl_biome_type = minetest.registered_biomes[biome]._mcl_biome_type, _mcl_palette_index = minetest.registered_biomes[biome]._mcl_palette_index, @@ -1489,10 +1488,10 @@ local function register_dimension_biomes() node_water = "air", node_river_water = "air", node_cave_liquid = "air", - y_min = mcl_vars.mg_nether_min, + y_min = mcl_mapgen.nether.min, -- FIXME: For some reason the Nether stops generating early if this constant is not added. -- Figure out why. - y_max = mcl_vars.mg_nether_max + 80, + y_max = mcl_mapgen.nether.max + 80, heat_point = 100, humidity_point = 0, _mcl_biome_type = "hot", @@ -1509,8 +1508,8 @@ local function register_dimension_biomes() node_cave_liquid = "air", -- FIXME: For some reason the End stops generating early if this constant is not added. -- Figure out why. - y_min = mcl_vars.mg_end_min, - y_max = mcl_vars.mg_end_max + 80, + y_min = mcl_mapgen.end_.min, + y_max = mcl_mapgen.end_.max + 80, heat_point = 50, humidity_point = 50, _mcl_biome_type = "medium", @@ -1543,7 +1542,7 @@ local function register_biome_ores() -- Rarely replace stone with stone monster eggs. -- In v6 this can happen anywhere, in other mapgens only in Extreme Hills. local monster_egg_scarcity - if mg_name == "v6" then + if mcl_mapgen.v6 then monster_egg_scarcity = 28 * 28 * 28 else monster_egg_scarcity = 26 * 26 * 26 @@ -1555,7 +1554,7 @@ local function register_biome_ores() clust_scarcity = monster_egg_scarcity, clust_num_ores = 3, clust_size = 2, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(61), biomes = { "ExtremeHills", "ExtremeHills_beach", "ExtremeHills_ocean", "ExtremeHills_deep_ocean", "ExtremeHills_underground", @@ -1565,7 +1564,7 @@ local function register_biome_ores() }) -- Bonus gold spawn in Mesa - if mg_name ~= "v6" then + if not mcl_mapgen.v6 then minetest.register_ore({ ore_type = "scatter", ore = "mcl_core:stone_with_gold", @@ -1594,8 +1593,8 @@ local function register_biomelike_ores() clust_scarcity = 1, clust_num_ores = 12, clust_size = 10, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_threshold = 0.2, noise_params = {offset=0, scale=15, spread={x=130, y=130, z=130}, seed=24, octaves=3, persist=0.70}, biomes = { "MegaTaiga" }, @@ -1607,8 +1606,8 @@ local function register_biomelike_ores() wherein = {"mcl_core:dirt_with_grass", "mcl_core:dirt"}, column_height_max = 1, column_midpoint_factor = 0.0, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_threshold = 0.0, noise_params = {offset=0, scale=15, spread={x=250, y=250, z=250}, seed=24, octaves=3, persist=0.70}, biomes = { "MesaPlateauF_grasstop" }, @@ -1620,8 +1619,8 @@ local function register_biomelike_ores() clust_scarcity = 1500, clust_num_ores = 25, clust_size = 7, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -1640,8 +1639,8 @@ local function register_biomelike_ores() wherein = {"mcl_core:dirt_with_grass", "mcl_core:dirt"}, column_height_max = 1, column_midpoint_factor = 0.0, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_threshold = -2.5, noise_params = {offset=1, scale=15, spread={x=250, y=250, z=250}, seed=24, octaves=3, persist=0.80}, biomes = { "MesaPlateauFM_grasstop" }, @@ -1653,8 +1652,8 @@ local function register_biomelike_ores() clust_scarcity = 1800, clust_num_ores = 65, clust_size = 15, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -1674,8 +1673,8 @@ local function register_biomelike_ores() wherein = {"group:hardened_clay", "group:sand","mcl_core:coarse_dirt"}, clust_scarcity = 4000, clust_size = 5, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -1694,8 +1693,8 @@ local function register_biomelike_ores() wherein = {"mcl_colorblocks:hardened_clay_orange"}, clust_scarcity = 300, clust_size = 8, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -1716,8 +1715,8 @@ local function register_biomelike_ores() clust_scarcity = 1, clust_num_ores = 12, clust_size = 10, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_threshold = 0.1, noise_params = {offset=0, scale=15, spread={x=130, y=130, z=130}, seed=95, octaves=3, persist=0.70}, biomes = { "MesaPlateauFM" }, @@ -1728,8 +1727,8 @@ local function register_biomelike_ores() wherein = {"group:hardened_clay"}, clust_scarcity = 1500, clust_size = 4, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -1752,8 +1751,8 @@ local function register_biomelike_ores() clust_scarcity = 5000, clust_num_ores = 12, clust_size = 4, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_threshold = 0.2, noise_params = {offset=0, scale=5, spread={x=250, y=250, z=250}, seed=64, octaves=3, persist=0.60}, biomes = { "ExtremeHillsM" }, @@ -1951,7 +1950,7 @@ local function register_dimension_ores() wherein = {"mcl_nether:netherrack", "mcl_core:stone"}, clust_scarcity = 13 * 13 * 13, clust_size = 5, - y_min = mcl_vars.mg_nether_min, + y_min = mcl_mapgen.nether.min, y_max = mcl_worlds.layer_to_y(64, "nether"), noise_threshold = 0.0, noise_params = { @@ -2013,8 +2012,8 @@ local function register_dimension_ores() wherein = {"mcl_nether:netherrack", "mcl_core:stone"}, clust_scarcity = 26 * 26 * 26, clust_size = 5, - y_min = mcl_vars.mg_lava_nether_max + 10, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_mapgen.nether.lava_max + 10, + y_max = mcl_mapgen.nether.max, noise_threshold = 0.0, noise_params = { offset = 0.5, @@ -2057,8 +2056,8 @@ local function register_dimension_ores() clust_scarcity = 850, clust_num_ores = 4, -- MC cluster amount: 4-10 clust_size = 3, - y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_mapgen.nether.min, + y_max = mcl_mapgen.nether.max, }) minetest.register_ore({ ore_type = "scatter", @@ -2067,8 +2066,22 @@ local function register_dimension_ores() clust_scarcity = 1650, clust_num_ores = 8, -- MC cluster amount: 4-10 clust_size = 4, - y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_mapgen.nether.min, + y_max = mcl_mapgen.nether.max, + }) + end + + -- Ancient debris + if minetest.settings:get_bool("mcl_generate_ores", true) then + minetest.register_ore({ + ore_type = "scatter", + ore = "mcl_nether:ancient_debris", + wherein = {"mcl_nether:netherrack"}, + clust_scarcity = 10000, + clust_num_ores = 4, + clust_size = 1, + y_min = mcl_worlds.layer_to_y(8, "nether"), + y_max = mcl_worlds.layer_to_y(119, "nether"), }) end @@ -2080,8 +2093,8 @@ local function register_dimension_ores() clust_scarcity = 500, clust_num_ores = 1, clust_size = 1, - y_min = mcl_vars.mg_nether_min, - y_max = mcl_vars.mg_lava_nether_max + 1, + y_min = mcl_mapgen.nether.min, + y_max = mcl_mapgen.nether.lava_max + 1, }) minetest.register_ore({ @@ -2091,8 +2104,8 @@ local function register_dimension_ores() clust_scarcity = 1000, clust_num_ores = 1, clust_size = 1, - y_min = mcl_vars.mg_lava_nether_max + 2, - y_max = mcl_vars.mg_lava_nether_max + 12, + y_min = mcl_mapgen.nether.lava_max + 2, + y_max = mcl_mapgen.nether.lava_max + 12, }) minetest.register_ore({ @@ -2102,8 +2115,8 @@ local function register_dimension_ores() clust_scarcity = 2000, clust_num_ores = 1, clust_size = 1, - y_min = mcl_vars.mg_lava_nether_max + 13, - y_max = mcl_vars.mg_lava_nether_max + 48, + y_min = mcl_mapgen.nether.lava_max + 13, + y_max = mcl_mapgen.nether.lava_max + 48, }) minetest.register_ore({ ore_type = "scatter", @@ -2112,8 +2125,8 @@ local function register_dimension_ores() clust_scarcity = 3500, clust_num_ores = 1, clust_size = 1, - y_min = mcl_vars.mg_lava_nether_max + 49, - y_max = mcl_vars.mg_nether_max, + y_min = mcl_mapgen.nether.lava_max + 49, + y_max = mcl_mapgen.nether.max, }) --[[ THE END ]] @@ -2123,7 +2136,7 @@ local function register_dimension_ores() -- FIXME: Broken lighting in v6 mapgen local end_wherein - if mg_name == "v6" then + if mcl_mapgen.v6 then end_wherein = {"air", "mcl_core:stone"} else end_wherein = {"air"} @@ -2133,11 +2146,11 @@ local function register_dimension_ores() ore_type = "stratum", ore = "mcl_end:end_stone", wherein = end_wherein, - y_min = mcl_vars.mg_end_min+64, - y_max = mcl_vars.mg_end_min+80, + y_min = mcl_mapgen.end_.min+64, + y_max = mcl_mapgen.end_.min+80, noise_params = { - offset = mcl_vars.mg_end_min+70, + offset = mcl_mapgen.end_.min+70, scale = -1, spread = {x=126, y=126, z=126}, seed = mg_seed+9999, @@ -2160,11 +2173,11 @@ local function register_dimension_ores() ore_type = "stratum", ore = "mcl_end:end_stone", wherein = end_wherein, - y_min = mcl_vars.mg_end_min+64, - y_max = mcl_vars.mg_end_min+80, + y_min = mcl_mapgen.end_.min+64, + y_max = mcl_mapgen.end_.min+80, noise_params = { - offset = mcl_vars.mg_end_min+72, + offset = mcl_mapgen.end_.min+72, scale = -3, spread = {x=84, y=84, z=84}, seed = mg_seed+999, @@ -2186,11 +2199,11 @@ local function register_dimension_ores() ore_type = "stratum", ore = "mcl_end:end_stone", wherein = end_wherein, - y_min = mcl_vars.mg_end_min+64, - y_max = mcl_vars.mg_end_min+80, + y_min = mcl_mapgen.end_.min+64, + y_max = mcl_mapgen.end_.min+80, noise_params = { - offset = mcl_vars.mg_end_min+70, + offset = mcl_mapgen.end_.min+70, scale = -2, spread = {x=84, y=84, z=84}, seed = mg_seed+99, @@ -2243,7 +2256,7 @@ local function register_grass_decoration(grasstype, offset, scale, biomes) noise_params = noise, biomes = { biomes[b] }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = node, param2 = param2, }) @@ -2310,7 +2323,7 @@ local function register_decorations() }, biomes = {"IcePlainsSpikes"}, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_structures.."/schematics/mcl_structures_ice_spike_large.mts", rotation = "random", flags = "place_center_x, place_center_z", @@ -2331,7 +2344,7 @@ local function register_decorations() }, biomes = {"IcePlainsSpikes"}, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_structures.."/schematics/mcl_structures_ice_spike_small.mts", rotation = "random", flags = "place_center_x, place_center_z", @@ -2354,7 +2367,7 @@ local function register_decorations() }, biomes = {"Forest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_large_"..i..".mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2374,7 +2387,7 @@ local function register_decorations() }, biomes = {"ExtremeHills", "ExtremeHillsM", "ExtremeHills+", "ExtremeHills+_snowtop"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_large_"..i..".mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2395,7 +2408,7 @@ local function register_decorations() }, biomes = {"Forest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2414,7 +2427,7 @@ local function register_decorations() }, biomes = {"FlowerForest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2433,7 +2446,7 @@ local function register_decorations() }, biomes = {"ExtremeHills", "ExtremeHillsM", "ExtremeHills+", "ExtremeHills+_snowtop"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2453,7 +2466,7 @@ local function register_decorations() }, biomes = {"ExtremeHills+", "ExtremeHills+_snowtop"}, y_min = 50, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2472,7 +2485,7 @@ local function register_decorations() }, biomes = {"MesaPlateauF_grasstop"}, y_min = 30, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2491,7 +2504,7 @@ local function register_decorations() }, biomes = {"MesaPlateauFM_grasstop"}, y_min = 30, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2511,7 +2524,7 @@ local function register_decorations() }, biomes = {"IcePlains"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2523,7 +2536,7 @@ local function register_decorations() fill_ratio = 0.004, biomes = {"Jungle", "JungleM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2535,7 +2548,7 @@ local function register_decorations() fill_ratio = 0.0004, biomes = {"JungleEdge", "JungleEdgeM", "Savanna"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_classic.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2557,7 +2570,7 @@ local function register_decorations() }, biomes = {"Forest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_balloon.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2578,7 +2591,7 @@ local function register_decorations() }, biomes = {"Swampland", "Swampland_shore"}, y_min = 0, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_oak_swamp.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2595,7 +2608,7 @@ local function register_decorations() fill_ratio = 0.00125, biomes = {"Jungle"}, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_jungle_tree_huge_"..i..".mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2607,7 +2620,7 @@ local function register_decorations() fill_ratio = 0.004, biomes = {"JungleM"}, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_jungle_tree_huge_"..i..".mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2622,7 +2635,7 @@ local function register_decorations() fill_ratio = 0.045, biomes = {"Jungle"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_jungle_tree.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2634,7 +2647,7 @@ local function register_decorations() fill_ratio = 0.0045, biomes = {"JungleEdge", "JungleEdgeM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_jungle_tree.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2647,7 +2660,7 @@ local function register_decorations() fill_ratio = 0.09, biomes = {"JungleM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_jungle_tree.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2672,7 +2685,7 @@ local function register_decorations() }, biomes = biomes, y_min = y, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/"..sprucename, flags = "place_center_x, place_center_z", }) @@ -2726,7 +2739,7 @@ local function register_decorations() }, biomes = {"Taiga", "ColdTaiga"}, y_min = 2, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_spruce_lollipop.mts", flags = "place_center_x, place_center_z", }) @@ -2746,7 +2759,7 @@ local function register_decorations() }, biomes = {"Taiga", "ColdTaiga"}, y_min = 3, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_spruce_matchstick.mts", flags = "place_center_x, place_center_z", }) @@ -2766,7 +2779,7 @@ local function register_decorations() }, biomes = {"IcePlains"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_spruce_5.mts", flags = "place_center_x, place_center_z", }) @@ -2780,7 +2793,7 @@ local function register_decorations() fill_ratio = 0.0002, biomes = {"Savanna", "SavannaM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_acacia_"..a..".mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2802,7 +2815,7 @@ local function register_decorations() }, biomes = {"BirchForest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_birch.mts", flags = "place_center_x, place_center_z", }) @@ -2820,7 +2833,7 @@ local function register_decorations() }, biomes = {"BirchForestM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_birch_tall.mts", flags = "place_center_x, place_center_z", }) @@ -2839,7 +2852,7 @@ local function register_decorations() }, biomes = {"Forest", "FlowerForest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_birch.mts", flags = "place_center_x, place_center_z", }) @@ -2859,7 +2872,7 @@ local function register_decorations() }, biomes = {"RoofedForest"}, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_core.."/schematics/mcl_core_dark_oak.mts", flags = "place_center_x, place_center_z", rotation = "random", @@ -2881,7 +2894,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_huge, biomes = { "RoofedForest" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_huge_brown.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2893,7 +2906,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_giant, biomes = { "RoofedForest" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_giant_brown.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2906,7 +2919,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_mycelium_huge, biomes = { "MushroomIsland", "MushroomIslandShore" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_huge_brown.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2918,7 +2931,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_mycelium_giant, biomes = { "MushroomIsland", "MushroomIslandShore" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_giant_brown.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2932,7 +2945,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_huge, biomes = { "RoofedForest" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_huge_red.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2944,7 +2957,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_giant, biomes = { "RoofedForest" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_giant_red.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2957,7 +2970,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_mycelium_huge, biomes = { "MushroomIsland", "MushroomIslandShore" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_huge_red.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2969,7 +2982,7 @@ local function register_decorations() fill_ratio = ratio_mushroom_mycelium_giant, biomes = { "MushroomIsland", "MushroomIslandShore" }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_mushrooms.."/schematics/mcl_mushrooms_giant_red.mts", flags = "place_center_x, place_center_z", rotation = "0", @@ -2990,7 +3003,7 @@ local function register_decorations() }, biomes = {"MegaTaiga", "MegaSpruceTaiga"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_structures.."/schematics/mcl_structures_boulder.mts", flags = "place_center_x, place_center_z", }) @@ -3010,7 +3023,7 @@ local function register_decorations() }, biomes = {"MegaTaiga", "MegaSpruceTaiga"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = mod_mcl_structures.."/schematics/mcl_structures_boulder_small.mts", flags = "place_center_x, place_center_z", }) @@ -3029,7 +3042,7 @@ local function register_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:cactus", biomes = {"Desert", "Mesa","Mesa_sandlevel", @@ -3053,7 +3066,7 @@ local function register_decorations() persist = 0.7 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:reeds", height = 1, height_max = 3, @@ -3074,7 +3087,7 @@ local function register_decorations() }, biomes = {"Swampland", "Swampland_shore"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:reeds", height = 1, height_max = 3, @@ -3108,7 +3121,7 @@ local function register_decorations() persist = 0.6, }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = { biomes[b] }, }) end @@ -3143,7 +3156,7 @@ local function register_decorations() persist = 0.66, }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = biomes[b], }) end @@ -3192,7 +3205,7 @@ local function register_decorations() persist = 0.62, }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, flags = "", biomes = b, }) @@ -3220,7 +3233,7 @@ local function register_decorations() }, biomes = {"Jungle"}, y_min = 3, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = jungle_bush_schematic, flags = "place_center_x, place_center_z", }) @@ -3238,7 +3251,7 @@ local function register_decorations() }, biomes = {"JungleM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = jungle_bush_schematic, flags = "place_center_x, place_center_z", }) @@ -3256,7 +3269,7 @@ local function register_decorations() }, biomes = {"JungleEdge", "JungleEdgeM"}, y_min = 3, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = jungle_bush_schematic, flags = "place_center_x, place_center_z", }) @@ -3279,7 +3292,7 @@ local function register_decorations() }, biomes = {"MegaTaiga", "MegaSpruceTaiga", "Taiga"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = {x = 3, y = 3, z = 1}, data = { @@ -3312,7 +3325,7 @@ local function register_decorations() }, biomes = {"ColdTaiga"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = {x = 3, y = 3, z = 1}, data = { @@ -3345,7 +3358,7 @@ local function register_decorations() }, biomes = {"BirchForest", "BirchForestM",}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = {x = 3, y = 3, z = 1}, data = { @@ -3371,7 +3384,7 @@ local function register_decorations() fill_ratio = 0.005, biomes = {"Jungle", "JungleM"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = {x = 3, y = 3, z = 1}, data = { @@ -3404,7 +3417,7 @@ local function register_decorations() }, biomes = {"Forest"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = {x = 3, y = 3, z = 1}, data = { @@ -3477,7 +3490,7 @@ local function register_decorations() persist = 0.6 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_farming:melon", biomes = { "Jungle" }, }) @@ -3494,7 +3507,7 @@ local function register_decorations() persist = 0.6 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_farming:melon", biomes = { "JungleM" }, }) @@ -3511,7 +3524,7 @@ local function register_decorations() persist = 0.6 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_farming:melon", biomes = { "JungleEdge", "JungleEdgeM" }, }) @@ -3530,7 +3543,7 @@ local function register_decorations() persist = 0.6 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_farming:melon", biomes = { "JungleEdgeM" }, }) @@ -3552,7 +3565,7 @@ local function register_decorations() persist = 0.666 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, }) -- Grasses and ferns @@ -3628,7 +3641,7 @@ local function register_decorations() persist = 0.666 }, flags = "force_placement", - y_min = mcl_vars.mg_lava_overworld_max + 5, + y_min = mcl_mapgen.overworld.lava_max + 5, y_max = -20, }) @@ -3647,7 +3660,7 @@ local function register_decorations() }, biomes = {"IcePlains"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = { x=1, y=2, z=1 }, data = { @@ -3670,7 +3683,7 @@ local function register_decorations() }, biomes = {"ExtremeHills+_snowtop"}, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, schematic = { size = { x=1, y=2, z=1 }, data = { @@ -3695,7 +3708,7 @@ local function register_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = {"Desert", "Mesa", "Mesa_sandlevel", "MesaPlateauF", "MesaPlateauF_sandlevel", "MesaPlateauF_grasstop","MesaBryce","Taiga", "MegaTaiga"}, decoration = "mcl_core:deadbush", height = 1, @@ -3713,7 +3726,7 @@ local function register_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = {"MesaPlateauFM_grasstop"}, decoration = "mcl_core:deadbush", height = 1, @@ -3731,7 +3744,7 @@ local function register_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = {"MesaPlateauFM","MesaPlateauFM_sandlevel"}, decoration = "mcl_core:deadbush", height = 1, @@ -3749,7 +3762,7 @@ local function register_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = {"MesaPlateauFM", "MesaPlateauFM_sandlevel", "MesaPlateauFM_grasstop"}, decoration = "mcl_core:deadbush", height = 1, @@ -3763,8 +3776,8 @@ local function register_decorations() fill_ratio = 0.009, biomes = {"MushroomIsland", "MushroomIslandShore"}, noise_threshold = 2.0, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_mushrooms:mushroom_red", }) minetest.register_decoration({ @@ -3773,8 +3786,8 @@ local function register_decorations() sidelen = 80, fill_ratio = 0.009, biomes = {"MushroomIsland", "MushroomIslandShore"}, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_mushrooms:mushroom_brown", }) @@ -3785,8 +3798,8 @@ local function register_decorations() sidelen = 80, fill_ratio = 0.003, biomes = {"Taiga", "MegaTaiga", "MegaSpruceTaiga"}, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_mushrooms:mushroom_red", }) minetest.register_decoration({ @@ -3795,8 +3808,8 @@ local function register_decorations() sidelen = 80, fill_ratio = 0.003, biomes = {"Taiga", "MegaTaiga", "MegaSpruceTaiga"}, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_mushrooms:mushroom_brown", }) @@ -3819,7 +3832,7 @@ local function register_decorations() persist = 0.66, }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = mushrooms[m], spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree" }, num_spawn_by = 1, @@ -3839,7 +3852,7 @@ local function register_decorations() persist = 0.6, }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = mushrooms[m], biomes = { "Swampland"}, spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree" }, @@ -3864,7 +3877,7 @@ local function register_decorations() persist = 0.6 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = biomes, decoration = "mcl_flowers:"..name, }) @@ -3883,7 +3896,7 @@ local function register_decorations() persist = 0.6, }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, biomes = {"FlowerForest"}, decoration = "mcl_flowers:"..name, }) @@ -3930,8 +3943,8 @@ local function register_dimension_decorations() octaves = 3, persist = 0.6 }, - y_min = mcl_vars.mg_end_min, - y_max = mcl_vars.mg_end_max, + y_min = mcl_mapgen.end_.min, + y_max = mcl_mapgen.end_.max, decoration = "mcl_end:chorus_flower", height = 1, biomes = { "End" }, @@ -3948,14 +3961,15 @@ end -- -- Detect mapgen to select functions -- -if mg_name ~= "singlenode" then + +if not mcl_mapgen.singlenode then if not superflat then - if mg_name ~= "v6" then + if not mcl_mapgen.v6 then register_biomes() register_biomelike_ores() end register_biome_ores() - if mg_name ~= "v6" then + if not mcl_mapgen.v6 then register_decorations() end else @@ -3976,21 +3990,16 @@ if mg_name ~= "singlenode" then -- Overworld decorations for v6 are handled in mcl_mapgen_core if deco_id_chorus_plant then - mcl_mapgen_core.register_generator("chorus_grow", nil, function(minp, maxp, blockseed) - local gennotify = minetest.get_mapgen_object("gennotify") - --local poslist = {} - local pr = PseudoRandom(blockseed + 14) - for _, pos in ipairs(gennotify["decoration#"..deco_id_chorus_plant] or {}) do - local x, y, z = pos.x, pos.y, pos.z - if x < -2 or x > 2 or z < -2 or z > 2 then - local realpos = { x = x, y = y + 1, z = z } - local node = minetest.get_node(realpos) - if node and node.name == "mcl_end:chorus_flower" then - mcl_end.grow_chorus_plant(realpos, node, pr) - end - end + mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object("gennotify") + local gennotify = vm_context.gennotify + for _, pos in pairs(gennotify["decoration#"..deco_id_chorus_plant] or {}) do + local realpos = { x = pos.x, y = pos.y + 1, z = pos.z } + local pr = PseudoRandom(vm_context.blockseed) + minetest.after(1, mcl_end.grow_chorus_plant, realpos, false, pr) end - end) + return vm_context + end, mcl_mapgen.order.CHORUS) end end diff --git a/mods/MAPGEN/mcl_biomes/mod.conf b/mods/MAPGEN/mcl_biomes/mod.conf index 0c6095f3d..d389640a8 100644 --- a/mods/MAPGEN/mcl_biomes/mod.conf +++ b/mods/MAPGEN/mcl_biomes/mod.conf @@ -1,4 +1,4 @@ name = mcl_biomes author = maikerumine description = Adds the various biomes and biome-related things for non-v6 map generators. -depends = mcl_init, mcl_mapgen_core, mcl_core, mcl_worlds, mcl_farming, mcl_flowers, mcl_end, mcl_ocean +depends = mcl_mapgen, mcl_mapgen_core, mcl_core, mcl_worlds, mcl_farming, mcl_flowers, mcl_end, mcl_ocean diff --git a/mods/MAPGEN/mcl_dungeons/init.lua b/mods/MAPGEN/mcl_dungeons/init.lua index 905e26396..c3e406ca1 100644 --- a/mods/MAPGEN/mcl_dungeons/init.lua +++ b/mods/MAPGEN/mcl_dungeons/init.lua @@ -2,21 +2,19 @@ mcl_dungeons = {} -local mg_name = minetest.get_mapgen_setting("mg_name") - -- Are dungeons disabled? -if mcl_vars.mg_dungeons == false or mg_name == "singlenode" then +if mcl_mapgen.dungeons == false or mcl_mapgen.singlenode == true then return end --lua locals --minetest +local minetest_find_nodes_in_area = minetest.find_nodes_in_area local registered_nodes = minetest.registered_nodes local swap_node = minetest.swap_node local set_node = minetest.set_node local dir_to_facedir = minetest.dir_to_facedir local get_meta = minetest.get_meta -local emerge_area = minetest.emerge_area --vector local vector_add = vector.add @@ -32,15 +30,15 @@ local math_max = math.max local math_ceil = math.ceil --custom mcl_vars -local get_node = mcl_vars.get_node +local get_node = mcl_mapgen.get_far_node -local min_y = math_max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1 -local max_y = mcl_vars.mg_overworld_max - 1 +local min_y = math_max(mcl_mapgen.overworld.min, mcl_mapgen.overworld.bedrock_max) + 1 +local max_y = mcl_mapgen.overworld.max - 1 -- Calculate the number of dungeon spawn attempts -- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks). -- Minetest chunks don't have this size, so scale the number accordingly. -local attempts = math_ceil(((mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE) ^ 3) / 8192) -- 63 = 80*80*80/8192 +local attempts = math_ceil((mcl_mapgen.CS_NODES ^ 3) / 8192) -- 63 = 80*80*80/8192 local dungeonsizes = { { x=5, y=4, z=5}, @@ -112,7 +110,7 @@ local loottable = } -- Bonus loot for v6 mapgen: Otherwise unobtainable saplings. -if mg_name == "v6" then +if mcl_mapgen.v6 then table.insert(loottable, { stacks_min = 1, stacks_max = 3, @@ -124,20 +122,28 @@ if mg_name == "v6" then }) end -local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) - if calls_remaining >= 1 then return end +--local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) +-- if calls_remaining >= 1 then return end +-- local p1, _, dim, pr = param.p1, param.p2, param.dim, param.pr +-- local check = not (param.dontcheck or false) +local m1, m2 = 0, 0 +local function spawn_dungeon(p1, p2, dim, pr, dontcheck) - local p1, _, dim, pr = param.p1, param.p2, param.dim, param.pr local x, y, z = p1.x, p1.y, p1.z - local check = not (param.dontcheck or false) + local check = not (dontcheck or false) -- Check floor and ceiling: Must be *completely* solid local y_floor = y local y_ceiling = y + dim.y + 1 - if check then for tx = x+1, x+dim.x do for tz = z+1, z+dim.z do - if not registered_nodes[get_node({x = tx, y = y_floor , z = tz}).name].walkable - or not registered_nodes[get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end - end end end + + if check then + local dim_x, dim_z = dim.x, dim.z + local size = dim_z*dim_x + if #minetest_find_nodes_in_area({x=x+1,y=y_floor,z=z+1}, {x=x+dim_z,y=y_floor,z=z+dim_z}, "group:walkabke") < size + or #minetest_find_nodes_in_area({x=x+1,y=y_floor,z=z+1}, {x=x+dim_z,y=y_floor,z=z+dim_z}, "group:walkabke") < size then + return + end + end -- Check for air openings (2 stacked air at ground level) in wall positions local openings_counter = 0 @@ -404,8 +410,7 @@ local function dungeons_nodes(minp, maxp, blockseed) local z = pr:next(minp.z, maxp.z-dim.z-1) local p1 = {x=x,y=y,z=z} local p2 = {x = x+dim.x+1, y = y+dim.y+1, z = z+dim.z+1} - minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) - emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr}) + spawn_dungeon(p1, p2, dim, pr) end end @@ -413,8 +418,7 @@ function mcl_dungeons.spawn_dungeon(p1, _, pr) if not p1 or not pr or not p1.x or not p1.y or not p1.z then return end local dim = dungeonsizes[pr:next(1, #dungeonsizes)] local p2 = {x = p1.x+dim.x+1, y = p1.y+dim.y+1, z = p1.z+dim.z+1} - minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) - emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr, dontcheck=true}) + spawn_dungeon(p1, p2, dim, pr, true) end -mcl_mapgen_core.register_generator("dungeons", nil, dungeons_nodes, 999999) +mcl_mapgen.register_mapgen(dungeons_nodes, mcl_mapgen.order.DUNGEONS) diff --git a/mods/MAPGEN/mcl_dungeons/mod.conf b/mods/MAPGEN/mcl_dungeons/mod.conf index fe02286fa..e7a7d921c 100644 --- a/mods/MAPGEN/mcl_dungeons/mod.conf +++ b/mods/MAPGEN/mcl_dungeons/mod.conf @@ -1,4 +1,4 @@ name = mcl_dungeons author = Wuzzy description = Generates random dungeons in the world -depends = mcl_init, mcl_core, mcl_chests, mcl_mobs, mcl_mobspawners, mcl_mapgen_core, mobs_mc +depends = mcl_mapgen, mcl_core, mcl_chests, mcl_mobs, mcl_mobspawners, mcl_mapgen_core, mobs_mc diff --git a/mods/MAPGEN/mcl_end_island/init.lua b/mods/MAPGEN/mcl_end_island/init.lua index 730176257..5a0bde2c7 100644 --- a/mods/MAPGEN/mcl_end_island/init.lua +++ b/mods/MAPGEN/mcl_end_island/init.lua @@ -10,25 +10,21 @@ local noisemap = PerlinNoiseMap({ local c_end_stone = minetest.get_content_id("mcl_end:end_stone") local y_offset = -2 -minetest.register_on_generated(function(minp, maxp) +mcl_mapgen.register_on_generated(function(vm_context) + local minp, maxp = vm_context.minp, vm_context.maxp if maxp.y < (-27025 + y_offset) or minp.y > (-27000 + y_offset + 4) or maxp.x < -75 or minp.x > 75 or maxp.z < -75 or minp.z > 75 then return end - - local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") - local data = vm:get_data() - local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) - + local data = vm_context.data + local area = vm_context.area + local write = false for idx in area:iter(math.max(minp.x, -75), math.max(minp.y, -27025 + y_offset + 4), math.max(minp.z, -75), math.min(maxp.x, 75), math.min(maxp.y, -27000 + y_offset), math.min(maxp.z, 75)) do local pos = area:position(idx) local y = 27025 + pos.y - y_offset if noisemap[pos.x + 75 + 1][y + 1][pos.z + 75 + 1] > (math.abs(1 - y / 25) ^ 2 + math.abs(pos.x / 75) ^ 2 + math.abs(pos.z / 75) ^ 2) then data[idx] = c_end_stone + write = true end end - - vm:set_data(data) - vm:calc_lighting() - vm:update_liquids() - vm:write_to_map() + vm_context.write = vm_context.write or write end) diff --git a/mods/MAPGEN/mcl_mapgen_core/clay.lua b/mods/MAPGEN/mcl_mapgen_core/clay.lua new file mode 100644 index 000000000..56e0e023f --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/clay.lua @@ -0,0 +1,63 @@ +local c_water = minetest.get_content_id("mcl_core:water_source") +local c_dirt = minetest.get_content_id("mcl_core:dirt") +local c_clay = minetest.get_content_id("mcl_core:clay") + +local perlin_clay + +local math_max = math.max +local math_min = math.min +local math_floor = math.floor +local math_abs = math.abs +local offset = math_floor(mcl_mapgen.BS / 2) +local minetest_get_item_group = minetest.get_item_group +local minetest_get_name_from_content_id = minetest.get_name_from_content_id + +mcl_mapgen.register_mapgen_block_lvm(function(c) + local minp, maxp, blockseed, voxelmanip_data, voxelmanip_area = c.minp, c.maxp, c.blockseed, c.data, c.area + local max_y = maxp.y + if max_y < -7 then return end + local min_y = minp.y + if min_y > 0 then return end + + c.vm = c.vm or mcl_mapgen.get_voxel_manip(c) + + 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(min_y, -8), math_min(max_y, 0) do + -- Assume X and Z lengths are equal + local x = minp.x + offset + pr:next(-2, 2) + local z = minp.z + offset + pr:next(-2, 2) + if perlin_clay:get_3d({x = x, y = y, z = z}) + pr:next(1, 20) > 19 then + -- Get position and shift it a bit randomly so the clay do not obviously appear in a grid + local water_pos = voxelmanip_area:index(x, y + 1, z) + local water_node = voxelmanip_data[water_pos] + if water_node == c_water or water_node == c_clay then + local surface_pos = voxelmanip_area:index(x, y, z) + local surface_node = voxelmanip_data[surface_pos] + if (surface_node == c_dirt or surface_node == c_clay or minetest_get_item_group(minetest_get_name_from_content_id(surface_node), "sand") == 1) then + local diamondsize = pr:next(1, 3) + for x1 = -diamondsize, diamondsize do + local abs_x1 = math_abs(x1) + for z1 = -(diamondsize - abs_x1), diamondsize - abs_x1 do + local ccpos = voxelmanip_area:index(x + x1, y, z + 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 + c.write = true + end + end + end + end + end + end + end +end) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 41bee508b..8f4278357 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -1,13 +1,11 @@ mcl_mapgen_core = {} -local registered_generators = {} - -local lvm, nodes, param2 = 0, 0, 0 -local lvm_buffer = {} -- -- Aliases for map generator outputs -- +local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms") + minetest.register_alias("mapgen_air", "air") minetest.register_alias("mapgen_stone", "mcl_core:stone") minetest.register_alias("mapgen_tree", "mcl_core:tree") @@ -28,7 +26,9 @@ minetest.register_alias("mapgen_clay", "mcl_core:clay") minetest.register_alias("mapgen_lava_source", "air") -- Built-in lava generator is too unpredictable, we generate lava on our own minetest.register_alias("mapgen_cobble", "mcl_core:cobble") minetest.register_alias("mapgen_mossycobble", "mcl_core:mossycobble") -minetest.register_alias("mapgen_junglegrass", "mcl_flowers:fern") +if minetest.get_modpath("mcl_flowers") then + minetest.register_alias("mapgen_junglegrass", "mcl_flowers:fern") +end minetest.register_alias("mapgen_stone_with_coal", "mcl_core:stone_with_coal") minetest.register_alias("mapgen_stone_with_iron", "mcl_core:stone_with_iron") minetest.register_alias("mapgen_desert_sand", "mcl_core:sand") @@ -43,19 +43,19 @@ minetest.register_alias("mapgen_snow", "mcl_core:snow") minetest.register_alias("mapgen_snowblock", "mcl_core:snowblock") minetest.register_alias("mapgen_ice", "mcl_core:ice") -minetest.register_alias("mapgen_stair_cobble", "mcl_stairs:stair_cobble") minetest.register_alias("mapgen_sandstonebrick", "mcl_core:sandstonesmooth") -minetest.register_alias("mapgen_stair_sandstonebrick", "mcl_stairs:stair_sandstone") -minetest.register_alias("mapgen_stair_sandstone_block", "mcl_stairs:stair_sandstone") -minetest.register_alias("mapgen_stair_desert_stone", "mcl_stairs:stair_sandstone") -local mg_name = minetest.get_mapgen_setting("mg_name") -local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" +if minetest.get_modpath("mcl_stairs") then + minetest.register_alias("mapgen_stair_cobble", "mcl_stairs:stair_cobble") + minetest.register_alias("mapgen_stair_sandstonebrick", "mcl_stairs:stair_sandstone") + minetest.register_alias("mapgen_stair_sandstone_block", "mcl_stairs:stair_sandstone") + minetest.register_alias("mapgen_stair_desert_stone", "mcl_stairs:stair_sandstone") +end -local WITCH_HUT_HEIGHT = 3 -- Exact Y level to spawn witch huts at. This height refers to the height of the floor - --- End exit portal position -local END_EXIT_PORTAL_POS = vector.new(-3, -27003, -3) +local mg_name = mcl_mapgen.name +local superflat = mcl_mapgen.superflat +local v6 = mcl_mapgen.v6 +local singlenode = mcl_mapgen.singlenode -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") @@ -69,21 +69,22 @@ local c_sand = minetest.get_content_id("mcl_core:sand") local c_void = minetest.get_content_id("mcl_core:void") local c_lava = minetest.get_content_id("mcl_core:lava_source") local c_water = minetest.get_content_id("mcl_core:water_source") -local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand") -local c_netherrack = minetest.get_content_id("mcl_nether:netherrack") -local c_nether_lava = minetest.get_content_id("mcl_nether:nether_lava_source") + +local c_nether = nil +if minetest.get_modpath("mcl_nether") then + c_nether = { + soul_sand = minetest.get_content_id("mcl_nether:soul_sand"), + netherrack = minetest.get_content_id("mcl_nether:netherrack"), + lava = minetest.get_content_id("mcl_nether:nether_lava_source") + } +end + --local c_end_stone = minetest.get_content_id("mcl_end:end_stone") 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_cocoa_1 = minetest.get_content_id("mcl_cocoas:cocoa_1") -local c_cocoa_2 = minetest.get_content_id("mcl_cocoas:cocoa_2") -local c_cocoa_3 = minetest.get_content_id("mcl_cocoas:cocoa_3") -local c_vine = minetest.get_content_id("mcl_core:vine") local c_air = minetest.CONTENT_AIR -- @@ -101,8 +102,8 @@ for s=1, #specialstones do clust_scarcity = 15*15*15, clust_num_ores = 33, clust_size = 5, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -121,8 +122,8 @@ for s=1, #specialstones do clust_scarcity = 10*10*10, clust_num_ores = 58, clust_size = 7, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -146,8 +147,8 @@ minetest.register_ore({ clust_scarcity = 15*15*15, clust_num_ores = 33, clust_size = 4, - y_min = mcl_vars.mg_overworld_min, - y_max = mcl_vars.mg_overworld_max, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, noise_params = { offset = 0, scale = 1, @@ -168,7 +169,7 @@ minetest.register_ore({ clust_scarcity = 14*14*14, clust_num_ores = 33, clust_size = 5, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(111), noise_params = { offset = 0, @@ -195,7 +196,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 525*3, clust_num_ores = 5, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(50), }) minetest.register_ore({ @@ -205,7 +206,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 510*3, clust_num_ores = 8, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(50), }) minetest.register_ore({ @@ -215,7 +216,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 500*3, clust_num_ores = 12, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(50), }) @@ -293,7 +294,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 830, clust_num_ores = 5, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(39), }) minetest.register_ore({ @@ -319,7 +320,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 4775, clust_num_ores = 5, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(30), }) minetest.register_ore({ @@ -329,7 +330,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 6560, clust_num_ores = 7, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(30), }) @@ -357,7 +358,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 10000, clust_num_ores = 4, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(12), }) minetest.register_ore({ @@ -367,7 +368,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 5000, clust_num_ores = 2, clust_size = 2, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(12), }) minetest.register_ore({ @@ -377,7 +378,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 10000, clust_num_ores = 8, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(12), }) @@ -415,7 +416,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 500, clust_num_ores = 4, clust_size = 3, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(13), }) minetest.register_ore({ @@ -425,7 +426,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 800, clust_num_ores = 7, clust_size = 4, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(13), }) @@ -455,7 +456,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then -- Emerald -- - if mg_name == "v6" then + if v6 then -- Generate everywhere in v6, but rarely. -- Common spawn @@ -466,7 +467,7 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then clust_scarcity = 14340, clust_num_ores = 1, clust_size = 1, - y_min = mcl_vars.mg_overworld_min, + y_min = mcl_mapgen.overworld.min, y_max = mcl_worlds.layer_to_y(29), }) -- Rare spawn @@ -682,7 +683,7 @@ local function register_mgv6_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:cactus", height = 1, height_max = 3, @@ -702,7 +703,7 @@ local function register_mgv6_decorations() persist = 0.7 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:reeds", height = 1, height_max = 3, @@ -710,343 +711,332 @@ local function register_mgv6_decorations() num_spawn_by = 1, }) - -- Doubletall grass - minetest.register_decoration({ - deco_type = "schematic", - schematic = { - size = { x=1, y=3, z=1 }, - data = { - { name = "air", prob = 0 }, - { name = "mcl_flowers:double_grass", param1 = 255, }, - { name = "mcl_flowers:double_grass_top", param1 = 255, }, - }, - }, - place_on = {"group:grass_block_no_snow"}, - sidelen = 8, - noise_params = { - offset = -0.0025, - scale = 0.03, - spread = {x = 100, y = 100, z = 100}, - seed = 420, - octaves = 3, - persist = 0.0, - }, - y_min = 1, - y_max = mcl_vars.mg_overworld_max, - }) - - -- Large ferns - minetest.register_decoration({ - deco_type = "schematic", - schematic = { - size = { x=1, y=3, z=1 }, - data = { - { name = "air", prob = 0 }, - { name = "mcl_flowers:double_fern", param1=255, }, - { name = "mcl_flowers:double_fern_top", param1=255, }, - }, - }, - -- v6 hack: This makes sure large ferns only appear in jungles - spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" }, - num_spawn_by = 1, - place_on = {"group:grass_block_no_snow"}, - - sidelen = 16, - noise_params = { - offset = 0, - scale = 0.01, - spread = {x = 250, y = 250, z = 250}, - seed = 333, - octaves = 2, - persist = 0.66, - }, - y_min = 1, - y_max = mcl_vars.mg_overworld_max, - }) - - -- Large flowers - local function register_large_flower(name, seed, offset) + if minetest.get_modpath("mcl_flowers") then + -- Doubletall grass minetest.register_decoration({ deco_type = "schematic", schematic = { size = { x=1, y=3, z=1 }, data = { { name = "air", prob = 0 }, - { name = "mcl_flowers:"..name, param1=255, }, - { name = "mcl_flowers:"..name.."_top", param1=255, }, + { name = "mcl_flowers:double_grass", param1 = 255, }, + { name = "mcl_flowers:double_grass_top", param1 = 255, }, }, }, place_on = {"group:grass_block_no_snow"}, + sidelen = 8, + noise_params = { + offset = -0.0025, + scale = 0.03, + spread = {x = 100, y = 100, z = 100}, + seed = 420, + octaves = 3, + persist = 0.0, + }, + y_min = 1, + y_max = mcl_mapgen.overworld.max, + }) + + -- Large ferns + minetest.register_decoration({ + deco_type = "schematic", + schematic = { + size = { x=1, y=3, z=1 }, + data = { + { name = "air", prob = 0 }, + { name = "mcl_flowers:double_fern", param1=255, }, + { name = "mcl_flowers:double_fern_top", param1=255, }, + }, + }, + -- v6 hack: This makes sure large ferns only appear in jungles + spawn_by = spawn_by_in_jungle, + num_spawn_by = 1, + place_on = {"group:grass_block_no_snow"}, sidelen = 16, noise_params = { - offset = offset, + offset = 0, scale = 0.01, - spread = {x = 300, y = 300, z = 300}, - seed = seed, - octaves = 5, - persist = 0.62, + spread = {x = 250, y = 250, z = 250}, + seed = 333, + octaves = 2, + persist = 0.66, }, y_min = 1, - y_max = mcl_vars.overworld_max, - flags = "", + y_max = mcl_mapgen.overworld.max, + }) + + -- Large flowers + local function register_large_flower(name, seed, offset) + minetest.register_decoration({ + deco_type = "schematic", + schematic = { + size = { x=1, y=3, z=1 }, + data = { + { name = "air", prob = 0 }, + { name = "mcl_flowers:"..name, param1=255, }, + { name = "mcl_flowers:"..name.."_top", param1=255, }, + }, + }, + place_on = {"group:grass_block_no_snow"}, + + sidelen = 16, + noise_params = { + offset = offset, + scale = 0.01, + spread = {x = 300, y = 300, z = 300}, + seed = seed, + octaves = 5, + persist = 0.62, + }, + y_min = 1, + y_max = mcl_mapgen.overworld.max, + flags = "", + }) + end + + register_large_flower("rose_bush", 9350, -0.008) + register_large_flower("peony", 10450, -0.008) + register_large_flower("lilac", 10600, -0.007) + register_large_flower("sunflower", 2940, -0.005) + + -- Lily pad + minetest.register_decoration({ + deco_type = "schematic", + schematic = { + size = { x=1, y=3, z=1 }, + data = { + { name = "mcl_core:water_source", prob = 0 }, + { name = "mcl_core:water_source" }, + { name = "mcl_flowers:waterlily", param1 = 255 }, + }, + }, + place_on = "mcl_core:dirt", + sidelen = 16, + noise_params = { + offset = -0.12, + scale = 0.3, + spread = {x = 200, y = 200, z = 200}, + seed = 503, + octaves = 6, + persist = 0.7, + }, + y_min = 0, + y_max = 0, + rotation = "random", }) end - register_large_flower("rose_bush", 9350, -0.008) - register_large_flower("peony", 10450, -0.008) - register_large_flower("lilac", 10600, -0.007) - register_large_flower("sunflower", 2940, -0.005) - - -- Lily pad - minetest.register_decoration({ - deco_type = "schematic", - schematic = { - size = { x=1, y=3, z=1 }, - data = { - { name = "mcl_core:water_source", prob = 0 }, - { name = "mcl_core:water_source" }, - { name = "mcl_flowers:waterlily", param1 = 255 }, + if minetest.get_modpath("mcl_farming") then + -- Pumpkin + minetest.register_decoration({ + deco_type = "simple", + decoration = "mcl_farming:pumpkin_face", + param2 = 0, + param2_max = 3, + place_on = {"group:grass_block_no_snow"}, + sidelen = 16, + noise_params = { + offset = -0.008, + scale = 0.00666, + spread = {x = 250, y = 250, z = 250}, + seed = 666, + octaves = 6, + persist = 0.666 }, - }, - place_on = "mcl_core:dirt", - sidelen = 16, - noise_params = { - offset = -0.12, - scale = 0.3, - spread = {x = 200, y = 200, z = 200}, - seed = 503, - octaves = 6, - persist = 0.7, - }, - y_min = 0, - y_max = 0, - rotation = "random", - }) + y_min = 1, + y_max = mcl_mapgen.overworld.max, + }) - -- Pumpkin - minetest.register_decoration({ - deco_type = "simple", - decoration = "mcl_farming:pumpkin_face", - param2 = 0, - param2_max = 3, - place_on = {"group:grass_block_no_snow"}, - sidelen = 16, - noise_params = { - offset = -0.008, - scale = 0.00666, - spread = {x = 250, y = 250, z = 250}, - seed = 666, - octaves = 6, - persist = 0.666 - }, - y_min = 1, - y_max = mcl_vars.overworld_max, - }) - - -- Melon - minetest.register_decoration({ - deco_type = "simple", - place_on = {"group:grass_block_no_snow"}, - sidelen = 16, - noise_params = { - offset = 0.002, - scale = 0.006, - spread = {x = 250, y = 250, z = 250}, - seed = 333, - octaves = 3, - persist = 0.6 - }, - -- Small trick to make sure melon spawn in jungles - spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" }, - num_spawn_by = 1, - y_min = 1, - y_max = 40, - decoration = "mcl_farming:melon", - }) + -- Melon + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:grass_block_no_snow"}, + sidelen = 16, + noise_params = { + offset = 0.002, + scale = 0.006, + spread = {x = 250, y = 250, z = 250}, + seed = 333, + octaves = 3, + persist = 0.6 + }, + -- Small trick to make sure melon spawn in jungles + spawn_by = spawn_by_in_jungle, + num_spawn_by = 1, + y_min = 1, + y_max = 40, + decoration = "mcl_farming:melon", + }) + end -- Tall grass - minetest.register_decoration({ - deco_type = "simple", - place_on = {"group:grass_block_no_snow"}, - sidelen = 8, - noise_params = { - offset = 0.01, - scale = 0.3, - spread = {x = 100, y = 100, z = 100}, - seed = 420, - octaves = 3, - persist = 0.6 - }, - y_min = 1, - y_max = mcl_vars.overworld_max, - decoration = "mcl_flowers:tallgrass", - }) - minetest.register_decoration({ - deco_type = "simple", - place_on = {"group:grass_block_no_snow"}, - sidelen = 8, - noise_params = { - offset = 0.04, - scale = 0.03, - spread = {x = 100, y = 100, z = 100}, - seed = 420, - octaves = 3, - persist = 0.6 - }, - y_min = 1, - y_max = mcl_vars.overworld_max, - decoration = "mcl_flowers:tallgrass", - }) - - -- Seagrass and kelp - local materials = {"dirt","sand"} - for i=1, #materials do - local mat = materials[i] - + if minetest.get_modpath("mcl_flowers") then minetest.register_decoration({ deco_type = "simple", - spawn_by = {"group:water"}, - num_spawn_by = 1, - place_on = {"mcl_core:"..mat}, + place_on = {"group:grass_block_no_snow"}, sidelen = 8, noise_params = { - offset = 0.04, + offset = 0.01, scale = 0.3, spread = {x = 100, y = 100, z = 100}, - seed = 421, - octaves = 3, - persist = 0.6 - }, - flags = "force_placement", - place_offset_y = -1, - y_min = mcl_vars.overworld_min, - y_max = 0, - decoration = "mcl_ocean:seagrass_"..mat, - }) - minetest.register_decoration({ - deco_type = "simple", - spawn_by = {"group:water"}, - num_spawn_by = 1, - place_on = {"mcl_core:mat"}, - sidelen = 8, - noise_params = { - offset = 0.08, - scale = 0.03, - spread = {x = 100, y = 100, z = 100}, - seed = 421, - octaves = 3, - persist = 0.6 - }, - flags = "force_placement", - place_offset_y = -1, - y_min = mcl_vars.overworld_min, - y_max = -5, - decoration = "mcl_ocean:seagrass_"..mat, - }) - - minetest.register_decoration({ - deco_type = "simple", - spawn_by = {"group:water"}, - num_spawn_by = 1, - place_on = {"mcl_core:"..mat}, - sidelen = 16, - noise_params = { - offset = 0.01, - scale = 0.01, - spread = {x = 300, y = 300, z = 300}, - seed = 505, - octaves = 5, - persist = 0.62, - }, - flags = "force_placement", - place_offset_y = -1, - y_min = mcl_vars.overworld_min, - y_max = -6, - decoration = "mcl_ocean:kelp_"..mat, - param2 = 16, - param2_max = 96, - }) - minetest.register_decoration({ - deco_type = "simple", - spawn_by = {"group:water"}, - num_spawn_by = 1, - place_on = {"mcl_core:"..mat}, - sidelen = 16, - noise_params = { - offset = 0.01, - scale = 0.01, - spread = {x = 100, y = 100, z = 100}, - seed = 506, - octaves = 5, - persist = 0.62, - }, - flags = "force_placement", - place_offset_y = -1, - y_min = mcl_vars.overworld_min, - y_max = -15, - decoration = "mcl_ocean:kelp_"..mat, - param2 = 32, - param2_max = 160, - }) - - end - - -- Wet Sponge - -- TODO: Remove this when we got ocean monuments - minetest.register_decoration({ - deco_type = "simple", - decoration = "mcl_sponges:sponge_wet", - spawn_by = {"group:water"}, - num_spawn_by = 1, - place_on = {"mcl_core:dirt","mcl_core:sand"}, - sidelen = 16, - noise_params = { - offset = 0.00295, - scale = 0.006, - spread = {x = 250, y = 250, z = 250}, - seed = 999, - octaves = 3, - persist = 0.666 - }, - flags = "force_placement", - y_min = mcl_vars.mg_lava_overworld_max + 5, - y_max = -20, - }) - - -- Add a small amount of tall grass everywhere to avoid areas completely empty devoid of tall grass - minetest.register_decoration({ - deco_type = "simple", - place_on = {"group:grass_block_no_snow"}, - sidelen = 8, - fill_ratio = 0.004, - y_min = 1, - y_max = mcl_vars.overworld_max, - decoration = "mcl_flowers:tallgrass", - }) - - local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"} - local mseeds = { 7133, 8244 } - for m=1, #mushrooms do - -- Mushrooms next to trees - minetest.register_decoration({ - deco_type = "simple", - place_on = {"group:grass_block_no_snow", "mcl_core:dirt", "mcl_core:podzol", "mcl_core:mycelium", "mcl_core:stone", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite"}, - sidelen = 16, - noise_params = { - offset = 0.04, - scale = 0.04, - spread = {x = 100, y = 100, z = 100}, - seed = mseeds[m], + seed = 420, octaves = 3, persist = 0.6 }, y_min = 1, - y_max = mcl_vars.mg_overworld_max, - decoration = mushrooms[m], - spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree", }, - num_spawn_by = 1, + y_max = mcl_mapgen.overworld.max, + decoration = "mcl_flowers:tallgrass", }) + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:grass_block_no_snow"}, + sidelen = 8, + noise_params = { + offset = 0.04, + scale = 0.03, + spread = {x = 100, y = 100, z = 100}, + seed = 420, + octaves = 3, + persist = 0.6 + }, + y_min = 1, + y_max = mcl_mapgen.overworld.max, + decoration = "mcl_flowers:tallgrass", + }) + end + + -- Seagrass and kelp + if minetest.get_modpath("mcl_ocean") then + local materials = {"dirt","sand"} + for i=1, #materials do + local mat = materials[i] + + minetest.register_decoration({ + deco_type = "simple", + spawn_by = {"group:water"}, + num_spawn_by = 1, + place_on = {"mcl_core:"..mat}, + sidelen = 8, + noise_params = { + offset = 0.04, + scale = 0.3, + spread = {x = 100, y = 100, z = 100}, + seed = 421, + octaves = 3, + persist = 0.6 + }, + flags = "force_placement", + place_offset_y = -1, + y_min = mcl_mapgen.overworld.min, + y_max = 0, + decoration = "mcl_ocean:seagrass_"..mat, + }) + minetest.register_decoration({ + deco_type = "simple", + spawn_by = {"group:water"}, + num_spawn_by = 1, + place_on = {"mcl_core:mat"}, + sidelen = 8, + noise_params = { + offset = 0.08, + scale = 0.03, + spread = {x = 100, y = 100, z = 100}, + seed = 421, + octaves = 3, + persist = 0.6 + }, + flags = "force_placement", + place_offset_y = -1, + y_min = mcl_mapgen.overworld.min, + y_max = -5, + decoration = "mcl_ocean:seagrass_"..mat, + }) + + minetest.register_decoration({ + deco_type = "simple", + spawn_by = {"group:water"}, + num_spawn_by = 1, + place_on = {"mcl_core:"..mat}, + sidelen = 16, + noise_params = { + offset = 0.01, + scale = 0.01, + spread = {x = 300, y = 300, z = 300}, + seed = 505, + octaves = 5, + persist = 0.62, + }, + flags = "force_placement", + place_offset_y = -1, + y_min = mcl_mapgen.overworld.min, + y_max = -6, + decoration = "mcl_ocean:kelp_"..mat, + param2 = 16, + param2_max = 96, + }) + minetest.register_decoration({ + deco_type = "simple", + spawn_by = {"group:water"}, + num_spawn_by = 1, + place_on = {"mcl_core:"..mat}, + sidelen = 16, + noise_params = { + offset = 0.01, + scale = 0.01, + spread = {x = 100, y = 100, z = 100}, + seed = 506, + octaves = 5, + persist = 0.62, + }, + flags = "force_placement", + place_offset_y = -1, + y_min = mcl_mapgen.overworld.min, + y_max = -15, + decoration = "mcl_ocean:kelp_"..mat, + param2 = 32, + param2_max = 160, + }) + end + end + + -- Add a small amount of tall grass everywhere to avoid areas completely empty devoid of tall grass + if minetest.get_modpath("mcl_flowers") then + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:grass_block_no_snow"}, + sidelen = 8, + fill_ratio = 0.004, + y_min = 1, + y_max = mcl_mapgen.overworld.max, + decoration = "mcl_flowers:tallgrass", + }) + end + + if mcl_mushrooms then + local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"} + local mseeds = { 7133, 8244 } + for m=1, #mushrooms do + -- Mushrooms next to trees + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:grass_block_no_snow", "mcl_core:dirt", "mcl_core:podzol", "mcl_core:mycelium", "mcl_core:stone", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite"}, + sidelen = 16, + noise_params = { + offset = 0.04, + scale = 0.04, + spread = {x = 100, y = 100, z = 100}, + seed = mseeds[m], + octaves = 3, + persist = 0.6 + }, + y_min = 1, + y_max = mcl_mapgen.overworld.max, + decoration = mushrooms[m], + spawn_by = { "mcl_core:tree", "mcl_core:sprucetree", "mcl_core:darktree", "mcl_core:birchtree", }, + num_spawn_by = 1, + }) + end end -- Dead bushes @@ -1063,50 +1053,52 @@ local function register_mgv6_decorations() persist = 0.6 }, y_min = 4, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:deadbush", }) - local function register_mgv6_flower(name, seed, offset, y_max) - if offset == nil then - offset = 0 + if minetest.get_modpath("mcl_flowers") then + local function register_mgv6_flower(name, seed, offset, y_max) + if offset == nil then + offset = 0 + end + if y_max == nil then + y_max = mcl_mapgen.overworld.max + end + minetest.register_decoration({ + deco_type = "simple", + place_on = {"group:grass_block_no_snow"}, + sidelen = 16, + noise_params = { + offset = offset, + scale = 0.006, + spread = {x = 100, y = 100, z = 100}, + seed = seed, + octaves = 3, + persist = 0.6 + }, + y_min = 1, + y_max = y_max, + decoration = "mcl_flowers:"..name, + }) end - if y_max == nil then - y_max = mcl_vars.mg_overworld_max - end - minetest.register_decoration({ - deco_type = "simple", - place_on = {"group:grass_block_no_snow"}, - sidelen = 16, - noise_params = { - offset = offset, - scale = 0.006, - spread = {x = 100, y = 100, z = 100}, - seed = seed, - octaves = 3, - persist = 0.6 - }, - y_min = 1, - y_max = y_max, - decoration = "mcl_flowers:"..name, - }) - end - register_mgv6_flower("tulip_red", 436) - register_mgv6_flower("tulip_orange", 536) - register_mgv6_flower("tulip_pink", 636) - register_mgv6_flower("tulip_white", 736) - register_mgv6_flower("azure_bluet", 800) - register_mgv6_flower("dandelion", 8) - -- Allium is supposed to only appear in flower forest in MC. There are no flower forests in v6. - -- We compensate by making it slightly rarer in v6. - register_mgv6_flower("allium", 0, -0.001) - --[[ Blue orchid is supposed to appear in swamplands. There are no swamplands in v6. - We emulate swamplands by limiting the height to 5 levels above sea level, - which should be close to the water. ]] - register_mgv6_flower("blue_orchid", 64500, nil, mcl_worlds.layer_to_y(67)) - register_mgv6_flower("oxeye_daisy", 3490) - register_mgv6_flower("poppy", 9439) + register_mgv6_flower("tulip_red", 436) + register_mgv6_flower("tulip_orange", 536) + register_mgv6_flower("tulip_pink", 636) + register_mgv6_flower("tulip_white", 736) + register_mgv6_flower("azure_bluet", 800) + register_mgv6_flower("dandelion", 8) + -- Allium is supposed to only appear in flower forest in MC. There are no flower forests in v6. + -- We compensate by making it slightly rarer in v6. + register_mgv6_flower("allium", 0, -0.001) + --[[ Blue orchid is supposed to appear in swamplands. There are no swamplands in v6. + We emulate swamplands by limiting the height to 5 levels above sea level, + which should be close to the water. ]] + register_mgv6_flower("blue_orchid", 64500, nil, mcl_worlds.layer_to_y(67)) + register_mgv6_flower("oxeye_daisy", 3490) + register_mgv6_flower("poppy", 9439) + end -- Put top snow on snowy grass blocks. The v6 mapgen does not generate the top snow on its own. minetest.register_decoration({ @@ -1115,7 +1107,7 @@ local function register_mgv6_decorations() sidelen = 16, fill_ratio = 11.0, -- complete coverage y_min = 1, - y_max = mcl_vars.mg_overworld_max, + y_max = mcl_mapgen.overworld.max, decoration = "mcl_core:snow", }) @@ -1124,13 +1116,13 @@ end local mg_flags = minetest.settings:get_flags("mg_flags") -- Inform other mods of dungeon setting for MCL2-style dungeons -mcl_vars.mg_dungeons = mg_flags.dungeons and not superflat +mcl_vars.mg_dungeons = mcl_mapgen.dungeons -- Disable builtin dungeons, we provide our own dungeons mg_flags.dungeons = false -- Apply mapgen-specific mapgen code -if mg_name == "v6" then +if v6 then register_mgv6_decorations() elseif superflat then -- Enforce superflat-like mapgen: no caves, decor, lakes and hills @@ -1151,20 +1143,6 @@ if string.len(mg_flags_str) > 0 then end minetest.set_mapgen_setting("mg_flags", mg_flags_str, true) --- Helper function for converting a MC probability to MT, with --- regards to MapBlocks. --- Some MC generated structures are generated on per-chunk --- probability. --- The MC probability is 1/x per Minecraft chunk (16×16). - --- x: The MC probability is 1/x. --- minp, maxp: MapBlock limits --- returns: Probability (1/return_value) for a single MT mapblock -local function minecraft_chunk_probability(x, minp, maxp) - -- 256 is the MC chunk height - return x * (((maxp.x-minp.x+1)*(maxp.z-minp.z+1)) / 256) -end - -- 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. @@ -1177,554 +1155,54 @@ end 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 +local dragon_spawn_pos = false +local dragon_spawned, portal_generated = false, false - return (minix + miniz * zwidth) + 1 +local function spawn_ender_dragon() + local obj = minetest.add_entity(dragon_spawn_pos, "mobs_mc:enderdragon") + if not obj then return false end + local dragon_entity = obj:get_luaentity() + dragon_entity._initial = true + dragon_entity._portal_pos = pos + return obj 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 +local function try_to_spawn_ender_dragon() + if spawn_ender_dragon() then + dragon_spawned = true + return 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 + minetest.after(2, try_to_spawn_ender_dragon) + minetest.log("warning", "[mcl_mapgen_core] WARNING! Ender dragon doesn't want to spawn at "..minetest.pos_to_string(dragon_spawn_pos)) 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") +if portal_generated and not dragon_spawned then + minetest.after(10, try_to_spawn_ender_dragon) end --- TODO: Try to use more efficient structure generating code -local function generate_structures(minp, maxp, blockseed, biomemap) - local chunk_has_desert_well = false - local chunk_has_desert_temple = false - local chunk_has_igloo = false - local struct_min, struct_max = -3, 111 --64 - - if maxp.y >= struct_min and minp.y <= struct_max then - -- Generate structures - local pr = PcgRandom(blockseed) - perlin_structures = perlin_structures or minetest.get_perlin(329, 3, 0.6, 100) - -- Assume X and Z lengths are equal - local divlen = 5 - for x0 = minp.x, maxp.x, divlen do for z0 = minp.z, maxp.z, divlen do - -- Determine amount from perlin noise - local amount = math.floor(perlin_structures:get_2d({x=x0, y=z0}) * 9) - -- Find random positions based on this random - local p, ground_y - for i=0, amount do - p = {x = pr:next(x0, x0+divlen-1), y = 0, z = pr:next(z0, z0+divlen-1)} - -- Find ground level - ground_y = nil - local nn - for y = struct_max, struct_min, -1 do - p.y = y - local checknode = minetest.get_node(p) - if checknode then - nn = checknode.name - local def = minetest.registered_nodes[nn] - if def and def.walkable then - ground_y = y - break - end - end - end - - if ground_y then - p.y = ground_y+1 - local nn0 = minetest.get_node(p).name - -- Check if the node can be replaced - if minetest.registered_nodes[nn0] and minetest.registered_nodes[nn0].buildable_to then - -- Desert temples and desert wells - if nn == "mcl_core:sand" or (nn == "mcl_core:sandstone") then - if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then - -- Spawn desert temple - -- TODO: Check surface - if pr:next(1,12000) == 1 then - mcl_structures.call_struct(p, "desert_temple", nil, pr) - chunk_has_desert_temple = true - end - end - if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then - local desert_well_prob = minecraft_chunk_probability(1000, minp, maxp) - - -- Spawn desert well - if pr:next(1, desert_well_prob) == 1 then - -- Check surface - local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, {x=p.x+5, y=p.y-1, z=p.z+5}, "mcl_core:sand") - if #surface >= 25 then - mcl_structures.call_struct(p, "desert_well", nil, pr) - chunk_has_desert_well = true - end - end - end - - -- Igloos - elseif not chunk_has_igloo and (nn == "mcl_core:snowblock" or nn == "mcl_core:snow" or (minetest.get_item_group(nn, "grass_block_snow") == 1)) then - if pr:next(1, 4400) == 1 then - -- Check surface - local floor = {x=p.x+9, y=p.y-1, z=p.z+9} - local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:snowblock") - local surface2 = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:dirt_with_grass_snow") - if #surface + #surface2 >= 63 then - mcl_structures.call_struct(p, "igloo", nil, pr) - chunk_has_igloo = true - end - end - end - - -- Fossil - if nn == "mcl_core:sandstone" or nn == "mcl_core:sand" and not chunk_has_desert_temple and ground_y > 3 then - local fossil_prob = minecraft_chunk_probability(64, minp, maxp) - - if pr:next(1, fossil_prob) == 1 then - -- Spawn fossil below desert surface between layers 40 and 49 - local p1 = {x=p.x, y=pr:next(mcl_worlds.layer_to_y(40), mcl_worlds.layer_to_y(49)), z=p.z} - -- Very rough check of the environment (we expect to have enough stonelike nodes). - -- Fossils may still appear partially exposed in caves, but this is O.K. - local p2 = vector.add(p1, 4) - local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_core:sandstone", "mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:dirt", "mcl_core:gravel"}) - - if #nodes >= 100 then -- >= 80% - mcl_structures.call_struct(p1, "fossil", nil, pr) - end - end - end - - -- Witch hut - if ground_y <= 0 and nn == "mcl_core:dirt" then - local prob = minecraft_chunk_probability(48, minp, maxp) - if pr:next(1, prob) == 1 then - - local swampland = minetest.get_biome_id("Swampland") - local swampland_shore = minetest.get_biome_id("Swampland_shore") - - -- Where do witches live? - - local here_be_witches = false - if mg_name == "v6" then - -- v6: In Normal biome - if biomeinfo.get_v6_biome(p) == "Normal" then - here_be_witches = true - end - else - -- Other mapgens: In swampland biome - local bi = xz_to_biomemap_index(p.x, p.z, minp, maxp) - if biomemap[bi] == swampland or biomemap[bi] == swampland_shore then - here_be_witches = true - end - end - - if here_be_witches then - local r = tostring(pr:next(0, 3) * 90) -- "0", "90", "180" or 270" - local p1 = {x=p.x-1, y=WITCH_HUT_HEIGHT+2, z=p.z-1} - local size - if r == "0" or r == "180" then - size = {x=10, y=4, z=8} - else - size = {x=8, y=4, z=10} - end - local p2 = vector.add(p1, size) - - -- This checks free space at the “body” of the hut and a bit around. - -- ALL nodes must be free for the placement to succeed. - local free_nodes = minetest.find_nodes_in_area(p1, p2, {"air", "mcl_core:water_source", "mcl_flowers:waterlily"}) - if #free_nodes >= ((size.x+1)*(size.y+1)*(size.z+1)) then - local place = {x=p.x, y=WITCH_HUT_HEIGHT-1, z=p.z} - - -- FIXME: For some mysterious reason (black magic?) this - -- function does sometimes NOT spawn the witch hut. One can only see the - -- oak wood nodes in the water, but no hut. :-/ - mcl_structures.call_struct(place, "witch_hut", r, pr) - - -- TODO: Spawn witch in or around hut when the mob sucks less. - - local function place_tree_if_free(pos, prev_result) - local nn = minetest.get_node(pos).name - if nn == "mcl_flowers:waterlily" or nn == "mcl_core:water_source" or nn == "mcl_core:water_flowing" or nn == "air" then - minetest.set_node(pos, {name="mcl_core:tree", param2=0}) - return prev_result - else - return false - end - end - local offsets - if r == "0" then - offsets = { - {x=1, y=0, z=1}, - {x=1, y=0, z=5}, - {x=6, y=0, z=1}, - {x=6, y=0, z=5}, - } - elseif r == "180" then - offsets = { - {x=2, y=0, z=1}, - {x=2, y=0, z=5}, - {x=7, y=0, z=1}, - {x=7, y=0, z=5}, - } - elseif r == "270" then - offsets = { - {x=1, y=0, z=1}, - {x=5, y=0, z=1}, - {x=1, y=0, z=6}, - {x=5, y=0, z=6}, - } - elseif r == "90" then - offsets = { - {x=1, y=0, z=2}, - {x=5, y=0, z=2}, - {x=1, y=0, z=7}, - {x=5, y=0, z=7}, - } - end - for o=1, #offsets do - local ok = true - for y=place.y-1, place.y-64, -1 do - local tpos = vector.add(place, offsets[o]) - tpos.y = y - ok = place_tree_if_free(tpos, ok) - if not ok then - break - end - end - end - end - end - end - end - - -- Ice spikes in v6 - -- In other mapgens, ice spikes are generated as decorations. - if mg_name == "v6" and not chunk_has_igloo and nn == "mcl_core:snowblock" then - local spike = pr:next(1,58000) - if spike < 3 then - -- Check surface - local floor = {x=p.x+4, y=p.y-1, z=p.z+4} - local surface = minetest.find_nodes_in_area({x=p.x+1,y=p.y-1,z=p.z+1}, floor, {"mcl_core:snowblock"}) - -- Check for collision with spruce - local spruce_collisions = minetest.find_nodes_in_area({x=p.x+1,y=p.y+2,z=p.z+1}, {x=p.x+4, y=p.y+6, z=p.z+4}, {"mcl_core:sprucetree", "mcl_core:spruceleaves"}) - - if #surface >= 9 and #spruce_collisions == 0 then - mcl_structures.call_struct(p, "ice_spike_large", nil, pr) - end - elseif spike < 100 then - -- Check surface - local floor = {x=p.x+6, y=p.y-1, z=p.z+6} - local surface = minetest.find_nodes_in_area({x=p.x+1,y=p.y-1,z=p.z+1}, floor, {"mcl_core:snowblock", "mcl_core:dirt_with_grass_snow"}) - - -- Check for collision with spruce - local spruce_collisions = minetest.find_nodes_in_area({x=p.x+1,y=p.y+1,z=p.z+1}, {x=p.x+6, y=p.y+6, z=p.z+6}, {"mcl_core:sprucetree", "mcl_core:spruceleaves"}) - - if #surface >= 25 and #spruce_collisions == 0 then - mcl_structures.call_struct(p, "ice_spike_small", nil, pr) - end - end - end - end - end - - end - end end - -- End exit portal - elseif 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 - --- 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 - - 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) - if c == 1 then - data[p_pos] = c_cocoa_1 - elseif c == 2 then - data[p_pos] = c_cocoa_2 - else - data[p_pos] = c_cocoa_3 - end - param2_data[p_pos] = minetest.dir_to_facedir(vector.subtract(treepos, pos)) - lvm_used = true - 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 +function mcl_mapgen_core.generate_end_exit_portal(pos) + if dragon_spawn_pos then return false end + dragon_spawn_pos = vector.add(pos, vector.new(3, 11, 3)) + mcl_structures.call_struct(pos, "end_exit_portal", nil, nil, function() + minetest.after(2, function() + minetest.emerge_area(vector.subtract(dragon_spawn_pos, {x = 64, y = 12, z = 5}), vector.add(dragon_spawn_pos, {x = 3, y = 3, z = 5}), function(blockpos, action, calls_remaining, param) + if calls_remaining > 0 then return end + minetest.after(2, try_to_spawn_ender_dragon) + end) + end) + end) + portal_generated = true end -- Generate mushrooms in caves manually. -- Minetest's API does not support decorations in caves yet. :-( local function generate_underground_mushrooms(minp, maxp, seed) + if not mcl_mushrooms then return end + local pr_shroom = PseudoRandom(seed-24359) -- Generate rare underground mushrooms -- TODO: Make them appear in groups, use Perlin noise - local min, max = mcl_vars.mg_lava_overworld_max + 4, 0 + local min, max = mcl_mapgen.overworld.lava_max + 4, 0 if minp.y > max or maxp.y < min then return end @@ -1747,7 +1225,7 @@ local function generate_underground_mushrooms(minp, maxp, seed) end local nether_wart_chance -if mg_name == "v6" then +if v6 then nether_wart_chance = 85 else nether_wart_chance = 170 @@ -1755,9 +1233,13 @@ end -- Generate Nether decorations manually: Eternal fire, mushrooms, nether wart -- Minetest's API does not support decorations in caves yet. :-( local function generate_nether_decorations(minp, maxp, seed) + if c_nether == nil then + return + end + local pr_nether = PseudoRandom(seed+667) - if minp.y > mcl_vars.mg_nether_max or maxp.y < mcl_vars.mg_nether_min then + if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then return end @@ -1797,17 +1279,19 @@ local function generate_nether_decorations(minp, maxp, seed) -- Mushrooms on netherrack -- Note: Spawned *after* the fire because of light level checks - special_deco(rack, function(bpos) - local l = minetest.get_node_light(bpos, 0.5) - if bpos.y > mcl_vars.mg_lava_nether_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then - -- TODO: Make mushrooms appear in groups, use Perlin noise - if pr_nether:next(1,2) == 1 then - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) - else - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) + if mcl_mushrooms then + special_deco(rack, function(bpos) + local l = minetest.get_node_light(bpos, 0.5) + if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then + -- TODO: Make mushrooms appear in groups, use Perlin noise + if pr_nether:next(1,2) == 1 then + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) + else + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) + end end - end - end) + end) + end -- Nether wart on soul sand -- TODO: Spawn in Nether fortresses @@ -1819,105 +1303,19 @@ local function generate_nether_decorations(minp, maxp, seed) end -minetest.register_on_generated(function(minp, maxp, blockseed) - minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) - local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z} - if lvm > 0 then - local lvm_used, shadow = false, false - local lb2 = {} -- param2 - local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") - local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z} - local data2 - local data = vm:get_data(lvm_buffer) - if param2 > 0 then - data2 = vm:get_param2_data(lb2) - end - local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2}) - - for _, rec in pairs(registered_generators) do - if rec.vf then - local lvm_used0, shadow0 = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed) - if lvm_used0 then - lvm_used = true - end - if shadow0 then - shadow = true - end - end - end - - if lvm_used then - -- Write stuff - vm:set_data(data) - if param2 > 0 then - vm:set_param2_data(data2) - end - vm:calc_lighting(p1, p2, shadow) - vm:write_to_map() - vm:update_liquids() - end - end - - if nodes > 0 then - for _, rec in pairs(registered_generators) do - if rec.nf then - rec.nf(p1, p2, blockseed) - end - end - end - - mcl_vars.add_chunk(minp) -end) - -function minetest.register_on_generated(node_function) - mcl_mapgen_core.register_generator("mod_"..tostring(#registered_generators+1), nil, node_function) -end - -function mcl_mapgen_core.register_generator(id, lvm_function, node_function, priority, needs_param2) - if not id then return end - - local priority = priority or 5000 - - if lvm_function then lvm = lvm + 1 end - if lvm_function then nodes = nodes + 1 end - if needs_param2 then param2 = param2 + 1 end - - local new_record = { - i = priority, - vf = lvm_function, - nf = node_function, - needs_param2 = needs_param2, - } - - registered_generators[id] = new_record - table.sort(registered_generators, function(a, b) - return (a.i < b.i) or ((a.i == b.i) and a.vf and (b.vf == nil)) - end) -end - -function mcl_mapgen_core.unregister_generator(id) - if not registered_generators[id] then return end - local rec = registered_generators[id] - registered_generators[id] = nil - if rec.vf then lvm = lvm - 1 end - if rec.nf then nodes = nodes - 1 end - if rec.needs_param2 then param2 = param2 - 1 end - --if rec.needs_level0 then level0 = level0 - 1 end -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 +if mcl_mapgen.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 diff = mcl_mapgen.overworld.bedrock_max - y -- Overworld bedrock + local ndiff1 = mcl_mapgen.nether.bedrock_bottom_max - y -- Nether bedrock, bottom + local ndiff2 = mcl_mapgen.nether.bedrock_top_max - y -- Nether bedrock, ceiling local top if diff == 0 or ndiff1 == 0 or ndiff2 == 4 then @@ -1981,53 +1379,55 @@ local function set_layers(data, area, content_id, check, min, max, minp, maxp, l end -- Below the bedrock, generate air/void -local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) - local biomemap --ymin, ymax +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.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) -- 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) + lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min -1, minp, maxp, lvm_used, pr) - -- [[ THE NETHER: mcl_vars.mg_nether_min mcl_vars.mg_nether_max ]] + -- [[ THE NETHER: mcl_mapgen.nether.min mcl_mapgen.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) + lvm_used = set_layers(data, area, c_air , nil, mcl_mapgen.nether.max +1, mcl_mapgen.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) + lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.nether.max + 128 +1, mcl_mapgen.end_.min -1, minp, maxp, lvm_used, pr) - -- [[ THE END: mcl_vars.mg_end_min mcl_vars.mg_end_max ]] + -- [[ THE END: mcl_mapgen.end_.min mcl_mapgen.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) + lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.end_.max +1, mcl_mapgen.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) + lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_mapgen.realm_barrier_overworld_end_min , mcl_mapgen.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) + lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.realm_barrier_overworld_end_max+1, mcl_mapgen.overworld.min -1, minp, maxp, lvm_used, pr) - if mg_name ~= "singlenode" then + if not 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) + lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.overworld.bedrock_min, mcl_mapgen.overworld.bedrock_max, minp, maxp, lvm_used, pr) + lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max, minp, maxp, lvm_used, pr) + lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_top_min, mcl_mapgen.nether.bedrock_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) + lvm_used = set_layers(data, area, c_air, nil, mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_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) + if mcl_mapgen.lava then + lvm_used = set_layers(data, area, c_lava, c_air, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, minp, maxp, lvm_used, pr) + if c_nether then + lvm_used = set_layers(data, area, c_nether.lava, c_air, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, minp, maxp, lvm_used, pr) + end end - -- Clay, vines, cocoas - lvm_used = generate_clay(minp, maxp, blockseed, data, area, lvm_used) - - biomemap = minetest.get_mapgen_object("biomemap") - lvm_used = generate_tree_decorations(minp, maxp, blockseed, data, data2, area, biomemap, lvm_used, pr) + vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") + local biomemap = vm_context.biomemap ----- Interactive block fixing section ----- ----- The section to perform basic block overrides of the core mapgen generated world. ----- @@ -2035,9 +1435,9 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) -- 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 + if minp.y <= mcl_mapgen.overworld.max and maxp.y >= mcl_mapgen.overworld.min then -- v6 mapgen: - if mg_name == "v6" then + if v6 then --[[ Remove broken double plants caused by v6 weirdness. v6 might break the bottom part of double plants because of how it works. @@ -2086,8 +1486,8 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) 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 @@ -2101,26 +1501,31 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) -- 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, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether_lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true + elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then + -- elseif emin.y <= mcl_mapgen.nether.max and emax.y >= mcl_mapgen.nether.min then + if c_nether then + if v6 then + -- local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + for n=1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether.lava + lvm_used = true + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + lvm_used = true + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand + lvm_used = true + end + end + else + -- local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"}) + local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether.lava end - end - else - 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 @@ -2128,12 +1533,14 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) -- * 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 + elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then local nodes - if mg_name == "v6" then - nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + if v6 then + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + -- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) else - nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"}) + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) + -- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"}) end if #nodes > 0 then lvm_used = true @@ -2143,18 +1550,18 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) 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 + if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and + minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and + minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.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)} + --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} + --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.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 + for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do + for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do + for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do local p_pos = area:index(x, y, z) - if y == mcl_vars.mg_end_platform_pos.y then + if y == mcl_mapgen.end_.platform_pos.y then data[p_pos] = c_obsidian else data[p_pos] = c_air @@ -2167,27 +1574,46 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed) 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 - if mg_name ~= "singlenode" then + if not singlenode then -- Generate special decorations generate_underground_mushrooms(minp, maxp, blockseed) generate_nether_decorations(minp, maxp, blockseed) - generate_structures(minp, maxp, blockseed, biomemap) end - return lvm_used, shadow + vm_context.write = vm_context.write or lvm_used end -mcl_mapgen_core.register_generator("main", basic, nil, 1, true) +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") + +-- Nether Roof Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.nether.max+127 then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy <= mcl_mapgen.nether.max then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} + vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.write = true +end, 999999999) + +-- End Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.end_.max then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy <= mcl_mapgen.end_.min then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z} + vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.write = true +end, 9999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/mod.conf b/mods/MAPGEN/mcl_mapgen_core/mod.conf index 9f7d9ebaa..11f51e252 100644 --- a/mods/MAPGEN/mcl_mapgen_core/mod.conf +++ b/mods/MAPGEN/mcl_mapgen_core/mod.conf @@ -1,5 +1,5 @@ name = mcl_mapgen_core author = Wuzzy description = The core of the MCL2 mapgen -depends = mcl_init, mcl_core, biomeinfo, mcl_worlds, mcl_cocoas, mcl_sponges, mcl_ocean, mcl_stairs, mcl_monster_eggs, mcl_structures -optional_depends = mclx_core +depends = mcl_mapgen, mcl_init, mcl_core, biomeinfo, mcl_worlds +optional_depends = mclx_core, mcl_cocoas, mcl_sponges, mcl_ocean, mcl_stairs, mcl_monster_eggs, mcl_structures, mcl_flowers, mcl_farming, mcl_mushrooms, mcl_nether 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) diff --git a/mods/MAPGEN/mcl_ocean_monument/init.lua b/mods/MAPGEN/mcl_ocean_monument/init.lua new file mode 100644 index 000000000..fffa6f6b0 --- /dev/null +++ b/mods/MAPGEN/mcl_ocean_monument/init.lua @@ -0,0 +1,97 @@ + +-- Check it: +-- seed 1, v7 mapgen +-- /teleport 14958,8,11370 + +local mcl_mapgen_get_far_node = mcl_mapgen.get_far_node +local minetest_log = minetest.log +local minetest_place_schematic = minetest.place_schematic +local minetest_pos_to_string = minetest.pos_to_string +local minetest_swap_node = minetest.swap_node + +local path = minetest.get_modpath("mcl_ocean_monument") .. "/schematics/ocean_monument.mts" + +local water = "mcl_core:water_source" +local air = "air" +local ice = "mcl_core:ice" + +local leg_materials = { + "mcl_ocean:prismarine_brick", + "mcl_ocean:prismarine", +} +local what_we_can_replace_by_legs = { + water, + air, + "mcl_core:water_flowing", + "mcl_core:stone", +} + +local leg_search_quick_index = {} +for _, v in pairs(leg_materials) do + leg_search_quick_index[v] = true +end + +local leg_replace_quick_index = {} +for _, v in pairs(what_we_can_replace_by_legs) do + leg_replace_quick_index[v] = true +end + +local y_wanted = mcl_mapgen.OFFSET_NODES -- supposed to be -32 +local y_bottom = mcl_mapgen.overworld.min -- -62 + +mcl_mapgen.register_mapgen(function(minp, maxp, seed) + local minp = minp + local y = minp.y + if y ~= y_wanted then return end + + local x, z = minp.x, minp.z + local pr = PseudoRandom(seed) + + -- scan the ocean - it should be the ocean: + for i = 1, pr:next(10, 100) do + local pos = {x = pr:next(15, 64) + x, y = pr:next(0, 25) - 25, z = pr:next(15, 64) + z} + local node_name = mcl_mapgen_get_far_node(pos).name + if node_name ~= water then return end + end + + -- scan nodes above water level - there should be the air: + for i = 1, pr:next(10, 100) do + local pos = {x = pr:next(0, 79) + x, y = 2, z = pr:next(0,79) + z} + local node_name = mcl_mapgen_get_far_node(pos).name + if node_name ~= air then return end + end + + -- scan ocean surface - allow only water and ice: + for i = 1, pr:next(10,100) do + local pos = {x=pr:next(0, 79)+x, y=1, z=pr:next(0,79)+z} + local node_name = mcl_mapgen_get_far_node(pos).name + if node_name ~= water and node_name ~= ice then return end + end + + -- random rotation: + local rotation = pr:next(0, 3) + local rotation_str = tostring(rotation * 90) + minetest_place_schematic(minp, path, rotation_str, nil, true) + + -- search prismarine legs at base level and continue them up to the bottom: + for x = x, maxp.x do + for z = z, maxp.z do + local pos = {x = x, y = y, z = z} + local node_name = mcl_mapgen_get_far_node(pos).name + if leg_search_quick_index[node_name] then + local node_leg = {name = node_name} + for y = y - 1, y_bottom, -1 do + pos.y = y + local next_name = mcl_mapgen_get_far_node(pos).name + if not leg_replace_quick_index[next_name] then + break + end + minetest_swap_node(pos, node_leg) + end + end + end + end + + minetest_log("action", "[mcl_ocean_monument] Placed at " .. minetest_pos_to_string(minp) .. ", " .. rotation_str .. " deg.") + +end, mcl_mapgen.order.OCEAN_MONUMENT) diff --git a/mods/MAPGEN/mcl_ocean_monument/mod.conf b/mods/MAPGEN/mcl_ocean_monument/mod.conf new file mode 100644 index 000000000..945a81166 --- /dev/null +++ b/mods/MAPGEN/mcl_ocean_monument/mod.conf @@ -0,0 +1,4 @@ +name = mcl_ocean_monument +author = TrashPanda +description = Adds Ocean Monument, https://git.minetest.land/MineClone2/MineClone2/issues/958#issuecomment-14102 +depends = mcl_mapgen, mcl_structures diff --git a/mods/MAPGEN/mcl_ocean_monument/schematics/ocean_monument.mts b/mods/MAPGEN/mcl_ocean_monument/schematics/ocean_monument.mts new file mode 100644 index 0000000000000000000000000000000000000000..f94b808b521a431c82d0ed5a708156daf748171b GIT binary patch literal 8342 zcmaKRcU)7+yLa3*t8TEMNU#73i--h+K$I3(lqwyhgg`)gZ&4vsH)}y!%!(ip0wTR? z=#YT10Ma28DFV_WHMAsz2)qaP_rCY@dGGz)`6HQgX6BjaJpDUke9O`pv>&7j5(lY9 z|L+ZS5cKP9uVBz=KNnxe02jC0{;Gk&URb}|!CwAuj?TeeEVJCc=z2TY z2PC~WguMgM#j0X`Z#z5w|0Eq<1MWKex`9sq7Y(f2ZAahR{&(Dh{Xxfnt`7|G_izIU z{QUp-ol8Klo2o~EudB0ffQwIP+ERKPeiBx$sAIH6AJHWlmP;D6S_Ef&#WizC9|~{c{0}U{c&b` z4+9$(wTPb;&CXqxBeQ4=;RDe(q&RpVQO=;{U>|kj!^^d{W6N&|P=T^5N%N^U$fmf5 zy55hNd3Q7nLwI#AFS+;zZkzas1yX!W!xA0O)BXkYjvMp{s(r#(sjLK-4Bcq6yc9&v z$Y-&f+3bR)k_86o74%NqRM=ypA3L5lAxSdviWh;#w?Vy=BT|d={Orv}-e;8i3?x8? znGDk4I{wu{dYyWT5;h|-=!@YOo0FPH05vm%9~@00KqaY8UiN_xpcRRbx*0w#^RE5M zGDiL^G=7c+E}6nBIF~_P?T_u5MdzduyoNhwfDX9I1g~?2yty&My4OZE2n8OCVAfrN z=a}LgMn*&PE;pts+R-dA`FUbVC0UZ@6ndocA3Ob}ysoi5)0xmuFzh~R=IqiP)hT*3J=Hddx71tl zGC|CnTSZYM#1WxA=E)n_P|jn{;VS5`Cnf+cGU)h{H3udXdd!LSkV(TD>y7Tu2JSF$ zDLLbkc6M1AU4eDK`5+s+Aj@SQD1_LcxTUEhJ3nk7{})h2kgII4Zrj5PB+n`@v8jDI zq<+cI$J@pwL;-spCFH5}Lh5R(!kREEg2pLIg9!gcc(jI;H6dwW@mrfO6Wf0lm}eiV z(Tt;SNY`$>RFU~A6KeCFtnE|V+ITprH$s~sGk%iXh{UX%C#Totki)4?qZ(g25tw5j zJC(e$+IG>`wU=H45$I}%8jfC*;#uZb1Wh98;poX>%WQm9G*<-veUP!Mwz`Vt*JQqI z+pUU!sKG9N-6Wn}wRB^yu3sa-(Yl{A7p0c(h>W!ANH6W$ZUzHUq}FuI9CZkkII&JU zNAk=<<>8?4nzAZCOkl?3T3r`pm~ed&+{TT$*%7!Ti0RJIbOuatR+Q>AB9dp8Ty6|3Md2ke~A#P0Kvjj!CYFUhIE^I3ivg6;#mVDC1s$oG|rFN`6Lg@{p zIRDzOfO7Afx)k#b*|sSSMhyYx%a$WSAtD0_vOkOf3SS*fi{eaJj9eLhz2*q%N73t@ zfDRT{KSv{o7g2@Nsy^U1uMU3^wQ&ZTgm{AdhZ;g*)=a!_gFI>!Ra_J6nL+Wh(<2F< zjV=p5jbdFN*Du0j`1?U1WkNZ1B949YPRk94^13Xyy5-9SNQ^v{+d13D!D;19CR!hs z!*pv_HHT_BFihg00$m<7cN%mwT7w%szh$|I{c z>7Y2l21^&(z$lNl%^>>~&rfc$$`rQW@ zGfuemdkyRF;06ATZ?>^lPY#ynLHqJLSM_-cWu&h6MSV$3MKUE+N3-ebPC>YMG%D5{ zBQLHw%g6KNnnxu`E=kb#00f}KBpK=s552jL4_BJn`Lxbb#R?qMG|jm!!wQrr>i3EiEdIpyDnJ_sXE@-A9Lr?#Dr)OBPa_k7%jq5c8V zQ031nAtC{pyq*S+-0~CqOc*Mf_t{~MOLFi>uZVKZybT4z=(Y^exb7RsTrrHiMwR9y z>F?aR&XAYTJ`r=%mrx^I3OVW%2jif`2SQx$;sSAcHGX@d?vo%UkcR$RB90?`zv0JC zJPoZVIh7L&eGtAPNnW5svH&I;E?~ONw}BpLy#?>u(U2L zHPia|HAE9+_Ld_?{)a}krl!BWnF)6-qi&waRP5{IQB2qIwfD{dSrDz<47t3>K5}mh zM?d{(rgE{Zb?jABq&GhX(T3?3m!6ve&s=1fW4a^Dca`B^s>#;TD=#L^bKJb!xnKlg zdRA{#a(LV$oIQ)sH(aI7}{%y=oN)Etaj8l5p(03bze=Fv6VmBQ*~)IJ}7c zBU|foA6Xx78CUYiQ}|_m{m$B3%*yw$%i$H3xwM{6|K-TTppcms(~9w^2+C|>`~^}- zUmuMgqqoU3;$DMA&JPba>@c^igjr^JHPnHy!q5hjp4>wIL1+M1Og5Ar#2#gV`3aD% z43Fv`f*stmP$QaYbC?zy*|mb-Q~-H`;mX&sR=OuT)V#?|uuoe)E_)OsHr6)@HUtXq zj&0FbchfiUQZURL`!2nTKlB;`hGxNr#UAtotp}tihxg1H>#Fr3zF5!kIL%LGu5Jk3~plN%ThV`ux#~b{)HvvyQIdEos@zvkO5AWjj^8(8o7#JD%9IjD3bk< z0{F>0huRG29rPmtJLNZixK>C-Z)D>bMt<~}i6h*T5m5*PiSKZqB9HXk=#0sLI~qPG z{V?6*rpg)jl;$XDQ{YO|9w7ER{s!>Yol#D6;*A;9Lyfq<1HxdyA|2oKLy{K?Sklzp zE7l2l5$sW97QsM#%10bJYS~52tMt3315u?MBgO!^|&1KzS$#0yR9AEE`A4p^QwpR$Gk|&%89x6lectBhW(|3$|N8i9tuv zT_Vx;@-tb%1i>l%>vUfB6 z&)Fi}VYo=Lyv^k1?QKzWgU_9HSKf0_aC28Ip+jw#+f?`h~)2s^Y_ zNJknEeGsSpu>^J`Y_N=4Ppc{s9PJGHoK<$0V2lKNrS52vG`5QcR@mFAY z!tNt2Y1Ob>`$WfrkJtj35WTl30=fPps(@UhJAJ397o$c=KoUV955}0cF3$r!X{}?J z{KWOopviSf4vQYWK=*~4-02anm!ZdScU)a`?Ifh52_uUY-m;rS zdY%2WdS$Y;+yPJoBBb71Z@Q-C>ZJXJ(;s^AQ7-AWkRPk=7Qwj zvB}d+Lt*u`kW)4rGdB)ZeU)wQ8SbL_o> z8v9X;p?yxr8}NsPM*-pe*uDS0{hjH);N$ z70&_gJ%)AvPb$U;L3>Oe?0V47*l|`DL~xkpT!x4(kbrMu$tVlf~}%+^tt@&Ute8G zQa=Jx^U}Xxo?({NlmvTGYI=F?2kand<*w2n?}ns=xRcDPN@E)mN)uwO?XOa3&2ZCd zTv^?Bto)>n_TR1+K{|Z|0m_7PTUPHS;&!>y%q$3WEvN8v-^iyW1V?VTt=?_?Y&sGU zMD(*{eFUTl0Gq}&O-5eTE|-o57-uhoPY^#Zx~h1{R5^dz_ps%k2C3tqiNIE4_qRIF z%M4}H1GZ)hu2`s6X71;;C_~&O_H-vKBS40G#0l7tB%Yl_kb7^r220=Uh<{~84C^rl z%+@dIrI8_a-j|GkRB2yEy*UqTU!`AtF|S~@sAknv*ZZWLj{A}2?B~*VhZQRHOq?05 zElAWGx%{r zouvl1+|K+oEw5HQ)>7Esan@ib?iU5(p?lhe(uE3Y7d@0ya8qU|L7(h{>CCzo2UK9< z4jpQ?F1-5s^axs_>~w9MpDEo3bM+Y*^4AQ^b_I`ld!w=UDR_G@DR{ialH&BLBFM9* z{rD+YI!T{;uCJFP>=lg_#LcuMzHmjOi&5}(>r_8UIWvfZB;&DU<%M`7VcegthQfWE z?50w<^GHn}ZhpStBn^WtgZd`yzdvH>uYfJ_%4*h3DUH$n+$y9}MjvW%#lBdR#?+tL zf$PLVD_hhgKQYdux|dwPGWa<1qK)>pg|+t9;CDj3#A&?|$-LP=K{fklE+`JZXw~&5 zPf@cBXUiwjF87^Ii*3KAeS?z8M4v_|61|0C1LYBuu@6vYCB~{1atbYY1hKx{DXdh8 zly)V*D(NJs&SH<9f|O^|thDLiR5JKOi$RzEO<{q`m%M*k|8ejfD3++V>` zyaH7(;q8M+K$#t_bfs(mHKmU(!eMsQRUvih#o-ipEzJr!%6Uj#cU72wkMmJ+GT4JP zGfxD4khzvxaCDgJrZxEdXsL6KWomsZQ~jgeSwrEZq4UN1b%nRHEBlQc(l-V?C{F0? z_VYn=-jqy)g?|#PM5aP6*dpS~ZIqcduqkR`H1)biPJqo3zb^c>50RmDtXkf8K^~5% zv(aL&Yj@2c#-xOZ4u5;H=qjXD->2x5-j>wZDX-29>y8@C`tZ=jiq(;CWqkr%^Vf5a zw>o!Tz?92Sfg>r1;NQFKbTU(}e#RRVszEO+M2Ft1AT8-gti=+SQ1T7ILbD3tK_$dF zn5_oLPFUc`eHDufYd=^uA`*(I?vZCGMb&79`dgv&&uWDT;HXijp{+Lkd2CDOK&A2M zV)T>BtB`p`#4A_&J|U70C4w1lChdI>{sAA5zYICf3nHqOXNLYB zj8Z5H)k5rT=r3FW^UTjXJ(m*d;d%kGrPoq;YH*=MlPRh5ThV_$#h-}&Y)qU#GbGIG ztdz)9g>(kzUb;2s_vLz#EDrs9Eey&#{P+Ne0jQ_i>#p#qol0sOg@sv8T;&v}Ty=!k zLw#dMDNd2oB=8xD5I4G42Yy7bTJQG-^jG^h!cmm`L;eaV{oEi#n;^F_c|W6pgPeKZPKMJ zQSk5g-gMYqA5jVqrT5v_wm&)bx3?i`U#9Gyza=LRhdT8B17`o3gG9`j2E^6Ok5G}2 zFo*kvFkA6jcP(u8xAx~TluSdfWV7(jBR58rxE}O@mI9SyCb>%yl^I?VWoL)LyxdC; zyWa6aHYGnoPZcaVb>QbHc>{R^`$;EH&Bg17V}_1o37ssPYcU(Q8`k#BnQefzI9hMr z95&h5Qc+b3=Is|$xkO1{i8UGJK#M9E&QM?dr6KGm3Sn9 z>WHbeaaD_*RpFm+m{Kb1rB1(vu0Ue5wfp}92V79Rp?pla9Sm6zX zPw>#D{)beMVrgB|1>@iS{-hclx^U<<;rMPmaqN!fZN&bS;z; zh@ainE{da$ft>b&CL?*4l3BIR?Y%B+FX?uE{I7?w8vj2Qn8`DgOyRi_b49dCxs*Z% z`0p0i+&5{pLd!z^y2%@IKrVa?#BN2uIZ|>iyYeY`&^M`3qE5HqNT_j)uHf0@X=ttHj31LVM9a=JYnEo|wBr3o z9zBvv6qx^h6>;mLs%q1(Ii6M8v*npIprCfjE`590ZcJIyPtq^ihh1gYg@4qdEiAxY z9_*4+1g0xA{Vn9}UK(S)cmM>_wHz|y8{d1|Z+!;GUKTOTCIg?>1j`?ID@D1b0@S(( z{XCmxN@j+1c!xDo6^0~Ej34%MY|9`dntf|$oEtUGctDOHdy_FE14ep}F ze;#e$z591X-%2?$67j+Sbia$qHMHY9N|o(WSvz}|OaP?2+R(fQsP5~{#$Lpo08Pm9 z&iv`}4gic3gmHMS%LdbM9=MuB{D}J8PiM8@BTnoc5&)xdJhx5g&+gujMtUPUeff^e zhTe}oWCYMFn=%m={@FE|MI7Utwg@v4klP1(XS>XntAGfx?}Zel9efOs{8%p`t4sp`LoYw#U=q{^0STpR;&&JEl#mypB?4?4&0NjhIjmD2sp@DEl4>WEph?a z7W~hLyw!u4eV_?fO5>$%+5ddvJMLei`$6|5Ra`e>8p{C_Ij|mA{;y~@Rafx;QVKi} xSO(}<{iy%9y}OLZ2XG=k2PQ(TrJHKb0A#)tExW&J82nTGe*g|}P=Npd literal 0 HcmV?d00001 diff --git a/mods/MAPGEN/mcl_strongholds/init.lua b/mods/MAPGEN/mcl_strongholds/init.lua deleted file mode 100644 index 083172a3c..000000000 --- a/mods/MAPGEN/mcl_strongholds/init.lua +++ /dev/null @@ -1,106 +0,0 @@ --- Generate strongholds. - --- A total of 128 strongholds are generated in rings around the world origin. --- This is the list of rings, starting with the innermost ring first. -local stronghold_rings = { - -- amount: Number of strongholds in ring. - -- min, max: Minimum and maximum distance from (X=0, Z=0). - { amount = 3, min = 1408, max = 2688 }, - { amount = 6, min = 4480, max = 5760 }, - { amount = 10, min = 7552, max = 8832 }, - { amount = 15, min = 10624, max = 11904 }, - { amount = 21, min = 13696, max = 14976 }, - { amount = 28, min = 16768, max = 18048 }, - { amount = 36, min = 19840, max = 21120 }, - { amount = 9, min = 22912, max = 24192 }, -} - -local strongholds = {} -local strongholds_inited = false - -local mg_name = minetest.get_mapgen_setting("mg_name") -local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" - --- Determine the stronghold positions and store them into the strongholds table. --- The stronghold positions are based on the world seed. --- The actual position might be offset by a few blocks because it might be shifted --- to make sure the end portal room is completely within the boundaries of a mapchunk. -local function init_strongholds() - if strongholds_inited then - return - end - -- Don't generate strongholds in singlenode - if mg_name == "singlenode" then - strongholds_inited = true - return - end - local seed = tonumber(minetest.get_mapgen_setting("seed")) - local pr = PseudoRandom(seed) - for s=1, #stronghold_rings do - local ring = stronghold_rings[s] - - -- Get random angle - local angle = pr:next() - -- Scale angle to 0 .. 2*math.pi - angle = (angle / 32767) * (math.pi*2) - for a=1, ring.amount do - local dist = pr:next(ring.min, ring.max) - local y - if superflat then - y = mcl_vars.mg_bedrock_overworld_max + 3 - else - y = pr:next(mcl_vars.mg_bedrock_overworld_max+1, mcl_vars.mg_overworld_min+48) - end - local pos = { x = math.cos(angle) * dist, y = y, z = math.sin(angle) * dist } - pos = vector.round(pos) - table.insert(strongholds, { pos = pos, generated = false }) - - -- Rotate angle by (360 / amount) degrees. - -- This will cause the angles to be evenly distributed in the stronghold ring - angle = math.fmod(angle + ((math.pi*2) / ring.amount), math.pi*2) - end - end - - mcl_structures.register_structures("stronghold", table.copy(strongholds)) - - strongholds_inited = true -end - --- Stronghold generation for register_on_generated. -local function generate_strongholds(minp, maxp, blockseed) - local pr = PseudoRandom(blockseed) - for s=1, #strongholds do - if not strongholds[s].generated then - local pos = strongholds[s].pos - if minp.x <= pos.x and maxp.x >= pos.x and minp.z <= pos.z and maxp.z >= pos.z and minp.y <= pos.y and maxp.y >= pos.y then - -- Make sure the end portal room is completely within the current mapchunk - -- The original pos is changed intentionally. - if pos.x - 6 < minp.x then - pos.x = minp.x + 7 - end - if pos.x + 6 > maxp.x then - pos.x = maxp.x - 7 - end - if pos.y - 4 < minp.y then - pos.y = minp.y + 5 - end - if pos.y + 4 > maxp.y then - pos.y = maxp.y - 5 - end - if pos.z - 6 < minp.z then - pos.z = minp.z + 7 - end - if pos.z + 6 > maxp.z then - pos.z = maxp.z - 7 - end - - mcl_structures.call_struct(pos, "end_portal_shrine", nil, pr) - strongholds[s].generated = true - end - end - end -end - -init_strongholds() - -mcl_mapgen_core.register_generator("strongholds", nil, generate_strongholds, 999999) diff --git a/mods/MAPGEN/mcl_strongholds/mod.conf b/mods/MAPGEN/mcl_strongholds/mod.conf deleted file mode 100644 index 8edec9a51..000000000 --- a/mods/MAPGEN/mcl_strongholds/mod.conf +++ /dev/null @@ -1,4 +0,0 @@ -name = mcl_strongholds -author = Wuzzy -description = Generates strongholds with end portals in the Overworld -depends = mcl_init, mcl_structures, mcl_mapgen_core diff --git a/mods/MAPGEN/mcl_structures/desert_temple.lua b/mods/MAPGEN/mcl_structures/desert_temple.lua new file mode 100644 index 000000000..bb4c08b3a --- /dev/null +++ b/mods/MAPGEN/mcl_structures/desert_temple.lua @@ -0,0 +1,174 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 11 +local noise_multiplier = 1 +local random_offset = 999 +local scanning_ratio = 0.00003 +local struct_threshold = chance_per_chunk - 1 + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local node_list = {"mcl_core:sand", "mcl_core:sandstone", "mcl_core:redsand", "mcl_colorblocks:hardened_clay_orange"} + +local schematic_file = modpath .. "/schematics/mcl_structures_desert_temple.mts" + +local temple_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +local temple_schematic = loadstring(temple_schematic_lua)() + +local red_temple_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +red_temple_schematic_lua = red_temple_schematic_lua:gsub("mcl_colorblocks:hardened_clay_orange", "mcl_colorblocks:hardened_clay_red") +red_temple_schematic_lua = red_temple_schematic_lua:gsub("mcl_core:sand_stone", "mcl_colorblocks:hardened_clay_orange") +red_temple_schematic_lua = red_temple_schematic_lua:gsub("mcl_core:sand", "mcl_core:redsand") +red_temple_schematic_lua = red_temple_schematic_lua:gsub("mcl_stairs:stair_sandstone", "mcl_stairs:stair_redsandstone") +red_temple_schematic_lua = red_temple_schematic_lua:gsub("mcl_stairs:slab_sandstone", "mcl_stairs:slab_redsandstone") +red_temple_schematic_lua = red_temple_schematic_lua:gsub("mcl_colorblocks:hardened_clay_yellow", "mcl_colorblocks:hardened_clay_pink") +local red_temple_schematic = loadstring(red_temple_schematic_lua)() + +local function on_placed(p1, rotation, pr, size) + local p2 = {x = p1.x + size.x - 1, y = p1.y + size.y - 1, z = p1.z + size.z - 1} + -- Delete cacti leftovers: + local cactus_nodes = minetest.find_nodes_in_area_under_air({x = p1.x, y = p1.y + 11, z = p1.z}, {x = p2.x, y = p2.y - 2, z = p2.z}, "mcl_core:cactus", false) + for _, pos in pairs(cactus_nodes) do + local node_below = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) + local nn = node_below.name + if nn == "mcl_core:sandstone" then + minetest.swap_node(pos, {name="air"}) + end + end + + -- Find chests. + local chests = minetest.find_nodes_in_area(p1, {x = p2.x, y = p1.y + 5, z = p2.z}, "mcl_chests:chest") + + -- Add desert temple loot into chests + for c=1, #chests do + local lootitems = mcl_loot.get_multi_loot({ + { + stacks_min = 2, + stacks_max = 4, + items = { + { itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 }, + { itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 }, + { itemstring = "mcl_books:book", weight = 20, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_mobitems:saddle", weight = 20, }, + { itemstring = "mcl_core:apple_gold", weight = 20, }, + { itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 }, + { itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_core:emerald", weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "", weight = 15, }, + { itemstring = "mobs_mc:iron_horse_armor", weight = 15, }, + { itemstring = "mobs_mc:gold_horse_armor", weight = 10, }, + { itemstring = "mobs_mc:diamond_horse_armor", weight = 5, }, + { itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:apple_gold_enchanted", weight = 2, }, + } + }, + { + stacks_min = 4, + stacks_max = 4, + items = { + { itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:gunpowder", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_core:sand", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:string", weight = 10, amount_min = 1, amount_max = 8 }, + } + }}, pr) + mcl_structures.init_node_construct(chests[c]) + local meta = minetest.get_meta(chests[c]) + local inv = meta:get_inventory() + mcl_loot.fill_inventory(inv, "main", lootitems, pr) + end + + -- Initialize pressure plates and randomly remove up to 5 plates + local pplates = minetest.find_nodes_in_area(p1, {x = p2.x, y = p1.y + 5, z = p2.z}, "mesecons_pressureplates:pressure_plate_stone_off") + local pplates_remove = 5 + for p=1, #pplates do + if pplates_remove > 0 and pr:next(1, 100) >= 50 then + -- Remove plate + minetest.remove_node(pplates[p]) + pplates_remove = pplates_remove - 1 + else + -- Initialize plate + minetest.registered_nodes["mesecons_pressureplates:pressure_plate_stone_off"].on_construct(pplates[p]) + end + end +end + +local function place(pos, rotation, pr) + local pos_below = {x = pos.x, y = pos.y - 1, z = pos.z} + local pos_temple = {x = pos.x - 10, y = pos.y - 12, z = pos.z - 10} + local node_below = minetest.get_node(pos_below) + local nn = node_below.name + if string.find(nn, "red") then + mcl_structures.place_schematic({pos = pos_temple, schematic = red_temple_schematic, pr = pr, on_placed = on_placed}) + else + mcl_structures.place_schematic({pos = pos_temple, schematic = temple_schematic, pr = pr, on_placed = on_placed}) + end +end + +local function get_place_rank(pos) + local x, y, z = pos.x, pos.y - 1, pos.z + local p1 = {x = x - 8, y = y, z = z - 8} + local p2 = {x = x + 8, y = y, z = z + 8} + local best_pos_list_surface = minetest.find_nodes_in_area(p1, p2, node_list, false) + local other_pos_list_surface = minetest.find_nodes_in_area(p1, p2, "group:opaque", false) + p1 = {x = x - 4, y = y - 7, z = z - 4} + p2 = {x = x + 4, y = y - 3, z = z + 4} + local best_pos_list_underground = minetest.find_nodes_in_area(p1, p2, node_list, false) + local other_pos_list_underground = minetest.find_nodes_in_area(p1, p2, "group:opaque", false) + return 10 * (#best_pos_list_surface) + 2 * (#other_pos_list_surface) + 5 * (#best_pos_list_underground) + #other_pos_list_underground +end + +mcl_structures.register_structure({ + name = "desert_temple", + decoration = { + deco_type = "simple", + place_on = node_list, + flags = "all_floors", + fill_ratio = scanning_ratio, + y_min = 3, + y_max = mcl_mapgen.overworld.max, + height = 1, + biomes = not mcl_mapgen.v6 and { + "ColdTaiga_beach", + "ColdTaiga_beach_water", + "Desert", + "Desert_ocean", + "ExtremeHills_beach", + "FlowerForest_beach", + "Forest_beach", + "MesaBryce_sandlevel", + "MesaPlateauF_sandlevel", + "MesaPlateauFM_sandlevel", + "Savanna", + "Savanna_beach", + "StoneBeach", + "StoneBeach_ocean", + "Taiga_beach", + }, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos = pos_list[1] + if #pos_list > 1 then + local count = get_place_rank(pos) + for i = 2, #pos_list do + local pos_i = pos_list[i] + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_structures/desert_well.lua b/mods/MAPGEN/mcl_structures/desert_well.lua new file mode 100644 index 000000000..af57c8183 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/desert_well.lua @@ -0,0 +1,93 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 60 +local noise_multiplier = 1 +local random_offset = 999 +local scanning_ratio = 0.00001 +local struct_threshold = chance_per_chunk - 1 + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local node_list = {"mcl_core:sand", "mcl_core:sandstone", "mcl_core:redsand", "mcl_colorblocks:hardened_clay_orange"} + +local schematic_file = modpath .. "/schematics/mcl_structures_desert_well.mts" + +local well_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +local well_schematic = loadstring(well_schematic_lua)() + +local red_well_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +red_well_schematic_lua = red_well_schematic_lua:gsub("mcl_core:sand", "mcl_core:redsand") +red_well_schematic_lua = red_well_schematic_lua:gsub("mcl_stairs:slab_sandstone", "mcl_stairs:slab_redsandstone") +local red_well_schematic = loadstring(red_well_schematic_lua)() + +local function place(pos, rotation, pr) + local pos_below = {x = pos.x, y = pos.y - 1, z = pos.z} + local pos_well = {x = pos.x, y = pos.y - 2, z = pos.z} + local node_below = minetest.get_node(pos_below) + local nn = node_below.name + if string.find(nn, "red") then + mcl_structures.place_schematic({pos = pos_well, rotaton = rotation, schematic = red_well_schematic, pr = pr}) + else + mcl_structures.place_schematic({pos = pos_well, rotaton = rotation, schematic = well_schematic, pr = pr}) + end +end + +local function get_place_rank(pos) + local x, y, z = pos.x, pos.y - 1, pos.z + local p1 = {x = x , y = y, z = z } + local p2 = {x = x + 5, y = y, z = z + 5} + local post_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, node_list, false) + local other_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, "group:opaque", false) + return post_pos_list_surface * 5 + other_pos_list_surface +end + +mcl_structures.register_structure({ + name = "desert_well", + decoration = { + deco_type = "simple", + place_on = node_list, + flags = "all_floors", + fill_ratio = scanning_ratio, + y_min = -5, + y_max = mcl_mapgen.overworld.max, + height = 1, + biomes = not mcl_mapgen.v6 and { + "ColdTaiga_beach", + "ColdTaiga_beach_water", + "Desert", + "Desert_ocean", + "ExtremeHills_beach", + "FlowerForest_beach", + "Forest_beach", + "MesaBryce_sandlevel", + "MesaPlateauF_sandlevel", + "MesaPlateauFM_sandlevel", + "Savanna", + "Savanna_beach", + "StoneBeach", + "StoneBeach_ocean", + "Taiga_beach", + }, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos = pos_list[1] + if #pos_list > 1 then + local count = get_place_rank(pos) + for i = 2, #pos_list do + local pos_i = pos_list[i] + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_structures/end_exit_portal.lua b/mods/MAPGEN/mcl_structures/end_exit_portal.lua new file mode 100644 index 000000000..a0a171ee7 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/end_exit_portal.lua @@ -0,0 +1,52 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local END_EXIT_PORTAL_POS_X = -3 +local END_EXIT_PORTAL_POS_Y = -27003 +local END_EXIT_PORTAL_POS_Z = -3 +local p0 = { + x = END_EXIT_PORTAL_POS_X, + y = END_EXIT_PORTAL_POS_Y, + z = END_EXIT_PORTAL_POS_Z, +} + +local schematic = modpath .. "/schematics/mcl_structures_end_exit_portal.mts" + +local function place(pos, rotation, pr) + mcl_structures.place_schematic({pos = pos, schematic = schematic, rotation = rotation, pr = pr}) +end + +mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) + local minp = minp + local y1 = minp.y + if y1 > END_EXIT_PORTAL_POS_Y then return end + local maxp = maxp + local y2 = maxp.y + if y2 < END_EXIT_PORTAL_POS_Y then return end + if minp.x > END_EXIT_PORTAL_POS_X then return end + if maxp.x < END_EXIT_PORTAL_POS_X then return end + if minp.z > END_EXIT_PORTAL_POS_Z then return end + if maxp.z < END_EXIT_PORTAL_POS_Z then return end + + local p = table.copy(p0) + + for y = y2, y1, -1 do + p.y = y + if minetest.get_node(p).name == "mcl_end:end_stone" then + place(p, "0", PseudoRandom(vm_context.chunkseed)) + return + end + end + + for y = y2, y1, -1 do + p.y = y + if minetest.get_node(p).name ~= "air" then + place(p, "0", PseudoRandom(vm_context.chunkseed)) + return + end + end + + place(p0, "0", PseudoRandom(vm_context.chunkseed)) +end) + +mcl_structures.register_structure({name = "end_exit_portal", place_function = place}) diff --git a/mods/MAPGEN/mcl_structures/fossil.lua b/mods/MAPGEN/mcl_structures/fossil.lua new file mode 100644 index 000000000..b26b7320a --- /dev/null +++ b/mods/MAPGEN/mcl_structures/fossil.lua @@ -0,0 +1,53 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_block = mcl_structures.from_16x16_to_block_inverted_chance(64) +local noise_multiplier = 2 +local random_offset = 5 +local struct_threshold = chance_per_block - 1 +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level +local minetest_find_nodes_in_area = minetest.find_nodes_in_area +local min_y = mcl_worlds.layer_to_y(40) +local max_y = mcl_worlds.layer_to_y(49) +local fossils = { + "mcl_structures_fossil_skull_1.mts", -- 4×5×5 + "mcl_structures_fossil_skull_2.mts", -- 5×5×5 + "mcl_structures_fossil_skull_3.mts", -- 5×5×7 + "mcl_structures_fossil_skull_4.mts", -- 7×5×5 + "mcl_structures_fossil_spine_1.mts", -- 3×3×13 + "mcl_structures_fossil_spine_2.mts", -- 5×4×13 + "mcl_structures_fossil_spine_3.mts", -- 7×4×13 + "mcl_structures_fossil_spine_4.mts", -- 8×5×13 +} +local nodes_for_fossil = {"mcl_core:sandstone", "mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:dirt", "mcl_core:gravel"} + +function spawn_fossil(pos, rotation, pr, placer) + -- Generates one out of 8 possible fossil pieces + local def = { + pos = {x = pos.x, y = pos.y - 1, z = pos.z}, + schematic = modpath .. "/schematics/" .. fossils[pr:next(1, #fossils)], + rotation = rotation, + pr = pr, + } + mcl_structures.place_schematic(def) +end + +mcl_mapgen.register_mapgen_block(function(minp, maxp, seed) + local p1 = table.copy(minp) + local y1 = p1.y + if y1 > max_y then return end + local p2 = table.copy(maxp) + local y2 = p2.y + if y2 < min_y then return end + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_block) + p1.y = math.max(y1, min_y) + local noise = mcl_structures_get_perlin_noise_level(p1) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + p2.y = math.min(y2, max_y) + local nodes = minetest_find_nodes_in_area(p1, p2, nodes_for_fossil, false) + if #nodes < 100 then return end + spawn_fossil(p1, nil, pr) +end, 1000) + +mcl_structures.register_structure({name = 'fossil', place_function = spawn_fossil}) diff --git a/mods/MAPGEN/mcl_structures/ice_spike_large.lua b/mods/MAPGEN/mcl_structures/ice_spike_large.lua new file mode 100644 index 000000000..b46f09465 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/ice_spike_large.lua @@ -0,0 +1,66 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 5 +local random_offset = 24435 +local struct_threshold = chance_per_chunk - 1 +local noise_params = { + offset = 0, + scale = 1, + spread = { + x = 1000, + y = 1000, + z = 1000, + }, + scale = 0.01, + seed = 29313, + octaves = 2, + persistence = 0.7, +} + +local node_list = {"mcl_core:snowblock", "mcl_core:dirt_with_grass_snow"} +local schematic = modpath.."/schematics/mcl_structures_ice_spike_large.mts" + +minetest_find_nodes_in_area = minetest.find_nodes_in_area + +local function place(pos, rotation, pr) + mcl_structures.place_schematic({pos = pos, schematic = schematic, rotation = rotation, pr = pr}) +end + +local function is_place_ok(p) + -- Check surface + local floor = {x=p.x+4, y=p.y-1, z=p.z+4} + local surface = #minetest_find_nodes_in_area({x=p.x+1,y=p.y-1,z=p.z+1}, floor, node_list, false) + if surface < 9 then return end + + -- Check for collision with spruce + local spruce_collisions = #minetest_find_nodes_in_area({x=p.x+1,y=p.y+2,z=p.z+1}, {x=p.x+4, y=p.y+6, z=p.z+4}, {"group:tree"}, false) + if spruce_collisions > 0 then return end + + return true +end + +local def = mcl_mapgen.v6 and { + decoration = { + deco_type = "simple", + place_on = node_list, + noise_params = noise_params, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, + height = 1, + }, + on_finished_chunk = mcl_mapgen.v6 and function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + if random_number < struct_threshold then return end + for i = 1, #pos_list do + local pos = pos_list[i] + if is_place_ok(pos) then + place(pos, nil, pr) + end + end + end, +} or {} +def.name = "ice_spike_large" +def.place_function = place +mcl_structures.register_structure(def) diff --git a/mods/MAPGEN/mcl_structures/ice_spike_small.lua b/mods/MAPGEN/mcl_structures/ice_spike_small.lua new file mode 100644 index 000000000..801c5f66e --- /dev/null +++ b/mods/MAPGEN/mcl_structures/ice_spike_small.lua @@ -0,0 +1,65 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 3 +local random_offset = 1264 +local struct_threshold = chance_per_chunk - 1 +local noise_params = { + offset = 0, + scale = 1, + spread = { + x = mcl_mapgen.CS, + y = mcl_mapgen.CS, + z = mcl_mapgen.CS, + }, + scale = 0.3, + seed = 32931, + octaves = 2, + persistence = 0.7, +} + +local node_list = {"mcl_core:snowblock", "mcl_core:dirt_with_grass_snow"} +local schematic = modpath.."/schematics/mcl_structures_ice_spike_small.mts" + +minetest_find_nodes_in_area = minetest.find_nodes_in_area + +local function place(pos, rotation, pr) + mcl_structures.place_schematic({pos = pos, schematic = schematic, rotation = rotation, pr = pr}) +end + +local function is_place_ok(p) + local floor = {x=p.x+6, y=p.y-1, z=p.z+6} + local surface = #minetest_find_nodes_in_area({x=p.x+1,y=p.y-1,z=p.z+1}, floor, node_list, false) + if surface < 25 then return end + + -- Check for collision with spruce + local spruce_collisions = #minetest_find_nodes_in_area({x=p.x+1,y=p.y+1,z=p.z+1}, {x=p.x+6, y=p.y+6, z=p.z+6}, {"group:tree"}, false) + if spruce_collisions > 0 then return end + + return true +end + +local def = mcl_mapgen.v6 and { + decoration = { + deco_type = "simple", + place_on = node_list, + noise_params = noise_params, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, + height = 1, + }, + on_finished_chunk = mcl_mapgen.v6 and function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + if random_number < struct_threshold then return end + for i = 1, #pos_list do + local pos = pos_list[i] + if is_place_ok(pos) then + place(pos, nil, pr) + end + end + end, +} or {} +def.name = "ice_spike_small" +def.place_function = place +mcl_structures.register_structure(def) diff --git a/mods/MAPGEN/mcl_structures/igloo.lua b/mods/MAPGEN/mcl_structures/igloo.lua new file mode 100644 index 000000000..4f6c9574f --- /dev/null +++ b/mods/MAPGEN/mcl_structures/igloo.lua @@ -0,0 +1,195 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +-- local chance_per_chunk = mcl_structures.from_16x16_to_chunk_inverted_chance(4400) +local chance_per_chunk = 100 +local noise_multiplier = 1.4 +local random_offset = 555 +local struct_threshold = chance_per_chunk - 1 +local scanning_ratio = 0.0003 + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local node_list = {"mcl_core:snowblock", "mcl_core:snow", "group:grass_block_snow"} + +local schematic_top = modpath.."/schematics/mcl_structures_igloo_top.mts" +local schematic_basement = modpath.."/schematics/mcl_structures_igloo_basement.mts" + +local brick = { + -- monster egg: + [false] = { + -- cracked: + [false] = "mcl_core:stonebrick", + [true ] = "mcl_core:stonebrickcracked", + }, + [true] = { + [false] = "mcl_monster_eggs:monster_egg_stonebrick", + [true ] = "mcl_monster_eggs:monster_egg_stonebrickcracked", + }, +} +local dirs = { + ["0"] = {x=-1, y=0, z= 0}, + ["90"] = {x= 0, y=0, z=-1}, + ["180"] = {x= 1, y=0, z= 0}, + ["270"] = {x= 0, y=0, z= 1}, +} +local tdirs = { + ["0"] = {x= 1, y=0, z= 0}, + ["90"] = {x= 0, y=0, z=-1}, + ["180"] = {x=-1, y=0, z= 0}, + ["270"] = {x= 0, y=0, z= 1} +} +local tposes = { + ["0"] = {x=7, y=-1, z=3}, + ["90"] = {x=3, y=-1, z=1}, + ["180"] = {x=1, y=-1, z=3}, + ["270"] = {x=3, y=-1, z=7}, +} +local chest_offsets = { + ["0"] = {x=5, y=1, z=5}, + ["90"] = {x=5, y=1, z=3}, + ["180"] = {x=3, y=1, z=1}, + ["270"] = {x=1, y=1, z=5}, +} + +local function on_placed(pos, rotation, pr, size) + local chest_offset = chest_offsets[rotation] + if not chest_offset then return end + local lootitems = mcl_loot.get_multi_loot({ + { + stacks_min = 1, + stacks_max = 1, + items = { + { itemstring = "mcl_core:apple_gold", weight = 1 }, + } + }, + { + stacks_min = 2, + stacks_max = 8, + items = { + { itemstring = "mcl_core:coal_lump", weight = 15, amount_min = 1, amount_max = 4 }, + { itemstring = "mcl_core:apple", weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_farming:wheat_item", weight = 10, amount_min = 2, amount_max = 3 }, + { itemstring = "mcl_core:gold_nugget", weight = 10, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 10 }, + { itemstring = "mcl_tools:axe_stone", weight = 2 }, + { itemstring = "mcl_core:emerald", weight = 1 }, + } + }}, pr) + + local chest_pos = vector.add(pos, chest_offset) + mcl_structures.init_node_construct(chest_pos) + local meta = minetest.get_meta(chest_pos) + local inv = meta:get_inventory() + mcl_loot.fill_inventory(inv, "main", lootitems, pr) +end + +local function on_placed_top(p1, rotation, pr, size) + local y = p1.y + 1 + local pos = {x = p1.x, y = y, z = p1.z} + local dim = mcl_mapgen[mcl_worlds.pos_to_dimension(pos)] + local bottom_of_dimension = (dim and dim.min or mcl_mapgen.EDGE_MIN) + 10 + local bottom_of_chunk = mcl_mapgen.get_chunk_beginning(y) + local buffer = y - math.max(bottom_of_chunk, bottom_of_dimension) + if buffer < 20 then return end + + local depth = pr:next(19, buffer) + local bpos = {x=pos.x, y=pos.y-depth, z=pos.z} + local dir = dirs[rotation] + if not dir then return end + local tdir = tdirs[rotation] + + -- Trapdoor position + local tpos = vector.add(pos, tposes[rotation]) + local ladder_param2 = minetest.dir_to_wallmounted(tdir) + + -- Check how deep we can actuall dig + local real_depth = 0 + for y = 1, depth - 5 do + local node = minetest.get_node({x=tpos.x,y=tpos.y-y,z=tpos.z}) + local def = minetest.registered_nodes[node.name] + if (not def) or (not def.walkable) or (def.liquidtype ~= "none") then + bpos.y = tpos.y-y+1 + break + end + real_depth = real_depth + 1 + end + if real_depth < 6 then return end + + -- Generate ladder to basement + for y=1, real_depth-1 do + minetest.set_node({x=tpos.x-1,y=tpos.y-y,z=tpos.z }, {name = brick[pr:next(1, 10) == 1][pr:next(1, 3) == 1]}) + minetest.set_node({x=tpos.x+1,y=tpos.y-y,z=tpos.z }, {name = brick[pr:next(1, 10) == 1][pr:next(1, 3) == 1]}) + minetest.set_node({x=tpos.x ,y=tpos.y-y,z=tpos.z-1}, {name = brick[pr:next(1, 10) == 1][pr:next(1, 3) == 1]}) + minetest.set_node({x=tpos.x ,y=tpos.y-y,z=tpos.z+1}, {name = brick[pr:next(1, 10) == 1][pr:next(1, 3) == 1]}) + minetest.set_node({x=tpos.x ,y=tpos.y-y,z=tpos.z }, {name="mcl_core:ladder", param2=ladder_param2}) + end + + -- Place basement + local def = { + pos = bpos, + schematic = schematic_basement, + rotation = rotation, + pr = pr, + on_placed = on_placed, + } + mcl_structures.place_schematic(def) + + minetest.after(5, function(tpos, dir) + minetest.swap_node(tpos, {name="mcl_doors:trapdoor", param2=20+minetest.dir_to_facedir(dir)}) -- TODO: more reliable param2 + end, tpos, dir) +end + +local function place(pos, rotation, pr) + local def = { + pos = {x = pos.x, y = pos.y - 1, z = pos.z}, + schematic = schematic_top, + rotation = rotation or tostring(pr:next(0,3)*90), + pr = pr, + on_placed = on_placed_top, + } + -- FIXME: This spawns bookshelf instead of furnace. Fix this! + -- Furnace does not work atm because apparently meta is not set. :-( + mcl_structures.place_schematic(def) +end + +local function get_place_rank(pos) + local x, y, z = pos.x, pos.y, pos.z + local p1 = {x = x , y = y, z = z } + local p2 = {x = x + 9, y = y, z = z + 9} + local best_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, node_list, false) + local other_pos_list_surface = #minetest.find_nodes_in_area(p1, p2, "group:opaque", false) + return 10 * (best_pos_list_surface) + other_pos_list_surface - 640 +end + +mcl_structures.register_structure({ + name = "igloo", + decoration = { + deco_type = "simple", + place_on = node_list, + flags = "all_floors", + fill_ratio = scanning_ratio, + y_min = -33, + y_max = mcl_mapgen.overworld.max, + height = 1, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos + local count = -1 + for i = 1, #pos_list do + local pos_i = vector.subtract(pos_list[i], {x = 4, y = 1, z = 4}) + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + if count < 0 then return end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index be1be0f67..64f6db937 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -2,46 +2,309 @@ local modname = minetest.get_current_modname() local S = minetest.get_translator(modname) local modpath = minetest.get_modpath(modname) -mcl_structures = {} +local name_prefix = "mcl_structures:" +mcl_structures = {} local rotations = { "0", "90", "180", "270" } +local registered_structures = {} +local use_process_mapgen_block_lvm = false +local use_process_mapgen_chunk = false +local on_finished_block_callbacks = {} +local on_finished_chunk_callbacks = {} -local function ecb_place(blockpos, action, calls_remaining, param) - if calls_remaining >= 1 then return end - minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags) - if param.after_placement_callback and param.p1 and param.p2 then - param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param) +local noise_params = { + offset = 0, + scale = 1, + spread = { + x = mcl_mapgen.CS_NODES, + y = mcl_mapgen.CS_NODES, + z = mcl_mapgen.CS_NODES, + }, + seed = 329, + octaves = 1, + persistence = 0.6, +} + +local perlin_noise +local get_perlin_noise_level = function(minp) + perlin_noise = perlin_noise or minetest.get_perlin(noise_params) + return perlin_noise:get_3d(minp) +end +mcl_structures.get_perlin_noise_level = get_perlin_noise_level + +local spawnstruct_hint = S("Use /help spawnstruct to see a list of avaiable types.") + +local function dir_to_rotation(dir) + local ax, az = math.abs(dir.x), math.abs(dir.z) + if ax > az then + if dir.x < 0 then + return "270" + end + return "90" + end + if dir.z < 0 then + return "180" + end + return "0" +end + +local function spawnstruct_function(name, param) + local player = minetest.get_player_by_name(name) + if not player then return end + if param == "" then + minetest.chat_send_player(name, S("Error: No structure type given. Please use “/spawnstruct ”.")) + minetest.chat_send_player(name, spawnstruct_hint) + return + end + local struct = registered_structures[param] + if not struct then + struct = registered_structures[name_prefix .. param] + end + if not struct then + minetest.chat_send_player(name, S("Error: Unknown structure type. Please use “/spawnstruct ”.")) + minetest.chat_send_player(name, spawnstruct_hint) + return + end + local place = struct.place_function + if not place then return end + + local pos = player:get_pos() + if not pos then return end + local pr = PseudoRandom(math.floor(pos.x * 333 + pos.y * 19 - pos.z + 4)) + pos = vector.round(pos) + local dir = minetest.yaw_to_dir(player:get_look_horizontal()) + local rot = dir_to_rotation(dir) + place(pos, rot, pr, player) + minetest.chat_send_player(name, S("Structure placed.")) +end + +local function update_spawnstruct_chatcommand() + local spawnstruct_params = "" + for _, registered_structure in pairs(registered_structures) do + if spawnstruct_params ~= "" then + spawnstruct_params = spawnstruct_params .. " | " + end + spawnstruct_params = spawnstruct_params .. registered_structure.short_name + end + local def = { + params = spawnstruct_params, + description = S("Generate a pre-defined structure near your position."), + privs = {debug = true}, + func = spawnstruct_function, + } + local registered_chatcommands = minetest.registered_chatcommands + if registered_chatcommands["spawnstruct"] then + minetest.override_chatcommand("spawnstruct", def) + else + minetest.register_chatcommand("spawnstruct", def) end end -function mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param) - local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")() - if s and s.size then - local x, z = s.size.x, s.size.z - if rotation then - if rotation == "random" and pr then - rotation = rotations[pr:next(1,#rotations)] - end - if rotation == "random" then - x = math.max(x, z) - z = x - elseif rotation == "90" or rotation == "270" then - x, z = z, x +function process_mapgen_block_lvm(vm_context) + local nodes = minetest.find_nodes_in_area(vm_context.minp, vm_context.maxp, {"group:struct"}, true) + for node_name, pos_list in pairs(nodes) do + local lvm_callback = on_finished_block_callbacks[node_name] + if lvm_callback then + lvm_callback(vm_context, pos_list) + end + end +end + +function process_mapgen_chunk(minp, maxp, seed, vm_context) + local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:struct"}, true) + for node_name, pos_list in pairs(nodes) do + local chunk_callback = on_finished_chunk_callbacks[node_name] + if chunk_callback then + chunk_callback(minp, maxp, seed, vm_context, pos_list) + end + end + for node_name, pos_list in pairs(nodes) do + for _, pos in pairs(pos_list) do + local node = minetest.get_node(pos) + if string.sub(node.name, 1, 15) == 'mcl_structures:' then + minetest.swap_node(pos, {name = 'air'}) end end - local p1 = {x=pos.x , y=pos.y , z=pos.z } - local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1} - minetest.log("verbose", "[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) - local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param} - minetest.emerge_area(p1, p2, ecb_place, param) end end +-------------------------------------------------------------------------------------- +-- mcl_structures.register_structure(struct_def) +-- struct_def: +-- name - name, like 'desert_temple' +-- decoration - decoration definition, to use as structure seed (thanks cora for the idea) +-- on_finished_block - callback, if needed, to use with decorations: funcion(vm_context, pos_list) +-- on_finished_chunk - next callback if needed: funcion(minp, maxp, seed, vm_context, pos_list) +-- place_function - callback to place schematic by /spawnstruct debug command: function(pos, rotation, pr, placer) +-- on_placed - useful when you want to process the area after placement: function(pos, rotation, pr, size) +function mcl_structures.register_structure(def) + local short_name = def.name + local name = "mcl_structures:" .. short_name + local decoration = def.decoration + local on_finished_block = def.on_finished_block + local on_finished_chunk = def.on_finished_chunk + local place_function = def.place_function + if not name then + minetest.log('warning', 'Structure name is not passed for registration - ignoring') + return + end + if registered_structures[name] then + minetest.log('warning', 'Structure '..name..' is already registered - owerwriting') + end + local decoration_id + if decoration then + minetest.register_node(':' .. name, { + drawtype = "airlike", + sunlight_propagates = true, + pointable = false, + walkable = false, + diggable = false, + buildable_to = true, + groups = { + struct = 1, + not_in_creative_inventory = 1, + }, + }) + decoration_id = minetest.register_decoration({ + deco_type = decoration.deco_type, + place_on = decoration.place_on, + sidelen = decoration.sidelen, + fill_ratio = decoration.fill_ratio, + noise_params = decoration.noise_params, + biomes = decoration.biomes, + y_min = decoration.y_min, + y_max = decoration.y_max, + spawn_by = decoration.spawn_by, + num_spawn_by = decoration.num_spawn_by, + flags = decoration.flags, + decoration = name, + height = decoration.height, + height_max = decoration.height_max, + param2 = decoration.param2, + param2_max = decoration.param2_max, + place_offset_y = decoration.place_offset_y, + schematic = decoration.schematic, + replacements = decoration.replacements, + flags = decoration.flags, + rotation = decoration.rotation, + }) + end + registered_structures[name] = { + place_function = place_function, + on_finished_block = on_finished_block, + on_finished_chunk = on_finished_chunk, + decoration_id = decoration_id, + short_name = short_name, + } + update_spawnstruct_chatcommand() + if on_finished_block then + on_finished_block_callbacks[name] = on_finished_block + if not use_process_mapgen_block_lvm then + use_process_mapgen_block_lvm = true + mcl_mapgen.register_mapgen_block_lvm(process_mapgen_block_lvm, mcl_mapgen.order.BUILDINGS) + end + end + if on_finished_chunk then + on_finished_chunk_callbacks[name] = on_finished_chunk + if not use_process_mapgen_chunk then + use_process_mapgen_chunk = true + mcl_mapgen.register_mapgen(process_mapgen_chunk, mcl_mapgen.order.BUILDINGS) + end + end +end + +-- It doesN'T remove registered node and decoration! +function mcl_structures.unregister_structure(name) + if not registered_structures[name] then + minetest.log('warning','Structure '..name..' is not registered - skipping') + return + end + registered_structures[name] = nil +end + +local function ecb_place(blockpos, action, calls_remaining, param) + if calls_remaining >= 1 then return end + local pos = param.pos + local rotation = param.rotation + minetest.place_schematic(pos, param.schematic, rotation, param.replacements, param.force_placement, param.flags) + local on_placed = param.on_placed + if not on_placed then + return + end + on_placed(pos, rotation, param.pr, param.size) +end + +function mcl_structures.place_schematic(def) + local pos = def.pos + local schematic = def.schematic + local rotation = def.rotation + local pr = def.pr + local on_placed = def.on_placed -- on_placed(pos, rotation, pr, size) + local emerge = def.emerge + if not pos then + minetest.log('warning', '[mcl_structures] No pos. specified to place schematic') + return + end + if not schematic then + minetest.log('warning', '[mcl_structures] No schematic specified to place at ' .. minetest.pos_to_string(pos)) + return + end + if not rotation or rotation == 'random' then + if pr then + rotation = rotations[pr:next(1,#rotations)] + else + rotation = rotations[math.random(1,#rotations)] + end + end + + if not emerge and not on_placed then + minetest.place_schematic(pos, schematic, rotation, def.replacements, def.force_placement, def.flags) + return + end + + local serialized_schematic = minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" + local loaded_schematic = loadstring(serialized_schematic)() + if not loaded_schematic then + minetest.log('warning', '[mcl_structures] Schematic ' .. schematic .. ' load serialized string problem at ' .. minetest.pos_to_string(pos)) + return + end + local size = loaded_schematic.size + if not size then + minetest.log('warning', '[mcl_structures] Schematic ' .. schematic .. ' has no size at ' .. minetest.pos_to_string(pos)) + return + end + local size_x, size_y, size_z = size.x, size.y, size.z + if rotation == "90" or rotation == "270" then + size_x, size_z = size_z, size_x + end + local x, y, z = pos.x, pos.y, pos.z + local p1 = {x = x, y = y, z = z} + local p2 = {x = x + size_x - 1, y = y + size_y - 1, z = size_z - 1} + local ecb_param = { + pos = vector.new(pos), + schematic = loaded_schematic, + rotation = rotation, + replacements = replacements, + force_placement = force_placement, + flags = flags, + size = vector.new(size), + pr = pr, + on_placed = on_placed, + } + if not emerge then + ecb_place(p1, nil, 0, ecb_param) + return + end + minetest.log("verbose", "[mcl_structures] Emerge area " .. minetest.pos_to_string(p1) .. " - " .. minetest.pos_to_string(p2) + .. " of size " ..minetest.pos_to_string(size) .. " to place " .. schematic .. ", rotation " .. tostring(rotation)) + minetest.emerge_area(p1, p2, ecb_place, ecb_param) +end + function mcl_structures.get_struct(file) local localfile = modpath.."/schematics/"..file local file, errorload = io.open(localfile, "rb") @@ -58,7 +321,7 @@ end -- Call on_construct on pos. -- Useful to init chests from formspec. -local function init_node_construct(pos) +function mcl_structures.init_node_construct(pos) local node = minetest.get_node(pos) local def = minetest.registered_nodes[node.name] if def and def.on_construct then @@ -69,200 +332,42 @@ local function init_node_construct(pos) end -- The call of Struct -function mcl_structures.call_struct(pos, struct_style, rotation, pr) +function mcl_structures.call_struct(pos, struct_style, rotation, pr, callback) minetest.log("action","[mcl_structures] call_struct " .. struct_style.." at "..minetest.pos_to_string(pos)) if not rotation then rotation = "random" end - if struct_style == "desert_temple" then - return mcl_structures.generate_desert_temple(pos, rotation, pr) - elseif struct_style == "desert_well" then - return mcl_structures.generate_desert_well(pos, rotation) - elseif struct_style == "igloo" then - return mcl_structures.generate_igloo(pos, rotation, pr) - elseif struct_style == "witch_hut" then + if struct_style == "witch_hut" then return mcl_structures.generate_witch_hut(pos, rotation) - elseif struct_style == "ice_spike_small" then - return mcl_structures.generate_ice_spike_small(pos, rotation) - elseif struct_style == "ice_spike_large" then - return mcl_structures.generate_ice_spike_large(pos, rotation) elseif struct_style == "boulder" then return mcl_structures.generate_boulder(pos, rotation, pr) - elseif struct_style == "fossil" then - return mcl_structures.generate_fossil(pos, rotation, pr) elseif struct_style == "end_exit_portal" then - return mcl_structures.generate_end_exit_portal(pos, rotation) + return mcl_structures.generate_end_exit_portal(pos, rotation, pr, callback) elseif struct_style == "end_exit_portal_open" then return mcl_structures.generate_end_exit_portal_open(pos, rotation) elseif struct_style == "end_gateway_portal" then return mcl_structures.generate_end_gateway_portal(pos, rotation) elseif struct_style == "end_portal_shrine" then return mcl_structures.generate_end_portal_shrine(pos, rotation, pr) + elseif struct_style == "end_portal" then + return mcl_structures.generate_end_portal(pos, rotation, pr) end end -function mcl_structures.generate_desert_well(pos, rot) - local newpos = {x=pos.x,y=pos.y-2,z=pos.z} - local path = modpath.."/schematics/mcl_structures_desert_well.mts" - return mcl_structures.place_schematic(newpos, path, rot or "0", nil, true) -end - -function mcl_structures.generate_igloo(pos, rotation, pr) - -- Place igloo - local success, rotation = mcl_structures.generate_igloo_top(pos, pr) - -- Place igloo basement with 50% chance - local r = pr:next(1,2) - if r == 1 then - -- Select basement depth - local dim = mcl_worlds.pos_to_dimension(pos) - --local buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10) - local buffer - if dim == "nether" then - buffer = pos.y - (mcl_vars.mg_lava_nether_max + 10) - elseif dim == "end" then - buffer = pos.y - (mcl_vars.mg_end_min + 1) - elseif dim == "overworld" then - buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10) - else - return success - end - if buffer <= 19 then - return success - end - local depth = pr:next(19, buffer) - local bpos = {x=pos.x, y=pos.y-depth, z=pos.z} - -- trapdoor position - local tpos - local dir, tdir - if rotation == "0" then - dir = {x=-1, y=0, z=0} - tdir = {x=1, y=0, z=0} - tpos = {x=pos.x+7, y=pos.y-1, z=pos.z+3} - elseif rotation == "90" then - dir = {x=0, y=0, z=-1} - tdir = {x=0, y=0, z=-1} - tpos = {x=pos.x+3, y=pos.y-1, z=pos.z+1} - elseif rotation == "180" then - dir = {x=1, y=0, z=0} - tdir = {x=-1, y=0, z=0} - tpos = {x=pos.x+1, y=pos.y-1, z=pos.z+3} - elseif rotation == "270" then - dir = {x=0, y=0, z=1} - tdir = {x=0, y=0, z=1} - tpos = {x=pos.x+3, y=pos.y-1, z=pos.z+7} - else - return success - end - local function set_brick(pos) - local c = pr:next(1, 3) -- cracked chance - local m = pr:next(1, 10) -- chance for monster egg - local brick - if m == 1 then - if c == 1 then - brick = "mcl_monster_eggs:monster_egg_stonebrickcracked" - else - brick = "mcl_monster_eggs:monster_egg_stonebrick" +function mcl_structures.generate_end_portal(pos, rotation, pr) + -- todo: proper facedir + local x0, y0, z0 = pos.x - 2, pos.y, pos.z - 2 + for x = 0, 4 do + for z = 0, 4 do + if x % 4 == 0 or z % 4 == 0 then + if x % 4 ~= 0 or z % 4 ~= 0 then + minetest.swap_node({x = x0 + x, y = y0, z = z0 + z}, {name = "mcl_portals:end_portal_frame_eye"}) end else - if c == 1 then - brick = "mcl_core:stonebrickcracked" - else - brick = "mcl_core:stonebrick" - end - end - minetest.set_node(pos, {name=brick}) - end - local ladder_param2 = minetest.dir_to_wallmounted(tdir) - local real_depth = 0 - -- Check how deep we can actuall dig - for y=1, depth-5 do - real_depth = real_depth + 1 - local node = minetest.get_node({x=tpos.x,y=tpos.y-y,z=tpos.z}) - local def = minetest.registered_nodes[node.name] - if (not def) or (not def.walkable) or (def.liquidtype ~= "none") or (not def.is_ground_content) then - bpos.y = tpos.y-y+1 - break + minetest.swap_node({x = x0 + x, y = y0, z = z0 + z}, {name = "mcl_portals:portal_end"}) end end - if real_depth <= 6 then - return success - end - -- Generate ladder to basement - for y=1, real_depth-1 do - set_brick({x=tpos.x-1,y=tpos.y-y,z=tpos.z }) - set_brick({x=tpos.x+1,y=tpos.y-y,z=tpos.z }) - set_brick({x=tpos.x ,y=tpos.y-y,z=tpos.z-1}) - set_brick({x=tpos.x ,y=tpos.y-y,z=tpos.z+1}) - minetest.set_node({x=tpos.x,y=tpos.y-y,z=tpos.z}, {name="mcl_core:ladder", param2=ladder_param2}) - end - -- Place basement - mcl_structures.generate_igloo_basement(bpos, rotation, pr) - -- Place hidden trapdoor - minetest.after(5, function(tpos, dir) - minetest.set_node(tpos, {name="mcl_doors:trapdoor", param2=20+minetest.dir_to_facedir(dir)}) -- TODO: more reliable param2 - end, tpos, dir) end - return success -end - -function mcl_structures.generate_igloo_top(pos, pr) - -- FIXME: This spawns bookshelf instead of furnace. Fix this! - -- Furnace does ot work atm because apparently meta is not set. :-( - local newpos = {x=pos.x,y=pos.y-1,z=pos.z} - local path = modpath.."/schematics/mcl_structures_igloo_top.mts" - local rotation = tostring(pr:next(0,3)*90) - return mcl_structures.place_schematic(newpos, path, rotation, nil, true), rotation -end - -local function igloo_placement_callback(p1, p2, size, orientation, pr) - local chest_offset - if orientation == "0" then - chest_offset = {x=5, y=1, z=5} - elseif orientation == "90" then - chest_offset = {x=5, y=1, z=3} - elseif orientation == "180" then - chest_offset = {x=3, y=1, z=1} - elseif orientation == "270" then - chest_offset = {x=1, y=1, z=5} - else - return - end - --local size = {x=9,y=5,z=7} - local lootitems = mcl_loot.get_multi_loot({ - { - stacks_min = 1, - stacks_max = 1, - items = { - { itemstring = "mcl_core:apple_gold", weight = 1 }, - } - }, - { - stacks_min = 2, - stacks_max = 8, - items = { - { itemstring = "mcl_core:coal_lump", weight = 15, amount_min = 1, amount_max = 4 }, - { itemstring = "mcl_core:apple", weight = 15, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_farming:wheat_item", weight = 10, amount_min = 2, amount_max = 3 }, - { itemstring = "mcl_core:gold_nugget", weight = 10, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_mobitems:rotten_flesh", weight = 10 }, - { itemstring = "mcl_tools:axe_stone", weight = 2 }, - { itemstring = "mcl_core:emerald", weight = 1 }, - } - }}, pr) - - local chest_pos = vector.add(p1, chest_offset) - init_node_construct(chest_pos) - local meta = minetest.get_meta(chest_pos) - local inv = meta:get_inventory() - mcl_loot.fill_inventory(inv, "main", lootitems, pr) -end - -function mcl_structures.generate_igloo_basement(pos, orientation, pr) - -- TODO: Add brewing stand - -- TODO: Add monster eggs - -- TODO: Spawn villager and zombie villager - local path = modpath.."/schematics/mcl_structures_igloo_basement.mts" - mcl_structures.place_schematic(pos, path, orientation, nil, true, nil, igloo_placement_callback, pr) end function mcl_structures.generate_boulder(pos, rotation, pr) @@ -284,7 +389,7 @@ local function hut_placement_callback(p1, p2, size, orientation, pr) if not p1 or not p2 then return end local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree") for i = 1, #legs do - while minetest.get_item_group(mcl_vars.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do + while minetest.get_item_group(mcl_mapgen.get_far_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do legs[i].y = legs[i].y - 1 minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2}) end @@ -296,37 +401,14 @@ function mcl_structures.generate_witch_hut(pos, rotation, pr) mcl_structures.place_schematic(pos, path, rotation, nil, true, nil, hut_placement_callback, pr) end -function mcl_structures.generate_ice_spike_small(pos, rotation) - local path = modpath.."/schematics/mcl_structures_ice_spike_small.mts" - return minetest.place_schematic(pos, path, rotation or "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0 -end - function mcl_structures.generate_ice_spike_large(pos, rotation) local path = modpath.."/schematics/mcl_structures_ice_spike_large.mts" return minetest.place_schematic(pos, path, rotation or "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0 end -function mcl_structures.generate_fossil(pos, rotation, pr) - -- Generates one out of 8 possible fossil pieces - local newpos = {x=pos.x,y=pos.y-1,z=pos.z} - local fossils = { - "mcl_structures_fossil_skull_1.mts", -- 4×5×5 - "mcl_structures_fossil_skull_2.mts", -- 5×5×5 - "mcl_structures_fossil_skull_3.mts", -- 5×5×7 - "mcl_structures_fossil_skull_4.mts", -- 7×5×5 - "mcl_structures_fossil_spine_1.mts", -- 3×3×13 - "mcl_structures_fossil_spine_2.mts", -- 5×4×13 - "mcl_structures_fossil_spine_3.mts", -- 7×4×13 - "mcl_structures_fossil_spine_4.mts", -- 8×5×13 - } - local r = pr:next(1, #fossils) - local path = modpath.."/schematics/"..fossils[r] - return mcl_structures.place_schematic(newpos, path, rotation or "random", nil, true) -end - -function mcl_structures.generate_end_exit_portal(pos, rot) +function mcl_structures.generate_end_exit_portal(pos, rot, pr, callback) local path = modpath.."/schematics/mcl_structures_end_exit_portal.mts" - return mcl_structures.place_schematic(pos, path, rot or "0", {["mcl_portals:portal_end"] = "air"}, true) + return mcl_structures.place_schematic(pos, path, rot or "0", {["mcl_portals:portal_end"] = "air"}, true, nil, callback) end function mcl_structures.generate_end_exit_portal_open(pos, rot) @@ -339,275 +421,15 @@ function mcl_structures.generate_end_gateway_portal(pos, rot) return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) end -local function shrine_placement_callback(p1, p2, size, rotation, pr) - -- Find and setup spawner with silverfish - local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner") - for s=1, #spawners do - --local meta = minetest.get_meta(spawners[s]) - mcl_mobspawners.setup_spawner(spawners[s], "mobs_mc:silverfish") - end +local chunk_square = mcl_mapgen.CS_NODES * mcl_mapgen.CS_NODES +local block_square = mcl_mapgen.BS * mcl_mapgen.BS - -- Shuffle stone brick types - local bricks = minetest.find_nodes_in_area(p1, p2, "mcl_core:stonebrick") - for b=1, #bricks do - local r_bricktype = pr:next(1, 100) - local r_infested = pr:next(1, 100) - local bricktype - if r_infested <= 5 then - if r_bricktype <= 30 then -- 30% - bricktype = "mcl_monster_eggs:monster_egg_stonebrickmossy" - elseif r_bricktype <= 50 then -- 20% - bricktype = "mcl_monster_eggs:monster_egg_stonebrickcracked" - else -- 50% - bricktype = "mcl_monster_eggs:monster_egg_stonebrick" - end - else - if r_bricktype <= 30 then -- 30% - bricktype = "mcl_core:stonebrickmossy" - elseif r_bricktype <= 50 then -- 20% - bricktype = "mcl_core:stonebrickcracked" - end - -- 50% stonebrick (no change necessary) - end - if bricktype then - minetest.set_node(bricks[b], { name = bricktype }) - end - end - - -- Also replace stairs - local stairs = minetest.find_nodes_in_area(p1, p2, {"mcl_stairs:stair_stonebrick", "mcl_stairs:stair_stonebrick_outer", "mcl_stairs:stair_stonebrick_inner"}) - for s=1, #stairs do - local stair = minetest.get_node(stairs[s]) - local r_type = pr:next(1, 100) - if r_type <= 30 then -- 30% mossy - if stair.name == "mcl_stairs:stair_stonebrick" then - stair.name = "mcl_stairs:stair_stonebrickmossy" - elseif stair.name == "mcl_stairs:stair_stonebrick_outer" then - stair.name = "mcl_stairs:stair_stonebrickmossy_outer" - elseif stair.name == "mcl_stairs:stair_stonebrick_inner" then - stair.name = "mcl_stairs:stair_stonebrickmossy_inner" - end - minetest.set_node(stairs[s], stair) - elseif r_type <= 50 then -- 20% cracky - if stair.name == "mcl_stairs:stair_stonebrick" then - stair.name = "mcl_stairs:stair_stonebrickcracked" - elseif stair.name == "mcl_stairs:stair_stonebrick_outer" then - stair.name = "mcl_stairs:stair_stonebrickcracked_outer" - elseif stair.name == "mcl_stairs:stair_stonebrick_inner" then - stair.name = "mcl_stairs:stair_stonebrickcracked_inner" - end - minetest.set_node(stairs[s], stair) - end - -- 50% no change - end - - -- Randomly add ender eyes into end portal frames, but never fill the entire frame - local frames = minetest.find_nodes_in_area(p1, p2, "mcl_portals:end_portal_frame") - local eyes = 0 - for f=1, #frames do - local r_eye = pr:next(1, 10) - if r_eye == 1 then - eyes = eyes + 1 - if eyes < #frames then - local frame_node = minetest.get_node(frames[f]) - frame_node.name = "mcl_portals:end_portal_frame_eye" - minetest.set_node(frames[f], frame_node) - end - end - end +function mcl_structures.from_16x16_to_chunk_inverted_chance(x) + return math.floor(x * 256 / chunk_square + 0.5) end -function mcl_structures.generate_end_portal_shrine(pos, rotation, pr) - local offset = {x=6, y=4, z=6} - --local size = {x=13, y=8, z=13} - local newpos = { x = pos.x - offset.x, y = pos.y, z = pos.z - offset.z } - - local path = modpath.."/schematics/mcl_structures_end_portal_room_simple.mts" - mcl_structures.place_schematic(newpos, path, rotation or "0", nil, true, nil, shrine_placement_callback, pr) +function mcl_structures.from_16x16_to_block_inverted_chance(x) + return math.floor(x * 256 / block_square + 0.5) end -local function temple_placement_callback(p1, p2, size, rotation, pr) - - -- Delete cacti leftovers: - local cactus_nodes = minetest.find_nodes_in_area_under_air(p1, p2, "mcl_core:cactus") - if cactus_nodes and #cactus_nodes > 0 then - for _, pos in pairs(cactus_nodes) do - local node_below = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) - if node_below and node_below.name == "mcl_core:sandstone" then - minetest.swap_node(pos, {name="air"}) - end - end - end - - -- Find chests. - -- FIXME: Searching this large area just for the chets is not efficient. Need a better way to find the chests; - -- probably let's just infer it from newpos because the schematic always the same. - local chests = minetest.find_nodes_in_area(p1, p2, "mcl_chests:chest") - - -- Add desert temple loot into chests - for c=1, #chests do - local lootitems = mcl_loot.get_multi_loot({ - { - stacks_min = 2, - stacks_max = 4, - items = { - { itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 }, - { itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 }, - { itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 }, - { itemstring = "mcl_books:book", weight = 20, func = function(stack, pr) - mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) - end }, - { itemstring = "mcl_mobitems:saddle", weight = 20, }, - { itemstring = "mcl_core:apple_gold", weight = 20, }, - { itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 }, - { itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 }, - { itemstring = "mcl_core:emerald", weight = 15, amount_min = 1, amount_max = 3 }, - { itemstring = "", weight = 15, }, - { itemstring = "mobs_mc:iron_horse_armor", weight = 15, }, - { itemstring = "mobs_mc:gold_horse_armor", weight = 10, }, - { itemstring = "mobs_mc:diamond_horse_armor", weight = 5, }, - { itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 3 }, - { itemstring = "mcl_core:apple_gold_enchanted", weight = 2, }, - } - }, - { - stacks_min = 4, - stacks_max = 4, - items = { - { itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 1, amount_max = 8 }, - { itemstring = "mcl_mobitems:rotten_flesh", weight = 10, amount_min = 1, amount_max = 8 }, - { itemstring = "mcl_mobitems:gunpowder", weight = 10, amount_min = 1, amount_max = 8 }, - { itemstring = "mcl_core:sand", weight = 10, amount_min = 1, amount_max = 8 }, - { itemstring = "mcl_mobitems:string", weight = 10, amount_min = 1, amount_max = 8 }, - } - }}, pr) - init_node_construct(chests[c]) - local meta = minetest.get_meta(chests[c]) - local inv = meta:get_inventory() - mcl_loot.fill_inventory(inv, "main", lootitems, pr) - end - - -- Initialize pressure plates and randomly remove up to 5 plates - local pplates = minetest.find_nodes_in_area(p1, p2, "mesecons_pressureplates:pressure_plate_stone_off") - local pplates_remove = 5 - for p=1, #pplates do - if pplates_remove > 0 and pr:next(1, 100) >= 50 then - -- Remove plate - minetest.remove_node(pplates[p]) - pplates_remove = pplates_remove - 1 - else - -- Initialize plate - minetest.registered_nodes["mesecons_pressureplates:pressure_plate_stone_off"].on_construct(pplates[p]) - end - end -end - -function mcl_structures.generate_desert_temple(pos, rotation, pr) - -- No Generating for the temple ... Why using it ? No Change - local path = modpath.."/schematics/mcl_structures_desert_temple.mts" - local newpos = {x=pos.x,y=pos.y-12,z=pos.z} - --local size = {x=22, y=24, z=22} - if newpos == nil then - return - end - mcl_structures.place_schematic(newpos, path, rotation or "random", nil, true, nil, temple_placement_callback, pr) -end - -local registered_structures = {} - ---[[ Returns a table of structure of the specified type. -Currently the only valid parameter is "stronghold". -Format of return value: -{ - { pos = , generated= }, -- first structure - { pos = , generated= }, -- second structure - -- and so on -} - -TODO: Implement this function for all other structure types as well. -]] -function mcl_structures.get_registered_structures(structure_type) - if registered_structures[structure_type] then - return table.copy(registered_structures[structure_type]) - else - return {} - end -end - --- Register a structures table for the given type. The table format is the same as for --- mcl_structures.get_registered_structures. -function mcl_structures.register_structures(structure_type, structures) - registered_structures[structure_type] = structures -end - -local function dir_to_rotation(dir) - local ax, az = math.abs(dir.x), math.abs(dir.z) - if ax > az then - if dir.x < 0 then - return "270" - end - return "90" - end - if dir.z < 0 then - return "180" - end - return "0" -end - --- Debug command -minetest.register_chatcommand("spawnstruct", { - params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_open | end_gateway_portal | end_portal_shrine | nether_portal | dungeon", - description = S("Generate a pre-defined structure near your position."), - privs = {debug = true}, - func = function(name, param) - local player = minetest.get_player_by_name(name) - if not player then return end - local pos = player:get_pos() - if not pos then return end - pos = vector.round(pos) - local dir = minetest.yaw_to_dir(player:get_look_horizontal()) - local rot = dir_to_rotation(dir) - local pr = PseudoRandom(pos.x+pos.y+pos.z) - local errord = false - local message = S("Structure placed.") - if param == "desert_temple" then - mcl_structures.generate_desert_temple(pos, rot, pr) - elseif param == "desert_well" then - mcl_structures.generate_desert_well(pos, rot) - elseif param == "igloo" then - mcl_structures.generate_igloo(pos, rot, pr) - elseif param == "witch_hut" then - mcl_structures.generate_witch_hut(pos, rot, pr) - elseif param == "boulder" then - mcl_structures.generate_boulder(pos, rot, pr) - elseif param == "fossil" then - mcl_structures.generate_fossil(pos, rot, pr) - elseif param == "ice_spike_small" then - mcl_structures.generate_ice_spike_small(pos, rot, pr) - elseif param == "ice_spike_large" then - mcl_structures.generate_ice_spike_large(pos, rot, pr) - elseif param == "end_exit_portal" then - mcl_structures.generate_end_exit_portal(pos, rot, pr) - elseif param == "end_exit_portal_open" then - mcl_structures.generate_end_exit_portal_open(pos, rot, pr) - elseif param == "end_gateway_portal" then - mcl_structures.generate_end_gateway_portal(pos, rot, pr) - elseif param == "end_portal_shrine" then - mcl_structures.generate_end_portal_shrine(pos, rot, pr) - elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then - mcl_dungeons.spawn_dungeon(pos, rot, pr) - elseif param == "nether_portal" and mcl_portals and mcl_portals.spawn_nether_portal then - mcl_portals.spawn_nether_portal(pos, rot, pr, name) - elseif param == "" then - message = S("Error: No structure type given. Please use “/spawnstruct ”.") - errord = true - else - message = S("Error: Unknown structure type. Please use “/spawnstruct ”.") - errord = true - end - minetest.chat_send_player(name, message) - if errord then - minetest.chat_send_player(name, S("Use /help spawnstruct to see a list of avaiable types.")) - end - end -}) +dofile(modpath .. "/structures.lua") diff --git a/mods/MAPGEN/mcl_structures/jungle_temple.lua b/mods/MAPGEN/mcl_structures/jungle_temple.lua new file mode 100644 index 000000000..635f35670 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/jungle_temple.lua @@ -0,0 +1,203 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 9 +local noise_multiplier = 1.3 +local random_offset = 132 +local struct_threshold = chance_per_chunk - 1 +local scanning_ratio = 0.0003 + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local node_list = {"mcl_core:dirt_with_grass", "mcl_core:dirt", "mcl_core:stone", "mcl_core:granite", "mcl_core:gravel", "mcl_core:diorite"} + +local schematic_file = modpath .. "/schematics/mcl_structures_jungle_temple.mts" + +local temple_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +local temple_schematic = loadstring(temple_schematic_lua)() +local size = temple_schematic.size +local sx = size.x +local sy = size.y +local sz = size.z +local offset = vector.round(vector.divide(size, 2)) +offset.y = 5 + +local ox = offset.x +local oy = offset.y +local oz = offset.z +local corner_x = sx - 3 +local corner_z = sz - 3 +local air_offset_x = ox - 6 +local air_offset_z = oz - 6 + +local function is_air(pos) + local node = minetest.get_node(pos) + return node.name == "air" +end + +local stair_support_node = { + {name = "mcl_core:cobble"}, + {name = "mcl_core:mossycobble"}, + {name = "mcl_core:stonebrick"}, + {name = "mcl_core:stonebrickmossy"}, + {name = "mcl_core:stonebrickcracked"}, +} + +local function on_placed(p1, rotation, pr, size) + local p2 + if rotation == "90" or rotation == "270" then + p2 = {x = p1.x + sz - 1, y = p1.y + sy - 1, z = p1.z + sx - 1} + else + p2 = {x = p1.x + sx - 1, y = p1.y + sy - 1, z = p1.z + sz - 1} + end + + -- Support stairs + local y = p1.y + 5 + local bottom = mcl_mapgen.get_chunk_beginning(y) + local stair_list = minetest.find_nodes_in_area({x = p1.x, y = y, z = p1.z}, {x = p2.x, y = y, z = p2.z}, {"mcl_stairs:stair_cobble"}, false) + for i = 1, #stair_list do + local pos = stair_list[i] + pos.y = y - 1 + while is_air(pos) and pos.y > bottom do + minetest.swap_node(pos, stair_support_node[pr:next(1, #stair_support_node)]) + pos.y = pos.y - 1 + end + end + + -- Initialize some nodes + local chest_node = "mcl_chests:trapped_chest_small" + local lever_node = "mesecons_walllever:wall_lever_off" + local nodes = minetest.find_nodes_in_area(p1, {x = p2.x, y = p1.y + 5, z = p2.z}, {chest_node, lever_node}, true) + + local levers = nodes[lever_node] + for _, pos in pairs(levers) do + mcl_structures.init_node_construct(pos) + end + + -- Add loot into chests TODO: fix items + local chests = nodes[chest_node] + for c=1, #chests do + local lootitems = mcl_loot.get_multi_loot({ + { + stacks_min = 2, + stacks_max = 4, + items = { + { itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 }, + { itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 }, + { itemstring = "mcl_books:book", weight = 20, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_mobitems:saddle", weight = 20, }, + { itemstring = "mcl_core:apple_gold", weight = 20, }, + { itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 }, + { itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_core:emerald", weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "", weight = 15, }, + { itemstring = "mobs_mc:iron_horse_armor", weight = 15, }, + { itemstring = "mobs_mc:gold_horse_armor", weight = 10, }, + { itemstring = "mobs_mc:diamond_horse_armor", weight = 5, }, + { itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:apple_gold_enchanted", weight = 2, }, + } + }, + { + stacks_min = 4, + stacks_max = 4, + items = { + { itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:gunpowder", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_core:sand", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:string", weight = 10, amount_min = 1, amount_max = 8 }, + } + }}, pr) + mcl_structures.init_node_construct(chests[c]) + local meta = minetest.get_meta(chests[c]) + local inv = meta:get_inventory() + mcl_loot.fill_inventory(inv, "main", lootitems, pr) + end +end + +local function place(pos, rotation, pr) + mcl_structures.place_schematic({pos = pos, schematic = temple_schematic, pr = pr, on_placed = on_placed}) +end + +local mcl_mapgen_clamp_to_chunk = mcl_mapgen.clamp_to_chunk +local function process_pos(pos) + return { + x = mcl_mapgen_clamp_to_chunk(pos.x - ox, sx), + y = mcl_mapgen_clamp_to_chunk(pos.y - oy, sy), + z = mcl_mapgen_clamp_to_chunk(pos.z - oz, sz), + } +end + +local function get_place_rank(pos) + local x1 = pos.x + 1 + local x2 = x1 + corner_x + local z1 = pos.z + 1 + local z2 = z1 + corner_z + local y2 = pos.y + 1 + local y1 = y2 - 2 + if is_air({x = x1, y = y1, z = z1}) then return -1 end + if is_air({x = x2, y = y1, z = z1}) then return -1 end + if is_air({x = x1, y = y1, z = z2}) then return -1 end + if is_air({x = x2, y = y1, z = z2}) then return -1 end + + local p1 = {x = x1 + air_offset_x, y = y2, z = z1 + air_offset_z} + local p2 = {x = x2 - air_offset_x, y = y2, z = z2 + air_offset_z} + local pos_counter_air = #minetest.find_nodes_in_area(p1, p2, {"air", "group:buildable_to", "group:deco_block"}, false) + local pos_counter_air = pos_counter_air - 2 * (#minetest.find_nodes_in_area(p1, p2, {"group:tree"}, false)) + + local p1 = {x = x1 + 1, y = y1, z = z1 + 1} + local p2 = {x = x2 - 1, y = y1, z = z2 - 1} + local pos_counter_ground = #minetest.find_nodes_in_area(p1, p2, node_list, false) + return pos_counter_ground + pos_counter_air +end + +mcl_structures.register_structure({ + name = "jungle_temple", + decoration = { + deco_type = "simple", + place_on = node_list, + flags = "all_floors", + fill_ratio = scanning_ratio, + y_min = -13, + y_max = mcl_mapgen.overworld.max, + height = 1, + biomes = + mcl_mapgen.v6 and { + "Jungle" + } or { + "Jungle", + "JungleEdge", + "JungleEdgeM", + "JungleEdgeM_ocean", + "JungleEdge_ocean", + "JungleM", + "JungleM_ocean", + "JungleM_shore", + "Jungle_ocean", + "Jungle_shore", + }, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos + local count = -1 + for i = 1, #pos_list do + local pos_i = process_pos(pos_list[i]) + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + if count < 0 then return end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_structures/mod.conf b/mods/MAPGEN/mcl_structures/mod.conf index 3150c7cec..1e34960a8 100644 --- a/mods/MAPGEN/mcl_structures/mod.conf +++ b/mods/MAPGEN/mcl_structures/mod.conf @@ -1,4 +1,4 @@ name = mcl_structures -author = Wuzzy -description = Structures for MCL2 -depends = mcl_loot +author = Wuzzy, kay27, cora +description = Structures for MineClone 2/5 +depends = mcl_loot, mcl_mapgen, mcl_worlds diff --git a/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua b/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua new file mode 100644 index 000000000..dd8df05d3 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/nice_jungle_temple.lua @@ -0,0 +1,209 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 15 +local noise_multiplier = 1 +local random_offset = 133 +local struct_threshold = chance_per_chunk - 1 +local scanning_ratio = 0.00021 +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local node_list = {"mcl_core:dirt_with_grass", "mcl_core:dirt", "mcl_core:stone", "mcl_core:granite", "mcl_core:gravel", "mcl_core:diorite"} + +local schematic_file = modpath .. "/schematics/mcl_structures_nice_jungle_temple.mts" + +local temple_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +local temple_schematic = loadstring(temple_schematic_lua)() +local size = temple_schematic.size +local sx = size.x +local sy = size.y +local sz = size.z +local offset = vector.round(vector.divide(size, 2)) +offset.y = 5 + +local ox = offset.x +local oy = offset.y +local oz = offset.z +local corner_x = sx - 3 +local corner_z = sz - 3 +local air_offset_x = ox - 6 +local air_offset_z = oz - 6 + +local function is_air(pos) + local node = minetest.get_node(pos) + return node.name == "air" +end + +local stair_support_node = { + {name = "mcl_core:cobble"}, + {name = "mcl_core:mossycobble"}, + {name = "mcl_core:stonebrick"}, + {name = "mcl_core:stonebrickmossy"}, + {name = "mcl_core:stonebrickcracked"}, +} + +local nodes_to_be_supported = { + "mcl_stairs:stair_cobble", + "mcl_stairs:stair_stonebrickmossy", + "mcl_stairs:stair_stonebrickcracked", +} + +local function on_placed(p1, rotation, pr, size) + local p2 + if rotation == "90" or rotation == "270" then + p2 = {x = p1.x + sz - 1, y = p1.y + sy - 1, z = p1.z + sx - 1} + else + p2 = {x = p1.x + sx - 1, y = p1.y + sy - 1, z = p1.z + sz - 1} + end + + -- Support stairs + local y = p1.y + 5 + local bottom = mcl_mapgen.get_chunk_beginning(y) + local stair_list = minetest.find_nodes_in_area({x = p1.x, y = y, z = p1.z}, {x = p2.x, y = y, z = p2.z}, nodes_to_be_supported, false) + for i = 1, #stair_list do + local pos = stair_list[i] + pos.y = y - 1 + while is_air(pos) and pos.y > bottom do + minetest.swap_node(pos, stair_support_node[pr:next(1, #stair_support_node)]) + pos.y = pos.y - 1 + end + end + + -- Initialize some nodes + local chest_node = "mcl_chests:trapped_chest_small" + local lever_node = "mesecons_walllever:wall_lever_off" + local nodes = minetest.find_nodes_in_area(p1, {x = p2.x, y = p1.y + 5, z = p2.z}, {chest_node, lever_node}, true) + + local levers = nodes[lever_node] + for _, pos in pairs(levers) do + mcl_structures.init_node_construct(pos) + end + + -- Add loot into chests TODO: fix items + local chests = nodes[chest_node] + for c=1, #chests do + local lootitems = mcl_loot.get_multi_loot({ + { + stacks_min = 2, + stacks_max = 4, + items = { + { itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 }, + { itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 }, + { itemstring = "mcl_books:book", weight = 20, func = function(stack, pr) + mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) + end }, + { itemstring = "mcl_mobitems:saddle", weight = 20, }, + { itemstring = "mcl_core:apple_gold", weight = 20, }, + { itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 }, + { itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 }, + { itemstring = "mcl_core:emerald", weight = 15, amount_min = 1, amount_max = 3 }, + { itemstring = "", weight = 15, }, + { itemstring = "mobs_mc:iron_horse_armor", weight = 15, }, + { itemstring = "mobs_mc:gold_horse_armor", weight = 10, }, + { itemstring = "mobs_mc:diamond_horse_armor", weight = 5, }, + { itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 3 }, + { itemstring = "mcl_core:apple_gold_enchanted", weight = 2, }, + } + }, + { + stacks_min = 4, + stacks_max = 4, + items = { + { itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:rotten_flesh", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:gunpowder", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_core:sand", weight = 10, amount_min = 1, amount_max = 8 }, + { itemstring = "mcl_mobitems:string", weight = 10, amount_min = 1, amount_max = 8 }, + } + }}, pr) + mcl_structures.init_node_construct(chests[c]) + local meta = minetest.get_meta(chests[c]) + local inv = meta:get_inventory() + mcl_loot.fill_inventory(inv, "main", lootitems, pr) + end + +end + +local function place(pos, rotation, pr) + mcl_structures.place_schematic({pos = pos, schematic = temple_schematic, pr = pr, on_placed = on_placed}) +end + +local mcl_mapgen_clamp_to_chunk = mcl_mapgen.clamp_to_chunk +local function process_pos(pos) + return { + x = mcl_mapgen_clamp_to_chunk(pos.x - ox, sx), + y = mcl_mapgen_clamp_to_chunk(pos.y - oy, sy), + z = mcl_mapgen_clamp_to_chunk(pos.z - oz, sz), + } +end + +local function get_place_rank(pos) + local x1 = pos.x + 1 + local x2 = x1 + corner_x + local z1 = pos.z + 1 + local z2 = z1 + corner_z + local y2 = pos.y + 1 + local y1 = y2 - 2 + if is_air({x = x1, y = y1, z = z1}) then return -1 end + if is_air({x = x2, y = y1, z = z1}) then return -1 end + if is_air({x = x1, y = y1, z = z2}) then return -1 end + if is_air({x = x2, y = y1, z = z2}) then return -1 end + + local p1 = {x = x1 + air_offset_x, y = y2, z = z1 + air_offset_z} + local p2 = {x = x2 - air_offset_x, y = y2, z = z2 + air_offset_z} + local pos_counter_air = #minetest.find_nodes_in_area(p1, p2, {"air", "group:buildable_to", "group:deco_block"}, false) + local pos_counter_air = pos_counter_air - 2 * (#minetest.find_nodes_in_area(p1, p2, {"group:tree"}, false)) + + local p1 = {x = x1 + 1, y = y1, z = z1 + 1} + local p2 = {x = x2 - 1, y = y1, z = z2 - 1} + local pos_counter_ground = #minetest.find_nodes_in_area(p1, p2, node_list, false) + return pos_counter_ground + pos_counter_air +end + +mcl_structures.register_structure({ + name = "nice_jungle_temple", + decoration = { + deco_type = "simple", + place_on = node_list, + flags = "all_floors", + fill_ratio = scanning_ratio, + y_min = -20, + y_max = mcl_mapgen.overworld.max, + height = 1, + biomes = + mcl_mapgen.v6 and { + "Jungle" + } or { + "Jungle", + "JungleEdge", + "JungleEdgeM", + "JungleEdgeM_ocean", + "JungleEdge_ocean", + "JungleM", + "JungleM_ocean", + "JungleM_shore", + "Jungle_ocean", + "Jungle_shore", + }, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos + local count = -1 + for i = 1, #pos_list do + local pos_i = process_pos(pos_list[i]) + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + if count < 0 then return end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_structures/noise_indicator.lua b/mods/MAPGEN/mcl_structures/noise_indicator.lua new file mode 100644 index 000000000..7cc130358 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/noise_indicator.lua @@ -0,0 +1,60 @@ +local step = 1 +local chunk_borders = false + +local levels = { + [-9] = "black", + [-8] = "brown", + [-7] = "brown", + [-6] = "gray", + [-5] = "gray", + [-4] = "red", + [-3] = "orange", + [-2] = "purple", + [-1] = "magenta", + [0] = "pink", + [1] = "yellow", + [2] = "green", + [3] = "lime", + [4] = "blue", + [5] = "cyan", + [6] = "light_blue", + [7] = "silver", + [8] = "silver", + [9] = "white", +} + +local math_min, math_max = math.min, math.max +local math_floor, math_ceil = math.floor, math.ceil + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local noise_offset_x_and_z = math_floor(mcl_mapgen.CS_NODES/2) + +mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) + local y0 = minp.y + for x0 = minp.x, maxp.x, step do + for z0 = minp.z, maxp.z, step do + local current_noise_level = mcl_structures_get_perlin_noise_level({x = x0 - noise_offset_x_and_z, y = y0, z = z0 - noise_offset_x_and_z}) + local amount + if current_noise_level < 0 then + amount = math_max(math_ceil(current_noise_level * 9), -9) + else + amount = math_min(math_floor(current_noise_level * 9), 9) + end + local y0 = maxp.y - 9 + amount + minetest.set_node({x=x0, y=y0, z=z0}, {name = "mcl_core:glass_"..levels[amount]}) + end + end + if chunk_borders then + for x0 = minp.x, maxp.x, step do + for y0 = minp.y, maxp.y, step do + minetest.set_node({x=x0, y=y0, z=maxp.z}, {name = "mcl_core:glass"}) + end + end + for z0 = minp.z, maxp.z, step do + for y0 = minp.y, maxp.y, step do + minetest.set_node({x=maxp.x, y=y0, z=z0}, {name = "mcl_core:glass"}) + end + end + end +end, -1) diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_jungle_temple.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_jungle_temple.mts new file mode 100644 index 0000000000000000000000000000000000000000..ec98a83ea359fafabc55ec0df882634a601a9790 GIT binary patch literal 2586 zcmZ`&4K$Q#8=f)EJHxy&C^JTQ(O6Q9pH#EaJ4~8N)*vY||MD{!<0mN@48}Gz`mj{H zA%B&evHcC-R$~mNrLDeHBeZI@8=F09Woe~P_UG*PefvG3s*i98{Tmn;@g6O&U@5Al+@T%iDA@@Mt;g3VGPR*;&O zN=*}UL?Qv7#rtq%r6zKOLIm+oL26oZl7K6Y<0ULzh#-7GQqvZ_QmIQ}(QV0t^fwZo zn8QmD@DY}OhjGLii;!KSAXUIiPD*7RTr?I6G6Z7khm5t9vXWzB5H^2O_yQs4&?4dY z_yJ|PBS?SX)Pr$i0gFPRxG!$XlJ>u`CFFO^{tq2X6!)RcRO)YWvAxB14=w4*|BsU{ z`YUbK|4ikt<2V1C_A{e-5@Y}n05}56ZeazUHOML>**>X_Z~}@^Gi1hr>Db6>wX3?d zv=|xV;DT~FeOo744u?tjRYX__oR(A|xdsgDq}@kgXW8d1u!U_ABU$lkZ@#g%=BX$rPbQjfN@=2v0L@|Am)=Xo3iEkn8LW7HOu6$;li zij;#oGGM>q>_72)e(II8gek>7)-{bQ0%G6#tv4OBr>`lTB3dec*v06`tEWZ9!(Zwq zU`Ot;<>8k-2+sgtfIENecA%74H`diyy0VIj=PbXqdmhYhl5_mld`ENd(Mo)tz;!P; z-Fa7r)qz%P!76TGL@4I!>rabwO}k5E`X2emeA8h8{ygZKzV_}uv+!h(r@9~H;Oq$U zALMZBEd$ZP9b9c_D=oxV`({>*N$+!HC)VPjy8bcls3=o-5Z>VyYDylgjhTUiXye01A~d z8ER2aG7KSclefWv`2#FPrl20$>FFWa7l=J0IdbQY%-L}z$YHCZ@onL~*yJYlj_mMy1svoiWT%XI zp_s)s7$~Rq5!3?eC)NqyfG#`wjK{c97xzmip_|VV%r9wvcC4-R)CPtF^KVS+`imND z`(LBSSPbw|C%NrGwhFyM#pbeO z;5%f!=2P?L)5mgyZ3^30)fqRE4!`B`;h=kgph|46TM>}yt2q;0RkJA{xh-mnHYvTr zlbj_uOl#Clbpb-L?6Rziv~UG&y`xHW4x)>iIk#`^#}iU}Qf6 zKLa9FHJ`=mdk+p;!gy0^&1*D^3TwCgG=u9eQ4Mt~yh>ii509gF1ADfAqe1*w(z#>5 z#iw5r0uL*Pz)J-01&#E;5kh57+k*_y3mNECYp`=r|BP@yD+YKr;Et~~KG|mEv zpfZhQQ{16n0ag}G>gj-5G|+6WvZ6#D(@hfS&c$&X{HzyV?e_(a0`$^?*_FS{;!q<< z2ULb^?+rF}`C+TlBk5qokW@~bJ8gO(JLvW(>Iw-;{3Q64fu<|Qm%pkCz4-=moW^l0 zg2xfz;c!oe@>&u6^VWG#nT7QFOxr`rMA&=d6F(BZLMHe_6YCgpCDpC)AzY&o)4t{c zPje!uT67r=CDC_1DldW-jv{nNbS+*C>*lD=5%YpsVm(T$+22ZgyoZu52hXx8QpD3V zL<+fWB7m2kS)`7o)-dNEIv}f74p{Kmh?7{d;wvW0#LWNI9v=o-0b8^bi6(BDI&8V? zWRm~>{g0hb3aPd`H=0|!Vy|OOnD#yJJJB4=WX5%KrTUwEtlhD97-XHM!DjDD-F1oy z50{s<`r`$E&X1;o0_pY3g>l%^ zZ3}1TEEBRiNv`S_WVa|$lU;lvF6PkIC|`r!{1;i4YV^_UY@dBk774LmE4$s+TI1I| zntE}uXt0EWJNXoz@n8173zw+uGtGM=8limamkqwLT`hpMM1>KtUzFRfKzcgku`Xs^ z=%^}aQ-jS&jPU!;x{F`P#0MFTgn?L|+PqOl#9-{NW_GRUO0tRZ?NV}vfw+gDv3J;4n1B~R2;lkS&AL|QHN6@_NE*Ts5#-b@#xip%htZcsQniB~GzxjnhJI`4>))Ip{SH zJuF;hQ7`?_hF499&?HK1u!8TMMGS5qYYNG-b8E++>Pb0gW$fZz)m-)9g(Bfxm~CxG zd2vwpZFZ2`v=It;3m9x4FEIQ;Ggfy0iGWMmo4DR|y7Uq;pJ;BbAksRaJi!#Zz5yk? O=Ofi15Yfy7q<;etnMdjX literal 0 HcmV?d00001 diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_nice_jungle_temple.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_nice_jungle_temple.mts new file mode 100644 index 0000000000000000000000000000000000000000..8a9babb9bfc2206450f07356bc2166847c6a2e99 GIT binary patch literal 3997 zcmaJ@30zX?+CMBJASxg#sDmKnlA5?=qq%^Rf-P=TE|nl+N?3&JSQ-*4E+vUMwwalf znHH8AHuv6eU$WiOx;dGelVyEQla5m}_F3Od_kMTg`_B2D-}Aoj|M@@9`9JS-mi3&- z^#Bww1B?OFegFFa%mD~5Spwiv_@X%eE{VW9WmjtIH~d}k@gf0W{AKm`1>)z0BtdFg zs&|@%Cl(75;`pDYaj7XhkqE$lA*815+9`;aB=dKC4hWckLQ>O~a;18IHcQz)=dkz- z3SYwG?+_#agulXgl8hyYoFYgS@OSM@jmun0ED~f0B;KD!ai52AyAl%t;un_$fr$6b zlEd%z6B_3VSp0!|XC_MoaWopub?Ksg=Kd%48TlQv`GXfHPW~h_)%$2xKrg6u70xjGJGi1O}Pgn_F;P(T`Qv%w)gjCT@iR<(0(qS-V zHX6}<46$SHtUJw(dnSF$?%rNtZDF6&4CZFx&=d}MY0`CUfbNAI_xIH784))W^!?V`3Jm`N6;pW(#Bb$qrX(LmbH3Hf2j6 zblq-k#4>A0LkYuY%N3_VQ_Uu0`{!`pdR0JFPQmDwdqW*hfRO8@cP?3Eo~J7qsF(gh zq!RHV1iK9kiD<3;Rz>nNfxLN(nq))k@zwPOuihBDDi_ zGR#lB4W^D$hLFL@>*2&bUDS}M4|y>Nd>fJ3av!c{%U^46_zg;oGLH=ON$u6V#0f_` z0s-yoq%;vfH~L$T=gqwxKytTk9a!y= z3(Gy;6zT_?+@wWA7C8vvG<_hBY;zp><7&(BYFSm`Q%+P#DaN6KKoDQCJA$tw;PGM4 zo6qN;BX4jviFj(g?^vZ?wFQ|6JJ)|GQV#63!s6c6w;AAeYG$SNf%QF`HU!8Br-GCq zH!zfaNbv+RKvp)dpL}doXAyhdXs8<3^};SNM)3k;u-wjdt$)}*m4?fR^cCE8FR-Id z*CDl{{F=3AS~k{f$ofv6KUTjY2@1Zqk8(zhMCJr|f$!P`q@3klEW@PhIhl?*+VQ+h zYAg5Wod9LN7sx9qjdx-oo2^fr1Z}F7ZRvyF{H^|*io+nULh=V_Ipm0Pz-j5JI6zBP zKCsEoX=HUYq7)B}BuC|?+*89((GOnm5R$JPD}h9T?&1D~?(jv88|i8XL-fSg$`2-A zOXrc+)vV*^e~XcGWI=EQslKt3He=Mo$iJ zCHmC8Q1nPK(Cz9EX?{+HKu%q=Y!kp7_s>4)t?`huwu?{;kE@@sE@^MDZDA{5lO719 z;g+d@0g7#Xo5n}}_m%oDZ%X%ez*n6>1Sie9>V|CYxtJW>O;N_M48RYILHQQ*;kL>c zk-)kYn_pHJUvLtH#VS1dp~TZ&0=N2MS-lD3=iO0w(r@JW$0{W@uVS8>d);PO(wDMU zlnYUBOB9dhJC&S&-H+gO<%iF6-OVc-$hPf+ovRWL!nd-F@v%ptYW=@g!3@Z#m;rjk=+kR7ebgEuXp0YHoapACzN7d&%|fdj}rdZ= z1$o+P^9Pm^wCObIY{<;SjlLW@(@@%UoJl-M^(li0LjyVx_g+f1_^0@*=oXwQm(+Av zN6*ytNx#A#vnA}VV~dvAI0$#o6{3@|ZHqmlm3c#B$|!mw|EH61?O8}UsJjVXt%W@3 z`}K}hdk^sJS+O_kg0$r}DTO|xzGko4+J0M#Psv}vJ@xTUT8V7@9(ptPvMb6Ma7;(1 zuvuI9p{jNE&iJZrTZDv~2C^ElGxdmO(qQSWb;T^n5N(;}i}ue;XDBP|q1B;Kb+Dgo z8I+}8S8BtlgiG(cu$&XRuyI0QZXb7IU~kqitw<&ytNmE|iyYX1m%@wAC2#-kt3+2iM7||CntGz5*R+vexP@27}?7 z?}XrzAWxET{+-NbWG&3NNOIWg-bi=qAGQzYQP9JKa3m3+X*y1E`q(vg_ z*IwLjWiIRQ`A}cACzp>X<$DOujp8~^e5d&?)?%>n<&Pgel;@Cr3P@%if?+sjnEh z=L*e|!ZL^UADbq<8f&v$0r3QgMsrGK{l#E*j%Ms!?@`Itr($I=YYP*^|nsBEZmL8#UzpfaAm6&Kb{R`xp8+fCXgA-s&*5- zkOl03GyGMbp*yTmdV!3%5X<#+Bkdt%9s^cxbXOj=Z61M@d<`29D9>Zje^xg3T9jw$ zy$U}{8$15iTCKTYceX6>b^AdErW`ewRldPjcz0Xb8t05q8mcmP)tMh=<=&j)Fv7;N zm3??_ZcoI+;o*q}N;qzUW`5ro6==kT0#EekqSTt=_%7p1WF^f1%UN?MgB0|J6_R=<#X=_VfR zk!nUkb1iNuT4S);5oPeol@(4=nXwu!jLMQvwXa5#`xO9-+;0zl>`(2m4~Q6YrEn-s z9Yh6(eO1Y0^2&#fUMX!-V55L<=1 zL+3N+4I{$%bCiH;1l#h+Iv7l-Pwk{1Rw>hpX1>aLYqAF0z0?_Ci|RWH*10|bVhH;V zSmrO)Z|nhi9Xa$80oiwO&8_b>N@gmU;&dIY`k8P@<@q|W9O2MRlOb2v%|hB@t+aOL z)KZp;9;(=HoQo0A*{X4+lFN*)b~Z8~R*>=v36caJf(3&$=G$dIGw`&$%!IYNqg%_Z z%d4h~ii)_*c(!~H6@_$8s&eJt>>KGswM|m25;bVs6@&DKBZ#bn@08FZ3PR!_iYd?^ z^5|EvRHdaO_o$TaCGHQdHYuM6Hw5R>|OE*h%T>2Q#CxqI&lf2AFpVx3?gvH4-Xkn#_ zT1Y$Cl|Smjs_je1hgSwj%!=Ez;8MhJK_pCAp(;gj^u!aawW^U(AXKFs%dZSlR3KX+ z@fhJ-0W_arn&U}&&F&k~dk-(bQ^a!k*FRi!wAOQP<{{js=%Fhd~ zQE)5fb+dwaY&(9C86p%%imiUo^9xrL= pos.x and minp.z <= pos.z and maxp.z >= pos.z and minp.y <= pos.y and maxp.y >= pos.y then + place(pos, nil, pr) + strongholds[s].generated = true + end + end + end +end, mcl_mapgen.order.STRONGHOLDS) diff --git a/mods/MAPGEN/mcl_structures/structures.lua b/mods/MAPGEN/mcl_structures/structures.lua new file mode 100644 index 000000000..fd6b21b26 --- /dev/null +++ b/mods/MAPGEN/mcl_structures/structures.lua @@ -0,0 +1,17 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +if not mcl_mapgen.singlenode then + dofile(modpath .. "/desert_temple.lua") + dofile(modpath .. "/desert_well.lua") + dofile(modpath .. "/end_exit_portal.lua") + dofile(modpath .. "/fossil.lua") + dofile(modpath .. "/igloo.lua") + dofile(modpath .. "/ice_spike_small.lua") + dofile(modpath .. "/ice_spike_large.lua") + dofile(modpath .. "/jungle_temple.lua") + dofile(modpath .. "/nice_jungle_temple.lua") + -- dofile(modpath .. "/noise_indicator.lua") + dofile(modpath .. "/stronghold.lua") + dofile(modpath .. "/witch_hut.lua") +end diff --git a/mods/MAPGEN/mcl_structures/witch_hut.lua b/mods/MAPGEN/mcl_structures/witch_hut.lua new file mode 100644 index 000000000..f6dc6ec9b --- /dev/null +++ b/mods/MAPGEN/mcl_structures/witch_hut.lua @@ -0,0 +1,136 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +local chance_per_chunk = 3 +local noise_multiplier = -0.9 +local random_offset = 8 +local scanning_ratio = 0.01 +local struct_threshold = chance_per_chunk - 1 + +local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level + +local schematic_file = modpath .. "/schematics/mcl_structures_witch_hut.mts" + +local witch_hut_schematic_lua = minetest.serialize_schematic(schematic_file, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic" +local witch_hut_schematic = loadstring(witch_hut_schematic_lua)() + +local node_list = {"mcl_core:dirt_with_grass", "mcl_core:dirt"} + +local WITCH_HUT_HEIGHT = 2 -- Exact Y level to spawn witch huts at. This height refers to the height of the floor + +local witch_hut_offsets = { + ["0"] = { + {x=1, y=0, z=1}, {x=1, y=0, z=5}, {x=6, y=0, z=1}, {x=6, y=0, z=5}, + }, + ["180"] = { + {x=2, y=0, z=1}, {x=2, y=0, z=5}, {x=7, y=0, z=1}, {x=7, y=0, z=5}, + }, + ["270"] = { + {x=1, y=0, z=1}, {x=5, y=0, z=1}, {x=1, y=0, z=6}, {x=5, y=0, z=6}, + }, + ["90"] = { + {x=1, y=0, z=2}, {x=5, y=0, z=2}, {x=1, y=0, z=7}, {x=5, y=0, z=7}, + }, +} + +local function on_placed(place, rotation, pr, size) + local offsets = witch_hut_offsets[rotation] + if not offsets then return end + for _, offset in pairs(offsets) do + local tpos = vector.add(place, offset) + for y = place.y - 1, mcl_mapgen.get_chunk_beginning(place.y - 1), -1 do + tpos.y = y + local nn = minetest.get_node(tpos).name + if not nn then break end + local node = minetest.registered_nodes[nn] + local groups = node.groups + if nn == "mcl_flowers:waterlily" or nn == "mcl_core:water_source" or nn == "mcl_core:water_flowing" or nn == "air" or groups.deco_block then + minetest.swap_node(tpos, {name="mcl_core:tree"}) + else + break + end + end + end +end + + +local function place(pos, rotation, pr) + mcl_structures.place_schematic({pos = pos, rotaton = rotation, schematic = witch_hut_schematic, pr = pr, on_placed = on_placed}) +end + +local function get_place_rank(pos) + local x, y, z = pos.x, pos.y, pos.z + local p1 = {x = x + 1, y = y + 1, z = z + 1} + local p2 = {x = x + 4, y = y + 4, z = z + 4} + local counter = #minetest.find_nodes_in_area(p1, p2, {"air", "group:buildable_to", "group:deco_block"}, false) + return counter +end + +local function tune_pos(pos) + local pos = table.copy(pos) + local y = pos.y - 1 + if y >= WITCH_HUT_HEIGHT - 5 and y <= WITCH_HUT_HEIGHT + 5 then + pos.y = WITCH_HUT_HEIGHT + return pos + end + local x = pos.x + local z = pos.z + local p1 = {x = x - 3, y = y , z = z - 3} + local p2 = {x = x + 3, y = y + 2, z = z + 3} + local water_list = minetest.find_nodes_in_area(p1, p2, {"group:water"}, false) + if not water_list or #water_list < 1 then + pos.y = y + return pos + end + local top = -1 + for _, pos in pairs(water_list) do + if pos.y > top then + top = pos.y + end + end + pos.y = top + return pos +end + +mcl_structures.register_structure({ + name = "witch_hut", + decoration = { + deco_type = "simple", + place_on = node_list, + spawn_by = {"mcl_core:water_source", "group:frosted_ice"}, + num_spawn_by = 1, + -- flags = "all_floors", + fill_ratio = scanning_ratio, + y_min = mcl_mapgen.overworld.min, + y_max = mcl_mapgen.overworld.max, + height = 1, + biomes = mcl_mapgen.v6 and { + "Normal", + } or { + "Swampland", + "Swampland_shore", + "Swampland_ocean", + "Swampland_deep_ocean", + }, + }, + on_finished_chunk = function(minp, maxp, seed, vm_context, pos_list) + local pr = PseudoRandom(seed + random_offset) + local random_number = pr:next(1, chance_per_chunk) + local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier + if (random_number + noise) < struct_threshold then return end + local pos = tune_pos(pos_list[1]) + if #pos_list > 1 then + local count = get_place_rank(pos) + for i = 2, #pos_list do + local pos_i = pos_list[i] + local count_i = get_place_rank(pos_i) + if count_i > count then + count = count_i + pos = pos_i + end + end + end + place(pos, nil, pr) + end, + place_function = place, +}) diff --git a/mods/MAPGEN/mcl_villages/README.txt b/mods/MAPGEN/mcl_villages/README.txt index b266a131a..7573084d8 100644 --- a/mods/MAPGEN/mcl_villages/README.txt +++ b/mods/MAPGEN/mcl_villages/README.txt @@ -1,6 +1,6 @@ MCL_Villages: ============================ -A fork of Rochambeau's "Settlements" mod converted for use in MineClone2. +A fork of Rochambeau's "Settlements" mod converted for use in MineClone5. -------------- Using the mod: diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index a69029063..7c70e1d3b 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -88,7 +88,7 @@ function settlements.create_site_plan(maxp, minp, pr) -- find center_surface of chunk local center_surface , surface_material = settlements.find_surface(center, true) local chunks = {} - chunks[mcl_vars.get_chunk_number(center)] = true + chunks[mcl_mapgen.get_chunk_number(center)] = true -- go build settlement around center if not center_surface then return false end @@ -124,7 +124,7 @@ function settlements.create_site_plan(maxp, minp, pr) ptx = settlements.round(ptx, 0) ptz = settlements.round(ptz, 0) local pos1 = { x=ptx, y=center_surface.y+50, z=ptz} - local chunk_number = mcl_vars.get_chunk_number(pos1) + local chunk_number = mcl_mapgen.get_chunk_number(pos1) local pos_surface, surface_material if chunks[chunk_number] then pos_surface, surface_material = settlements.find_surface(pos1) @@ -268,15 +268,13 @@ function settlements.place_schematics(settlement_info, pr) local schematic = loadstring(schem_lua)() -- build foundation for the building an make room above -- place schematic - mcl_structures.place_schematic( - pos, - schematic, - rotation, - nil, - true, - nil, - init_nodes, - pr - ) + mcl_structures.place_schematic({ + pos = pos, + schematic = schematic, + rotation = rotation, + force_placement = true, + on_place = init_nodes, + pr = pr, + }) end end diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index 7e460990e..47ca91f2e 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -1,6 +1,8 @@ settlements = {} settlements.modpath = minetest.get_modpath(minetest.get_current_modname()) +local minetest_get_spawn_level = minetest.get_spawn_level + dofile(settlements.modpath.."/const.lua") dofile(settlements.modpath.."/utils.lua") dofile(settlements.modpath.."/foundation.lua") @@ -53,6 +55,7 @@ end -- on map generation, try to build a settlement -- local function build_a_settlement(minp, maxp, blockseed) + minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp) .. ", blockseed = " .. tostring(blockseed)) local pr = PseudoRandom(blockseed) -- fill settlement_info with buildings and their data @@ -69,29 +72,38 @@ local function build_a_settlement(minp, maxp, blockseed) settlements.place_schematics(settlement_info, pr) end -local function ecb_village(blockpos, action, calls_remaining, param) - if calls_remaining >= 1 then return end - local minp, maxp, blockseed = param.minp, param.maxp, param.blockseed - build_a_settlement(minp, maxp, blockseed) -end - -- Disable natural generation in singlenode. local mg_name = minetest.get_mapgen_setting("mg_name") if mg_name ~= "singlenode" then - mcl_mapgen_core.register_generator("villages", nil, function(minp, maxp, blockseed) + mcl_mapgen.register_mapgen(function(minp, maxp, blockseed) + -- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no" + -- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed)) -- don't build settlement underground if maxp.y < 0 then return end -- randomly try to build settlements if blockseed % 77 ~= 17 then return end - -- needed for manual and automated settlement building + -- don't build settlements on (too) uneven terrain - --local heightmap = minetest.get_mapgen_object("heightmap") - local height_difference = settlements.evaluate_heightmap() + + -- lame and quick replacement of `heightmap` by kay27 - we maybe need to restore `heightmap` analysis if there will be a way for the engine to avoid cavegen conflicts: + -------------------------------------------------------------------------- + local height_difference, min, max + local pr1=PseudoRandom(blockseed) + for i=1,pr1:next(5,10) do + local x = pr1:next(0, 40) + minp.x + 19 + local z = pr1:next(0, 40) + minp.z + 19 + local y = minetest_get_spawn_level(x, z) + if not y then return end + if y < (min or y+1) then min = y end + if y > (max or y-1) then max = y end + end + height_difference = max - min + 1 + -------------------------------------------------------------------------- + if height_difference > max_height_difference then return end - local param={minp=vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed} - minetest.emerge_area(minp, maxp, ecb_village, param) - end) + build_a_settlement(minp, maxp, blockseed) + end, mcl_mapgen.order.VILLAGES) end -- manually place villages if minetest.is_creative_enabled("") then diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua index 993de11c4..1d94ead0c 100644 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ b/mods/MAPGEN/mcl_villages/utils.lua @@ -1,4 +1,4 @@ -local get_node = mcl_vars.get_node +local get_node = mcl_mapgen.get_far_node ------------------------------------------------------------------------------- -- function to copy tables @@ -207,44 +207,6 @@ function shuffle(tbl, pr) return table end ------------------------------------------------------------------------------- --- evaluate heightmap -------------------------------------------------------------------------------- -function settlements.evaluate_heightmap() - local heightmap = minetest.get_mapgen_object("heightmap") - -- max height and min height, initialize with impossible values for easier first time setting - local max_y = -50000 - local min_y = 50000 - -- only evaluate the center square of heightmap 40 x 40 - local square_start = 1621 - local square_end = 1661 - for j = 1 , 40, 1 do - for i = square_start, square_end, 1 do - -- skip buggy heightmaps, return high value - if heightmap[i] == -31000 or heightmap[i] == 31000 then - return max_height_difference + 1 - end - if heightmap[i] < min_y then - min_y = heightmap[i] - end - if heightmap[i] > max_y then - max_y = heightmap[i] - end - end - -- set next line - square_start = square_start + 80 - square_end = square_end + 80 - end - -- return the difference between highest and lowest pos in chunk - local height_diff = max_y - min_y - -- filter buggy heightmaps - if height_diff <= 1 then - return max_height_difference + 1 - end - -- debug info - settlements.debug("heightdiff ".. height_diff) - return height_diff -end -------------------------------------------------------------------------------- -- Set array to list -- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list ------------------------------------------------------------------------------- diff --git a/mods/MAPGEN/tsm_railcorridors/init.lua b/mods/MAPGEN/tsm_railcorridors/init.lua index 65a7d6a69..654a05672 100644 --- a/mods/MAPGEN/tsm_railcorridors/init.lua +++ b/mods/MAPGEN/tsm_railcorridors/init.lua @@ -19,8 +19,7 @@ end local probability_railcaves_in_mapchunk = P(0.33333) setting = tonumber(minetest.settings:get("tsm_railcorridors_probability_railcaves_in_mapchunk")) -- Extra check to prevent mod griefing in singlenode, mcimported worlds. -local mg_name = minetest.get_mapgen_setting("mg_name") -if mg_name == "singlenode" then +if mcl_mapgen.singlenode then probability_railcaves_in_mapchunk = P(0) elseif setting then probability_railcaves_in_mapchunk = P(setting) @@ -96,10 +95,10 @@ end -- Max. and min. heights between rail corridors are generated local height_min -if mcl_vars.mg_lava then - height_min = mcl_vars.mg_lava_overworld_max + 2 +if mcl_mapgen.lava then + height_min = mcl_mapgen.overworld.lava_max + 2 else - height_min = mcl_vars.mg_bedrock_overworld_max + 2 + height_min = mcl_mapgen.overworld.bedrock_max + 2 end local height_max = mcl_worlds.layer_to_y(60) @@ -1093,7 +1092,7 @@ local function create_corridor_system(main_cave_coords) end -- The rail corridor algorithm starts here -mcl_mapgen_core.register_generator("railcorridors", nil, function(minp, maxp, blockseed, _pr) +mcl_mapgen.register_mapgen(function(minp, maxp, blockseed) -- We re-init the randomizer for every mapchunk as we start generating in the middle of each mapchunk. -- We can't use the mapgen seed as this would make the algorithm depending on the order the mapchunk generate. InitRandomizer(blockseed) diff --git a/mods/PLAYER/mcl_spawn/init.lua b/mods/PLAYER/mcl_spawn/init.lua index 113a4d27f..de4db5094 100644 --- a/mods/PLAYER/mcl_spawn/init.lua +++ b/mods/PLAYER/mcl_spawn/init.lua @@ -81,7 +81,7 @@ local dir_step = storage:get_int("mcl_spawn_dir_step") or 0 local dir_ind = storage:get_int("mcl_spawn_dir_ind") or 1 local emerge_pos1, emerge_pos2 -local spawn_limit = mcl_vars.mapgen_edge_max +local spawn_limit = mcl_mapgen.EDGE_MAX --Functions @@ -500,7 +500,11 @@ function mcl_spawn.shadow_worker() if success then local wsp_node = minetest.get_node(wsp) - if not (wsp_node and wsp_node.name == "ignore") + if wsp_node and + ( + (minetest.compare_block_status and (minetest.compare_block_status(wsp, "loaded") or minetest.compare_block_status(wsp, "active"))) + or minetest.get_node_or_nil(wsp) + ) and ((not good_for_respawn(wsp)) or ((no_trees_area_counter >= 0) and not can_find_tree(wsp))) then success = false minetest.log("action", "[mcl_spawn] World spawn position isn't safe anymore: "..minetest.pos_to_string(wsp)) diff --git a/mods/PLAYER/mcl_spawn/mod.conf b/mods/PLAYER/mcl_spawn/mod.conf index 954f831db..2c7953fe7 100644 --- a/mods/PLAYER/mcl_spawn/mod.conf +++ b/mods/PLAYER/mcl_spawn/mod.conf @@ -1,4 +1,4 @@ name = mcl_spawn author = Wuzzy description = Set and get the player's respawn position -depends = mcl_init +depends = mcl_mapgen