From 6d4f7d2e62c07e55a4fe2e38e0afe3e92c92e33a Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 16 Jan 2022 05:20:34 +0400 Subject: [PATCH] Fix strongholds --- mods/CORE/mcl_mapgen/init.lua | 6 + mods/ITEMS/mcl_end/eye_of_ender.lua | 2 +- mods/MAPGEN/mcl_structures/stronghold.lua | 185 ++++++++++++++++++++++ 3 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 mods/MAPGEN/mcl_structures/stronghold.lua diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index f34211b06..a64bc1e6f 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -476,5 +476,11 @@ function mcl_mapgen.clamp_to_chunk(x, size) 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 diff --git a/mods/ITEMS/mcl_end/eye_of_ender.lua b/mods/ITEMS/mcl_end/eye_of_ender.lua index ea3d70aba..5974e59dd 100644 --- a/mods/ITEMS/mcl_end/eye_of_ender.lua +++ b/mods/ITEMS/mcl_end/eye_of_ender.lua @@ -87,7 +87,7 @@ minetest.register_craftitem("mcl_end:ender_eye", { end local origin = user:get_pos() origin.y = origin.y + 1.5 - local strongholds = mcl_structures.get_registered_structures("stronghold") + local strongholds = mcl_structures.strongholds local dim = mcl_worlds.pos_to_dimension(origin) local is_creative = minetest.is_creative_enabled(user:get_player_name()) diff --git a/mods/MAPGEN/mcl_structures/stronghold.lua b/mods/MAPGEN/mcl_structures/stronghold.lua new file mode 100644 index 000000000..a33c79fcf --- /dev/null +++ b/mods/MAPGEN/mcl_structures/stronghold.lua @@ -0,0 +1,185 @@ +-- Generate strongholds. + +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) + +-- 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 superflat = mcl_mapgen.superflat + +local size = {x = 13, y = 8, z = 13} +local offset = vector.round(vector.divide(size, 2)) + +local function place(pos, rotation, pr) + local p1 = { x = pos.x - offset.x, y = pos.y - offset.y, z = pos.z - offset.z } + local p2 = vector.add(p1, vector.subtract(size, 1)) + + local path = modpath.."/schematics/mcl_structures_end_portal_room_simple.mts" + + mcl_structures.place_schematic({ + pos = p1, + schematic = path, + rotation = rotation or "0", + pr = pr, + }) + minetest.chat_send_all("place! pos=" .. minetest.pos_to_string(p1) .. ", " .. minetest.pos_to_string(p2) .. ", " .. minetest.pos_to_string(size) .. ", " .. minetest.pos_to_string(offset)) + -- Find and setup spawner with silverfish + local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner") + for s=1, #spawners do + mcl_mobspawners.setup_spawner(spawners[s], "mobs_mc:silverfish") + end + + -- 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 +end + + +-- 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 mcl_mapgen.singlenode then + strongholds_inited = true + return + end + local pr = PseudoRandom(mcl_mapgen.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_mapgen.overworld.bedrock_max + offset.y + else + y = pr:next(mcl_mapgen.overworld.bedrock_max+1+offset.y, mcl_mapgen.overworld.bedrock_min+48+offset.y) + end + local pos = { + x = mcl_mapgen.clamp_to_chunk(math.floor(math.cos(angle) * dist) - offset.x, size.x) + offset.x, + y = mcl_mapgen.clamp_to_chunk(y - offset.y, size.y) + offset.y, + z = mcl_mapgen.clamp_to_chunk(math.floor(math.sin(angle) * dist) - offset.z, size.z) + offset.z, + } + 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.strongholds = strongholds + + mcl_structures.register_structure({ + name = "stronghold", + place_function = place, + }) + + strongholds_inited = true +end + +init_strongholds() + +-- Stronghold generation for register_on_generated. +mcl_mapgen.register_mapgen(function(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 + place(pos, nil, pr) + strongholds[s].generated = true + end + end + end +end, mcl_mapgen.order.STRONGHOLDS)