MineClone5/mods/ITEMS/mcl_amethyst/geode.lua

94 lines
2.8 KiB
Lua

local radius_min = 3
local radius_max = mcl_mapgen.HALF_BS
local layers = {
{
[8] = "mcl_blackstone:basalt_polished",
[92] = "mcl_deepslate:deepslate",
},
{
[100] = "mcl_amethyst:calcite",
},
{
[85] = "mcl_amethyst:amethyst_block",
[15] = "mcl_amethyst:budding_amethyst_block",
},
{
[98] = "mcl_amethyst:amethyst_block",
[2] = "mcl_amethyst:budding_amethyst_block",
},
{
[100] = "air",
}
}
local function round(v)
if v < 0 then
return math.ceil(v - 0.5)
end
return math.floor(v + 0.5)
end
local function place(pos, rotation, pr)
local radius1 = vector.new(
-pr:next(radius_min, radius_max),
-pr:next(radius_min, radius_max),
-pr:next(radius_min, radius_max)
)
local radius2 = vector.new(
pr:next(radius_min, radius_max),
pr:next(radius_min, radius_max),
pr:next(radius_min, radius_max)
)
local layer_radius = pr:next(radius_min, radius_max)
local radius1_normalized = vector.normalize(radius1)
local radius2_normalized = vector.normalize(radius2)
local pos = vector.subtract(pos, radius1)
for x = radius1.x, radius2.x do
local max_x = (x < 0) and radius1.x or radius2.x
for y = radius1.y, radius2.y do
local max_y = (y < 0) and radius1.y or radius2.y
for z = radius1.z, radius2.z do
local max_z = (z < 0) and radius1.z or radius2.z
local normal_abs = vector.new(x / max_x, y / max_y, z / max_z)
local inverted_layer = round(vector.length(normal_abs) * layer_radius)
if inverted_layer <= layer_radius then
local layer = math.min(math.max(1, layer_radius - inverted_layer + 1), #layers)
local offset = vector.new(x, y, z)
local node_pos = pos + offset
local node_candidates = layers[layer]
local node_name
local chance_index = pr:next(1, 100)
local current_weight = 0
for chance, node_name_iterated in pairs(node_candidates) do
if chance_index <= current_weight + chance then
node_name = node_name_iterated
break
end
current_weight = current_weight + chance
end
minetest.swap_node(node_pos, {name = node_name})
end
end
end
end
end
mcl_structures.register_structure({
name = "amethyst_geode",
place_function = place,
})
local decrease_scan_area = 1
local mapblock_opacity_placement_threshold = 0.98
local threshold = math.floor(((mcl_mapgen.BS - 2 * decrease_scan_area)^3) * mapblock_opacity_placement_threshold)
local upper_than = mcl_mapgen.overworld.bedrock_max
mcl_mapgen.register_mapgen_block(function(minp, maxp, blockseed)
local y = minp.y
if y <= upper_than then return end
local pr = PseudoRandom(blockseed + 143)
if pr:next(1, 120) ~= 54 then return end
local opacity_counter = #minetest.find_nodes_in_area(vector.add(minp, decrease_scan_area), vector.subtract(maxp, decrease_scan_area), "group:opaque")
if opacity_counter < threshold then return end
place(minp, nil, pr)
end)